egraph opts: fix uextend-of-i32. (#5061)
This is a simple error in the const-prop rules: uextend was not masking iconst's u64 immediate when extending from i32 to i64. Arguably an iconst.i32 should not have nonzero bits in the upper 32 of its immediate, but that's a separate design question. For now, if our invariant is that the upper bits are ignored, then it is required to mask the bits when const-evaling a `uextend`. Fixes #5047.
This commit is contained in:
@@ -95,6 +95,11 @@ macro_rules! isle_common_prelude_methods {
|
|||||||
Some(x as u32 as i32 as i64 as u64)
|
Some(x as u32 as i32 as i64 as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn u64_uextend_u32(&mut self, x: u64) -> Option<u64> {
|
||||||
|
Some(x & 0xffff_ffff)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ty_bits(&mut self, ty: Type) -> Option<u8> {
|
fn ty_bits(&mut self, ty: Type) -> Option<u8> {
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
;; can freely rewrite e.g. `x+y-y` to `x`.
|
;; can freely rewrite e.g. `x+y-y` to `x`.
|
||||||
|
|
||||||
;; uextend/sextend of a constant.
|
;; uextend/sextend of a constant.
|
||||||
(rule (simplify (uextend $I64 (iconst $I32 imm)))
|
(rule (simplify (uextend $I64 (iconst $I32 (u64_from_imm64 imm))))
|
||||||
(iconst $I64 imm))
|
(iconst $I64 (imm64 (u64_uextend_u32 imm))))
|
||||||
(rule (simplify (sextend $I64 (iconst $I32 (u64_from_imm64 imm))))
|
(rule (simplify (sextend $I64 (iconst $I32 (u64_from_imm64 imm))))
|
||||||
(iconst $I64 (imm64 (u64_sextend_u32 imm))))
|
(iconst $I64 (imm64 (u64_sextend_u32 imm))))
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,9 @@
|
|||||||
(decl pure u64_sextend_u32 (u64) u64)
|
(decl pure u64_sextend_u32 (u64) u64)
|
||||||
(extern constructor u64_sextend_u32 u64_sextend_u32)
|
(extern constructor u64_sextend_u32 u64_sextend_u32)
|
||||||
|
|
||||||
|
(decl pure u64_uextend_u32 (u64) u64)
|
||||||
|
(extern constructor u64_uextend_u32 u64_uextend_u32)
|
||||||
|
|
||||||
(decl u64_is_zero (bool) u64)
|
(decl u64_is_zero (bool) u64)
|
||||||
(extern extractor infallible u64_is_zero u64_is_zero)
|
(extern extractor infallible u64_is_zero u64_is_zero)
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ set opt_level=none
|
|||||||
set use_egraphs=true
|
set use_egraphs=true
|
||||||
target x86_64
|
target x86_64
|
||||||
|
|
||||||
function %f(i32) -> i32 {
|
function %f0(i32) -> i32 {
|
||||||
block0(v0: i32):
|
block0(v0: i32):
|
||||||
v1 = iconst.i32 2
|
v1 = iconst.i32 2
|
||||||
v2 = imul v0, v1
|
v2 = imul v0, v1
|
||||||
@@ -11,3 +11,12 @@ block0(v0: i32):
|
|||||||
; nextln: return v1
|
; nextln: return v1
|
||||||
return v2
|
return v2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function %f1() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 0xffff_ffff_9876_5432
|
||||||
|
v1 = uextend.i64 v0
|
||||||
|
return v1
|
||||||
|
; check: v0 = iconst.i64 0x9876_5432
|
||||||
|
; nextln: return v0 ; v0 = 0x9876_5432
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user