[flang-commits] [flang] e3349fa - [flang][CodeGen] Transform `fir.{store|load}` to `llvm.{store|load}`
Andrzej Warzynski via flang-commits
flang-commits at lists.llvm.org
Tue Nov 9 12:22:53 PST 2021
Author: Andrzej Warzynski
Date: 2021-11-09T20:22:45Z
New Revision: e3349fa1a35130ce7434ea62ba50921411093d22
URL: https://github.com/llvm/llvm-project/commit/e3349fa1a35130ce7434ea62ba50921411093d22
DIFF: https://github.com/llvm/llvm-project/commit/e3349fa1a35130ce7434ea62ba50921411093d22.diff
LOG: [flang][CodeGen] Transform `fir.{store|load}` to `llvm.{store|load}`
This patch extends the `FIRToLLVMLowering` pass in Flang by adding a
hook to transform `fir.store`/`fir.load` to `llvm.store`/`fir.load`,
respectively.
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/D113090
Patch originally written by:
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 c81f385f21df0..6d48354f97282 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -366,6 +366,29 @@ struct SelectOpConversion : public FIROpConversion<fir::SelectOp> {
}
};
+/// `fir.load` --> `llvm.load`
+struct LoadOpConversion : public FIROpConversion<fir::LoadOp> {
+ using FIROpConversion::FIROpConversion;
+
+ mlir::LogicalResult
+ matchAndRewrite(fir::LoadOp load, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ // fir.box is a special case because it is considered as an ssa values in
+ // fir, but it is lowered as a pointer to a descriptor. So fir.ref<fir.box>
+ // and fir.box end up being the same llvm types and loading a
+ // fir.ref<fir.box> is actually a no op in LLVM.
+ if (load.getType().isa<fir::BoxType>()) {
+ rewriter.replaceOp(load, adaptor.getOperands()[0]);
+ } else {
+ mlir::Type ty = convertType(load.getType());
+ ArrayRef<NamedAttribute> at = load->getAttrs();
+ rewriter.replaceOpWithNewOp<mlir::LLVM::LoadOp>(
+ load, ty, adaptor.getOperands(), at);
+ }
+ return success();
+ }
+};
+
/// conversion of fir::SelectRankOp to an if-then-else ladder
struct SelectRankOpConversion : public FIROpConversion<fir::SelectRankOp> {
using FIROpConversion::FIROpConversion;
@@ -378,7 +401,31 @@ struct SelectRankOpConversion : public FIROpConversion<fir::SelectRankOp> {
}
};
-// convert to LLVM IR dialect `undef`
+/// `fir.store` --> `llvm.store`
+struct StoreOpConversion : public FIROpConversion<fir::StoreOp> {
+ using FIROpConversion::FIROpConversion;
+
+ mlir::LogicalResult
+ matchAndRewrite(fir::StoreOp store, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ if (store.value().getType().isa<fir::BoxType>()) {
+ // fir.box value is actually in memory, load it first before storing it.
+ mlir::Location loc = store.getLoc();
+ mlir::Type boxPtrTy = adaptor.getOperands()[0].getType();
+ auto val = rewriter.create<mlir::LLVM::LoadOp>(
+ loc, boxPtrTy.cast<mlir::LLVM::LLVMPointerType>().getElementType(),
+ adaptor.getOperands()[0]);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::StoreOp>(
+ store, val, adaptor.getOperands()[1]);
+ } else {
+ rewriter.replaceOpWithNewOp<mlir::LLVM::StoreOp>(
+ store, adaptor.getOperands()[0], adaptor.getOperands()[1]);
+ }
+ return success();
+ }
+};
+
+/// convert to LLVM IR dialect `undef`
struct UndefOpConversion : public FIROpConversion<fir::UndefOp> {
using FIROpConversion::FIROpConversion;
@@ -391,7 +438,7 @@ struct UndefOpConversion : public FIROpConversion<fir::UndefOp> {
}
};
-// convert to LLVM IR dialect `unreachable`
+/// `fir.unreachable` --> `llvm.unreachable`
struct UnreachableOpConversion : public FIROpConversion<fir::UnreachableOp> {
using FIROpConversion::FIROpConversion;
@@ -788,14 +835,14 @@ class FIRToLLVMLowering : public fir::FIRToLLVMLoweringBase<FIRToLLVMLowering> {
auto *context = getModule().getContext();
fir::LLVMTypeConverter typeConverter{getModule()};
mlir::OwningRewritePatternList pattern(context);
- pattern
- .insert<AddcOpConversion, AddrOfOpConversion, CallOpConversion,
- ConvertOpConversion, DivcOpConversion, ExtractValueOpConversion,
- HasValueOpConversion, GlobalOpConversion,
- InsertOnRangeOpConversion, InsertValueOpConversion,
- NegcOpConversion, MulcOpConversion, SelectOpConversion,
- SelectRankOpConversion, SubcOpConversion, UndefOpConversion,
- UnreachableOpConversion, ZeroOpConversion>(typeConverter);
+ pattern.insert<AddcOpConversion, AddrOfOpConversion, CallOpConversion,
+ ConvertOpConversion, DivcOpConversion,
+ ExtractValueOpConversion, HasValueOpConversion,
+ GlobalOpConversion, InsertOnRangeOpConversion,
+ InsertValueOpConversion, LoadOpConversion, NegcOpConversion,
+ MulcOpConversion, SelectOpConversion, SelectRankOpConversion,
+ StoreOpConversion, SubcOpConversion, 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 b33a2294b3e3d..91a23d33172e4 100644
--- a/flang/test/Fir/convert-to-llvm.fir
+++ b/flang/test/Fir/convert-to-llvm.fir
@@ -632,3 +632,57 @@ func @convert_complex16(%arg0 : !fir.complex<16>) -> !fir.complex<2> {
// CHECK: %[[STRUCT1:.*]] = llvm.insertvalue %[[CONVERTX]], %[[STRUCT0]][0 : i32] : !llvm.struct<(f16, f16)>
// CHECK: %[[STRUCT2:.*]] = llvm.insertvalue %[[CONVERTY]], %[[STRUCT1]][1 : i32] : !llvm.struct<(f16, f16)>
// CHECK: llvm.return %[[STRUCT2]] : !llvm.struct<(f16, f16)>
+
+// -----
+
+// Test `fir.store` --> `llvm.store` conversion
+
+func @test_store_index(%val_to_store : index, %addr : !fir.ref<index>) {
+ fir.store %val_to_store to %addr : !fir.ref<index>
+ return
+}
+
+// CHECK-LABEL: llvm.func @test_store_index
+// CHECK-SAME: (%[[arg0:.*]]: i64, %[[arg1:.*]]: !llvm.ptr<i64>) {
+// CHECK-NEXT: llvm.store %[[arg0]], %[[arg1]] : !llvm.ptr<i64>
+// CHECK-NEXT: llvm.return
+// CHECK-NEXT: }
+
+func @test_store_box(%array : !fir.ref<!fir.box<!fir.array<?x?xf32>>>, %box : !fir.box<!fir.array<?x?xf32>>) {
+ fir.store %box to %array : !fir.ref<!fir.box<!fir.array<?x?xf32>>>
+ return
+}
+
+// CHECK-LABEL: llvm.func @test_store_box
+// CHECK-SAME: (%[[arg0:.*]]: !llvm.ptr<struct<(ptr<f{{.*}}>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i{{.*}}>>)>>,
+// CHECK-SAME: %[[arg1:.*]]: !llvm.ptr<struct<(ptr<f{{.*}}>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i{{.*}}>>)>>) {
+// CHECK-NEXT: %[[box_to_store:.*]] = llvm.load %arg1 : !llvm.ptr<struct<(ptr<f{{.*}}>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i{{.*}}>>)>>
+// CHECK-NEXT: llvm.store %[[box_to_store]], %[[arg0]] : !llvm.ptr<struct<(ptr<f{{.*}}>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i{{.*}}>>)>>
+// CHECK-NEXT: llvm.return
+// CHECK-NEXT: }
+
+// -----
+
+// Test `fir.load` --> `llvm.load` conversion
+
+func @test_load_index(%addr : !fir.ref<index>) {
+ %0 = fir.load %addr : !fir.ref<index>
+ return
+}
+
+// CHECK-LABEL: llvm.func @test_load_index(
+// CHECK-SAME: %[[arg1:.*]]: !llvm.ptr<i64>) {
+// CHECK-NEXT: %0 = llvm.load %[[arg1]] : !llvm.ptr<i64>
+// CHECK-NEXT: llvm.return
+// CHECK-NEXT: }
+
+func @test_load_box(%addr : !fir.ref<!fir.box<!fir.array<10xf32>>>) {
+ %0 = fir.load %addr : !fir.ref<!fir.box<!fir.array<10xf32>>>
+ return
+}
+
+// Loading a `fir.ref<!fir.box>> is a no-op
+// CHECK-LABEL: llvm.func @test_load_box
+// CHECK-SAME: (%{{.*}}: !llvm.ptr<struct<(ptr<array<10 x f{{.*}}>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>)>>) {
+// CHECK-NEXT: llvm.return
+// CHECK-NEXT: }
More information about the flang-commits
mailing list