[flang-commits] [flang] e6c66ef - [flang][CodeGen] Transform `fir.field_index` to a sequence of LLVM MLIR
Andrzej Warzynski via flang-commits
flang-commits at lists.llvm.org
Thu Nov 18 08:36:16 PST 2021
Author: Andrzej Warzynski
Date: 2021-11-18T16:35:16Z
New Revision: e6c66ef55e63bb0e19f435de33eb12257680120c
URL: https://github.com/llvm/llvm-project/commit/e6c66ef55e63bb0e19f435de33eb12257680120c
DIFF: https://github.com/llvm/llvm-project/commit/e6c66ef55e63bb0e19f435de33eb12257680120c.diff
LOG: [flang][CodeGen] Transform `fir.field_index` to a sequence of LLVM MLIR
This patch extends the `FIRToLLVMLowering` pass in Flang by adding a
hook to transform `fir.field_index` to a sequence of LLVM MLIR
instructions.
This is part of the upstreaming effort from the `fir-dev` branch in [1].
[1] https://github.com/flang-compiler/f18-llvm-project
Differential Revision: https://reviews.llvm.org/D113988
Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>
Co-authored-by: Jean Perier <jperier at nvidia.com>
Added:
Modified:
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/test/Fir/convert-to-llvm.fir
Removed:
################################################################################
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 5346dda6b8d4a..0cd62e6db768b 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -2089,6 +2089,48 @@ struct UnboxProcOpConversion : public FIROpConversion<fir::UnboxProcOp> {
}
};
+/// Convert `fir.field_index`. The conversion depends on whether the size of
+/// the record is static or dynamic.
+struct FieldIndexOpConversion : public FIROpConversion<fir::FieldIndexOp> {
+ using FIROpConversion::FIROpConversion;
+
+ // NB: most field references should be resolved by this point
+ mlir::LogicalResult
+ matchAndRewrite(fir::FieldIndexOp field, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ auto recTy = field.on_type().cast<fir::RecordType>();
+ unsigned index = recTy.getFieldIndex(field.field_id());
+
+ if (!fir::hasDynamicSize(recTy)) {
+ // Derived type has compile-time constant layout. Return index of the
+ // component type in the parent type (to be used in GEP).
+ rewriter.replaceOp(field, mlir::ValueRange{genConstantOffset(
+ field.getLoc(), rewriter, index)});
+ return success();
+ }
+
+ // Derived type has compile-time constant layout. Call the compiler
+ // generated function to determine the byte offset of the field at runtime.
+ // This returns a non-constant.
+ FlatSymbolRefAttr symAttr = mlir::SymbolRefAttr::get(
+ field.getContext(), getOffsetMethodName(recTy, field.field_id()));
+ NamedAttribute callAttr = rewriter.getNamedAttr("callee", symAttr);
+ NamedAttribute fieldAttr = rewriter.getNamedAttr(
+ "field", mlir::IntegerAttr::get(lowerTy().indexType(), index));
+ rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
+ field, lowerTy().offsetType(), adaptor.getOperands(),
+ llvm::ArrayRef<mlir::NamedAttribute>{callAttr, fieldAttr});
+ return success();
+ }
+
+ // Re-Construct the name of the compiler generated method that calculates the
+ // offset
+ inline static std::string getOffsetMethodName(fir::RecordType recTy,
+ llvm::StringRef field) {
+ return recTy.getName().str() + "P." + field.str() + ".offset";
+ }
+};
+
} // namespace
namespace {
@@ -2120,16 +2162,17 @@ class FIRToLLVMLowering : public fir::FIRToLLVMLoweringBase<FIRToLLVMLowering> {
CmpcOpConversion, ConstcOpConversion, ConvertOpConversion,
DispatchOpConversion, DispatchTableOpConversion, DTEntryOpConversion,
DivcOpConversion, EmboxOpConversion, EmboxCharOpConversion,
- EmboxProcOpConversion, ExtractValueOpConversion, FirEndOpConversion,
- HasValueOpConversion, GenTypeDescOpConversion, GlobalLenOpConversion,
- GlobalOpConversion, InsertOnRangeOpConversion, InsertValueOpConversion,
- IsPresentOpConversion, LoadOpConversion, NegcOpConversion,
- MulcOpConversion, SelectCaseOpConversion, SelectOpConversion,
- SelectRankOpConversion, SelectTypeOpConversion, ShapeOpConversion,
- ShapeShiftOpConversion, ShiftOpConversion, SliceOpConversion,
- StoreOpConversion, StringLitOpConversion, SubcOpConversion,
- UnboxCharOpConversion, UnboxProcOpConversion, UndefOpConversion,
- UnreachableOpConversion, ZeroOpConversion>(typeConverter);
+ EmboxProcOpConversion, ExtractValueOpConversion, FieldIndexOpConversion,
+ FirEndOpConversion, HasValueOpConversion, GenTypeDescOpConversion,
+ GlobalLenOpConversion, GlobalOpConversion, InsertOnRangeOpConversion,
+ InsertValueOpConversion, IsPresentOpConversion, LoadOpConversion,
+ NegcOpConversion, MulcOpConversion, SelectCaseOpConversion,
+ SelectOpConversion, SelectRankOpConversion, SelectTypeOpConversion,
+ ShapeOpConversion, ShapeShiftOpConversion, ShiftOpConversion,
+ SliceOpConversion, StoreOpConversion, StringLitOpConversion,
+ SubcOpConversion, UnboxCharOpConversion, UnboxProcOpConversion,
+ UndefOpConversion, UnreachableOpConversion, ZeroOpConversion>(
+ typeConverter);
mlir::populateStdToLLVMConversionPatterns(typeConverter, pattern);
mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter,
pattern);
diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir
index 90dd7d8c43962..af43418e3c31e 100644
--- a/flang/test/Fir/convert-to-llvm.fir
+++ b/flang/test/Fir/convert-to-llvm.fir
@@ -1530,3 +1530,42 @@ func @embox1(%arg0: !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>) {
// CHECK: %[[TDESC:.*]] = llvm.mlir.addressof @_QMtest_dinitE.dt.tseq : !llvm.ptr<i8>
// CHECK: %[[TDESC_CAST:.*]] = llvm.bitcast %22 : !llvm.ptr<i8> to !llvm.ptr<i8>
// CHECK: %{{.*}} = llvm.insertvalue %[[TDESC_CAST]], %{{.*}}[7 : i32] : !llvm.struct<(ptr<struct<"_QMtest_dinitTtseq", (i32)>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>
+
+// -----
+
+// Test `fir.field_index`
+
+func @field_index_static_size_1_elem() -> () {
+ %1 = fir.field_index i, !fir.type<t1{i:i32}>
+ return
+}
+
+// CHECK-LABEL: @field_index_static_size_1_elem
+// CHECK-NEXT: %{{.*}} = llvm.mlir.constant(0 : i32) : i32
+// CHECK-NEXT: llvm.return
+
+func @field_index_static_size_3_elems() -> () {
+ %1 = fir.field_index k, !fir.type<t2{i:i32, j:f32, k:i8}>
+ return
+}
+
+// CHECK-LABEL: @field_index_static_size_3_elems
+// CHECK-NEXT: %{{.*}} = llvm.mlir.constant(2 : i32) : i32
+// CHECK-NEXT: llvm.return
+
+// When converting `fir.field_index` for a dynamically sized record, the
+// offset will be calculated at runtime by calling methods like the ones
+// below. Note that these methods would normally be generated by the compiler.
+func private @custom_typeP.field_1.offset() -> i32
+func private @custom_typeP.field_2.offset() -> i32
+
+func @field_index_dynamic_size() -> () {
+ %1 = fir.field_index field_1, !fir.type<custom_type{field_1:i32, field_2:!fir.array<?xf32>}>
+ %2 = fir.field_index field_2, !fir.type<custom_type{field_1:i32, field_2:!fir.array<?xf32>}>
+ return
+}
+
+// CHECK-LABEL: @field_index_dynamic_size
+// CHECK-NEXT: %{{.*}} = llvm.call @custom_typeP.field_1.offset() {field = 0 : i64} : () -> i32
+// CHECK-NEXT: %{{.*}} = llvm.call @custom_typeP.field_2.offset() {field = 1 : i64} : () -> i32
+// CHECK-NEXT: llvm.return
More information about the flang-commits
mailing list