Skip to content

Commit c82d978

Browse files
committed
egraphs: canonicalize icmp
Canonicalize `icmp` instructions: * loose inequalities to strict inequalities (eg `ult(x, c) => ult(x, c+1)`) where possible * strict inequalities to equalities (eg `ult(x, 1) => eq(x, 0)`) where possible Copyright (c) 2024, Arm Limited. Signed-off-by: Karl Meakin <karl.meakin@arm.com>
1 parent 1e306fb commit c82d978

10 files changed

Lines changed: 718 additions & 120 deletions

File tree

cranelift/codegen/src/opts/icmp.isle

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515

1616
;; Optimize icmp-of-icmp.
1717
;; ne(icmp(ty, cc, x, y), 0) == icmp(ty, cc, x, y)
18-
;; e.g. neq(ugt(x, y), 0) == ugt(x, y)
18+
;; e.g. neq(ugt(x, y), 0) == ugt(x, y)
1919
(rule (simplify (ne ty
2020
(uextend_maybe _ inner @ (icmp ty _ _ _))
2121
(iconst_u _ 0)))
2222
(subsume inner))
2323

2424
;; eq(icmp(ty, cc, x, y), 0) == icmp(ty, cc_complement, x, y)
25-
;; e.g. eq(ugt(x, y), 0) == ule(x, y)
25+
;; e.g. eq(ugt(x, y), 0) == ule(x, y)
2626
(rule (simplify (eq ty
2727
(uextend_maybe _ (icmp ty cc x y))
2828
(iconst_u _ 0)))
@@ -65,11 +65,36 @@
6565
(iconst_u _ 1)))
6666
extend)
6767

68+
;; Rewrite loose inequalities to strict inequalities:
69+
;; ule(x, c) == ult(x, c+1), for c != UMAX.
70+
(rule (simplify (ule (fits_in_64 (ty_int bty)) x (iconst cty (u64_from_imm64 c))))
71+
(if-let $false (u64_eq c (ty_umax cty)))
72+
(ult bty x (iconst cty (imm64 (u64_add c 1)))))
73+
74+
;; uge(x, c) == ugt(x, c-1), for c != 0.
75+
(rule (simplify (uge (fits_in_64 (ty_int bty)) x (iconst cty (u64_from_imm64 c))))
76+
(if-let $false (u64_eq c 0))
77+
(ugt bty x (iconst cty (imm64 (u64_sub c 1)))))
78+
79+
;; sle(x, c) == slt(x, c+1), for c != SMAX.
80+
(rule (simplify (sle (fits_in_64 (ty_int bty)) x (iconst cty (u64_from_imm64 c))))
81+
(if-let $false (u64_eq c (ty_smax cty)))
82+
(slt bty x (iconst cty (imm64 (u64_add c 1)))))
83+
84+
;; sge(x, c) == sgt(x, c-1), for c != SMIN.
85+
;; (rule (simplify (sge (fits_in_64 (ty_int bty)) x (iconst cty (u64_from_imm64 c))))
86+
;; (if-let $false (u64_eq c (ty_smin cty)))
87+
;; (sgt bty x (iconst cty (imm64 (u64_sub c 1)))))
88+
6889
;; Comparisons against largest/smallest signed/unsigned values:
6990
;; ult(x, 0) == false.
7091
(rule (simplify (ult (fits_in_64 (ty_int bty)) x zero @ (iconst_u _ 0)))
7192
(subsume (iconst_u bty 0)))
7293

94+
;; ult(x, 1) == eq(x, 0)
95+
(rule (simplify (ult (fits_in_64 (ty_int bty)) x (iconst cty (u64_from_imm64 0))))
96+
(eq bty x (iconst cty (imm64 0))))
97+
7398
;; ule(x, 0) == eq(x, 0)
7499
(rule (simplify (ule (fits_in_64 (ty_int bty)) x zero @ (iconst_u _ 0)))
75100
(eq bty x zero))
@@ -78,6 +103,11 @@
78103
(rule (simplify (ugt (fits_in_64 (ty_int bty)) x zero @ (iconst_u _ 0)))
79104
(ne bty x zero))
80105

106+
;; ugt(x, UMAX-1) == eq(x, UMAX).
107+
(rule (simplify (ugt (fits_in_64 (ty_int bty)) x (iconst cty (u64_from_imm64 y))))
108+
(if-let $true (u64_eq y (u64_sub (ty_umax cty) 1)))
109+
(eq bty x (iconst cty (imm64 (ty_umax cty)))))
110+
81111
;; uge(x, 0) == true.
82112
(rule (simplify (uge (fits_in_64 (ty_int bty)) x zero @ (iconst_u _ 0)))
83113
(subsume (iconst_u bty 1)))
@@ -112,6 +142,11 @@
112142
(if-let $true (u64_eq y (ty_smin cty)))
113143
(eq bty x smin))
114144

145+
;; slt(x, SMIN+1) == eq(x, SMIN).
146+
(rule (simplify (slt (fits_in_64 (ty_int bty)) x (iconst cty (u64_from_imm64 y))))
147+
(if-let $true (u64_eq y (u64_add (ty_smin cty) 1)))
148+
(eq bty x (iconst cty (imm64 (ty_smin cty)))))
149+
115150
;; sgt(x, SMIN) == ne(x, SMIN).
116151
(rule (simplify (sgt (fits_in_64 (ty_int bty)) x smin @ (iconst_u cty y)))
117152
(if-let $true (u64_eq y (ty_smin cty)))
@@ -142,6 +177,11 @@
142177
(if-let $true (u64_eq y (ty_smax cty)))
143178
(eq bty x smax))
144179

180+
;; sgt(x, SMAX-1) == eq(x, SMAX).
181+
(rule (simplify (sgt (fits_in_64 (ty_int bty)) x (iconst cty (u64_from_imm64 y))))
182+
(if-let $true (u64_eq y (u64_sub (ty_smax cty) 1)))
183+
(eq bty x (iconst cty (imm64 (ty_smax cty)))))
184+
145185
;; `band`/`bor` of 2 comparisons:
146186
(rule (simplify (band (fits_in_64 ty) (icmp ty cc1 x y) (icmp ty cc2 x y)))
147187
(if-let signed (intcc_comparable cc1 cc2))

cranelift/filetests/filetests/egraph/cprop.clif

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ block0:
162162
return v2
163163
}
164164

165-
; check: v3 = iconst.i8 1
166-
; nextln: return v3
165+
; check: v5 = iconst.i8 1
166+
; nextln: return v5
167167

168168
function %icmp_uge_i32() -> i8 {
169169
block0:
@@ -173,8 +173,8 @@ block0:
173173
return v2
174174
}
175175

176-
; check: v3 = iconst.i8 0
177-
; nextln: return v3
176+
; check: v4 = iconst.i8 0
177+
; nextln: return v4
178178

179179
function %icmp_ugt_i32() -> i8 {
180180
block0:
@@ -206,8 +206,8 @@ block0:
206206
return v2
207207
}
208208

209-
; check: v3 = iconst.i8 1
210-
; nextln: return v3
209+
; check: v5 = iconst.i8 1
210+
; nextln: return v5
211211

212212
function %icmp_sge_i32() -> i8 {
213213
block0:

0 commit comments

Comments
 (0)