mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-25 21:11:25 +00:00
[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@nvidia.com> Co-authored-by: Jean Perier <jperier@nvidia.com>
This commit is contained in:
parent
37c7211f11
commit
14867ffc7c
@ -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)
|
||||
```
|
||||
}];
|
||||
|
||||
|
@ -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 @@ public:
|
||||
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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user