[Flang] - Handle BoxCharType in fir.box_offset op (#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.
This commit is contained in:
committed by
GitHub
parent
399865cbf0
commit
8395912895
@@ -3240,11 +3240,17 @@ def fir_BoxOffsetOp : fir_Op<"box_offset", [NoMemoryEffect]> {
|
||||
descriptor implementation must have, only the base_addr and derived_type
|
||||
descriptor fields can be addressed.
|
||||
|
||||
It also accepts the address of a fir.boxchar and returns
|
||||
address of the data pointer encapsulated by the fir.boxchar.
|
||||
|
||||
```
|
||||
%addr = fir.box_offset %box base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>
|
||||
%tdesc = fir.box_offset %box derived_type : (!fir.ref<!fir.box<!fir.type<t>>>) -> !fir.llvm_ptr<!fir.tdesc<!fir.type<t>>>
|
||||
|
||||
%addr1 = fir.box_offset %boxchar base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<fir.char<1,?>>>
|
||||
```
|
||||
|
||||
The derived_type field cannot be used when the input to this op is a reference to a fir.boxchar.
|
||||
}];
|
||||
|
||||
let arguments = (ins
|
||||
|
||||
@@ -3930,12 +3930,25 @@ struct BoxOffsetOpConversion : public fir::FIROpConversion<fir::BoxOffsetOp> {
|
||||
mlir::ConversionPatternRewriter &rewriter) const override {
|
||||
|
||||
mlir::Type pty = ::getLlvmPtrType(boxOffset.getContext());
|
||||
mlir::Type boxType = fir::unwrapRefType(boxOffset.getBoxRef().getType());
|
||||
mlir::Type llvmBoxTy =
|
||||
lowerTy().convertBoxTypeAsStruct(mlir::cast<fir::BaseBoxType>(boxType));
|
||||
int fieldId = boxOffset.getField() == fir::BoxFieldAttr::derived_type
|
||||
? getTypeDescFieldId(boxType)
|
||||
: kAddrPosInBox;
|
||||
mlir::Type boxRefType = fir::unwrapRefType(boxOffset.getBoxRef().getType());
|
||||
|
||||
assert((mlir::isa<fir::BaseBoxType>(boxRefType) ||
|
||||
mlir::isa<fir::BoxCharType>(boxRefType)) &&
|
||||
"boxRef should be a reference to either fir.box or fir.boxchar");
|
||||
|
||||
mlir::Type llvmBoxTy;
|
||||
int fieldId;
|
||||
if (auto boxType = mlir::dyn_cast_or_null<fir::BaseBoxType>(boxRefType)) {
|
||||
llvmBoxTy = lowerTy().convertBoxTypeAsStruct(
|
||||
mlir::cast<fir::BaseBoxType>(boxType));
|
||||
fieldId = boxOffset.getField() == fir::BoxFieldAttr::derived_type
|
||||
? getTypeDescFieldId(boxType)
|
||||
: kAddrPosInBox;
|
||||
} else {
|
||||
auto boxCharType = mlir::cast<fir::BoxCharType>(boxRefType);
|
||||
llvmBoxTy = lowerTy().convertType(boxCharType);
|
||||
fieldId = kAddrPosInBox;
|
||||
}
|
||||
rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
|
||||
boxOffset, pty, llvmBoxTy, adaptor.getBoxRef(),
|
||||
llvm::ArrayRef<mlir::LLVM::GEPArg>{0, fieldId});
|
||||
|
||||
@@ -4484,15 +4484,24 @@ void fir::IfOp::resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> &results,
|
||||
llvm::LogicalResult fir::BoxOffsetOp::verify() {
|
||||
auto boxType = mlir::dyn_cast_or_null<fir::BaseBoxType>(
|
||||
fir::dyn_cast_ptrEleTy(getBoxRef().getType()));
|
||||
if (!boxType)
|
||||
return emitOpError("box_ref operand must have !fir.ref<!fir.box<T>> type");
|
||||
mlir::Type boxCharType;
|
||||
if (!boxType) {
|
||||
boxCharType = mlir::dyn_cast_or_null<fir::BoxCharType>(
|
||||
fir::dyn_cast_ptrEleTy(getBoxRef().getType()));
|
||||
if (!boxCharType)
|
||||
return emitOpError("box_ref operand must have !fir.ref<!fir.box<T>> or "
|
||||
"!fir.ref<!fir.boxchar<k>> type");
|
||||
if (getField() == fir::BoxFieldAttr::derived_type)
|
||||
return emitOpError("cannot address derived_type field of a fir.boxchar");
|
||||
}
|
||||
if (getField() != fir::BoxFieldAttr::base_addr &&
|
||||
getField() != fir::BoxFieldAttr::derived_type)
|
||||
return emitOpError("cannot address provided field");
|
||||
if (getField() == fir::BoxFieldAttr::derived_type)
|
||||
if (getField() == fir::BoxFieldAttr::derived_type) {
|
||||
if (!fir::boxHasAddendum(boxType))
|
||||
return emitOpError("can only address derived_type field of derived type "
|
||||
"or unlimited polymorphic fir.box");
|
||||
}
|
||||
return mlir::success();
|
||||
}
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ mlir::Type dyn_cast_ptrOrBoxEleTy(mlir::Type t) {
|
||||
return llvm::TypeSwitch<mlir::Type, mlir::Type>(t)
|
||||
.Case<fir::ReferenceType, fir::PointerType, fir::HeapType,
|
||||
fir::LLVMPointerType>([](auto p) { return p.getEleTy(); })
|
||||
.Case<fir::BaseBoxType>(
|
||||
.Case<fir::BaseBoxType, fir::BoxCharType>(
|
||||
[](auto p) { return unwrapRefType(p.getEleTy()); })
|
||||
.Default([](mlir::Type) { return mlir::Type{}; });
|
||||
}
|
||||
|
||||
@@ -37,3 +37,13 @@ func.func @array_tdesc(%array : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.t
|
||||
// CHECK-SAME: ptr {{[^%]*}}%[[BOX:.*]]){{.*}}{
|
||||
// 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
|
||||
// CHECK: ret ptr %[[VAL_0]]
|
||||
|
||||
func.func @boxchar_addr(%boxchar : !fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> {
|
||||
%addr = fir.box_offset %boxchar base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>
|
||||
return %addr : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define ptr @boxchar_addr(
|
||||
// CHECK-SAME: ptr {{.*}}%[[BOXCHAR:.*]]){{.*}} {
|
||||
// CHECK: %[[VAL_0:.*]] = getelementptr { ptr, i64 }, ptr %[[BOXCHAR]], i32 0, i32 0
|
||||
// CHECK: ret ptr %[[VAL_0]]
|
||||
|
||||
@@ -21,6 +21,9 @@ func.func @test_box_offset(%unlimited : !fir.ref<!fir.class<none>>, %type_star :
|
||||
|
||||
%addr6 = fir.box_offset %type_star base_addr : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xnone>>>
|
||||
%tdesc6 = fir.box_offset %type_star derived_type : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> !fir.llvm_ptr<!fir.tdesc<none>>
|
||||
|
||||
%boxchar = fir.alloca !fir.boxchar<1>
|
||||
%addr7 = fir.box_offset %boxchar base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>
|
||||
return
|
||||
}
|
||||
// CHECK-LABEL: func.func @test_box_offset(
|
||||
@@ -40,3 +43,5 @@ func.func @test_box_offset(%unlimited : !fir.ref<!fir.class<none>>, %type_star :
|
||||
// CHECK: %[[VAL_13:.*]] = fir.box_offset %[[VAL_0]] derived_type : (!fir.ref<!fir.class<none>>) -> !fir.llvm_ptr<!fir.tdesc<none>>
|
||||
// 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>>>
|
||||
// CHECK: %[[VAL_15:.*]] = fir.box_offset %[[VAL_1]] derived_type : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> !fir.llvm_ptr<!fir.tdesc<none>>
|
||||
// CHECK: %[[VAL_16:.*]] = fir.alloca !fir.boxchar<1>
|
||||
// CHECK: %[[VAL_17:.*]] = fir.box_offset %[[VAL_16]] base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>
|
||||
|
||||
@@ -972,13 +972,21 @@ func.func @rec_to_rec(%arg0: !fir.type<t1{i:i32, f:f32}>) -> !fir.type<t2{f:f32,
|
||||
// -----
|
||||
|
||||
func.func @bad_box_offset(%not_a_box : !fir.ref<i32>) {
|
||||
// expected-error@+1{{'fir.box_offset' op box_ref operand must have !fir.ref<!fir.box<T>> type}}
|
||||
// expected-error@+1{{'fir.box_offset' op box_ref operand must have !fir.ref<!fir.box<T>> or !fir.ref<!fir.boxchar<k>> type}}
|
||||
%addr1 = fir.box_offset %not_a_box base_addr : (!fir.ref<i32>) -> !fir.llvm_ptr<!fir.ref<i32>>
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func.func @bad_box_offset(%boxchar : !fir.ref<!fir.boxchar<1>>) {
|
||||
// expected-error@+1{{'fir.box_offset' op cannot address derived_type field of a fir.boxchar}}
|
||||
%addr1 = fir.box_offset %boxchar derived_type : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func.func @bad_box_offset(%no_addendum : !fir.ref<!fir.box<i32>>) {
|
||||
// expected-error@+1{{'fir.box_offset' op can only address derived_type field of derived type or unlimited polymorphic fir.box}}
|
||||
%addr1 = fir.box_offset %no_addendum derived_type : (!fir.ref<!fir.box<i32>>) -> !fir.llvm_ptr<!fir.tdesc<!fir.type<none>>>
|
||||
|
||||
Reference in New Issue
Block a user