Skip to content

Commit a786919

Browse files
authored
[flang] allow assumed-rank box in fir.store (#95980)
Codegen is done with a memcpy using the rank from the "value" descriptor like for the fir.load case. Rational described in https://github.com/llvm/llvm-project/blob/main/flang/docs/AssumedRank.md.
1 parent bdc7840 commit a786919

File tree

4 files changed

+58
-13
lines changed

4 files changed

+58
-13
lines changed

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3143,23 +3143,32 @@ struct StoreOpConversion : public fir::FIROpConversion<fir::StoreOp> {
31433143
mlir::ConversionPatternRewriter &rewriter) const override {
31443144
mlir::Location loc = store.getLoc();
31453145
mlir::Type storeTy = store.getValue().getType();
3146-
mlir::LLVM::StoreOp newStoreOp;
3146+
mlir::Value llvmValue = adaptor.getValue();
3147+
mlir::Value llvmMemref = adaptor.getMemref();
3148+
mlir::LLVM::AliasAnalysisOpInterface newOp;
31473149
if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(storeTy)) {
3148-
// fir.box value is actually in memory, load it first before storing it.
31493150
mlir::Type llvmBoxTy = lowerTy().convertBoxTypeAsStruct(boxTy);
3150-
auto val = rewriter.create<mlir::LLVM::LoadOp>(loc, llvmBoxTy,
3151-
adaptor.getOperands()[0]);
3152-
attachTBAATag(val, boxTy, boxTy, nullptr);
3153-
newStoreOp = rewriter.create<mlir::LLVM::StoreOp>(
3154-
loc, val, adaptor.getOperands()[1]);
3151+
// fir.box value is actually in memory, load it first before storing it,
3152+
// or do a memcopy for assumed-rank descriptors.
3153+
if (boxTy.isAssumedRank()) {
3154+
TypePair boxTypePair{boxTy, llvmBoxTy};
3155+
mlir::Value boxSize =
3156+
computeBoxSize(loc, boxTypePair, llvmValue, rewriter);
3157+
newOp = rewriter.create<mlir::LLVM::MemcpyOp>(
3158+
loc, llvmMemref, llvmValue, boxSize, /*isVolatile=*/false);
3159+
} else {
3160+
auto val =
3161+
rewriter.create<mlir::LLVM::LoadOp>(loc, llvmBoxTy, llvmValue);
3162+
attachTBAATag(val, boxTy, boxTy, nullptr);
3163+
newOp = rewriter.create<mlir::LLVM::StoreOp>(loc, val, llvmMemref);
3164+
}
31553165
} else {
3156-
newStoreOp = rewriter.create<mlir::LLVM::StoreOp>(
3157-
loc, adaptor.getOperands()[0], adaptor.getOperands()[1]);
3166+
newOp = rewriter.create<mlir::LLVM::StoreOp>(loc, llvmValue, llvmMemref);
31583167
}
31593168
if (std::optional<mlir::ArrayAttr> optionalTag = store.getTbaa())
3160-
newStoreOp.setTBAATags(*optionalTag);
3169+
newOp.setTBAATags(*optionalTag);
31613170
else
3162-
attachTBAATag(newStoreOp, storeTy, storeTy, nullptr);
3171+
attachTBAATag(newOp, storeTy, storeTy, nullptr);
31633172
rewriter.eraseOp(store);
31643173
return mlir::success();
31653174
}

