[flang-commits] [flang] 14867ff - [flang][CodeGen] Transform `fir.unboxchar` to a sequence of LLVM MLIR

Andrzej Warzynski via flang-commits flang-commits at lists.llvm.org
Mon Nov 15 07:35:40 PST 2021


Author: Andrzej Warzynski
Date: 2021-11-15T15:34:55Z
New Revision: 14867ffc7c6dd78665b332fe2e815c83909eb93e

URL: https://github.com/llvm/llvm-project/commit/14867ffc7c6dd78665b332fe2e815c83909eb93e
DIFF: https://github.com/llvm/llvm-project/commit/14867ffc7c6dd78665b332fe2e815c83909eb93e.diff

LOG: [flang][CodeGen] Transform `fir.unboxchar` to a sequence of LLVM MLIR

This patch extends the `FIRToLLVMLowering` pass in Flang by adding a
hook to transform `fir.unboxchar` 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/D113747

Originally written by:
Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>
Co-authored-by: Jean Perier <jperier at nvidia.com>

Added: 
    

Modified: 
    flang/include/flang/Optimizer/Dialect/FIROps.td
    flang/lib/Optimizer/CodeGen/CodeGen.cpp
    flang/test/Fir/convert-to-llvm-target.fir

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index 57109bcada9f..d0156d37d6ab 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -1030,7 +1030,7 @@ def fir_UnboxCharOp : fir_SimpleOp<"unboxchar", [NoSideEffect]> {
 
     ```mlir
       %45   = ... : !fir.boxchar<1>
-      %46:2 = fir.unboxchar %45 : (!fir.boxchar<1>) -> (!fir.ref<!fir.character<1>>, i32)
+      %46:2 = fir.unboxchar %45 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1>>, i32)
     ```
   }];
 

diff  --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 590be4f3b5ab..ffc3b0a37aa0 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -1435,6 +1435,46 @@ struct EmboxCharOpConversion : public FIROpConversion<fir::EmboxCharOp> {
     return success();
   }
 };
+
+/// Construct an `llvm.extractvalue` instruction. It will return value at
+/// element \p x from  \p tuple.
+mlir::LLVM::ExtractValueOp
+genExtractValueWithIndex(mlir::Location loc, mlir::Value tuple, mlir::Type ty,
+                         mlir::ConversionPatternRewriter &rewriter,
+                         mlir::MLIRContext *ctx, int x) {
+  auto cx = mlir::ArrayAttr::get(ctx, rewriter.getI32IntegerAttr(x));
+  auto xty = ty.cast<mlir::LLVM::LLVMStructType>().getBody()[x];
+  return rewriter.create<mlir::LLVM::ExtractValueOp>(loc, xty, tuple, cx);
+}
+
+/// Convert `fir.unboxchar` into two `llvm.extractvalue` instructions. One for
+/// the character buffer and one for the buffer length.
+struct UnboxCharOpConversion : public FIROpConversion<fir::UnboxCharOp> {
+  using FIROpConversion::FIROpConversion;
+
+  mlir::LogicalResult
+  matchAndRewrite(fir::UnboxCharOp unboxchar, OpAdaptor adaptor,
+                  mlir::ConversionPatternRewriter &rewriter) const override {
+    MLIRContext *ctx = unboxchar.getContext();
+
+    mlir::Type lenTy = convertType(unboxchar.getType(1));
+    mlir::Value tuple = adaptor.getOperands()[0];
+    mlir::Type tupleTy = tuple.getType();
+
+    mlir::Location loc = unboxchar.getLoc();
+    mlir::Value ptrToBuffer =
+        genExtractValueWithIndex(loc, tuple, tupleTy, rewriter, ctx, 0);
+
+    mlir::LLVM::ExtractValueOp len =
+        genExtractValueWithIndex(loc, tuple, tupleTy, rewriter, ctx, 1);
+    mlir::Value lenAfterCast = integerCast(loc, rewriter, lenTy, len);
+
+    rewriter.replaceOp(unboxchar,
+                       ArrayRef<mlir::Value>{ptrToBuffer, lenAfterCast});
+    return success();
+  }
+};
+
 } // namespace
 
 namespace {
@@ -1469,8 +1509,8 @@ class FIRToLLVMLowering : public fir::FIRToLLVMLoweringBase<FIRToLLVMLowering> {
         IsPresentOpConversion, LoadOpConversion, NegcOpConversion,
         MulcOpConversion, SelectCaseOpConversion, SelectOpConversion,
         SelectRankOpConversion, SelectTypeOpConversion, StoreOpConversion,
-        SubcOpConversion, UndefOpConversion, UnreachableOpConversion,
-        ZeroOpConversion>(typeConverter);
+        SubcOpConversion, UnboxCharOpConversion, UndefOpConversion,
+        UnreachableOpConversion, ZeroOpConversion>(typeConverter);
     mlir::populateStdToLLVMConversionPatterns(typeConverter, pattern);
     mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter,
                                                             pattern);

diff  --git a/flang/test/Fir/convert-to-llvm-target.fir b/flang/test/Fir/convert-to-llvm-target.fir
index 46e693ca52e3..501e68741a8e 100644
--- a/flang/test/Fir/convert-to-llvm-target.fir
+++ b/flang/test/Fir/convert-to-llvm-target.fir
@@ -31,3 +31,43 @@ func @test_embox(%char_array : !fir.ref<!fir.char<1,?>>) -> () {
 // INT32:    %[[struct_with_buffer:.*]] = llvm.insertvalue %[[char_array]], %[[empty_struct]][0 : i32] : !llvm.struct<(ptr<i8>, i32)>
 // INT32:    %{{.*}} = llvm.insertvalue %[[c10_truncated:.*]], %[[struct_with_buffer]][1 : i32] : !llvm.struct<(ptr<i8>, i32)>
 // INT32-NEXT:    llvm.return
+
+// -----
+
+// Test fir.unboxchar
+
+func @unboxchar_i8(%arg0 : !fir.boxchar<1>) -> () {
+  %0:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1>>, i64)
+  return
+}
+
+// INT64-LABEL: llvm.func @unboxchar_i8
+// INT64-SAME: %[[box_char:.*]]: !llvm.struct<(ptr<i8>, i64)>
+// INT64:  %{{.*}} = llvm.extractvalue %[[box_char]][0 : i32] : !llvm.struct<(ptr<i8>, i64)>
+// INT64:  %{{.*}} = llvm.extractvalue %[[box_char]][1 : i32] : !llvm.struct<(ptr<i8>, i64)>
+// INT64-NEXT:  llvm.return
+
+// INT32-LABEL: llvm.func @unboxchar_i8
+// INT32-SAME: %[[box_char:.*]]: !llvm.struct<(ptr<i8>, i32)>
+// INT32:  %{{.*}} = llvm.extractvalue %[[box_char]][0 : i32] : !llvm.struct<(ptr<i8>, i32)>
+// INT32:  %[[len_unextended:.*]] = llvm.extractvalue %[[box_char]][1 : i32] : !llvm.struct<(ptr<i8>, i32)>
+// INT32:  %{{.*}} = llvm.sext %[[len_unextended]] : i32 to i64
+// INT32-NEXT:  llvm.return
+
+func @unboxchar_i32(%arg0 : !fir.boxchar<4>) -> () {
+  fir.unboxchar %arg0 : (!fir.boxchar<4>) -> (!fir.ref<!fir.char<4>>, i64)
+  return
+}
+
+// INT64-LABEL: llvm.func @unboxchar_i32
+// INT64-SAME: %[[box_char:.*]]: !llvm.struct<(ptr<i32>, i64)>
+// INT64:  %{{.*}} = llvm.extractvalue %[[box_char]][0 : i32] : !llvm.struct<(ptr<i32>, i64)>
+// INT64:  %{{.*}} = llvm.extractvalue %[[box_char]][1 : i32] : !llvm.struct<(ptr<i32>, i64)>
+// INT64-NEXT:  llvm.return
+
+// INT32-LABEL: llvm.func @unboxchar_i32
+// INT32-SAME: %[[box_char:.*]]: !llvm.struct<(ptr<i32>, i32)>
+// INT32:  %{{.*}} = llvm.extractvalue %[[box_char]][0 : i32] : !llvm.struct<(ptr<i32>, i32)>
+// INT32:  %[[len_unextended:.*]] = llvm.extractvalue %[[box_char]][1 : i32] : !llvm.struct<(ptr<i32>, i32)>
+// INT32:  %{{.*}} = llvm.sext %[[len_unextended]] : i32 to i64
+// INT32-NEXT:  llvm.return


        


More information about the flang-commits mailing list