1 ! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors combinators combinators.short-circuit arrays
4 fry kernel layouts math namespaces sequences cpu.architecture
5 math.bitwise math.order classes vectors
8 compiler.cfg.comparisons
9 compiler.cfg.instructions
10 compiler.cfg.value-numbering.expressions
11 compiler.cfg.value-numbering.graph
12 compiler.cfg.value-numbering.simplify ;
13 IN: compiler.cfg.value-numbering.rewrite
15 : vreg-small-constant? ( vreg -- ? )
18 [ value>> small-enough? ]
21 ! Outputs f to mean no change
23 GENERIC: rewrite* ( insn -- insn/f )
25 : rewrite ( insn -- insn' )
26 dup [ number-values ] [ rewrite* ] bi
29 M: insn rewrite* drop f ;
31 : ##branch-t? ( insn -- ? )
32 dup ##compare-imm-branch? [
35 [ src2>> \ f tag-number eq? ]
37 ] [ drop f ] if ; inline
39 : rewrite-boolean-comparison? ( insn -- ? )
41 src1>> vreg>expr compare-expr?
42 ] [ drop f ] if ; inline
44 : >compare-expr< ( expr -- in1 in2 cc )
45 [ in1>> vn>vreg ] [ in2>> vn>vreg ] [ cc>> ] tri ; inline
47 : >compare-imm-expr< ( expr -- in1 in2 cc )
48 [ in1>> vn>vreg ] [ in2>> vn>constant ] [ cc>> ] tri ; inline
50 : rewrite-boolean-comparison ( expr -- insn )
51 src1>> vreg>expr dup op>> {
52 { \ ##compare [ >compare-expr< \ ##compare-branch new-insn ] }
53 { \ ##compare-imm [ >compare-imm-expr< \ ##compare-imm-branch new-insn ] }
54 { \ ##compare-float [ >compare-expr< \ ##compare-float-branch new-insn ] }
57 : tag-fixnum-expr? ( expr -- ? )
58 dup op>> \ ##shl-imm eq?
59 [ in2>> vn>constant tag-bits get = ] [ drop f ] if ;
61 : rewrite-tagged-comparison? ( insn -- ? )
62 #! Are we comparing two tagged fixnums? Then untag them.
64 [ src1>> vreg>expr tag-fixnum-expr? ]
65 [ src2>> tag-mask get bitand 0 = ]
68 : tagged>constant ( n -- n' )
69 tag-bits get neg shift ; inline
71 : (rewrite-tagged-comparison) ( insn -- src1 src2 cc )
72 [ src1>> vreg>expr in1>> vn>vreg ]
73 [ src2>> tagged>constant ]
77 GENERIC: rewrite-tagged-comparison ( insn -- insn/f )
79 M: ##compare-imm-branch rewrite-tagged-comparison
80 (rewrite-tagged-comparison) \ ##compare-imm-branch new-insn ;
82 M: ##compare-imm rewrite-tagged-comparison
83 [ dst>> ] [ (rewrite-tagged-comparison) ] bi
84 i \ ##compare-imm new-insn ;
86 : rewrite-redundant-comparison? ( insn -- ? )
88 [ src1>> vreg>expr compare-expr? ]
89 [ src2>> \ f tag-number = ]
90 [ cc>> { cc= cc/= } memq? ]
93 : rewrite-redundant-comparison ( insn -- insn' )
94 [ cc>> ] [ dst>> ] [ src1>> vreg>expr dup op>> ] tri {
95 { \ ##compare [ >compare-expr< i \ ##compare new-insn ] }
96 { \ ##compare-imm [ >compare-imm-expr< i \ ##compare-imm new-insn ] }
97 { \ ##compare-float [ >compare-expr< i \ ##compare-float new-insn ] }
99 swap cc= eq? [ [ negate-cc ] change-cc ] when ;
101 ERROR: bad-comparison ;
103 : (fold-compare-imm) ( insn -- ? )
104 [ [ src1>> vreg>constant ] [ src2>> ] bi ] [ cc>> ] bi
106 [ [ <=> ] dip evaluate-cc ]
115 : fold-compare-imm? ( insn -- ? )
116 src1>> vreg>expr [ constant-expr? ] [ reference-expr? ] bi or ;
118 : fold-branch ( ? -- insn )
120 basic-block get [ nth 1vector ] change-successors drop
121 \ ##branch new-insn ;
123 : fold-compare-imm-branch ( insn -- insn/f )
124 (fold-compare-imm) fold-branch ;
126 M: ##compare-imm-branch rewrite*
128 { [ dup rewrite-boolean-comparison? ] [ rewrite-boolean-comparison ] }
129 { [ dup rewrite-tagged-comparison? ] [ rewrite-tagged-comparison ] }
130 { [ dup fold-compare-imm? ] [ fold-compare-imm-branch ] }
134 : swap-compare ( src1 src2 cc swap? -- src1 src2 cc )
135 [ [ swap ] dip swap-cc ] when ; inline
137 : >compare-imm-branch ( insn swap? -- insn' )
145 [ vreg>constant ] dip
146 \ ##compare-imm-branch new-insn ; inline
148 : self-compare? ( insn -- ? )
149 [ src1>> ] [ src2>> ] bi [ vreg>vn ] bi@ = ; inline
151 : (rewrite-self-compare) ( insn -- ? )
152 cc>> { cc= cc<= cc>= } memq? ;
154 : rewrite-self-compare-branch ( insn -- insn' )
155 (rewrite-self-compare) fold-branch ;
157 M: ##compare-branch rewrite*
159 { [ dup src1>> vreg-small-constant? ] [ t >compare-imm-branch ] }
160 { [ dup src2>> vreg-small-constant? ] [ f >compare-imm-branch ] }
161 { [ dup self-compare? ] [ rewrite-self-compare-branch ] }
165 : >compare-imm ( insn swap? -- insn' )
175 [ vreg>constant ] dip
176 i \ ##compare-imm new-insn ; inline
178 : >boolean-insn ( insn ? -- insn' )
181 { t [ t \ ##load-reference new-insn ] }
182 { f [ \ f tag-number \ ##load-immediate new-insn ] }
185 : rewrite-self-compare ( insn -- insn' )
186 dup (rewrite-self-compare) >boolean-insn ;
188 M: ##compare rewrite*
190 { [ dup src1>> vreg-small-constant? ] [ t >compare-imm ] }
191 { [ dup src2>> vreg-small-constant? ] [ f >compare-imm ] }
192 { [ dup self-compare? ] [ rewrite-self-compare ] }
196 : fold-compare-imm ( insn -- insn' )
197 dup (fold-compare-imm) >boolean-insn ;
199 M: ##compare-imm rewrite*
201 { [ dup rewrite-redundant-comparison? ] [ rewrite-redundant-comparison ] }
202 { [ dup rewrite-tagged-comparison? ] [ rewrite-tagged-comparison ] }
203 { [ dup fold-compare-imm? ] [ fold-compare-imm ] }
207 : constant-fold? ( insn -- ? )
208 src1>> vreg>expr constant-expr? ; inline
210 GENERIC: constant-fold* ( x y insn -- z )
212 M: ##add-imm constant-fold* drop + ;
213 M: ##sub-imm constant-fold* drop - ;
214 M: ##mul-imm constant-fold* drop * ;
215 M: ##and-imm constant-fold* drop bitand ;
216 M: ##or-imm constant-fold* drop bitor ;
217 M: ##xor-imm constant-fold* drop bitxor ;
218 M: ##shr-imm constant-fold* drop [ cell-bits 2^ wrap ] dip neg shift ;
219 M: ##sar-imm constant-fold* drop neg shift ;
220 M: ##shl-imm constant-fold* drop shift ;
222 : constant-fold ( insn -- insn' )
224 [ [ src1>> vreg>constant ] [ src2>> ] [ ] tri constant-fold* ] bi
225 \ ##load-immediate new-insn ; inline
227 : reassociate? ( insn -- ? )
228 [ src1>> vreg>expr op>> ] [ class ] bi = ; inline
230 : reassociate ( insn op -- insn )
234 [ src1>> vreg>expr [ in1>> vn>vreg ] [ in2>> vn>constant ] bi ]
237 } cleave constant-fold*
239 over small-enough? [ new-insn ] [ 2drop 2drop f ] if ; inline
241 M: ##add-imm rewrite*
243 { [ dup constant-fold? ] [ constant-fold ] }
244 { [ dup reassociate? ] [ \ ##add-imm reassociate ] }
248 : sub-imm>add-imm ( insn -- insn' )
249 [ dst>> ] [ src1>> ] [ src2>> neg ] tri dup small-enough?
250 [ \ ##add-imm new-insn ] [ 3drop f ] if ;
252 M: ##sub-imm rewrite*
254 { [ dup constant-fold? ] [ constant-fold ] }
258 : strength-reduce-mul ( insn -- insn' )
259 [ [ dst>> ] [ src1>> ] bi ] [ src2>> log2 ] bi \ ##shl-imm new-insn ;
261 : strength-reduce-mul? ( insn -- ? )
264 M: ##mul-imm rewrite*
266 { [ dup constant-fold? ] [ constant-fold ] }
267 { [ dup strength-reduce-mul? ] [ strength-reduce-mul ] }
268 { [ dup reassociate? ] [ \ ##mul-imm reassociate ] }
272 M: ##and-imm rewrite*
274 { [ dup constant-fold? ] [ constant-fold ] }
275 { [ dup reassociate? ] [ \ ##and-imm reassociate ] }
281 { [ dup constant-fold? ] [ constant-fold ] }
282 { [ dup reassociate? ] [ \ ##or-imm reassociate ] }
286 M: ##xor-imm rewrite*
288 { [ dup constant-fold? ] [ constant-fold ] }
289 { [ dup reassociate? ] [ \ ##xor-imm reassociate ] }
293 M: ##shl-imm rewrite*
295 { [ dup constant-fold? ] [ constant-fold ] }
299 M: ##shr-imm rewrite*
301 { [ dup constant-fold? ] [ constant-fold ] }
305 M: ##sar-imm rewrite*
307 { [ dup constant-fold? ] [ constant-fold ] }
311 : insn>imm-insn ( insn op swap? -- )
313 [ [ dst>> ] [ src1>> ] [ src2>> ] tri ] dip
314 [ swap ] when vreg>constant
315 ] dip new-insn ; inline
317 : rewrite-arithmetic ( insn op -- ? )
319 { [ over src2>> vreg-small-constant? ] [ f insn>imm-insn ] }
323 : rewrite-arithmetic-commutative ( insn op -- ? )
325 { [ over src2>> vreg-small-constant? ] [ f insn>imm-insn ] }
326 { [ over src1>> vreg-small-constant? ] [ t insn>imm-insn ] }
330 M: ##add rewrite* \ ##add-imm rewrite-arithmetic-commutative ;
332 : subtraction-identity? ( insn -- ? )
333 [ src1>> ] [ src2>> ] bi [ vreg>vn ] bi@ eq? ;
335 : rewrite-subtraction-identity ( insn -- insn' )
336 dst>> 0 \ ##load-immediate new-insn ;
340 { [ dup subtraction-identity? ] [ rewrite-subtraction-identity ] }
341 [ \ ##sub-imm rewrite-arithmetic ]
344 M: ##mul rewrite* \ ##mul-imm rewrite-arithmetic-commutative ;
346 M: ##and rewrite* \ ##and-imm rewrite-arithmetic-commutative ;
348 M: ##or rewrite* \ ##or-imm rewrite-arithmetic-commutative ;
350 M: ##xor rewrite* \ ##xor-imm rewrite-arithmetic-commutative ;
352 M: ##shl rewrite* \ ##shl-imm rewrite-arithmetic ;
354 M: ##shr rewrite* \ ##shr-imm rewrite-arithmetic ;
356 M: ##sar rewrite* \ ##sar-imm rewrite-arithmetic ;