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

More spaceship patterns #7702

Merged
merged 1 commit into from
Dec 19, 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
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
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Specifically this truthy part:

(rule (truthy (select _ x (iconst_u _ (u64_nonzero _)) (iconst_u _ 0))) x)

;; 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