Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions cranelift/codegen/src/isle_prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,42 @@ macro_rules! isle_common_prelude_methods {
self.checked_add_with_type(ty, a, b).is_none()
}

#[inline]
fn imm64_rotl(&mut self, ty: Type, x: Imm64, k: Imm64) -> Imm64 {
let bw: u32 = ty.bits().min(64);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The min here should be an assert of some form because if ty.bits() is >=64 then that's an invalid state for this function to be in and it should panic.

let amt: u32 = if bw == 0 { 0 } else { (k.bits() as u32) % bw };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ok to not test for 0 here because a 0-size integral type should cause a panic (which % 0 would do I believe). Handling it here would accidentally try to recover from what should otherwise be a panicking situation.


let xv = x.bits() as u64;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend using cast_unsigned here as it avoid using as which is something we try to avoid since it's by default a lossy cast.

let v = match bw {
8 => (xv as u8).rotate_left(amt) as u64,
16 => (xv as u16).rotate_left(amt) as u64,
32 => (xv as u32).rotate_left(amt) as u64,
Comment on lines +37 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For promotion back up to u64 I'd recommend using u64::from((xv as u8).rotate_left(amt)) to avoid as u64. The as u8 is still required, however, as this is intentionally truncating data.

64 => xv.rotate_left(amt),
_ => xv,
};

let masked = v & self.ty_mask(ty);
Imm64::new(masked as i64)
}

#[inline]
fn imm64_rotr(&mut self, ty: Type, x: Imm64, k: Imm64) -> Imm64 {
let bw: u32 = ty.bits().min(64);
let amt: u32 = if bw == 0 { 0 } else { (k.bits() as u32) % bw };

let xv = x.bits() as u64;
let v = match bw {
8 => (xv as u8).rotate_right(amt) as u64,
16 => (xv as u16).rotate_right(amt) as u64,
32 => (xv as u32).rotate_right(amt) as u64,
64 => xv.rotate_right(amt),
_ => xv,
};

let masked = v & self.ty_mask(ty);
Imm64::new(masked as i64)
}

#[inline]
fn imm64_sdiv(&mut self, ty: Type, x: Imm64, y: Imm64) -> Option<Imm64> {
// Sign extend `x` and `y`.
Expand Down
12 changes: 12 additions & 0 deletions cranelift/codegen/src/opts/cprop.isle
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
;; Constant propagation.

(rule (simplify
(rotl (fits_in_64 ty)
(iconst ty kx)
(iconst ty kk)))
(subsume (iconst ty (imm64_rotl ty kx kk))))

(rule (simplify
(rotr (fits_in_64 ty)
(iconst ty kx)
(iconst ty kk)))
(subsume (iconst ty (imm64_rotr ty kx kk))))

(rule (simplify
(iadd (fits_in_64 ty)
(iconst ty (u64_from_imm64 k1))
Expand Down
6 changes: 6 additions & 0 deletions cranelift/codegen/src/prelude.isle
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@
(decl pure imm64_icmp (Type IntCC Imm64 Imm64) Imm64)
(extern constructor imm64_icmp imm64_icmp)

(decl pure imm64_rotl (Type Imm64 Imm64) Imm64)
(extern constructor imm64_rotl imm64_rotl)

(decl pure imm64_rotr (Type Imm64 Imm64) Imm64)
(extern constructor imm64_rotr imm64_rotr)

;; Each of these extractors tests whether the upper half of the input equals the
;; lower half of the input
(decl u128_replicated_u64 (u64) u128)
Expand Down