Skip to content

Commit

Permalink
ISLE: rewrite and/or of icmp
Browse files Browse the repository at this point in the history
  • Loading branch information
Kmeakin committed Mar 23, 2023
1 parent 6f66abd commit 4e7b540
Show file tree
Hide file tree
Showing 5 changed files with 1,347 additions and 8 deletions.
14 changes: 14 additions & 0 deletions cranelift/codegen/src/ir/condcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,20 @@ impl IntCC {
]
}

/// Get the corresponding IntCC with the equal component added.
/// For conditions with a zero component, this is a no-op.
pub fn with_equal(self) -> Self {
use self::IntCC::*;
match self {
SignedGreaterThan => SignedGreaterThanOrEqual,
SignedLessThan => SignedLessThanOrEqual,
UnsignedGreaterThan => UnsignedGreaterThanOrEqual,
UnsignedLessThan => UnsignedLessThanOrEqual,
NotEqual => Equal,
_ => self,
}
}

/// Get the corresponding IntCC with the equal component removed.
/// For conditions without a zero component, this is a no-op.
pub fn without_equal(self) -> Self {
Expand Down
43 changes: 35 additions & 8 deletions cranelift/codegen/src/isle_prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,16 +721,33 @@ macro_rules! isle_common_prelude_methods {
#[inline]
fn signed_cond_code(&mut self, cc: &condcodes::IntCC) -> Option<condcodes::IntCC> {
match cc {
IntCC::Equal
| IntCC::UnsignedGreaterThanOrEqual
| IntCC::UnsignedGreaterThan
| IntCC::UnsignedLessThanOrEqual
| IntCC::UnsignedLessThan
| IntCC::NotEqual => None,
IntCC::SignedGreaterThanOrEqual
IntCC::SignedLessThan
| IntCC::SignedLessThanOrEqual
| IntCC::SignedGreaterThan
| IntCC::SignedGreaterThanOrEqual => Some(*cc),
_ => None,
}
}

#[inline]
fn intcc_lt_or_gt(&mut self, cc: &IntCC) -> Option<IntCC> {
match cc {
IntCC::UnsignedLessThan
| IntCC::SignedLessThan
| IntCC::UnsignedGreaterThan
| IntCC::SignedGreaterThan => Some(*cc),
_ => None,
}
}

#[inline]
fn intcc_le_or_ge(&mut self, cc: &IntCC) -> Option<IntCC> {
match cc {
IntCC::UnsignedLessThanOrEqual
| IntCC::SignedLessThanOrEqual
| IntCC::SignedLessThan => Some(*cc),
| IntCC::UnsignedGreaterThanOrEqual
| IntCC::SignedGreaterThanOrEqual => Some(*cc),
_ => None,
}
}

Expand All @@ -744,6 +761,16 @@ macro_rules! isle_common_prelude_methods {
cc.inverse()
}

#[inline]
fn intcc_with_equal(&mut self, cc: &IntCC) -> IntCC {
cc.with_equal()
}

#[inline]
fn intcc_without_equal(&mut self, cc: &IntCC) -> IntCC {
cc.without_equal()
}

#[inline]
fn floatcc_reverse(&mut self, cc: &FloatCC) -> FloatCC {
cc.reverse()
Expand Down
168 changes: 168 additions & 0 deletions cranelift/codegen/src/opts/algebraic.isle
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,174 @@
(iconst _ (u64_from_imm64 0))))
(iconst ty (imm64 1)))

;; eq(x, y) && ne(x, y) == ne(x, y) && eq(x, y) == false.
(rule (simplify (band ty (eq ty x y) (ne ty x y))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band ty (ne ty x y) (eq ty x y))) (subsume (iconst ty (imm64 0))))

;; eq(x, y) && ult(x, y) == ult(x, y) && eq(x, y) == false.
;; eq(x, y) && ugt(x, y) == ugt(x, y) && eq(x, y) == false.
;; eq(x, y) && slt(x, y) == slt(x, y) && eq(x, y) == false.
;; eq(x, y) && sgt(x, y) == sgt(x, y) && eq(x, y) == false.
(rule (simplify (band ty (eq ty x y) (icmp ty (intcc_lt_or_gt _) x y))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band ty (icmp ty (intcc_lt_or_gt _) x y) (eq ty x y))) (subsume (iconst ty (imm64 0))))

;; eq(x, y) && ule(x, y) == ule(x, y) && eq(x, y) == eq(x, y).
;; eq(x, y) && uge(x, y) == uge(x, y) && eq(x, y) == eq(x, y).
;; eq(x, y) && sle(x, y) == sle(x, y) && eq(x, y) == eq(x, y).
;; eq(x, y) && sge(x, y) == sge(x, y) && eq(x, y) == eq(x, y).
(rule (simplify (band ty eq @ (eq ty x y) (icmp ty (intcc_le_or_ge _) x y))) (subsume eq))
(rule (simplify (band ty (icmp ty (intcc_le_or_ge _) x y) eq @ (eq ty x y))) (subsume eq))

;; ne(x, y) && ult(x, y) == ult(x, y) && ne(x, y) == ult(x, y).
;; ne(x, y) && ugt(x, y) == ugt(x, y) && ne(x, y) == ugt(x, y).
;; ne(x, y) && slt(x, y) == slt(x, y) && ne(x, y) == slt(x, y).
;; ne(x, y) && sgt(x, y) == sgt(x, y) && ne(x, y) == sgt(x, y).
(rule (simplify (band ty (ne ty x y) icmp @ (icmp ty (intcc_lt_or_gt _) x y))) (subsume icmp))
(rule (simplify (band ty icmp @ (icmp ty (intcc_lt_or_gt _) x y) (ne ty x y))) (subsume icmp))

;; ne(x, y) && ule(x, y) == ule(x, y) && ne(x, y) == ult(x, y).
;; ne(x, y) && uge(x, y) == uge(x, y) && ne(x, y) == ugt(x, y).
;; ne(x, y) && sle(x, y) == sle(x, y) && ne(x, y) == slt(x, y).
;; ne(x, y) && sge(x, y) == sge(x, y) && ne(x, y) == sgt(x, y).
(rule (simplify (band ty (ne ty x y) (icmp ty (intcc_le_or_ge cc) x y))) (subsume (icmp ty (intcc_without_equal cc) x y)))
(rule (simplify (band ty (icmp ty (intcc_le_or_ge cc) x y) (ne ty x y))) (subsume (icmp ty (intcc_without_equal cc) x y)))

;; ult(x, y) && ule(x, y) == ule(x, y) && ult(x, y) == ult(x, y).
(rule (simplify (band ty ult @ (ult ty x y) (ule ty x y))) (subsume ult))
(rule (simplify (band ty (ule ty x y) ult @ (ult ty x y))) (subsume ult))

;; ult(x, y) && ugt(x, y) == ugt(x, y) && ult(x, y) == false.
(rule (simplify (band ty (ult ty x y) (ugt ty x y))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band ty (ugt ty x y) (ult ty x y))) (subsume (iconst ty (imm64 0))))

;; ult(x, y) && uge(x, y) == uge(x, y) && ult(x, y) == false.
(rule (simplify (band ty (ult ty x y) (uge ty x y))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band ty (uge ty x y) (ult ty x y))) (subsume (iconst ty (imm64 0))))

;; ule(x, y) && ugt(x, y) == ugt(x, y) && ule(x, y) == false.
(rule (simplify (band ty (ule ty x y) (ugt ty x y))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band ty (ugt ty x y) (ule ty x y))) (subsume (iconst ty (imm64 0))))

