Skip to content

Commit 6fce08f

Browse files
bhandarkar-pranavtomtor
authored andcommitted
[Flang] - Handle BoxCharType in fir.box_offset op (llvm#141713)
To map `fir.boxchar` types reliably onto an offload target, such as a GPU, the `omp.map.info` operation is used to map the underlying data pointer (`fir.ref<fir.char<k, ?>>`) wrapped by the `fir.boxchar` MLIR value. The `omp.map.info` operation needs a pointer to the underlying data pointer. Given a reference to a descriptor (`fir.box`), the `fir.box_offset` is used to obtain the address of the underlying data pointer. This PR extends `fir.box_offset` to provide the same functionality for `fir.boxchar` as well.
1 parent afbc2c7 commit 6fce08f

File tree

7 files changed

+62
-11
lines changed

7 files changed

+62
-11
lines changed

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3240,11 +3240,17 @@ def fir_BoxOffsetOp : fir_Op<"box_offset", [NoMemoryEffect]> {
32403240
descriptor implementation must have, only the base_addr and derived_type
32413241
descriptor fields can be addressed.
32423242

3243+
It also accepts the address of a fir.boxchar and returns
3244+
address of the data pointer encapsulated by the fir.boxchar.
3245+
32433246
```
32443247
%addr = fir.box_offset %box base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>
32453248
%tdesc = fir.box_offset %box derived_type : (!fir.ref<!fir.box<!fir.type<t>>>) -> !fir.llvm_ptr<!fir.tdesc<!fir.type<t>>>
32463249

3250+
%addr1 = fir.box_offset %boxchar base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<fir.char<1,?>>>
32473251
```
3252+
3253+
The derived_type field cannot be used when the input to this op is a reference to a fir.boxchar.
32483254
}];
32493255

