From 11731f8d485675b6eff6cf18c060256f9cb06a78 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 14 Jul 2009 20:05:01 -0500 Subject: [PATCH] compiler.cfg.value-numbering: merge in compiler.cfg.branch-folding --- .../branch-folding-tests.factor | 89 ------ .../cfg/branch-folding/branch-folding.factor | 33 --- basis/compiler/cfg/optimizer/optimizer.factor | 2 - .../value-numbering/rewrite/rewrite.factor | 55 +++- .../value-numbering-tests.factor | 263 +++++++++++++++++- .../value-numbering/value-numbering.factor | 2 + basis/compiler/tests/codegen.factor | 5 +- 7 files changed, 309 insertions(+), 140 deletions(-) delete mode 100644 basis/compiler/cfg/branch-folding/branch-folding-tests.factor delete mode 100644 basis/compiler/cfg/branch-folding/branch-folding.factor diff --git a/basis/compiler/cfg/branch-folding/branch-folding-tests.factor b/basis/compiler/cfg/branch-folding/branch-folding-tests.factor deleted file mode 100644 index 1d43ea0af3..0000000000 --- a/basis/compiler/cfg/branch-folding/branch-folding-tests.factor +++ /dev/null @@ -1,89 +0,0 @@ -IN: compiler.cfg.branch-folding.tests -USING: compiler.cfg.branch-folding compiler.cfg.instructions -compiler.cfg compiler.cfg.registers compiler.cfg.debugger -arrays compiler.cfg.phi-elimination compiler.cfg.dce -compiler.cfg.predecessors compiler.cfg.comparisons -kernel accessors assocs sequences classes namespaces -tools.test cpu.architecture ; - -V{ T{ ##branch } } 0 test-bb - -V{ - T{ ##peek f V int-regs 0 D 0 } - T{ ##compare-branch f V int-regs 0 V int-regs 0 cc< } -} 1 test-bb - -V{ - T{ ##load-immediate f V int-regs 1 1 } - T{ ##branch } -} 2 test-bb - -V{ - T{ ##load-immediate f V int-regs 2 2 } - T{ ##branch } -} 3 test-bb - -V{ - T{ ##phi f V int-regs 3 { } } - T{ ##replace f V int-regs 3 D 0 } - T{ ##return } -} 4 test-bb - -4 get instructions>> first -2 get V int-regs 1 2array -3 get V int-regs 2 2array 2array ->>inputs drop - -test-diamond - -[ ] [ cfg new 0 get >>entry fold-branches compute-predecessors eliminate-phis drop ] unit-test - -[ 1 ] [ 1 get successors>> length ] unit-test -[ t ] [ 1 get successors>> first 3 get eq? ] unit-test - -[ T{ ##copy f V int-regs 3 V int-regs 2 } ] -[ 3 get successors>> first instructions>> first ] -unit-test - -[ 2 ] [ 4 get instructions>> length ] unit-test - -V{ - T{ ##peek f V int-regs 0 D 0 } - T{ ##branch } -} 0 test-bb - -V{ - T{ ##peek f V int-regs 1 D 1 } - T{ ##compare-branch f V int-regs 1 V int-regs 1 cc< } -} 1 test-bb - -V{ - T{ ##copy f V int-regs 2 V int-regs 0 } - T{ ##branch } -} 2 test-bb - -V{ - T{ ##phi f V int-regs 3 V{ } } - T{ ##branch } -} 3 test-bb - -V{ - T{ ##replace f V int-regs 3 D 0 } - T{ ##return } -} 4 test-bb - -1 get V int-regs 1 2array -2 get V int-regs 0 2array 2array 3 get instructions>> first (>>inputs) - -test-diamond - -[ ] [ - cfg new 0 get >>entry - compute-predecessors - fold-branches - compute-predecessors - eliminate-dead-code - drop -] unit-test - -[ 1 ] [ 3 get instructions>> first inputs>> assoc-size ] unit-test \ No newline at end of file diff --git a/basis/compiler/cfg/branch-folding/branch-folding.factor b/basis/compiler/cfg/branch-folding/branch-folding.factor deleted file mode 100644 index 04842552b7..0000000000 --- a/basis/compiler/cfg/branch-folding/branch-folding.factor +++ /dev/null @@ -1,33 +0,0 @@ -! Copyright (C) 2009 Slava Pestov. -! See http://factorcode.org/license.txt for BSD license. -USING: accessors combinators.short-circuit kernel sequences vectors -compiler.cfg.instructions -compiler.cfg.comparisons -compiler.cfg.rpo -compiler.cfg ; -IN: compiler.cfg.branch-folding - -! Fold comparisons where both inputs are the same. Predecessors must be -! recomputed after this - -: fold-branch? ( bb -- ? ) - instructions>> last { - [ ##compare-branch? ] - [ [ src1>> ] [ src2>> ] bi = ] - } 1&& ; - -: chosen-successor ( bb -- succ ) - [ instructions>> last cc>> { cc= cc<= cc>= } memq? 0 1 ? ] - [ successors>> ] - bi nth ; - -: fold-branch ( bb -- ) - dup chosen-successor 1vector >>successors - instructions>> [ pop* ] [ [ \ ##branch new-insn ] dip push ] bi ; - -: fold-branches ( cfg -- cfg' ) - dup [ - dup fold-branch? - [ fold-branch ] [ drop ] if - ] each-basic-block - cfg-changed ; \ No newline at end of file diff --git a/basis/compiler/cfg/optimizer/optimizer.factor b/basis/compiler/cfg/optimizer/optimizer.factor index 5b0892a0ee..e16fb734e1 100644 --- a/basis/compiler/cfg/optimizer/optimizer.factor +++ b/basis/compiler/cfg/optimizer/optimizer.factor @@ -9,7 +9,6 @@ compiler.cfg.branch-splitting compiler.cfg.alias-analysis compiler.cfg.value-numbering compiler.cfg.dce -compiler.cfg.branch-folding compiler.cfg.write-barrier compiler.cfg.liveness compiler.cfg.rpo @@ -36,7 +35,6 @@ SYMBOL: check-optimizer? compute-liveness alias-analysis value-numbering - fold-branches compute-predecessors eliminate-dead-code eliminate-write-barriers diff --git a/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor b/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor index 5dd8884a89..3f7173c355 100755 --- a/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor +++ b/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor @@ -98,18 +98,31 @@ M: ##compare-imm rewrite-tagged-comparison } case swap cc= eq? [ [ negate-cc ] change-cc ] when ; +ERROR: bad-comparison ; + : (fold-compare-imm) ( insn -- ? ) [ [ src1>> vreg>constant ] [ src2>> ] bi ] [ cc>> ] bi - pick integer? [ [ <=> ] dip evaluate-cc ] [ 3drop f ] if ; + pick integer? + [ [ <=> ] dip evaluate-cc ] + [ + 2nip { + { cc= [ f ] } + { cc/= [ t ] } + [ bad-comparison ] + } case + ] if ; : fold-compare-imm? ( insn -- ? ) src1>> vreg>expr [ constant-expr? ] [ reference-expr? ] bi or ; -: fold-compare-imm-branch ( insn -- insn/f ) - (fold-compare-imm) 0 1 ? +: fold-branch ( ? -- insn ) + 0 1 ? basic-block get [ nth 1vector ] change-successors drop \ ##branch new-insn ; +: fold-compare-imm-branch ( insn -- insn/f ) + (fold-compare-imm) fold-branch ; + M: ##compare-imm-branch rewrite* { { [ dup rewrite-boolean-comparison? ] [ rewrite-boolean-comparison ] } @@ -132,10 +145,20 @@ M: ##compare-imm-branch rewrite* [ vreg>constant ] dip \ ##compare-imm-branch new-insn ; inline +: self-compare? ( insn -- ? ) + [ src1>> ] [ src2>> ] bi [ vreg>vn ] bi@ = ; inline + +: (rewrite-self-compare) ( insn -- ? ) + cc>> { cc= cc<= cc>= } memq? ; + +: rewrite-self-compare-branch ( insn -- insn' ) + (rewrite-self-compare) fold-branch ; + M: ##compare-branch rewrite* { { [ dup src1>> vreg-small-constant? ] [ t >compare-imm-branch ] } { [ dup src2>> vreg-small-constant? ] [ f >compare-imm-branch ] } + { [ dup self-compare? ] [ rewrite-self-compare-branch ] } [ drop f ] } cond ; @@ -152,21 +175,27 @@ M: ##compare-branch rewrite* [ vreg>constant ] dip i \ ##compare-imm new-insn ; inline -M: ##compare rewrite* - { - { [ dup src1>> vreg-small-constant? ] [ t >compare-imm ] } - { [ dup src2>> vreg-small-constant? ] [ f >compare-imm ] } - [ drop f ] - } cond ; - -: fold-compare-imm ( insn -- ) - [ dst>> ] - [ (fold-compare-imm) ] bi +: >boolean-insn ( insn ? -- insn' ) + [ dst>> ] dip { { t [ t \ ##load-reference new-insn ] } { f [ \ f tag-number \ ##load-immediate new-insn ] } } case ; +: rewrite-self-compare ( insn -- insn' ) + dup (rewrite-self-compare) >boolean-insn ; + +M: ##compare rewrite* + { + { [ dup src1>> vreg-small-constant? ] [ t >compare-imm ] } + { [ dup src2>> vreg-small-constant? ] [ f >compare-imm ] } + { [ dup self-compare? ] [ rewrite-self-compare ] } + [ drop f ] + } cond ; + +: fold-compare-imm ( insn -- insn' ) + dup (fold-compare-imm) >boolean-insn ; + M: ##compare-imm rewrite* { { [ dup rewrite-redundant-comparison? ] [ rewrite-redundant-comparison ] } diff --git a/basis/compiler/cfg/value-numbering/value-numbering-tests.factor b/basis/compiler/cfg/value-numbering/value-numbering-tests.factor index e808220716..60d23cefb7 100644 --- a/basis/compiler/cfg/value-numbering/value-numbering-tests.factor +++ b/basis/compiler/cfg/value-numbering/value-numbering-tests.factor @@ -2,7 +2,9 @@ IN: compiler.cfg.value-numbering.tests USING: compiler.cfg.value-numbering compiler.cfg.instructions compiler.cfg.registers compiler.cfg.debugger compiler.cfg.comparisons cpu.architecture tools.test kernel math combinators.short-circuit -accessors sequences compiler.cfg vectors arrays layouts namespaces ; +accessors sequences compiler.cfg.predecessors +compiler.cfg.phi-elimination compiler.cfg.dce compiler.cfg.liveness +compiler.cfg assocs vectors arrays layouts namespaces ; : trim-temps ( insns -- insns ) [ @@ -943,7 +945,79 @@ cell 8 = [ } test-value-numbering ] unit-test -: test-branch-folding ( insns -- insns' ) +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##load-immediate f V int-regs 1 5 } + } +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare f V int-regs 1 V int-regs 0 V int-regs 0 cc< } + } test-value-numbering +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##load-reference f V int-regs 1 t } + } +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare f V int-regs 1 V int-regs 0 V int-regs 0 cc<= } + } test-value-numbering +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##load-immediate f V int-regs 1 5 } + } +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare f V int-regs 1 V int-regs 0 V int-regs 0 cc> } + } test-value-numbering +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##load-reference f V int-regs 1 t } + } +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare f V int-regs 1 V int-regs 0 V int-regs 0 cc>= } + } test-value-numbering +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##load-immediate f V int-regs 1 5 } + } +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare f V int-regs 1 V int-regs 0 V int-regs 0 cc/= } + } test-value-numbering +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##load-reference f V int-regs 1 t } + } +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare f V int-regs 1 V int-regs 0 V int-regs 0 cc= } + } test-value-numbering +] unit-test + +: test-branch-folding ( insns -- insns' n ) [ V{ 0 1 } clone >>successors basic-block set test-value-numbering ] keep successors>> first ; @@ -1008,3 +1082,188 @@ cell 8 = [ } test-branch-folding ] unit-test +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##branch } + } + 1 +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare-branch f V int-regs 0 V int-regs 0 cc< } + } test-branch-folding +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##branch } + } + 0 +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare-branch f V int-regs 0 V int-regs 0 cc<= } + } test-branch-folding +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##branch } + } + 1 +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare-branch f V int-regs 0 V int-regs 0 cc> } + } test-branch-folding +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##branch } + } + 0 +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare-branch f V int-regs 0 V int-regs 0 cc>= } + } test-branch-folding +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##branch } + } + 0 +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare-branch f V int-regs 0 V int-regs 0 cc= } + } test-branch-folding +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##branch } + } + 1 +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare-branch f V int-regs 0 V int-regs 0 cc/= } + } test-branch-folding +] unit-test + +[ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##load-reference f V int-regs 1 t } + T{ ##branch } + } + 0 +] [ + { + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare f V int-regs 1 V int-regs 0 V int-regs 0 cc<= } + T{ ##compare-imm-branch f V int-regs 1 5 cc/= } + } test-branch-folding +] unit-test + +! More branch folding tests +V{ T{ ##branch } } 0 test-bb + +V{ + T{ ##peek f V int-regs 0 D 0 } + T{ ##compare-branch f V int-regs 0 V int-regs 0 cc< } +} 1 test-bb + +V{ + T{ ##load-immediate f V int-regs 1 1 } + T{ ##branch } +} 2 test-bb + +V{ + T{ ##load-immediate f V int-regs 2 2 } + T{ ##branch } +} 3 test-bb + +V{ + T{ ##phi f V int-regs 3 { } } + T{ ##replace f V int-regs 3 D 0 } + T{ ##return } +} 4 test-bb + +4 get instructions>> first +2 get V int-regs 1 2array +3 get V int-regs 2 2array 2array +>>inputs drop + +test-diamond + +[ ] [ + cfg new 0 get >>entry + compute-liveness + value-numbering + compute-predecessors + eliminate-phis drop +] unit-test + +[ 1 ] [ 1 get successors>> length ] unit-test + +[ t ] [ 1 get successors>> first 3 get eq? ] unit-test + +[ T{ ##copy f V int-regs 3 V int-regs 2 } ] +[ 3 get successors>> first instructions>> first ] +unit-test + +[ 2 ] [ 4 get instructions>> length ] unit-test + +V{ + T{ ##peek f V int-regs 0 D 0 } + T{ ##branch } +} 0 test-bb + +V{ + T{ ##peek f V int-regs 1 D 1 } + T{ ##compare-branch f V int-regs 1 V int-regs 1 cc< } +} 1 test-bb + +V{ + T{ ##copy f V int-regs 2 V int-regs 0 } + T{ ##branch } +} 2 test-bb + +V{ + T{ ##phi f V int-regs 3 V{ } } + T{ ##branch } +} 3 test-bb + +V{ + T{ ##replace f V int-regs 3 D 0 } + T{ ##return } +} 4 test-bb + +1 get V int-regs 1 2array +2 get V int-regs 0 2array 2array 3 get instructions>> first (>>inputs) + +test-diamond + +[ ] [ + cfg new 0 get >>entry + compute-predecessors + compute-liveness + value-numbering + compute-predecessors + eliminate-dead-code + drop +] unit-test + +[ t ] [ 1 get successors>> first 3 get eq? ] unit-test + +[ 1 ] [ 3 get instructions>> first inputs>> assoc-size ] unit-test \ No newline at end of file diff --git a/basis/compiler/cfg/value-numbering/value-numbering.factor b/basis/compiler/cfg/value-numbering/value-numbering.factor index 9e6e058b52..202b3d1e9b 100644 --- a/basis/compiler/cfg/value-numbering/value-numbering.factor +++ b/basis/compiler/cfg/value-numbering/value-numbering.factor @@ -11,6 +11,8 @@ compiler.cfg.value-numbering.simplify compiler.cfg.value-numbering.rewrite ; IN: compiler.cfg.value-numbering +! Local value numbering. Predecessors must be recomputed after this + : number-input-values ( live-in -- ) [ [ f next-input-expr simplify ] dip set-vn ] each ; diff --git a/basis/compiler/tests/codegen.factor b/basis/compiler/tests/codegen.factor index 8f7bc077b4..9f573019c2 100644 --- a/basis/compiler/tests/codegen.factor +++ b/basis/compiler/tests/codegen.factor @@ -318,4 +318,7 @@ M: cucumber equal? "The cucumber has no equal" throw ; cell 4 = [ [ 0 ] [ 101 [ dup fixnum-fast 1 fixnum+fast 20 fixnum-shift-fast 20 fixnum-shift-fast ] compile-call ] unit-test -] when \ No newline at end of file +] when + +! Regression from Slava's value numbering changes +[ 1 ] [ 31337 [ dup fixnum<= [ 1 ] [ 2 ] if ] compile-call ] unit-test \ No newline at end of file