;; ule(x, y) && uge(x, y) == uge(x, y) && ule(x, y) == eq(x, y).
(rule (simplify (band ty (ule ty x y) (uge ty x y))) (subsume (eq ty x y)))
(rule (simplify (band ty (uge ty x y) (ule ty x y))) (subsume (eq ty x y)))

;; ugt(x, y) && uge(x, y) == uge(x, y) && ugt(x, y) == ugt(x, y).
(rule (simplify (band ty ugt @ (ugt ty x y) (uge ty x y))) (subsume ugt))
(rule (simplify (band ty (uge ty x y) ugt @ (ugt ty x y))) (subsume ugt))

;; slt(x, y) && sle(x, y) == sle(x, y) && slt(x, y) == slt(x, y).
(rule (simplify (band ty slt @ (slt ty x y) (sle ty x y))) (subsume slt))
(rule (simplify (band ty (sle ty x y) slt @ (slt ty x y))) (subsume slt))

;; slt(x, y) && sgt(x, y) == sgt(x, y) && slt(x, y) == false.
(rule (simplify (band ty (slt ty x y) (sgt ty x y))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band ty (sgt ty x y) (slt ty x y))) (subsume (iconst ty (imm64 0))))

;; slt(x, y) && sge(x, y) == sge(x, y) && slt(x, y) == false.
(rule (simplify (band ty (slt ty x y) (sge ty x y))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band ty (sge ty x y) (slt ty x y))) (subsume (iconst ty (imm64 0))))

;; sle(x, y) && sgt(x, y) == sgt(x, y) && sle(x, y) == false.
(rule (simplify (band ty (sle ty x y) (sgt ty x y))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band ty (sgt ty x y) (sle ty x y))) (subsume (iconst ty (imm64 0))))

;; sle(x, y) && sge(x, y) == sge(x, y) && sle(x, y) == eq(x, y).
(rule (simplify (band ty (sle ty x y) (sge ty x y))) (subsume (eq ty x y)))
(rule (simplify (band ty (sge ty x y) (sle ty x y))) (subsume (eq ty x y)))

;; sgt(x, y) && sge(x, y) == sge(x, y) && sgt(x, y) == sgt(x, y).
(rule (simplify (band ty sgt @ (sgt ty x y) (sge ty x y))) (subsume sgt))
(rule (simplify (band ty (sge ty x y) sgt @ (sgt ty x y))) (subsume sgt))

;; eq(x, y) || ne(x, y) == ne(x, y) || eq(x, y) == true.
(rule (simplify (bor ty (eq ty x y) (ne ty x y))) (subsume (iconst ty (imm64 1))))
(rule (simplify (bor ty (ne ty x y) (eq ty x y))) (subsume (iconst ty (imm64 1))))

;; eq(x, y) || ule(x, y) == ule(x, y) || eq(x, y) == ule(x, y).
;; eq(x, y) || uge(x, y) == uge(x, y) || eq(x, y) == uge(x, y).
;; eq(x, y) || sle(x, y) == sle(x, y) || eq(x, y) == sle(x, y).
;; eq(x, y) || sge(x, y) == sge(x, y) || eq(x, y) == sge(x, y).
(rule (simplify (bor ty (eq ty x y) icmp @ (icmp ty (intcc_le_or_ge _) x y))) (subsume icmp))
(rule (simplify (bor ty icmp @ (icmp ty (intcc_le_or_ge _) x y) (eq ty x y))) (subsume icmp))

;; eq(x, y) || ult(x, y) == ult(x, y) || eq(x, y) == ule(x, y).
(rule (simplify (bor ty (eq ty x y) (ult ty x y))) (subsume (ule ty x y)))
(rule (simplify (bor ty (ult ty x y) (eq ty x y))) (subsume (ule ty x y)))

;; eq(x, y) || ugt(x, y) == ugt(x, y) || eq(x, y) == uge(x, y).
(rule (simplify (bor ty (eq ty x y) (ugt ty x y))) (subsume (uge ty x y)))
(rule (simplify (bor ty (ugt ty x y) (eq ty x y))) (subsume (uge ty x y)))

;; eq(x, y) || slt(x, y) == slt(x, y) || eq(x, y) == sle(x, y).
(rule (simplify (bor ty (eq ty x y) (slt ty x y))) (subsume (sle ty x y)))
(rule (simplify (bor ty (slt ty x y) (eq ty x y))) (subsume (sle ty x y)))

;; eq(x, y) || sgt(x, y) == sgt(x, y) || eq(x, y) == sge(x, y).
(rule (simplify (bor ty (eq ty x y) (sgt ty x y))) (subsume (sge ty x y)))
(rule (simplify (bor ty (sgt ty x y) (eq ty x y))) (subsume (sge ty x y)))

;; ne(x, y) || ult(x, y) == ult(x, y) || ne(x, y) == ne(x, y).
;; ne(x, y) || ugt(x, y) == ugt(x, y) || ne(x, y) == ne(x, y).
;; ne(x, y) || slt(x, y) == slt(x, y) || ne(x, y) == ne(x, y).
;; ne(x, y) || sgt(x, y) == sgt(x, y) || ne(x, y) == ne(x, y).
(rule (simplify (bor ty ne @ (ne ty x y) (icmp ty (intcc_lt_or_gt _) x y))) (subsume ne))
(rule (simplify (bor ty (icmp ty (intcc_lt_or_gt _) x y) ne @ (ne ty x y))) (subsume ne))

;; ne(x, y) || ule(x, y) == ule(x, y) || ne(x, y) == true.
;; ne(x, y) || uge(x, y) == uge(x, y) || ne(x, y) == true.
;; ne(x, y) || sle(x, y) == sle(x, y) || ne(x, y) == true.
;; ne(x, y) || sge(x, y) == sge(x, y) || ne(x, y) == true.
(rule (simplify (bor ty (ne ty x y) (icmp ty (intcc_le_or_ge _) x y))) (subsume (iconst ty (imm64 1))))
(rule (simplify (bor ty (icmp ty (intcc_le_or_ge _) x y) (ne ty x y))) (subsume (iconst ty (imm64 1))))

;; ult(x, y) || ule(x, y) == ule(x, y) || ult(x, y) == ule(x, y).
(rule (simplify (bor ty (ult ty x y) ule @ (ule ty x y))) (subsume ule))
(rule (simplify (bor ty ule @ (ule ty x y) (ult ty x y))) (subsume ule))

;; ult(x, y) || ugt(x, y) == ugt(x, y) || ult(x, y) == ne(x, y).
(rule (simplify (bor ty (ult ty x y) (ugt ty x y))) (subsume (ne ty x y)))
(rule (simplify (bor ty (ugt ty x y) (ult ty x y))) (subsume (ne ty x y)))

;; ult(x, y) || uge(x, y) == uge(x, y) || ult(x, y) == true.
(rule (simplify (bor ty (ult ty x y) (uge ty x y))) (subsume (iconst ty (imm64 1))))
(rule (simplify (bor ty (uge ty x y) (ult ty x y))) (subsume (iconst ty (imm64 1))))

;; ule(x, y) || ugt(x, y) == ugt(x, y) || ule(x, y) == true.
(rule (simplify (bor ty (ule ty x y) (ugt ty x y))) (subsume (iconst ty (imm64 1))))
(rule (simplify (bor ty (ugt ty x y) (ule ty x y))) (subsume (iconst ty (imm64 1))))

;; ule(x, y) || uge(x, y) == uge(x, y) || ule(x, y) == true.
(rule (simplify (bor ty (ule ty x y) (uge ty x y))) (subsume (iconst ty (imm64 1))))
(rule (simplify (bor ty (uge ty x y) (ule ty x y))) (subsume (iconst ty (imm64 1))))

;; ugt(x, y) || uge(x, y) == uge(x, y) || ugt(x, y) == uge(x, y).
(rule (simplify (bor ty (ugt ty x y) uge @ (uge ty x y))) (subsume uge))
(rule (simplify (bor ty uge @ (uge ty x y) (ugt ty x y))) (subsume uge))

;; slt(x, y) || sle(x, y) == sle(x, y) || slt(x, y) == sle(x, y).
(rule (simplify (bor ty (slt ty x y) sle @ (sle ty x y))) (subsume sle))
(rule (simplify (bor ty sle @ (sle ty x y) (slt ty x y))) (subsume sle))

;; slt(x, y) || sgt(x, y) == sgt(x, y) || slt(x, y) == ne(x, y).
(rule (simplify (bor ty (slt ty x y) (sgt ty x y))) (subsume (ne ty x y)))
(rule (simplify (bor ty (sgt ty x y) (slt ty x y))) (subsume (ne ty x y)))

;; slt(x, y) || sge(x, y) == sge(x, y) || slt(x, y) == true.
(rule (simplify (bor ty (slt ty x y) (sge ty x y))) (subsume (iconst ty (imm64 1))))
(rule (simplify (bor ty (sge ty x y) (slt ty x y))) (subsume (iconst ty (imm64 1))))

;; sle(x, y) || sgt(x, y) == sgt(x, y) || sle(x, y) == true.
(rule (simplify (bor ty (sle ty x y) (sgt ty x y))) (subsume (iconst ty (imm64 1))))
(rule (simplify (bor ty (sgt ty x y) (sle ty x y))) (subsume (iconst ty (imm64 1))))

;; sle(x, y) || sge(x, y) == sge(x, y) || sle(x, y) == true.
(rule (simplify (bor ty (sle ty x y) (sge ty x y))) (subsume (iconst ty (imm64 1))))
(rule (simplify (bor ty (sge ty x y) (sle ty x y))) (subsume (iconst ty (imm64 1))))

;; sgt(x, y) || sge(x, y) == sge(x, y) || sgt(x, y) == sge.
(rule (simplify (bor ty (sgt ty x y) sge @ (sge ty x y))) (subsume sge))
(rule (simplify (bor ty sge @ (sge ty x y) (sgt ty x y))) (subsume sge))

;; Transform select-of-icmp into {u,s}{min,max} instructions where possible.
(rule (simplify (select ty (sgt _ x y) x y)) (smax ty x y))
Expand Down
14 changes: 14 additions & 0 deletions cranelift/codegen/src/prelude.isle
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,14 @@
(decl intcc_inverse (IntCC) IntCC)
(extern constructor intcc_inverse intcc_inverse)

;; Add equal component to an IntCC
(decl intcc_with_equal (IntCC) IntCC)
(extern constructor intcc_with_equal intcc_with_equal)

;; Remove equal component from an IntCC
(decl intcc_without_equal (IntCC) IntCC)
(extern constructor intcc_without_equal intcc_without_equal)

;; Reverse an FloatCC flag.
(decl floatcc_reverse (FloatCC) FloatCC)
(extern constructor floatcc_reverse floatcc_reverse)
Expand Down Expand Up @@ -315,6 +323,12 @@
(decl sge (Type Value Value) Value)
(extractor (sge ty x y) (icmp ty (IntCC.SignedGreaterThanOrEqual) x y))

(decl intcc_le_or_ge (IntCC) IntCC)
(extern extractor intcc_le_or_ge intcc_le_or_ge)

(decl intcc_lt_or_gt (IntCC) IntCC)
(extern extractor intcc_lt_or_gt intcc_lt_or_gt)

;; An extractor that only matches types that can fit in 16 bits.
(decl fits_in_16 (Type) Type)
(extern extractor fits_in_16 fits_in_16)
Expand Down
Loading

0 comments on commit 4e7b540

Please sign in to comment.