aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorentin Ferry <corentin.ferry@amd.com>2024-06-03 13:22:52 +0200
committerGitHub <noreply@github.com>2024-06-03 13:22:52 +0200
commit12fcca0afeb08fbe41d79c5387cfacb249992bb4 (patch)
tree94c497a5176c704cf7b3842a3c8c540646712ee7
parent22a7f7c3314328dd1ac20042158f4b68a4ac5c1f (diff)
downloadllvm-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.cpp62
-rw-r--r--mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir39
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