flang/lib/Optimizer/Dialect/FIROps.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3791,8 +3791,6 @@ void fir::StoreOp::print(mlir::OpAsmPrinter &p) {
37913791
mlir::LogicalResult fir::StoreOp::verify() {
37923792
if (getValue().getType() != fir::dyn_cast_ptrEleTy(getMemref().getType()))
37933793
return emitOpError("store value type must match memory reference type");
3794-
if (fir::isa_unknown_size_box(getValue().getType()))
3795-
return emitOpError("cannot store !fir.box of unknown rank or type");
37963794
return mlir::success();
37973795
}
37983796

flang/test/Fir/convert-to-llvm.fir

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,25 @@ func.func @store_unlimited_polymorphic_box(%arg0 : !fir.class<none>, %arg1 : !fi
893893
// CHECK: llvm.store %[[VAL_11]], %{{.*}} : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>, ptr, array<1 x i{{.*}}>)>, !llvm.ptr
894894

895895

896+
// -----
897+
898+
func.func @store_assumed_rank_box(%box: !fir.box<!fir.array<*:f32>>, %ref: !fir.ref<!fir.box<!fir.array<*:f32>>>) {
899+
fir.store %box to %ref : !fir.ref<!fir.box<!fir.array<*:f32>>>
900+
return
901+
}
902+
903+
// CHECK-LABEL: llvm.func @store_assumed_rank_box(
904+
// CHECK-SAME: %[[VAL_0:[^:]*]]: !llvm.ptr,
905+
// CHECK-SAME: %[[VAL_1:.*]]: !llvm.ptr) {
906+
// CHECK: %[[VAL_2:.*]] = llvm.mlir.constant(24 : i32) : i32
907+
// CHECK: %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<15 x array<3 x i64>>)>
908+
// CHECK: %[[VAL_4:.*]] = llvm.load %[[VAL_3]] : !llvm.ptr -> i8
909+
// CHECK: %[[VAL_5:.*]] = llvm.sext %[[VAL_4]] : i8 to i32
910+
// CHECK: %[[VAL_6:.*]] = llvm.mlir.constant(24 : i32) : i32
911+
// CHECK: %[[VAL_7:.*]] = llvm.mul %[[VAL_6]], %[[VAL_5]] : i32
912+
// CHECK: %[[VAL_8:.*]] = llvm.add %[[VAL_2]], %[[VAL_7]] : i32
913+
// CHECK: "llvm.intr.memcpy"(%[[VAL_1]], %[[VAL_0]], %[[VAL_8]]) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
914+
896915
// -----
897916

898917
// Test `fir.load` --> `llvm.load` conversion

flang/test/Fir/tbaa.fir

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,3 +407,22 @@ func.func private @some_assumed_rank_func(!fir.box<!fir.array<*:f64>>) -> ()
407407
// CHECK: %[[VAL_9:.*]] = llvm.add %[[VAL_3]], %[[VAL_8]] : i32
408408
// CHECK: "llvm.intr.memcpy"(%[[VAL_2]], %[[VAL_0]], %[[VAL_9]]) <{isVolatile = false, tbaa = [#[[$BOXT]]]}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
409409
// CHECK: llvm.call @some_assumed_rank_func(%[[VAL_2]]) : (!llvm.ptr) -> ()
410+
411+
// -----
412+
413+
func.func @store_assumed_rank_box(%box: !fir.box<!fir.array<*:f32>>, %ref: !fir.ref<!fir.box<!fir.array<*:f32>>>) {
414+
fir.store %box to %ref : !fir.ref<!fir.box<!fir.array<*:f32>>>
415+
return
416+
}
417+
418+
// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root<id = "Flang function root ">
419+
// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[ROOT]], 0>}>
420+
// CHECK-DAG: #[[BOXMEM:.*]] = #llvm.tbaa_type_desc<id = "descriptor member", members = {<#[[ANYACC]], 0>}>
421+
// CHECK-DAG: #[[$BOXT:.*]] = #llvm.tbaa_tag<base_type = #[[BOXMEM]], access_type = #[[BOXMEM]], offset = 0>
422+
423+
// CHECK-LABEL: llvm.func @store_assumed_rank_box(
424+
// CHECK-SAME: %[[VAL_0:[^:]*]]: !llvm.ptr,
425+
// CHECK-SAME: %[[VAL_1:.*]]: !llvm.ptr) {
426+
// CHECK: %[[VAL_3:.*]] = llvm.getelementptr %[[VAL_0]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<15 x array<3 x i64>>)>
427+
// CHECK: %[[VAL_4:.*]] = llvm.load %[[VAL_3]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr -> i8
428+
// CHECK: "llvm.intr.memcpy"(%[[VAL_1]], %[[VAL_0]], %{{.*}}) <{isVolatile = false, tbaa = [#[[$BOXT]]]}> : (!llvm.ptr, !llvm.ptr, i32) -> ()

0 commit comments

Comments
 (0)