Skip to content

Commit 0d79d4a

Browse files
committed
Add optimizations for srem
1 parent 07bb9ce commit 0d79d4a

File tree

4 files changed

+46
-1
lines changed

4 files changed

+46
-1
lines changed

cranelift/codegen/src/isle_prelude.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,28 @@ macro_rules! isle_common_prelude_methods {
5959
Some(Imm64::new(result))
6060
}
6161

62+
#[inline]
63+
fn imm64_srem(&mut self, ty: Type, x: Imm64, y: Imm64) -> Option<Imm64> {
64+
// Sign extend `x` and `y`.
65+
let shift = u32::checked_sub(64, ty.bits()).unwrap_or(0);
66+
let x = (x.bits() << shift) >> shift;
67+
let y = (y.bits() << shift) >> shift;
68+
69+
// NB: We can't rely on `checked_rem` to detect `ty::MIN / -1`
70+
// (which overflows and should trap) because we are working with
71+
// `i64` values here, and `i32::MIN != i64::MIN`, for
72+
// example. Therefore, we have to explicitly check for this case
73+
// ourselves.
74+
let min = ((self.ty_smin(ty) as i64) << shift) >> shift;
75+
if x == min && y == -1 {
76+
return None;
77+
}
78+
79+
let ty_mask = self.ty_mask(ty) as i64;
80+
let result = x.checked_rem(y)? & ty_mask;
81+
Some(Imm64::new(result))
82+
}
83+
6284
#[inline]
6385
fn imm64_shl(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
6486
// Mask off any excess shift bits.

cranelift/codegen/src/opts/cprop.isle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@
3535
(if-let d (imm64_sdiv ty k1 k2))
3636
(iconst ty d))
3737

38+
(rule (simplify_skeleton
39+
(srem (iconst ty k1)
40+
(iconst _ k2)))
41+
(if-let d (imm64_srem ty k1 k2))
42+
(iconst ty d))
43+
3844
(rule (simplify_skeleton
3945
(udiv (iconst_u ty k1)
4046
(iconst_u ty k2)))

cranelift/codegen/src/prelude.isle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@
7373
(decl pure partial imm64_sdiv (Type Imm64 Imm64) Imm64)
7474
(extern constructor imm64_sdiv imm64_sdiv)
7575

76+
(decl pure partial imm64_srem (Type Imm64 Imm64) Imm64)
77+
(extern constructor imm64_srem imm64_srem)
78+
7679
(decl pure imm64_shl (Type Imm64 Imm64) Imm64)
7780
(extern constructor imm64_shl imm64_shl)
7881

cranelift/filetests/filetests/egraph/skeleton.clif

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,21 @@ block0:
110110
; return v11 ; v11 = -1
111111
; }
112112

113+
function %cprop_srem() -> i32 {
114+
block0:
115+
v0 = iconst.i32 -17
116+
v1 = iconst.i32 7
117+
v2 = srem v0, v1
118+
return v2
119+
}
120+
121+
; function %cprop_srem() -> i32 fast {
122+
; block0:
123+
; v28 = iconst.i32 -3
124+
; v2 -> v28
125+
; return v28 ; v28 = -3
126+
; }
127+
113128
function %udiv_by_one(i32) -> i32 {
114129
block0(v0: i32):
115130
v1 = iconst.i32 1
@@ -228,4 +243,3 @@ block0:
228243
; v2 = uadd_overflow_trap v0, v1, user42 ; v0 = -1, v1 = 1
229244
; return v2
230245
; }
231-

0 commit comments

Comments
 (0)