Improved value numbering

db4
Slava Pestov 2008-10-23 02:49:26 -05:00
parent d723b69990
commit 52967c5bf1
8 changed files with 66 additions and 253 deletions

View File

@ -1,48 +0,0 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences layouts accessors combinators
compiler.cfg.instructions
compiler.cfg.value-numbering.graph
compiler.cfg.value-numbering.expressions
compiler.cfg.value-numbering.liveness
compiler.cfg.value-numbering ;
IN: compiler.cfg.value-numbering.conditions
! The CFG builder produces naive code for the following code
! sequence:
!
! fixnum< [ ... ] [ ... ] if
!
! The fixnum< comparison generates a boolean, which is then
! tested against f.
!
! Using value numbering, we optimize the comparison of a boolean
! against f where the boolean is the result of comparison.
: ##branch-t? ( insn -- ? )
[ cc>> cc/= eq? ] [ src2>> \ f tag-number eq? ] bi and ; inline
: of-boolean? ( insn -- expr/f ? )
src1>> vreg>expr dup compare-expr? ; inline
: eliminate-boolean ( insn -- expr/f )
dup ##branch-t? [
of-boolean? [ drop f ] unless
] [ drop f ] if ; inline
M: ##compare-imm-branch number-values
dup eliminate-boolean [
[ in1>> live-vn ] [ in2>> live-vn ] bi
] [ call-next-method ] ?if ;
: >compare-expr< [ in1>> vn>vreg ] [ in2>> vn>vreg ] [ cc>> ] tri ; inline
: >compare-imm-expr< [ in1>> vn>vreg ] [ in2>> vn>constant ] [ cc>> ] tri ; inline
M: ##compare-imm-branch eliminate
dup eliminate-boolean [
dup op>> {
{ \ ##compare [ >compare-expr< f \ ##compare-branch boa ] }
{ \ ##compare-imm [ >compare-imm-expr< f \ ##compare-imm-branch boa ] }
{ \ ##compare-float [ >compare-expr< f \ ##compare-float-branch boa ] }
} case
] [ call-next-method ] ?if ;

View File

@ -1,18 +0,0 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel
compiler.cfg.value-numbering.graph
compiler.cfg.value-numbering.expressions ;
IN: compiler.cfg.value-numbering.constant-fold
GENERIC: constant-fold ( insn -- insn' )
M: vop constant-fold ;
: expr>insn ( out constant-expr -- constant-op )
[ value>> ] [ op>> ] bi new swap >>value swap >>out ;
M: pure-op constant-fold
dup out>>
dup vreg>expr
dup constant-expr? [ expr>insn nip ] [ 2drop ] if ;

View File

@ -1,39 +0,0 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces kernel assocs sets accessors
compiler.cfg.instructions
compiler.cfg.instructions.syntax
compiler.cfg.value-numbering.graph
compiler.cfg.value-numbering.expressions ;
IN: compiler.cfg.value-numbering.liveness
! A set of VNs which are (transitively) used by effect-ops. This
! is precisely the set of VNs whose value is needed outside of
! the basic block.
SYMBOL: live-vns
GENERIC: live-expr ( expr -- )
: live-vn ( vn -- )
#! Mark a VN and all VNs used in its computation as live.
dup live-vns get key? [ drop ] [
[ live-vns get conjoin ] [ vn>expr live-expr ] bi
] if ;
: live-vreg ( vreg -- ) vreg>vn live-vn ;
M: expr live-expr drop ;
M: unary-expr live-expr in>> live-vn ;
M: binary-expr live-expr [ in1>> live-vn ] [ in2>> live-vn ] bi ;
: live? ( vreg -- ? )
dup vreg>vn tuck vn>vreg =
[ live-vns get key? ] [ drop f ] if ;
: init-liveness ( -- )
H{ } clone live-vns set ;
GENERIC: eliminate ( insn -- insn' )
M: ##flushable eliminate dup dst>> live? [ drop f ] unless ;
M: insn eliminate ;

View File

@ -60,5 +60,3 @@ M: ##dispatch propagate
[ resolve ] change-src ;
M: insn propagate ;
M: f propagate ;

View File

@ -0,0 +1,55 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences layouts accessors combinators namespaces
math
compiler.cfg.instructions
compiler.cfg.instructions.syntax
compiler.cfg.value-numbering.graph
compiler.cfg.value-numbering.expressions ;
IN: compiler.cfg.value-numbering.rewrite
GENERIC: rewrite ( insn -- insn' )
: ##branch-t? ( insn -- ? )
[ cc>> cc/= eq? ] [ src2>> \ f tag-number eq? ] bi and ; inline
: rewrite-boolean-comparison? ( insn -- ? )
dup ##branch-t? [
src1>> vreg>expr compare-expr?
] [ drop f ] if ; inline
: >compare-expr< ( expr -- in1 in2 cc )
[ in1>> vn>vreg ] [ in2>> vn>vreg ] [ cc>> ] tri ; inline
: >compare-imm-expr< ( expr -- in1 in2 cc )
[ in1>> vn>vreg ] [ in2>> vn>constant ] [ cc>> ] tri ; inline
: rewrite-boolean-comparison ( expr -- insn )
src1>> vreg>expr dup op>> {
{ \ ##compare [ >compare-expr< f \ ##compare-branch boa ] }
{ \ ##compare-imm [ >compare-imm-expr< f \ ##compare-imm-branch boa ] }
{ \ ##compare-float [ >compare-expr< f \ ##compare-float-branch boa ] }
} case ;
: tag-fixnum-expr? ( expr -- ? )
dup op>> \ ##shl-imm eq?
[ in2>> vn>expr value>> tag-bits get = ] [ drop f ] if ;
: rewrite-tagged-comparison? ( insn -- ? )
#! Are we comparing two tagged fixnums? Then untag them.
[ src1>> vreg>expr tag-fixnum-expr? ]
[ src2>> tag-mask get bitand 0 = ]
bi and ; inline
: rewrite-tagged-comparison ( insn -- insn' )
[ src1>> vreg>expr in1>> vn>vreg ]
[ src2>> tag-bits get neg shift ]
[ cc>> ]
tri
f \ ##compare-imm-branch boa ;
M: ##compare-imm-branch rewrite
dup rewrite-boolean-comparison? [ rewrite-boolean-comparison ] when
dup rewrite-tagged-comparison? [ rewrite-tagged-comparison ] when ;
M: insn rewrite ;

View File

@ -10,13 +10,6 @@ IN: compiler.cfg.value-numbering.simplify
! Return value of f means we didn't simplify.
GENERIC: simplify* ( expr -- vn/expr/f )
: simplify-not ( in -- vn/expr/f )
{
{ [ dup constant-expr? ] [ value>> bitnot <constant> ] }
{ [ dup op>> \ ##not = ] [ in>> ] }
[ drop f ]
} cond ;
: simplify-box-float ( in -- vn/expr/f )
dup op>> \ ##unbox-float = [ in>> ] [ drop f ] if ;
@ -29,127 +22,11 @@ M: unary-expr simplify*
[ in>> vn>expr ] [ op>> ] bi {
{ \ ##copy [ ] }
{ \ ##copy-float [ ] }
{ \ ##not [ simplify-not ] }
{ \ ##box-float [ simplify-box-float ] }
{ \ ##unbox-float [ simplify-unbox-float ] }
[ 2drop f ]
} case ;
! : expr-zero? ( expr -- ? ) T{ constant-expr f f 0 } = ; inline
!
! : expr-one? ( expr -- ? ) T{ constant-expr f f 1 } = ; inline
!
! : expr-neg-one? ( expr -- ? ) T{ constant-expr f f -1 } = ; inline
!
! : identity ( in1 in2 val -- expr ) 2nip <constant> ; inline
!
! : constant-fold? ( in1 in2 -- ? )
! [ constant-expr? ] both? ;
!
! : constant-fold ( in1 in2 quot -- expr )
! 2over constant-fold? [
! [ [ value>> ] bi@ ] dip call <constant>
! ] [ 3drop f ] if ; inline
!
! : simplify-add ( in1 in2 -- vn/expr/f )
! {
! { [ over expr-zero? ] [ nip ] }
! { [ dup expr-zero? ] [ drop ] }
! [ [ + ] constant-fold ]
! } cond ;
!
! : simplify-mul ( in1 in2 -- vn/expr/f )
! {
! { [ over expr-one? ] [ nip ] }
! { [ dup expr-one? ] [ drop ] }
! [ [ * ] constant-fold ]
! } cond ;
!
! : simplify-and ( in1 in2 -- vn/expr/f )
! {
! { [ dup expr-zero? ] [ 0 identity ] }
! { [ dup expr-neg-one? ] [ drop ] }
! { [ 2dup = ] [ drop ] }
! [ [ bitand ] constant-fold ]
! } cond ;
!
! : simplify-or ( in1 in2 -- vn/expr/f )
! {
! { [ dup expr-zero? ] [ drop ] }
! { [ dup expr-neg-one? ] [ -1 identity ] }
! { [ 2dup = ] [ drop ] }
! [ [ bitor ] constant-fold ]
! } cond ;
!
! : simplify-xor ( in1 in2 -- vn/expr/f )
! {
! { [ dup expr-zero? ] [ drop ] }
! [ [ bitxor ] constant-fold ]
! } cond ;
!
! : commutative-operands ( expr -- in1 in2 )
! [ in1>> vn>expr ] [ in2>> vn>expr ] bi
! over constant-expr? [ swap ] when ;
!
! M: commutative-expr simplify*
! [ commutative-operands ] [ op>> ] bi {
! { ##add [ simplify-add ] }
! { ##mul [ simplify-mul ] }
! { ##and [ simplify-and ] }
! { ##or [ simplify-or ] }
! { ##xor [ simplify-xor ] }
! [ 3drop f ]
! } case ;
!
! : simplify-sub ( in1 in2 -- vn/expr/f )
! {
! { [ dup expr-zero? ] [ drop ] }
! { [ 2dup = ] [ 0 identity ] }
! [ [ - ] constant-fold ]
! } cond ;
!
! : simplify-shl ( in1 in2 -- vn/expr/f )
! {
! { [ dup expr-zero? ] [ drop ] }
! { [ over expr-zero? ] [ drop ] }
! [ [ shift ] constant-fold ]
! } cond ;
!
! : unsigned ( n -- n' )
! cell-bits 2^ 1- bitand ;
!
! : useless-shift? ( in1 in2 -- ? )
! over op>> ##shl = [ [ in2>> ] [ expr>vn ] bi* = ] [ 2drop f ] if ;
!
! : simplify-shr ( in1 in2 -- vn/expr/f )
! {
! { [ dup expr-zero? ] [ drop ] }
! { [ over expr-zero? ] [ drop ] }
! { [ 2dup useless-shift? ] [ drop in1>> ] }
! [ [ neg shift unsigned ] constant-fold ]
! } cond ;
!
! : simplify-sar ( in1 in2 -- vn/expr/f )
! {
! { [ dup expr-zero? ] [ drop ] }
! { [ over expr-zero? ] [ drop ] }
! { [ 2dup useless-shift? ] [ drop in1>> ] }
! [ [ neg shift ] constant-fold ]
! } cond ;
!
! : simplify-compare ( in1 in2 -- vn/expr/f )
! = [ +eq+ %cconst constant ] [ f ] if ;
!
! M: binary-expr simplify*
! [ in1>> vn>expr ] [ in2>> vn>expr ] [ op>> ] tri {
! { ##sub [ simplify-isub ] }
! { ##shl [ simplify-shl ] }
! { ##shr [ simplify-shr ] }
! { ##sar [ simplify-sar ] }
! { ##compare [ simplify-compare ] }
! [ 3drop f ]
! } case ;
M: expr simplify* drop f ;
: simplify ( expr -- vn )
@ -158,3 +35,8 @@ M: expr simplify* drop f ;
{ [ dup expr? ] [ expr>vn nip ] }
{ [ dup integer? ] [ nip ] }
} cond ;
GENERIC: number-values ( insn -- )
M: ##flushable number-values [ >expr simplify ] [ dst>> ] bi set-vn ;
M: insn number-values drop ;

View File

@ -4,6 +4,7 @@ compiler.cfg.registers cpu.architecture tools.test kernel ;
[
{
T{ ##peek f V int-regs 45 D 1 }
T{ ##copy f V int-regs 48 V int-regs 45 }
T{ ##compare-imm-branch f V int-regs 45 7 cc/= }
}
] [
@ -16,6 +17,7 @@ compiler.cfg.registers cpu.architecture tools.test kernel ;
[
{
T{ ##load-immediate f V int-regs 2 8 }
T{ ##peek f V int-regs 3 D 0 }
T{ ##slot-imm f V int-regs 4 V int-regs 3 1 3 }
T{ ##replace f V int-regs 4 D 0 }

View File

@ -2,33 +2,14 @@
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces assocs biassocs classes kernel math accessors
sorting sets sequences
compiler.cfg.def-use
compiler.cfg.instructions
compiler.cfg.instructions.syntax
compiler.cfg.value-numbering.graph
compiler.cfg.value-numbering.expressions
compiler.cfg.value-numbering.liveness
compiler.cfg.value-numbering.propagate
compiler.cfg.value-numbering.simplify ;
compiler.cfg.value-numbering.simplify
compiler.cfg.value-numbering.rewrite ;
IN: compiler.cfg.value-numbering
: insn>vn ( insn -- vn ) >expr simplify ; inline
GENERIC: number-values ( insn -- )
M: ##flushable number-values
dup ##pure? [ dup call-next-method ] unless
[ insn>vn ] [ dst>> ] bi set-vn ;
M: insn number-values uses-vregs [ live-vreg ] each ;
: init-value-numbering ( -- )
: value-numbering ( insns -- insns' )
init-value-graph
init-expressions
init-liveness ;
: value-numbering ( insns -- insns' )
init-value-numbering
[ [ number-values ] each ]
[ [ eliminate propagate ] map sift ]
bi ;
[ [ number-values ] [ rewrite propagate ] bi ] map ;