32503256
let arguments = (ins

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3930,12 +3930,25 @@ struct BoxOffsetOpConversion : public fir::FIROpConversion<fir::BoxOffsetOp> {
39303930
mlir::ConversionPatternRewriter &rewriter) const override {
39313931

39323932
mlir::Type pty = ::getLlvmPtrType(boxOffset.getContext());
3933-
mlir::Type boxType = fir::unwrapRefType(boxOffset.getBoxRef().getType());
3934-
mlir::Type llvmBoxTy =
3935-
lowerTy().convertBoxTypeAsStruct(mlir::cast<fir::BaseBoxType>(boxType));
3936-
int fieldId = boxOffset.getField() == fir::BoxFieldAttr::derived_type
3937-
? getTypeDescFieldId(boxType)
3938-
: kAddrPosInBox;
3933+
mlir::Type boxRefType = fir::unwrapRefType(boxOffset.getBoxRef().getType());
3934+
3935+
assert((mlir::isa<fir::BaseBoxType>(boxRefType) ||
3936+
mlir::isa<fir::BoxCharType>(boxRefType)) &&
3937+
"boxRef should be a reference to either fir.box or fir.boxchar");
3938+
3939+
mlir::Type llvmBoxTy;
3940+
int fieldId;
3941+
if (auto boxType = mlir::dyn_cast_or_null<fir::BaseBoxType>(boxRefType)) {
3942+
llvmBoxTy = lowerTy().convertBoxTypeAsStruct(
3943+
mlir::cast<fir::BaseBoxType>(boxType));
3944+
fieldId = boxOffset.getField() == fir::BoxFieldAttr::derived_type
3945+
? getTypeDescFieldId(boxType)
3946+
: kAddrPosInBox;
3947+
} else {
3948+
auto boxCharType = mlir::cast<fir::BoxCharType>(boxRefType);
3949+
llvmBoxTy = lowerTy().convertType(boxCharType);
3950+
fieldId = kAddrPosInBox;
3951+
}
39393952
rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
39403953
boxOffset, pty, llvmBoxTy, adaptor.getBoxRef(),
39413954
llvm::ArrayRef<mlir::LLVM::GEPArg>{0, fieldId});

flang/lib/Optimizer/Dialect/FIROps.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4484,15 +4484,24 @@ void fir::IfOp::resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> &results,
44844484
llvm::LogicalResult fir::BoxOffsetOp::verify() {
44854485
auto boxType = mlir::dyn_cast_or_null<fir::BaseBoxType>(
44864486
fir::dyn_cast_ptrEleTy(getBoxRef().getType()));
4487-
if (!boxType)
4488-
return emitOpError("box_ref operand must have !fir.ref<!fir.box<T>> type");
4487+
mlir::Type boxCharType;
4488+
if (!boxType) {
4489+
boxCharType = mlir::dyn_cast_or_null<fir::BoxCharType>(
4490+
fir::dyn_cast_ptrEleTy(getBoxRef().getType()));
4491+
if (!boxCharType)
4492+
return emitOpError("box_ref operand must have !fir.ref<!fir.box<T>> or "
4493+
"!fir.ref<!fir.boxchar<k>> type");
4494+
if (getField() == fir::BoxFieldAttr::derived_type)
4495+
return emitOpError("cannot address derived_type field of a fir.boxchar");
4496+
}
44894497
if (getField() != fir::BoxFieldAttr::base_addr &&
44904498
getField() != fir::BoxFieldAttr::derived_type)
44914499
return emitOpError("cannot address provided field");
4492-
if (getField() == fir::BoxFieldAttr::derived_type)
4500+
if (getField() == fir::BoxFieldAttr::derived_type) {
44934501
if (!fir::boxHasAddendum(boxType))
44944502
return emitOpError("can only address derived_type field of derived type "
44954503
"or unlimited polymorphic fir.box");
4504+
}
44964505
return mlir::success();
44974506
}
44984507

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ mlir::Type dyn_cast_ptrOrBoxEleTy(mlir::Type t) {
255255
return llvm::TypeSwitch<mlir::Type, mlir::Type>(t)
256256
.Case<fir::ReferenceType, fir::PointerType, fir::HeapType,
257257
fir::LLVMPointerType>([](auto p) { return p.getEleTy(); })
258-
.Case<fir::BaseBoxType>(
258+
.Case<fir::BaseBoxType, fir::BoxCharType>(
259259
[](auto p) { return unwrapRefType(p.getEleTy()); })
260260
.Default([](mlir::Type) { return mlir::Type{}; });
261261
}

flang/test/Fir/box-offset-codegen.fir

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,13 @@ func.func @array_tdesc(%array : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.t
3737
// CHECK-SAME: ptr {{[^%]*}}%[[BOX:.*]]){{.*}}{
3838
// CHECK: %[[VAL_0:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[BOX]], i32 0, i32 8
3939
// CHECK: ret ptr %[[VAL_0]]
40+
41+
func.func @boxchar_addr(%boxchar : !fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> {
42+
%addr = fir.box_offset %boxchar base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>
43+
return %addr : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>
44+
}
45+
46+
// CHECK-LABEL: define ptr @boxchar_addr(
47+
// CHECK-SAME: ptr {{.*}}%[[BOXCHAR:.*]]){{.*}} {
48+
// CHECK: %[[VAL_0:.*]] = getelementptr { ptr, i64 }, ptr %[[BOXCHAR]], i32 0, i32 0
49+
// CHECK: ret ptr %[[VAL_0]]

flang/test/Fir/box-offset.fir

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ func.func @test_box_offset(%unlimited : !fir.ref<!fir.class<none>>, %type_star :
2121

2222
%addr6 = fir.box_offset %type_star base_addr : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xnone>>>
2323
%tdesc6 = fir.box_offset %type_star derived_type : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> !fir.llvm_ptr<!fir.tdesc<none>>
24+
25+
%boxchar = fir.alloca !fir.boxchar<1>
26+
%addr7 = fir.box_offset %boxchar base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>
2427
return
2528
}
2629
// CHECK-LABEL: func.func @test_box_offset(
@@ -40,3 +43,5 @@ func.func @test_box_offset(%unlimited : !fir.ref<!fir.class<none>>, %type_star :
4043
// CHECK: %[[VAL_13:.*]] = fir.box_offset %[[VAL_0]] derived_type : (!fir.ref<!fir.class<none>>) -> !fir.llvm_ptr<!fir.tdesc<none>>
4144
// CHECK: %[[VAL_14:.*]] = fir.box_offset %[[VAL_1]] base_addr : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xnone>>>
4245
// CHECK: %[[VAL_15:.*]] = fir.box_offset %[[VAL_1]] derived_type : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> !fir.llvm_ptr<!fir.tdesc<none>>
46+
// CHECK: %[[VAL_16:.*]] = fir.alloca !fir.boxchar<1>
47+
// CHECK: %[[VAL_17:.*]] = fir.box_offset %[[VAL_16]] base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>

flang/test/Fir/invalid.fir

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,13 +972,21 @@ func.func @rec_to_rec(%arg0: !fir.type<t1{i:i32, f:f32}>) -> !fir.type<t2{f:f32,
972972
// -----
973973

974974
func.func @bad_box_offset(%not_a_box : !fir.ref<i32>) {
975-
// expected-error@+1{{'fir.box_offset' op box_ref operand must have !fir.ref<!fir.box<T>> type}}
975+
// expected-error@+1{{'fir.box_offset' op box_ref operand must have !fir.ref<!fir.box<T>> or !fir.ref<!fir.boxchar<k>> type}}
976976
%addr1 = fir.box_offset %not_a_box base_addr : (!fir.ref<i32>) -> !fir.llvm_ptr<!fir.ref<i32>>
977977
return
978978
}
979979

980980
// -----
981981

982+
func.func @bad_box_offset(%boxchar : !fir.ref<!fir.boxchar<1>>) {
983+
// expected-error@+1{{'fir.box_offset' op cannot address derived_type field of a fir.boxchar}}
984+
%addr1 = fir.box_offset %boxchar derived_type : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>
985+
return
986+
}
987+
988+
// -----
989+
982990
func.func @bad_box_offset(%no_addendum : !fir.ref<!fir.box<i32>>) {
983991
// expected-error@+1{{'fir.box_offset' op can only address derived_type field of derived type or unlimited polymorphic fir.box}}
984992
%addr1 = fir.box_offset %no_addendum derived_type : (!fir.ref<!fir.box<i32>>) -> !fir.llvm_ptr<!fir.tdesc<!fir.type<none>>>

0 commit comments

Comments
 (0)