diff options
author | Corentin Ferry <corentin.ferry@amd.com> | 2024-06-03 13:22:52 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-03 13:22:52 +0200 |
commit | 12fcca0afeb08fbe41d79c5387cfacb249992bb4 (patch) | |
tree | 94c497a5176c704cf7b3842a3c8c540646712ee7 | |
parent | 22a7f7c3314328dd1ac20042158f4b68a4ac5c1f (diff) | |
download | llvm-12fcca0afeb08fbe41d79c5387cfacb249992bb4.zip llvm-12fcca0afeb08fbe41d79c5387cfacb249992bb4.tar.gz llvm-12fcca0afeb08fbe41d79c5387cfacb249992bb4.tar.bz2 |
[mlir][emitc] Lower arith.andi, arith.ori, arith.xori to EmitC
This commit lowers bitwise arith ops to EmitC and also brings in `adaptValueType` and `adaptIntegralTypeSignedness` that other ArithToEmitC functions can benefit from.
-rw-r--r-- | mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp | 62 | ||||
-rw-r--r-- | mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir | 39 |
2 files changed, 101 insertions, 0 deletions
diff --git a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp index 388794e..9b1e471 100644 --- a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp +++ b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp @@ -40,6 +40,25 @@ public: } }; +/// Get the signed or unsigned type corresponding to \p ty. +Type adaptIntegralTypeSignedness(Type ty, bool needsUnsigned) { + if (isa<IntegerType>(ty)) { + if (ty.isUnsignedInteger() != needsUnsigned) { + auto signedness = needsUnsigned + ? IntegerType::SignednessSemantics::Unsigned + : IntegerType::SignednessSemantics::Signed; + return IntegerType::get(ty.getContext(), ty.getIntOrFloatBitWidth(), + signedness); + } + } + return ty; +} + +/// Insert a cast operation to type \p ty if \p val does not have this type. +Value adaptValueType(Value val, ConversionPatternRewriter &rewriter, Type ty) { + return rewriter.createOrFold<emitc::CastOp>(val.getLoc(), ty, val); +} + class CmpIOpConversion : public OpConversionPattern<arith::CmpIOp> { public: using OpConversionPattern::OpConversionPattern; @@ -265,6 +284,46 @@ public: } }; +template <typename ArithOp, typename EmitCOp> +class BitwiseOpConversion : public OpConversionPattern<ArithOp> { +public: + using OpConversionPattern<ArithOp>::OpConversionPattern; + + LogicalResult + matchAndRewrite(ArithOp op, typename ArithOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + + Type type = this->getTypeConverter()->convertType(op.getType()); + if (!isa_and_nonnull<IntegerType>(type)) { + return rewriter.notifyMatchFailure( + op, + "expected integer type, vector/tensor support not yet implemented"); + } + + // Bitwise ops can be performed directly on booleans + if (type.isInteger(1)) { + rewriter.replaceOpWithNewOp<EmitCOp>(op, type, adaptor.getLhs(), + adaptor.getRhs()); + return success(); + } + + // Bitwise ops are defined by the C standard on unsigned operands. + Type arithmeticType = + adaptIntegralTypeSignedness(type, /*needsUnsigned=*/true); + + Value lhs = adaptValueType(adaptor.getLhs(), rewriter, arithmeticType); + Value rhs = adaptValueType(adaptor.getRhs(), rewriter, arithmeticType); + + Value arithmeticResult = rewriter.template create<EmitCOp>( + op.getLoc(), arithmeticType, lhs, rhs); + + Value result = adaptValueType(arithmeticResult, rewriter, type); + + rewriter.replaceOp(op, result); + return success(); + } +}; + class SelectOpConversion : public OpConversionPattern<arith::SelectOp> { public: using OpConversionPattern<arith::SelectOp>::OpConversionPattern; @@ -401,6 +460,9 @@ void mlir::populateArithToEmitCPatterns(TypeConverter &typeConverter, IntegerOpConversion<arith::AddIOp, emitc::AddOp>, IntegerOpConversion<arith::MulIOp, emitc::MulOp>, IntegerOpConversion<arith::SubIOp, emitc::SubOp>, + BitwiseOpConversion<arith::AndIOp, emitc::BitwiseAndOp>, + BitwiseOpConversion<arith::OrIOp, emitc::BitwiseOrOp>, + BitwiseOpConversion<arith::XOrIOp, emitc::BitwiseXorOp>, CmpIOpConversion, SelectOpConversion, // Truncation is guaranteed for unsigned types. diff --git a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir index dac3fd9..5b1a186 100644 --- a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir +++ b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir @@ -88,6 +88,45 @@ func.func @arith_index(%arg0: index, %arg1: index) { // ----- +// CHECK-LABEL: arith_bitwise +// CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32 +func.func @arith_bitwise(%arg0: i32, %arg1: i32) { + // CHECK: %[[C1:[^ ]*]] = emitc.cast %[[ARG0]] : i32 to ui32 + // CHECK: %[[C2:[^ ]*]] = emitc.cast %[[ARG1]] : i32 to ui32 + // CHECK: %[[AND:[^ ]*]] = emitc.bitwise_and %[[C1]], %[[C2]] : (ui32, ui32) -> ui32 + // CHECK: %[[C3:[^ ]*]] = emitc.cast %[[AND]] : ui32 to i32 + %0 = arith.andi %arg0, %arg1 : i32 + // CHECK: %[[C1:[^ ]*]] = emitc.cast %[[ARG0]] : i32 to ui32 + // CHECK: %[[C2:[^ ]*]] = emitc.cast %[[ARG1]] : i32 to ui32 + // CHECK: %[[OR:[^ ]*]] = emitc.bitwise_or %[[C1]], %[[C2]] : (ui32, ui32) -> ui32 + // CHECK: %[[C3:[^ ]*]] = emitc.cast %[[OR]] : ui32 to i32 + %1 = arith.ori %arg0, %arg1 : i32 + // CHECK: %[[C1:[^ ]*]] = emitc.cast %[[ARG0]] : i32 to ui32 + // CHECK: %[[C2:[^ ]*]] = emitc.cast %[[ARG1]] : i32 to ui32 + // CHECK: %[[XOR:[^ ]*]] = emitc.bitwise_xor %[[C1]], %[[C2]] : (ui32, ui32) -> ui32 + // CHECK: %[[C3:[^ ]*]] = emitc.cast %[[XOR]] : ui32 to i32 + %2 = arith.xori %arg0, %arg1 : i32 + + return +} + +// ----- + +// CHECK-LABEL: arith_bitwise_bool +// CHECK-SAME: %[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1 +func.func @arith_bitwise_bool(%arg0: i1, %arg1: i1) { + // CHECK: %[[AND:[^ ]*]] = emitc.bitwise_and %[[ARG0]], %[[ARG1]] : (i1, i1) -> i1 + %0 = arith.andi %arg0, %arg1 : i1 + // CHECK: %[[OR:[^ ]*]] = emitc.bitwise_or %[[ARG0]], %[[ARG1]] : (i1, i1) -> i1 + %1 = arith.ori %arg0, %arg1 : i1 + // CHECK: %[[xor:[^ ]*]] = emitc.bitwise_xor %[[ARG0]], %[[ARG1]] : (i1, i1) -> i1 + %2 = arith.xori %arg0, %arg1 : i1 + + return +} + +// ----- + // CHECK-LABEL: arith_signed_integer_div_rem func.func @arith_signed_integer_div_rem(%arg0: i32, %arg1: i32) { // CHECK: emitc.div %arg0, %arg1 : (i32, i32) -> i32 |