Skip to content
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

Cranelift: Add iconst shorthand to simplify ISLE opts #7670

Merged
merged 4 commits into from
Dec 12, 2023
Merged
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
12 changes: 0 additions & 12 deletions cranelift/codegen/src/isle_prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,18 +734,6 @@ macro_rules! isle_common_prelude_methods {
Imm64::new((x & self.ty_mask(ty)) as i64)
}

#[inline]
fn simm32(&mut self, x: Imm64) -> Option<i32> {
i64::from(x).try_into().ok()
}

#[inline]
fn uimm8(&mut self, x: Imm64) -> Option<u8> {
let x64: i64 = x.into();
let x8: u8 = x64.try_into().ok()?;
Some(x8)
}

#[inline]
fn offset32(&mut self, x: Offset32) -> i32 {
x.into()
Expand Down
12 changes: 12 additions & 0 deletions cranelift/codegen/src/machinst/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,18 @@ macro_rules! isle_lower_prelude_methods {
Some(value)
}

#[inline]
fn simm32(&mut self, x: Imm64) -> Option<i32> {
i64::from(x).try_into().ok()
}

#[inline]
fn uimm8(&mut self, x: Imm64) -> Option<u8> {
let x64: i64 = x.into();
let x8: u8 = x64.try_into().ok()?;
Some(x8)
}

#[inline]
fn preg_to_reg(&mut self, preg: PReg) -> Reg {
preg.into()
Expand Down
24 changes: 24 additions & 0 deletions cranelift/codegen/src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const MAX_ISLE_RETURNS: usize = 8;

pub type ConstructorVec<T> = SmallVec<[T; MAX_ISLE_RETURNS]>;

type TypeAndInstructionData = (Type, InstructionData);

impl<T: smallvec::Array> generated_code::Length for SmallVec<T> {
#[inline]
fn len(&self) -> usize {
Expand Down Expand Up @@ -128,6 +130,13 @@ impl<'a, 'b, 'c> generated_code::Context for IsleContext<'a, 'b, 'c> {
*returns = InstDataEtorIter::new(eclass);
}

type inst_data_tupled_etor_returns = InstDataEtorIter<'a, 'b, 'c>;

fn inst_data_tupled_etor(&mut self, eclass: Value, returns: &mut InstDataEtorIter<'a, 'b, 'c>) {
// Literally identical to `inst_data_etor`, just a different nominal type in ISLE
self.inst_data_etor(eclass, returns);
}

fn make_inst_ctor(&mut self, ty: Type, op: &InstructionData) -> Value {
let value = self
.ctx
Expand All @@ -149,6 +158,21 @@ impl<'a, 'b, 'c> generated_code::Context for IsleContext<'a, 'b, 'c> {
self.ctx.func.dfg.value_type(val)
}

fn iconst_sextend_etor(
&mut self,
(ty, inst_data): (Type, InstructionData),
) -> Option<(Type, i64)> {
if let InstructionData::UnaryImm {
opcode: Opcode::Iconst,
imm,
} = inst_data
{
Some((ty, self.i64_sextend_imm64(ty, imm)))
} else {
None
}
}

fn remat(&mut self, value: Value) -> Value {
trace!("remat: {}", value);
self.ctx.remat_values.insert(value);
Expand Down
28 changes: 13 additions & 15 deletions cranelift/codegen/src/opts/arithmetic.isle
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
;; x+0 == x.
(rule (simplify (iadd ty
x
(iconst ty (u64_from_imm64 0))))
(iconst_u ty 0)))
(subsume x))
;; x-0 == x.
(rule (simplify (isub ty
x
(iconst ty (u64_from_imm64 0))))
(iconst_u ty 0)))
(subsume x))
;; 0-x == (ineg x).
(rule (simplify (isub ty
(iconst ty (u64_from_imm64 0))
(iconst_u ty 0)
x))
(ineg ty x))

Expand Down Expand Up @@ -47,51 +47,49 @@
(subsume inner))

;; x-x == 0.
(rule (simplify (isub (fits_in_64 (ty_int ty)) x x)) (subsume (iconst ty (imm64 0))))
(rule (simplify (isub (fits_in_64 (ty_int ty)) x x)) (subsume (iconst_u ty 0)))

;; x*1 == x.
(rule (simplify (imul ty
x
(iconst ty (u64_from_imm64 1))))
(iconst_u ty 1)))
(subsume x))

;; x*0 == 0.
(rule (simplify (imul ty
_
zero @ (iconst ty (u64_from_imm64 0))))
zero @ (iconst_u ty 0)))
(subsume zero))

;; x*-1 == ineg(x).
(rule (simplify (imul ty x (iconst ty c)))
(if-let -1 (i64_sextend_imm64 ty c))
(rule (simplify (imul ty x (iconst_s ty -1)))
(ineg ty x))

;; (!x) + 1 == ineg(x)
(rule (simplify (iadd ty (bnot ty x) (iconst ty (u64_from_imm64 1))))
(rule (simplify (iadd ty (bnot ty x) (iconst_u ty 1)))
(ineg ty x))

;; !(x - 1) == !(x + (-1)) == ineg(x)
(rule (simplify (bnot ty (isub ty x (iconst ty (u64_from_imm64 1)))))
(rule (simplify (bnot ty (isub ty x (iconst_s ty 1))))
(ineg ty x))
(rule (simplify (bnot ty (iadd ty x (iconst ty c))))
(if-let -1 (i64_sextend_imm64 ty c))
(rule (simplify (bnot ty (iadd ty x (iconst_s ty -1))))
(ineg ty x))

;; x/1 == x.
(rule (simplify (sdiv ty
x
(iconst ty (u64_from_imm64 1))))
(iconst_u ty 1)))
(subsume x))
(rule (simplify (udiv ty
x
(iconst ty (u64_from_imm64 1))))
(iconst_u ty 1)))
(subsume x))

;; TODO: strength reduction: div to shifts
;; TODO: div/rem by constants -> magic multiplications

;; x*2 == x+x.
(rule (simplify (imul ty x (iconst _ (simm32 2))))
(rule (simplify (imul ty x (iconst_u _ 2)))
(iadd ty x x))

;; x*c == x<<log2(c) when c is a power of two.
Expand Down
64 changes: 31 additions & 33 deletions cranelift/codegen/src/opts/bitops.isle
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
;; x | 0 == x | x == x.
(rule (simplify (bor ty
x
(iconst ty (u64_from_imm64 0))))
(iconst_u ty 0)))
(subsume x))
(rule (simplify (bor ty x x))
(subsume x))

;; x ^ 0 == x.
(rule (simplify (bxor ty
x
(iconst ty (u64_from_imm64 0))))
(iconst_u ty 0)))
(subsume x))

;; x ^ x == 0.
(rule (simplify (bxor (fits_in_64 (ty_int ty)) x x))
(subsume (iconst ty (imm64 0))))
(subsume (iconst_u ty 0)))

;; x ^ not(x) == not(x) ^ x == x | not(x) == not(x) | x == -1.
;; This identity also holds for non-integer types, vectors, and wider types.
Expand All @@ -28,14 +28,13 @@

;; x & x == x & -1 == x.
(rule (simplify (band ty x x)) (subsume x))
(rule (simplify (band ty x (iconst ty k)))
(if-let -1 (i64_sextend_imm64 ty k))
(rule (simplify (band ty x (iconst_s ty -1)))
(subsume x))

;; x & 0 == x & not(x) == not(x) & x == 0.
(rule (simplify (band ty _ zero @ (iconst ty (u64_from_imm64 0)))) (subsume zero))
(rule (simplify (band (fits_in_64 (ty_int ty)) x (bnot ty x))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band (fits_in_64 (ty_int ty)) (bnot ty x) x)) (subsume (iconst ty (imm64 0))))
(rule (simplify (band ty _ zero @ (iconst_u ty 0))) (subsume zero))
(rule (simplify (band (fits_in_64 (ty_int ty)) x (bnot ty x))) (subsume (iconst_u ty 0)))
(rule (simplify (band (fits_in_64 (ty_int ty)) (bnot ty x) x)) (subsume (iconst_u ty 0)))

;; not(not(x)) == x.
(rule (simplify (bnot ty (bnot ty x))) (subsume x))
Expand Down Expand Up @@ -77,8 +76,7 @@
(bor ty x z))

;; (x ^ -1) can be replaced with the `bnot` instruction
(rule (simplify (bxor ty x (iconst ty k)))
(if-let -1 (i64_sextend_imm64 ty k))
(rule (simplify (bxor ty x (iconst_s ty -1)))
(bnot ty x))

;; sshr((x | -x), N) == bmask(x) where N = ty_bits(ty) - 1.
Expand Down Expand Up @@ -108,17 +106,17 @@
(rule (truthy (rotr _ x _)) x)
(rule (truthy (select _ x (iconst _ (u64_from_imm64 (u64_nonzero _))) (iconst _ (u64_from_imm64 0)))) x)
;; (ne ty (iconst 0) v) is also canonicalized into this form via another rule
(rule (truthy (ne _ x (iconst _ (u64_from_imm64 0)))) x)
(rule (truthy (ne _ x (iconst_u _ 0))) x)

;; All of these expressions don't care about their input as long as it is truthy.
;; so we can remove expressions that preserve that property from the input.
(rule (simplify (bmask ty v)) (if-let x (truthy v)) (bmask ty x))
(rule (simplify (select ty v t f)) (if-let c (truthy v)) (select ty c t f))
;; (ne ty (iconst 0) v) is also canonicalized into this form via another rule
(rule (simplify (ne cty v (iconst _ (u64_from_imm64 0))))
(rule (simplify (ne cty v (iconst_u _ 0)))
(if-let c (truthy v))
(if-let (value_type (ty_int_ref_scalar_64 ty)) c)
(ne cty c (iconst ty (imm64 0))))
(ne cty c (iconst_u ty 0)))



Expand All @@ -145,42 +143,42 @@
;; easy way to match all of them, so only one is matched here.
(rule (simplify (bor ty @ $I32
(bor ty
(ishl ty x (iconst ty (u64_from_imm64 24)))
(ishl ty x (iconst_u ty 24))
(ishl ty
(band ty x (iconst ty (u64_from_imm64 0xff00)))
(iconst ty (u64_from_imm64 8))))
(band ty x (iconst_u ty 0xff00))
(iconst_u ty 8)))
(bor ty
(band ty
(ushr ty x (iconst ty (u64_from_imm64 8)))
(iconst ty (u64_from_imm64 0xff00)))
(ushr ty x (iconst ty (u64_from_imm64 24))))))
(ushr ty x (iconst_u ty 8))
(iconst_u ty 0xff00))
(ushr ty x (iconst_u ty 24)))))
(bswap ty x))

(rule (simplify (bor ty @ $I64
(bor ty
(bor ty
(ishl ty x (iconst ty (u64_from_imm64 56)))
(ishl ty x (iconst_u ty 56))
(ishl ty
(band ty x (iconst ty (u64_from_imm64 0xff00)))
(iconst ty (u64_from_imm64 40))))
(band ty x (iconst_u ty 0xff00))
(iconst_u ty 40)))
(bor ty
(ishl ty
(band ty x (iconst ty (u64_from_imm64 0xff_0000)))
(iconst ty (u64_from_imm64 24)))
(band ty x (iconst_u ty 0xff_0000))
(iconst_u ty 24))
(ishl ty
(band ty x (iconst ty (u64_from_imm64 0xff00_0000)))
(iconst ty (u64_from_imm64 8)))))
(band ty x (iconst_u ty 0xff00_0000))
(iconst_u ty 8))))
(bor ty
(bor ty
(band ty
(ushr ty x (iconst ty (u64_from_imm64 8)))
(iconst ty (u64_from_imm64 0xff00_0000)))
(ushr ty x (iconst_u ty 8))
(iconst_u ty 0xff00_0000))
(band ty
(ushr ty x (iconst ty (u64_from_imm64 24)))
(iconst ty (u64_from_imm64 0xff_0000))))
(ushr ty x (iconst_u ty 24))
(iconst_u ty 0xff_0000)))
(bor ty
(band ty
(ushr ty x (iconst ty (u64_from_imm64 40)))
(iconst ty (u64_from_imm64 0xff00)))
(ushr ty x (iconst ty (u64_from_imm64 56)))))))
(ushr ty x (iconst_u ty 40))
(iconst_u ty 0xff00))
(ushr ty x (iconst_u ty 56))))))
(bswap ty x))
20 changes: 10 additions & 10 deletions cranelift/codegen/src/opts/extends.isle
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,22 @@
(rule (simplify
(slt ty
(uextend $I64 x @ (value_type $I32))
(iconst _ (u64_from_imm64 0))))
(iconst ty (imm64 0)))
(iconst_u _ 0)))
(iconst_u ty 0))
(rule (simplify
(sge ty
(uextend $I64 x @ (value_type $I32))
(iconst _ (u64_from_imm64 0))))
(iconst ty (imm64 1)))
(iconst_u _ 0)))
(iconst_u ty 1))

;; Sign-extending can't change whether a number is zero nor how it signed-compares to zero
(rule (simplify (eq _ (sextend _ x@(value_type ty)) (iconst _ (u64_from_imm64 0))))
(eq ty x (iconst ty (imm64 0))))
(rule (simplify (ne _ (sextend _ x@(value_type ty)) (iconst _ (u64_from_imm64 0))))
(ne ty x (iconst ty (imm64 0))))
(rule (simplify (icmp _ cc (sextend _ x@(value_type ty)) (iconst _ (u64_from_imm64 0))))
(rule (simplify (eq _ (sextend _ x@(value_type ty)) (iconst_s _ 0)))
(eq ty x (iconst_s ty 0)))
(rule (simplify (ne _ (sextend _ x@(value_type ty)) (iconst_s _ 0)))
(ne ty x (iconst_s ty 0)))
(rule (simplify (icmp _ cc (sextend _ x@(value_type ty)) (iconst_s _ 0)))
(if (signed_cond_code cc))
(icmp ty cc x (iconst ty (imm64 0))))
(icmp ty cc x (iconst_s ty 0)))

;; A reduction-of-an-extend back to the same original type is the same as not
;; actually doing the extend in the first place.
Expand Down
Loading