Skip to content

Commit cf66bae

Browse files
committed
[Cranelift] add imm64 operations
1 parent a8fc10c commit cf66bae

2 files changed

Lines changed: 152 additions & 0 deletions

File tree

cranelift/codegen/src/isle_prelude.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,116 @@ macro_rules! isle_common_prelude_methods {
8989
Some(Imm64::new(result).mask_to_width(type_width))
9090
}
9191

92+
#[inline]
93+
fn imm64_add(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
94+
let ty_mask = self.ty_mask(ty) as i64;
95+
Imm64::new(x.bits().wrapping_add(y.bits()) & ty_mask)
96+
}
97+
98+
#[inline]
99+
fn imm64_sub(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
100+
let ty_mask = self.ty_mask(ty) as i64;
101+
Imm64::new(x.bits().wrapping_sub(y.bits()) & ty_mask)
102+
}
103+
104+
#[inline]
105+
fn imm64_mul(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
106+
let ty_mask = self.ty_mask(ty) as i64;
107+
Imm64::new(x.bits().wrapping_mul(y.bits()) & ty_mask)
108+
}
109+
110+
#[inline]
111+
fn imm64_and(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
112+
let ty_mask = self.ty_mask(ty) as i64;
113+
Imm64::new((x.bits() & y.bits()) & ty_mask)
114+
}
115+
116+
#[inline]
117+
fn imm64_or(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
118+
let ty_mask = self.ty_mask(ty) as i64;
119+
Imm64::new((x.bits() | y.bits()) & ty_mask)
120+
}
121+
122+
#[inline]
123+
fn imm64_xor(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
124+
let ty_mask = self.ty_mask(ty) as i64;
125+
Imm64::new((x.bits() ^ y.bits()) & ty_mask)
126+
}
127+
128+
#[inline]
129+
fn imm64_not(&mut self, ty: Type, x: Imm64) -> Imm64 {
130+
let ty_mask = self.ty_mask(ty) as i64;
131+
Imm64::new((!x.bits()) & ty_mask)
132+
}
133+
134+
#[inline]
135+
fn imm64_neg(&mut self, ty: Type, x: Imm64) -> Imm64 {
136+
let ty_mask = self.ty_mask(ty) as i64;
137+
Imm64::new(x.bits().wrapping_neg() & ty_mask)
138+
}
139+
140+
#[inline]
141+
fn imm64_abs(&mut self, ty: Type, x: Imm64) -> Option<Imm64> {
142+
let type_width = ty.bits();
143+
assert!(type_width <= 64);
144+
145+
let x = x.sign_extend_from_width(type_width).bits();
146+
let shift = 64 - type_width;
147+
let min = ((self.ty_smin(ty) as i64) << shift) >> shift;
148+
if x == min {
149+
return None;
150+
}
151+
152+
Some(Imm64::new(x.abs()).mask_to_width(type_width))
153+
}
154+
155+
#[inline]
156+
fn imm64_ilog2(&mut self, ty: Type, x: Imm64) -> Imm64 {
157+
let type_width = ty.bits();
158+
assert!(type_width <= 64);
159+
let masked = (x.bits() as u64) & self.ty_mask(ty);
160+
let result = masked
161+
.checked_ilog2()
162+
.unwrap_or_else(|| panic!("ilog2 overflow: {masked}"));
163+
Imm64::new(result.into())
164+
}
165+
166+
#[inline]
167+
fn imm64_umin(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
168+
let ty_mask = self.ty_mask(ty);
169+
let x_u = (x.bits() as u64) & ty_mask;
170+
let y_u = (y.bits() as u64) & ty_mask;
171+
Imm64::new((if x_u <= y_u { x_u } else { y_u }) as i64)
172+
}
173+
174+
#[inline]
175+
fn imm64_umax(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
176+
let ty_mask = self.ty_mask(ty);
177+
let x_u = (x.bits() as u64) & ty_mask;
178+
let y_u = (y.bits() as u64) & ty_mask;
179+
Imm64::new((if x_u >= y_u { x_u } else { y_u }) as i64)
180+
}
181+
182+
#[inline]
183+
fn imm64_smin(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
184+
let type_width = ty.bits();
185+
assert!(type_width <= 64);
186+
let x_s = x.sign_extend_from_width(type_width).bits();
187+
let y_s = y.sign_extend_from_width(type_width).bits();
188+
let selected = if x_s <= y_s { x_s } else { y_s };
189+
Imm64::new(selected).mask_to_width(type_width)
190+
}
191+
192+
#[inline]
193+
fn imm64_smax(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
194+
let type_width = ty.bits();
195+
assert!(type_width <= 64);
196+
let x_s = x.sign_extend_from_width(type_width).bits();
197+
let y_s = y.sign_extend_from_width(type_width).bits();
198+
let selected = if x_s >= y_s { x_s } else { y_s };
199+
Imm64::new(selected).mask_to_width(type_width)
200+
}
201+
92202
#[inline]
93203
fn imm64_shl(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
94204
// Mask off any excess shift bits.

cranelift/codegen/src/prelude.isle

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,48 @@
7676
(decl pure partial imm64_srem (Type Imm64 Imm64) Imm64)
7777
(extern constructor imm64_srem imm64_srem)
7878

79+
(decl pure imm64_add (Type Imm64 Imm64) Imm64)
80+
(extern constructor imm64_add imm64_add)
81+
82+
(decl pure imm64_sub (Type Imm64 Imm64) Imm64)
83+
(extern constructor imm64_sub imm64_sub)
84+
85+
(decl pure imm64_mul (Type Imm64 Imm64) Imm64)
86+
(extern constructor imm64_mul imm64_mul)
87+
88+
(decl pure imm64_and (Type Imm64 Imm64) Imm64)
89+
(extern constructor imm64_and imm64_and)
90+
91+
(decl pure imm64_or (Type Imm64 Imm64) Imm64)
92+
(extern constructor imm64_or imm64_or)
93+
94+
(decl pure imm64_xor (Type Imm64 Imm64) Imm64)
95+
(extern constructor imm64_xor imm64_xor)
96+
97+
(decl pure imm64_not (Type Imm64) Imm64)
98+
(extern constructor imm64_not imm64_not)
99+
100+
(decl pure imm64_neg (Type Imm64) Imm64)
101+
(extern constructor imm64_neg imm64_neg)
102+
103+
(decl pure partial imm64_abs (Type Imm64) Imm64)
104+
(extern constructor imm64_abs imm64_abs)
105+
106+
(decl pure imm64_ilog2 (Type Imm64) Imm64)
107+
(extern constructor imm64_ilog2 imm64_ilog2)
108+
109+
(decl pure imm64_umin (Type Imm64 Imm64) Imm64)
110+
(extern constructor imm64_umin imm64_umin)
111+
112+
(decl pure imm64_umax (Type Imm64 Imm64) Imm64)
113+
(extern constructor imm64_umax imm64_umax)
114+
115+
(decl pure imm64_smin (Type Imm64 Imm64) Imm64)
116+
(extern constructor imm64_smin imm64_smin)
117+
118+
(decl pure imm64_smax (Type Imm64 Imm64) Imm64)
119+
(extern constructor imm64_smax imm64_smax)
120+
79121
(decl pure imm64_shl (Type Imm64 Imm64) Imm64)
80122
(extern constructor imm64_shl imm64_shl)
81123

0 commit comments

Comments
 (0)