Improved value numbering
parent
d723b69990
commit
52967c5bf1
|
@ -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 ;
|
|
@ -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 ;
|
|
@ -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 ;
|
|
@ -60,5 +60,3 @@ M: ##dispatch propagate
|
|||
[ resolve ] change-src ;
|
||||
|
||||
M: insn propagate ;
|
||||
|
||||
M: f propagate ;
|
||||
|
|
|
@ -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 ;
|
|
@ -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 ;
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 ;
|
||||
|
|
Loading…
Reference in New Issue