-
Notifications
You must be signed in to change notification settings - Fork 16
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
[Binding] Generate signless operands for arithmetic operations #7
Comments
I can think of two ways to do that:
module {
func @main() {
%a = arith.constant 1 : i32
%au = builtin.unrealized_conversion_cast %a : i32 to ui32
%b = arith.constant 2 : i32
%bu = builtin.unrealized_conversion_cast %b : i32 to ui32
%ai = builtin.unrealized_conversion_cast %au : ui32 to i32
%bi = builtin.unrealized_conversion_cast %bu : ui32 to i32
%ci = arith.muli %ai, %bi : i32
%c = builtin.unrealized_conversion_cast %ci : i32 to ui32
return
}
}
module {
func @main() {
%a = arith.constant 1 : i32
%b = arith.constant 2 : i32
%c = arith.muli %a, %b : i32
return
}
} |
Do you have any comments on this? @zhangzhiru @zzzDavid @hecmay |
Signed and unsigned semantics are added to MLIR in D72533. SPIRV had the same need to model signed and unsigned arithmetic operations, their solution is to build in-house integer Add/Mul operations. For example: spv.func @i8_const() -> () "None" {
// CHECK: spv.Constant 0 : i8
%0 = spv.Constant 0 : i8
// CHECK: spv.Constant -1 : i8
%1 = spv.Constant 255 : i8
// CHECK: spv.Constant 0 : si8
%2 = spv.Constant 0 : si8
// CHECK: spv.Constant 127 : si8
%3 = spv.Constant 127 : si8
// CHECK: spv.Constant -128 : si8
%4 = spv.Constant -128 : si8
// CHECK: spv.Constant 0 : i8
%5 = spv.Constant 0 : ui8
// CHECK: spv.Constant -1 : i8
%6 = spv.Constant 255 : ui8
%10 = spv.IAdd %0, %1: i8
%11 = spv.IAdd %2, %3: si8
%12 = spv.IAdd %3, %4: si8
%13 = spv.IAdd %5, %6: ui8
spv.Return
} |
Can we use signless and attach attributes to pass signed/unsigned type information to HLS backend? I think building our own integer operations may be unnecessary |
I adopted @zzzDavid 's advice. My current solution is attaching an Specifically, for operations, a unit attribute is simply attached, like %5 = memref.alloc() {name = "D", unsigned} : memref<32x32xi12> But for function arguments, I will generate func @top(%arg0: memref<32x32xi12>, %arg1: memref<32x32xi12>) -> memref<32x32xi12> attributes {extra_itypes = "us", extra_otypes = "u"} I will push the fix later and close this issue. |
Let's discuss a bit more about this in the next meeting. |
The current LLVM/MLIR ecosystem only accepts signless integers as the inputs and outputs for arithmetic operations, and lets specific operations do the interpretation (e.g.,
arith.divsi
vsarith.divui
). The rationale behind using the signless integers instead of signed/unsigned integers (si
/ui
) can be found here.Thus, based on this design, the following code is not allowed in MLIR.
The verifier throws the following error:
This issue seems to come up when we upgrade to LLVM 14 that adds more type checking facilities in the verifier. The error does not only appear in
arith.constant
but also inarith.addi
,arith.andi
, andarith.maxsi
, etc., so it requires our frontend compiler to map integers to signless types but also find a way to keep the signedness.The text was updated successfully, but these errors were encountered: