-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Use unsigned arithmetic builtins for UInt(N) operations #4740
Conversation
We were mistakenly using the signed builtins, which produce the same lowering for add/multiply right now, but don't for division and modulus. When manually flipping SignedOverflowIsUB on, the signed version of add gains the nsw (no signed wrap) flag, while the unsigned version (correctly after this change) does not: // CHECK:STDOUT: define i32 @_Cadd_i32.Main(i32 %a, i32 %b) !dbg !4 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %int.sadd = add nsw i32 %a, %b, !dbg !7 // CHECK:STDOUT: ret i32 %int.sadd, !dbg !8 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define i32 @_Cadd_u32.Main(i32 %a, i32 %b) !dbg !9 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %int.uadd = add i32 %a, %b, !dbg !10 // CHECK:STDOUT: ret i32 %int.uadd, !dbg !11 // CHECK:STDOUT: }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch, thank you!
} | ||
|
||
impl forall [N:! IntLiteral()] UInt(N) as Mul { | ||
fn Op[self: Self](other: Self) -> Self = "int.smul"; | ||
fn Op[self: Self](other: Self) -> Self = "int.umul"; | ||
} | ||
|
||
impl forall [N:! IntLiteral()] UInt(N) as Negate { | ||
fn Op[self: Self]() -> Self = "int.snegate"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fn Op[self: Self]() -> Self = "int.snegate"; | |
fn Op[self: Self]() -> Self = "int.unegate"; |
snegate
traps on signed overflow (eg, -(-0x8000_0000 as i32)
is an error); unegate
does not. This would be visible in the overflow flags in lowering if we emitted them; for now I think it is only visible in constant evaluation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in #4744. (It turns out that snegate
actually performed a unegate
when used on an unsigned operand, so this was already functionally correct.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes missed that one, thanks!
We were mistakenly using the signed builtins, which produce the same lowering for add/multiply right now, but don't for division and modulus.
When manually flipping SignedOverflowIsUB on, the signed version of add gains the nsw (no signed wrap) flag, while the unsigned version (correctly after this change) does not: