Skip to content

[mlir][emitc] Arith to EmitC: Handle addi, subi and muli #86120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 22, 2024

Conversation

mgehre-amd
Copy link
Contributor

@mgehre-amd mgehre-amd commented Mar 21, 2024

Important to consider that arith has wrap around semantics, and in C++ signed overflow is UB.
Unless the operation guarantees that no signed overflow happens, we will perform the arithmetic in an equivalent unsigned type.

No handling yet for divsi and divui, as they require
special considerations for signedness.
@llvmbot
Copy link
Member

llvmbot commented Mar 21, 2024

@llvm/pr-subscribers-mlir

Author: Matthias Gehre (mgehre-amd)

Changes

No handling yet for divsi and divui, as they require special considerations for signedness.


Full diff: https://github.com/llvm/llvm-project/pull/86120.diff

2 Files Affected:

  • (modified) mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp (+3)
  • (modified) mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir (+13)
diff --git a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
index 3532785c31b939..e85bb0f6b227b9 100644
--- a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
+++ b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
@@ -96,6 +96,9 @@ void mlir::populateArithToEmitCPatterns(TypeConverter &typeConverter,
     ArithOpConversion<arith::DivFOp, emitc::DivOp>,
     ArithOpConversion<arith::MulFOp, emitc::MulOp>,
     ArithOpConversion<arith::SubFOp, emitc::SubOp>,
+    ArithOpConversion<arith::AddIOp, emitc::AddOp>,
+    ArithOpConversion<arith::MulIOp, emitc::MulOp>,
+    ArithOpConversion<arith::SubIOp, emitc::SubOp>,
     SelectOpConversion
   >(typeConverter, ctx);
   // clang-format on
diff --git a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir
index 022530ef4db84b..e5f2c330b851c3 100644
--- a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir
+++ b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir
@@ -37,6 +37,19 @@ func.func @arith_ops(%arg0: f32, %arg1: f32) {
 
 // -----
 
+func.func @arith_integer_ops(%arg0: i32, %arg1: i32) {
+  // CHECK: emitc.add %arg0, %arg1 : (i32, i32) -> i32
+  %0 = arith.addi %arg0, %arg1 : i32
+  // CHECK: emitc.sub %arg0, %arg1 : (i32, i32) -> i32
+  %1 = arith.subi %arg0, %arg1 : i32
+  // CHECK: emitc.mul %arg0, %arg1 : (i32, i32) -> i32
+  %2 = arith.muli %arg0, %arg1 : i32
+
+  return
+}
+
+// -----
+
 func.func @arith_select(%arg0: i1, %arg1: tensor<8xi32>, %arg2: tensor<8xi32>) -> () {
   // CHECK: [[V0:[^ ]*]] = emitc.conditional %arg0, %arg1, %arg2 : tensor<8xi32>
   %0 = arith.select %arg0, %arg1, %arg2 : i1, tensor<8xi32>

Copy link
Member

@marbre marbre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No handling yet for divsi and divui, as they require special considerations for signedness.

Probably we already need some special considerations for this case. E.g. for arith.addi the docs https://mlir.llvm.org/docs/Dialects/ArithOps/#arithaddi-arithaddiop state

Performs N-bit addition on the operands. The operands are interpreted as unsigned bitvectors. The result is represented by a bitvector containing the mathematical value of the addition modulo 2^n, where n is the bitwidth.

Following https://en.cppreference.com/w/cpp/language/operator_arithmetic#Overflows

Unsigned integer arithmetic is always performed modulo 2n where n is the number of bits in that particular integer.

we should probably cast to unsigned, perform the arithmetic operation and add another cast. WDYT?

@mgehre-amd
Copy link
Contributor Author

No handling yet for divsi and divui, as they require special considerations for signedness.

Probably we already need some special considerations for this case. E.g. for arith.addi the docs mlir.llvm.org/docs/Dialects/ArithOps/#arithaddi-arithaddiop state

Performs N-bit addition on the operands. The operands are interpreted as unsigned bitvectors. The result is represented by a bitvector containing the mathematical value of the addition modulo 2^n, where n is the bitwidth.

Following en.cppreference.com/w/cpp/language/operator_arithmetic#Overflows

Unsigned integer arithmetic is always performed modulo 2n where n is the number of bits in that particular integer.

we should probably cast to unsigned, perform the arithmetic operation and add another cast. WDYT?

Good point, this will otherwise cause UB for when the C types are signed.

Copy link
Member

@marbre marbre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good now :) Just one minor wish, could you maybe add a more descriptive commit message? I think what is in the PR description right now is more additional context for review but not necessarily adding value as part of a commit message.

@mgehre-amd mgehre-amd merged commit 71db971 into llvm:main Mar 22, 2024
@mgehre-amd mgehre-amd deleted the mgehre.emitc_addi branch March 22, 2024 14:39
chencha3 pushed a commit to chencha3/llvm-project that referenced this pull request Mar 23, 2024
Important to consider that `arith` has wrap around semantics, and in C++
signed overflow is UB.
Unless the operation guarantees that no signed overflow happens, we will
perform the arithmetic in an equivalent unsigned type.
`bool` also doesn't wrap around in C++, and is not addressed here.
mgehre-amd added a commit to Xilinx/llvm-project that referenced this pull request Apr 26, 2024
Important to consider that `arith` has wrap around semantics, and in C++
signed overflow is UB.
Unless the operation guarantees that no signed overflow happens, we will
perform the arithmetic in an equivalent unsigned type.
`bool` also doesn't wrap around in C++, and is not addressed here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants