Skip to content

Commit

Permalink
More spaceship patterns (#7702)
Browse files Browse the repository at this point in the history
  • Loading branch information
scottmcm authored Dec 19, 2023
1 parent 866d97c commit f8c9f67
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 87 deletions.
5 changes: 5 additions & 0 deletions cranelift/codegen/src/opts/bitops.isle
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@
(if-let $true (u64_eq shift_amt (ty_shift_mask ty)))
(bmask ty x))

;; Since icmp is always 0 or 1, bmask is just a negation.
;; TODO: Explore whether this makes sense for things needing extension too.
(rule (simplify (bmask $I8 cmp@(icmp $I8 _ _ _)))
(ineg $I8 cmp))

;; Matches any expressions that preserve "truthiness".
;; i.e. If the input is zero it remains zero, and if it is nonzero it can have
;; a different value as long as it is still nonzero.
Expand Down
17 changes: 12 additions & 5 deletions cranelift/codegen/src/opts/selects.isle
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@
(rule (simplify (select ty _ x x)) x)
(rule (simplify (bitselect ty _ x x)) x)

;; Push zeroes to the right -- this makes the select `truthy`, as used elsewhere
;; if icmp { 0 } else { nonzero } => if !icmp { nonzero } else { 0 }
(rule (simplify (select sty (icmp cty cc x y)
zero@(iconst_u _ 0)
nonzero@(iconst_u _ (u64_nonzero _))))
(select sty (icmp cty (intcc_complement cc) x y) nonzero zero))

;; if icmp(x, y) { 1 } else { 0 } => uextend(icmp(x, y))
(rule (simplify (select ty cmp@(icmp _ cc x y)
(iconst_u _ 1)
(iconst_u _ 0)))
(uextend_from_i8 ty cmp))
;; if icmp(x, y) { 0 } else { 1 } => uextend(!icmp(x, y))
(rule (simplify (select sty (icmp cty cc x y)
(iconst_u _ 0)
(iconst_u _ 1)))
(uextend_from_i8 sty (icmp cty (intcc_complement cc) x y)))
;; if icmp(x, y) { -1 } else { 0 } => uextend(icmp(x, y))
(rule (simplify (select ty cmp@(icmp _ cc x y)
(iconst_s _ -1)
(iconst_s _ 0)))
(bmask ty cmp))

;; 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
59 changes: 31 additions & 28 deletions cranelift/codegen/src/opts/spaceship.isle
Original file line number Diff line number Diff line change
Expand Up @@ -59,32 +59,24 @@
(sextend_from_i8 ty (spaceship_u rty x y)))

;; x > y ? 1 : x < y ? -1 : 0
;; x > y ? 1 : x >= y ? 0 : -1
(rule (simplify (select ty (ugt rty x y)
(iconst_s ty 1)
(select ty (ult rty x y)
(iconst_s ty -1)
(iconst_s ty 0))))
(ineg rty (ult rty x y))))
(sextend_from_i8 ty (spaceship_u rty x y)))
;; x > y ? 1 : x != y ? -1 : 0
(rule (simplify (select ty (ugt rty x y)
(iconst_s ty 1)
(select ty (ne rty x y)
(iconst_s ty -1)
(iconst_s ty 0))))
(bmask ty (ult rty x y))))
(sextend_from_i8 ty (spaceship_u rty x y)))
;; x > y ? 1 : x != y ? -1 : 0
;; x > y ? 1 : x == y ? 0 : -1
(rule (simplify (select ty (ugt rty x y)
(iconst_s ty 1)
(select ty (eq rty x y)
(iconst_s ty 0)
(iconst_s ty -1))))
(ineg rty (ne rty x y))))
(sextend_from_i8 ty (spaceship_u rty x y)))
;; x > y ? 1 : x >= y ? 0 : -1
(rule (simplify (select ty (ugt rty x y)
(iconst_s ty 1)
(select ty (uge rty x y)
(iconst_s ty 0)
(iconst_s ty -1))))
(bmask ty (ne rty x y))))
(sextend_from_i8 ty (spaceship_u rty x y)))

;; Same, but for signed comparisons this time
Expand Down Expand Up @@ -140,32 +132,24 @@
(sextend_from_i8 ty (spaceship_s rty x y)))

;; x > y ? 1 : x < y ? -1 : 0
;; x > y ? 1 : x >= y ? 0 : -1
(rule (simplify (select ty (sgt rty x y)
(iconst_s ty 1)
(select ty (slt rty x y)
(iconst_s ty -1)
(iconst_s ty 0))))
(ineg rty (slt rty x y))))
(sextend_from_i8 ty (spaceship_s rty x y)))
;; x > y ? 1 : x != y ? -1 : 0
(rule (simplify (select ty (sgt rty x y)
(iconst_s ty 1)
(select ty (ne rty x y)
(iconst_s ty -1)
(iconst_s ty 0))))
(bmask ty (slt rty x y))))
(sextend_from_i8 ty (spaceship_s rty x y)))
;; x > y ? 1 : x != y ? -1 : 0
;; x > y ? 1 : x == y ? 0 : -1
(rule (simplify (select ty (sgt rty x y)
(iconst_s ty 1)
(select ty (eq rty x y)
(iconst_s ty 0)
(iconst_s ty -1))))
(ineg rty (ne rty x y))))
(sextend_from_i8 ty (spaceship_s rty x y)))
;; x > y ? 1 : x >= y ? 0 : -1
(rule (simplify (select ty (sgt rty x y)
(iconst_s ty 1)
(select ty (sge rty x y)
(iconst_s ty 0)
(iconst_s ty -1))))
(bmask ty (ne rty x y))))
(sextend_from_i8 ty (spaceship_s rty x y)))

;; Then once we have it normalized, we can apply some basic simplifications.
Expand Down Expand Up @@ -206,6 +190,25 @@
(rule (simplify (sge _ (spaceship_u ty x y) (iconst_s _ 0)))
(uge ty x y))

;; Rust's `sort_by` uses `compare(a, b) == Less`, which the general icmp rules
;; can't simplify to a comparison against zero, so catch things like that too.
(rule (simplify (eq _ (spaceship_s ty x y) (iconst_s _ -1)))
(slt ty x y))
(rule (simplify (eq _ (spaceship_u ty x y) (iconst_s _ -1)))
(ult ty x y))
(rule (simplify (ne _ (spaceship_s ty x y) (iconst_s _ -1)))
(sge ty x y))
(rule (simplify (ne _ (spaceship_u ty x y) (iconst_s _ -1)))
(uge ty x y))
(rule (simplify (eq _ (spaceship_s ty x y) (iconst_s _ 1)))
(sgt ty x y))
(rule (simplify (eq _ (spaceship_u ty x y) (iconst_s _ 1)))
(ugt ty x y))
(rule (simplify (ne _ (spaceship_s ty x y) (iconst_s _ 1)))
(sle ty x y))
(rule (simplify (ne _ (spaceship_u ty x y) (iconst_s _ 1)))
(ule ty x y))

;; extend from i8 to i8 is invalid CLIF, so this allows fixing that in the output
;; rather than needing to duplicate rules for the different width categories
(decl sextend_from_i8 (Type Value) Value)
Expand Down
27 changes: 25 additions & 2 deletions cranelift/filetests/filetests/egraph/select.clif
Original file line number Diff line number Diff line change
Expand Up @@ -183,5 +183,28 @@ block0(v0: i32, v1: i32):
return v5
}
; check: v6 = icmp sge v0, v1
; check: v7 = uextend.i64 v6
; check: return v7
; check: v8 = uextend.i64 v6
; check: return v8

function %then_negone_else_zero(i32, i32) -> i64 {
block0(v0: i32, v1: i32):
v2 = icmp ule v0, v1
v3 = iconst.i64 -1
v4 = iconst.i64 0
v5 = select v2, v3, v4
return v5
}
; check: v6 = bmask.i64 v2
; check: return v6

function %then_zero_else_else_negone(i32, i32) -> i64 {
block0(v0: i32, v1: i32):
v2 = icmp sle v0, v1
v3 = iconst.i64 0
v4 = iconst.i64 -1
v5 = select v2, v3, v4
return v5
}
; check: v6 = icmp sgt v0, v1
; check: v8 = bmask.i64 v6
; check: return v8
Loading

0 comments on commit f8c9f67

Please sign in to comment.