compiler.cfg.representations: new pass to make global unboxing decisions, relies on new compiler.cfg.loop-detection pass for loop nesting information
parent
926c46841b
commit
e21ca289c3
|
@ -56,8 +56,6 @@ IN: compiler.cfg.hats
|
||||||
: ^^allot-tuple ( n -- dst ) 2 + cells tuple ^^allot ; inline
|
: ^^allot-tuple ( n -- dst ) 2 + cells tuple ^^allot ; inline
|
||||||
: ^^allot-array ( n -- dst ) 2 + cells array ^^allot ; inline
|
: ^^allot-array ( n -- dst ) 2 + cells array ^^allot ; inline
|
||||||
: ^^allot-byte-array ( n -- dst ) 2 cells + byte-array ^^allot ; inline
|
: ^^allot-byte-array ( n -- dst ) 2 cells + byte-array ^^allot ; inline
|
||||||
: ^^box-float ( src -- dst ) ^^i1 i ##box-float ; inline
|
|
||||||
: ^^unbox-float ( src -- dst ) ^^d1 ##unbox-float ; inline
|
|
||||||
: ^^box-alien ( src -- dst ) ^^i1 i ##box-alien ; inline
|
: ^^box-alien ( src -- dst ) ^^i1 i ##box-alien ; inline
|
||||||
: ^^unbox-alien ( src -- dst ) ^^i1 ##unbox-alien ; inline
|
: ^^unbox-alien ( src -- dst ) ^^i1 ##unbox-alien ; inline
|
||||||
: ^^unbox-c-ptr ( src class -- dst ) ^^i2 i ##unbox-c-ptr ;
|
: ^^unbox-c-ptr ( src class -- dst ) ^^i2 i ##unbox-c-ptr ;
|
||||||
|
|
|
@ -250,6 +250,34 @@ UNION: kill-vreg-insn
|
||||||
##alien-indirect
|
##alien-indirect
|
||||||
##alien-callback ;
|
##alien-callback ;
|
||||||
|
|
||||||
|
! Instructions that output floats
|
||||||
|
UNION: output-float-insn
|
||||||
|
##add-float
|
||||||
|
##sub-float
|
||||||
|
##mul-float
|
||||||
|
##div-float
|
||||||
|
##integer>float
|
||||||
|
##unbox-float
|
||||||
|
##alien-float
|
||||||
|
##alien-double ;
|
||||||
|
|
||||||
|
! Instructions that take floats as inputs
|
||||||
|
UNION: input-float-insn
|
||||||
|
##add-float
|
||||||
|
##sub-float
|
||||||
|
##mul-float
|
||||||
|
##div-float
|
||||||
|
##float>integer
|
||||||
|
##box-float
|
||||||
|
##set-alien-float
|
||||||
|
##set-alien-double
|
||||||
|
##compare-float
|
||||||
|
##compare-float-branch ;
|
||||||
|
|
||||||
|
! Smackdown
|
||||||
|
INTERSECTION: ##unary-float ##unary input-float-insn ;
|
||||||
|
INTERSECTION: ##binary-float ##binary input-float-insn ;
|
||||||
|
|
||||||
! Instructions that have complex expansions and require that the
|
! Instructions that have complex expansions and require that the
|
||||||
! output registers are not equal to any of the input registers
|
! output registers are not equal to any of the input registers
|
||||||
UNION: def-is-use-insn
|
UNION: def-is-use-insn
|
||||||
|
|
|
@ -53,7 +53,7 @@ IN: compiler.cfg.intrinsics.alien
|
||||||
inline-alien ; inline
|
inline-alien ; inline
|
||||||
|
|
||||||
: inline-alien-float-setter ( node quot -- )
|
: inline-alien-float-setter ( node quot -- )
|
||||||
'[ ds-pop ^^unbox-float @ ]
|
'[ ds-pop @ ]
|
||||||
[ float inline-alien-setter? ]
|
[ float inline-alien-setter? ]
|
||||||
inline-alien ; inline
|
inline-alien ; inline
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ IN: compiler.cfg.intrinsics.alien
|
||||||
_ {
|
_ {
|
||||||
{ single-float-rep [ ^^alien-float ] }
|
{ single-float-rep [ ^^alien-float ] }
|
||||||
{ double-float-rep [ ^^alien-double ] }
|
{ double-float-rep [ ^^alien-double ] }
|
||||||
} case ^^box-float
|
} case
|
||||||
] inline-alien-getter ;
|
] inline-alien-getter ;
|
||||||
|
|
||||||
: emit-alien-float-setter ( node rep -- )
|
: emit-alien-float-setter ( node rep -- )
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
! Copyright (C) 2008, 2009 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel compiler.cfg.stacks compiler.cfg.hats
|
USING: kernel compiler.cfg.stacks compiler.cfg.hats
|
||||||
compiler.cfg.instructions compiler.cfg.utilities ;
|
compiler.cfg.instructions compiler.cfg.utilities ;
|
||||||
IN: compiler.cfg.intrinsics.float
|
IN: compiler.cfg.intrinsics.float
|
||||||
|
|
||||||
: emit-float-op ( insn -- )
|
: emit-float-op ( insn -- )
|
||||||
[ 2inputs [ ^^unbox-float ] bi@ ] dip call ^^box-float
|
[ 2inputs ] dip call ds-push ; inline
|
||||||
ds-push ; inline
|
|
||||||
|
|
||||||
: emit-float-comparison ( cc -- )
|
: emit-float-comparison ( cc -- )
|
||||||
[ 2inputs [ ^^unbox-float ] bi@ ] dip ^^compare-float
|
[ 2inputs ] dip ^^compare-float ds-push ; inline
|
||||||
ds-push ; inline
|
|
||||||
|
|
||||||
: emit-float>fixnum ( -- )
|
: emit-float>fixnum ( -- )
|
||||||
ds-pop ^^unbox-float ^^float>integer ^^tag-fixnum ds-push ;
|
ds-pop ^^float>integer ^^tag-fixnum ds-push ;
|
||||||
|
|
||||||
: emit-fixnum>float ( -- )
|
: emit-fixnum>float ( -- )
|
||||||
ds-pop ^^untag-fixnum ^^integer>float ^^box-float ds-push ;
|
ds-pop ^^untag-fixnum ^^integer>float ds-push ;
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
IN: compiler.cfg.loop-detection.tests
|
||||||
|
USING: compiler.cfg compiler.cfg.loop-detection
|
||||||
|
compiler.cfg.predecessors
|
||||||
|
compiler.cfg.debugger
|
||||||
|
tools.test kernel namespaces accessors ;
|
||||||
|
|
||||||
|
V{ } 0 test-bb
|
||||||
|
V{ } 1 test-bb
|
||||||
|
V{ } 2 test-bb
|
||||||
|
|
||||||
|
0 { 1 2 } edges
|
||||||
|
2 0 edge
|
||||||
|
|
||||||
|
: test-loop-detection ( -- ) cfg new 0 get >>entry compute-predecessors detect-loops drop ;
|
||||||
|
|
||||||
|
[ ] [ test-loop-detection ] unit-test
|
||||||
|
|
||||||
|
[ 1 ] [ 0 get loop-nesting-at ] unit-test
|
||||||
|
[ 0 ] [ 1 get loop-nesting-at ] unit-test
|
||||||
|
[ 1 ] [ 2 get loop-nesting-at ] unit-test
|
|
@ -0,0 +1,80 @@
|
||||||
|
! Copyright (C) 2009 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors assocs combinators deques dlists fry kernel
|
||||||
|
namespaces sequences sets compiler.cfg ;
|
||||||
|
IN: compiler.cfg.loop-detection
|
||||||
|
|
||||||
|
! Loop detection -- predecessors must be computed first
|
||||||
|
|
||||||
|
TUPLE: natural-loop header index ends blocks ;
|
||||||
|
|
||||||
|
<PRIVATE
|
||||||
|
|
||||||
|
SYMBOL: loops
|
||||||
|
|
||||||
|
: <natural-loop> ( header index -- loop )
|
||||||
|
H{ } clone H{ } clone natural-loop boa ;
|
||||||
|
|
||||||
|
: lookup-header ( header -- loop )
|
||||||
|
loops get [
|
||||||
|
loops get assoc-size <natural-loop>
|
||||||
|
] cache ;
|
||||||
|
|
||||||
|
SYMBOLS: visited active ;
|
||||||
|
|
||||||
|
: record-back-edge ( from to -- )
|
||||||
|
lookup-header ends>> conjoin ;
|
||||||
|
|
||||||
|
DEFER: find-loop-headers
|
||||||
|
|
||||||
|
: visit-edge ( from to -- )
|
||||||
|
dup active get key?
|
||||||
|
[ record-back-edge ]
|
||||||
|
[ nip find-loop-headers ]
|
||||||
|
if ;
|
||||||
|
|
||||||
|
: find-loop-headers ( bb -- )
|
||||||
|
dup visited get key? [ drop ] [
|
||||||
|
{
|
||||||
|
[ visited get conjoin ]
|
||||||
|
[ active get conjoin ]
|
||||||
|
[ dup successors>> [ visit-edge ] with each ]
|
||||||
|
[ active get delete-at ]
|
||||||
|
} cleave
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
SYMBOL: work-list
|
||||||
|
|
||||||
|
: process-loop-block ( bb loop -- )
|
||||||
|
2dup blocks>> key? [ 2drop ] [
|
||||||
|
[ blocks>> conjoin ] [
|
||||||
|
2dup header>> eq? [ 2drop ] [
|
||||||
|
drop predecessors>> work-list get push-all-front
|
||||||
|
] if
|
||||||
|
] 2bi
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: process-loop-ends ( loop -- )
|
||||||
|
[ ends>> keys <dlist> [ push-all-front ] [ work-list set ] [ ] tri ] keep
|
||||||
|
'[ _ process-loop-block ] slurp-deque ;
|
||||||
|
|
||||||
|
: process-loop-headers ( -- )
|
||||||
|
loops get values [ process-loop-ends ] each ;
|
||||||
|
|
||||||
|
SYMBOL: loop-nesting
|
||||||
|
|
||||||
|
: compute-loop-nesting ( -- )
|
||||||
|
loops get H{ } clone [
|
||||||
|
[ values ] dip '[ blocks>> values [ _ inc-at ] each ] each
|
||||||
|
] keep loop-nesting set ;
|
||||||
|
|
||||||
|
PRIVATE>
|
||||||
|
|
||||||
|
: loop-nesting-at ( bb -- n ) loop-nesting get at 0 or ;
|
||||||
|
|
||||||
|
: detect-loops ( cfg -- cfg' )
|
||||||
|
H{ } clone loops set
|
||||||
|
H{ } clone visited set
|
||||||
|
H{ } clone active set
|
||||||
|
H{ } clone loop-nesting set
|
||||||
|
dup entry>> find-loop-headers process-loop-headers compute-loop-nesting ;
|
|
@ -12,6 +12,8 @@ compiler.cfg.value-numbering
|
||||||
compiler.cfg.copy-prop
|
compiler.cfg.copy-prop
|
||||||
compiler.cfg.dce
|
compiler.cfg.dce
|
||||||
compiler.cfg.write-barrier
|
compiler.cfg.write-barrier
|
||||||
|
compiler.cfg.representations
|
||||||
|
compiler.cfg.loop-detection
|
||||||
compiler.cfg.two-operand
|
compiler.cfg.two-operand
|
||||||
compiler.cfg.ssa.destruction
|
compiler.cfg.ssa.destruction
|
||||||
compiler.cfg.empty-blocks
|
compiler.cfg.empty-blocks
|
||||||
|
@ -44,6 +46,8 @@ SYMBOL: check-optimizer?
|
||||||
copy-propagation
|
copy-propagation
|
||||||
eliminate-dead-code
|
eliminate-dead-code
|
||||||
eliminate-write-barriers
|
eliminate-write-barriers
|
||||||
|
detect-loops
|
||||||
|
select-representations
|
||||||
convert-two-operand
|
convert-two-operand
|
||||||
destruct-ssa
|
destruct-ssa
|
||||||
delete-empty-blocks
|
delete-empty-blocks
|
||||||
|
|
|
@ -4,7 +4,7 @@ USING: accessors namespaces kernel arrays parser math math.order ;
|
||||||
IN: compiler.cfg.registers
|
IN: compiler.cfg.registers
|
||||||
|
|
||||||
! Virtual registers, used by CFG and machine IRs
|
! Virtual registers, used by CFG and machine IRs
|
||||||
TUPLE: vreg { rep read-only } { n fixnum read-only } ;
|
TUPLE: vreg rep { n fixnum read-only } ;
|
||||||
|
|
||||||
M: vreg equal? over vreg? [ [ n>> ] bi@ eq? ] [ 2drop f ] if ;
|
M: vreg equal? over vreg? [ [ n>> ] bi@ eq? ] [ 2drop f ] if ;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
! Copyright (C) 2009 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: kernel accessors sequences arrays fry namespaces
|
||||||
|
cpu.architecture compiler.cfg compiler.cfg.rpo
|
||||||
|
compiler.cfg.instructions compiler.cfg.def-use ;
|
||||||
|
IN: compiler.cfg.representations.preferred
|
||||||
|
|
||||||
|
GENERIC: defs-vreg-rep ( insn -- rep/f )
|
||||||
|
GENERIC: temp-vreg-reps ( insn -- reps )
|
||||||
|
GENERIC: uses-vreg-reps ( insn -- reps )
|
||||||
|
|
||||||
|
M: ##flushable defs-vreg-rep drop int-rep ;
|
||||||
|
M: ##copy defs-vreg-rep rep>> ;
|
||||||
|
M: output-float-insn defs-vreg-rep drop double-float-rep ;
|
||||||
|
M: ##fixnum-overflow defs-vreg-rep drop int-rep ;
|
||||||
|
M: _fixnum-overflow defs-vreg-rep drop int-rep ;
|
||||||
|
M: ##phi defs-vreg-rep drop "##phi must be special-cased" throw ;
|
||||||
|
M: insn defs-vreg-rep drop f ;
|
||||||
|
|
||||||
|
M: ##write-barrier temp-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: ##unary/temp temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##allot temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##dispatch temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##slot temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##set-slot temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##string-nth temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##set-string-nth-fast temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##compare temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##compare-imm temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##compare-float temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##gc temp-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: _dispatch temp-vreg-reps drop { int-rep } ;
|
||||||
|
M: insn temp-vreg-reps drop f ;
|
||||||
|
|
||||||
|
M: ##copy uses-vreg-reps rep>> 1array ;
|
||||||
|
M: ##unary uses-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##unary-float uses-vreg-reps drop { double-float-rep } ;
|
||||||
|
M: ##binary uses-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: ##binary-imm uses-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##binary-float uses-vreg-reps drop { double-float-rep double-float-rep } ;
|
||||||
|
M: ##effect uses-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##slot uses-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: ##slot-imm uses-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##set-slot uses-vreg-reps drop { int-rep int-rep int-rep } ;
|
||||||
|
M: ##set-slot-imm uses-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: ##string-nth uses-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: ##set-string-nth-fast uses-vreg-reps drop { int-rep int-rep int-rep } ;
|
||||||
|
M: ##compare-branch uses-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: ##compare-imm-branch uses-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##compare-float-branch uses-vreg-reps drop { double-float-rep double-float-rep } ;
|
||||||
|
M: ##dispatch uses-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##alien-getter uses-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##alien-setter uses-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: ##set-alien-float uses-vreg-reps drop { int-rep double-float-rep } ;
|
||||||
|
M: ##set-alien-double uses-vreg-reps drop { int-rep double-float-rep } ;
|
||||||
|
M: ##fixnum-overflow uses-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: _compare-imm-branch uses-vreg-reps drop { int-rep } ;
|
||||||
|
M: _compare-branch uses-vreg-reps drop { int-rep int-rep } ;
|
||||||
|
M: _compare-float-branch uses-vreg-reps drop { double-float-rep double-float-rep } ;
|
||||||
|
M: _dispatch uses-vreg-reps drop { int-rep } ;
|
||||||
|
M: ##phi uses-vreg-reps drop "##phi must be special-cased" throw ;
|
||||||
|
M: insn uses-vreg-reps drop f ;
|
||||||
|
|
||||||
|
: each-def-rep ( insn vreg-quot: ( vreg rep -- ) -- )
|
||||||
|
[ [ defs-vreg ] [ defs-vreg-rep ] bi ] dip with when* ; inline
|
||||||
|
|
||||||
|
: each-use-rep ( insn vreg-quot: ( vreg rep -- ) -- )
|
||||||
|
[ [ uses-vregs ] [ uses-vreg-reps ] bi ] dip 2each ; inline
|
||||||
|
|
||||||
|
: each-temp-rep ( insn vreg-quot: ( vreg rep -- ) -- )
|
||||||
|
[ [ temp-vregs ] [ temp-vreg-reps ] bi ] dip 2each ; inline
|
||||||
|
|
||||||
|
: with-vreg-reps ( cfg vreg-quot: ( vreg rep -- ) -- )
|
||||||
|
'[
|
||||||
|
[ basic-block set ] [
|
||||||
|
instructions>> [
|
||||||
|
dup ##phi? [ drop ] [
|
||||||
|
_ [ each-def-rep ] [ each-use-rep ] [ each-temp-rep ] 2tri
|
||||||
|
] if
|
||||||
|
] each
|
||||||
|
] bi
|
||||||
|
] each-basic-block ; inline
|
|
@ -0,0 +1,19 @@
|
||||||
|
USING: tools.test cpu.architecture
|
||||||
|
compiler.cfg.registers compiler.cfg.instructions
|
||||||
|
compiler.cfg.representations.preferred ;
|
||||||
|
IN: compiler.cfg.representations
|
||||||
|
|
||||||
|
[ { double-float-rep double-float-rep } ] [
|
||||||
|
T{ ##add-float
|
||||||
|
{ dst V double-float-rep 5 }
|
||||||
|
{ src1 V double-float-rep 3 }
|
||||||
|
{ src2 V double-float-rep 4 }
|
||||||
|
} uses-vreg-reps
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ double-float-rep ] [
|
||||||
|
T{ ##alien-double
|
||||||
|
{ dst V double-float-rep 5 }
|
||||||
|
{ src V int-rep 3 }
|
||||||
|
} defs-vreg-rep
|
||||||
|
] unit-test
|
|
@ -0,0 +1,157 @@
|
||||||
|
! Copyright (C) 2009 Slava Pestov
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: kernel fry accessors sequences assocs sets namespaces
|
||||||
|
arrays combinators make locals cpu.architecture compiler.utilities
|
||||||
|
compiler.cfg
|
||||||
|
compiler.cfg.rpo
|
||||||
|
compiler.cfg.hats
|
||||||
|
compiler.cfg.registers
|
||||||
|
compiler.cfg.instructions
|
||||||
|
compiler.cfg.def-use
|
||||||
|
compiler.cfg.utilities
|
||||||
|
compiler.cfg.loop-detection
|
||||||
|
compiler.cfg.renaming.functor
|
||||||
|
compiler.cfg.representations.preferred ;
|
||||||
|
IN: compiler.cfg.representations
|
||||||
|
|
||||||
|
! Virtual register representation selection.
|
||||||
|
! Still needs a loop nesting heuristic
|
||||||
|
|
||||||
|
! For every vreg, compute possible representations.
|
||||||
|
SYMBOL: possibilities
|
||||||
|
|
||||||
|
: possible ( vreg -- reps ) possibilities get at ;
|
||||||
|
|
||||||
|
: compute-possibilities ( cfg -- )
|
||||||
|
H{ } clone [ '[ swap _ conjoin-at ] with-vreg-reps ] keep
|
||||||
|
[ keys ] assoc-map possibilities set ;
|
||||||
|
|
||||||
|
! For every vreg, compute the cost of keeping it in every possible
|
||||||
|
! representation.
|
||||||
|
|
||||||
|
! Cost map maps vreg to representation to cost.
|
||||||
|
SYMBOL: costs
|
||||||
|
|
||||||
|
: init-costs ( -- )
|
||||||
|
possibilities get [ [ 0 ] H{ } map>assoc ] assoc-map costs set ;
|
||||||
|
|
||||||
|
: increase-cost ( rep vreg -- )
|
||||||
|
! Increase cost of keeping vreg in rep, making a choice of rep less
|
||||||
|
! likely.
|
||||||
|
[ basic-block get loop-nesting-at ] 2dip costs get at at+ ;
|
||||||
|
|
||||||
|
: maybe-increase-cost ( possible vreg preferred -- )
|
||||||
|
pick eq? [ 2drop ] [ increase-cost ] if ;
|
||||||
|
|
||||||
|
: representation-cost ( vreg preferred -- )
|
||||||
|
! 'preferred' is a representation that the instruction can accept with no cost.
|
||||||
|
! So, for each representation that's not preferred, increase the cost of keeping
|
||||||
|
! the vreg in that representation.
|
||||||
|
[ drop possible ]
|
||||||
|
[ '[ _ _ maybe-increase-cost ] ]
|
||||||
|
2bi each ;
|
||||||
|
|
||||||
|
! For every vreg, compute preferred representation, that minimizes costs.
|
||||||
|
SYMBOL: preferred
|
||||||
|
|
||||||
|
: minimize-costs ( -- )
|
||||||
|
costs get [ >alist alist-min first ] assoc-map preferred set ;
|
||||||
|
|
||||||
|
: compute-costs ( cfg -- )
|
||||||
|
init-costs
|
||||||
|
[ representation-cost ] with-vreg-reps
|
||||||
|
minimize-costs ;
|
||||||
|
|
||||||
|
! Insert conversions. This introduces new temporaries, so we need
|
||||||
|
! to rename opearands too.
|
||||||
|
|
||||||
|
: emit-conversion ( dst src dst-rep src-rep -- )
|
||||||
|
2array {
|
||||||
|
{ { int-rep int-rep } [ int-rep ##copy ] }
|
||||||
|
{ { double-float-rep double-float-rep } [ double-float-rep ##copy ] }
|
||||||
|
{ { double-float-rep int-rep } [ ##unbox-float ] }
|
||||||
|
{ { int-rep double-float-rep } [ i ##box-float ] }
|
||||||
|
} case ;
|
||||||
|
|
||||||
|
:: emit-def-conversion ( dst preferred required -- new-dst' )
|
||||||
|
! If an instruction defines a register with representation 'required',
|
||||||
|
! but the register has preferred representation 'preferred', then
|
||||||
|
! we rename the instruction's definition to a new register, which
|
||||||
|
! becomes the input of a conversion instruction.
|
||||||
|
dst required next-vreg [ preferred required emit-conversion ] keep ;
|
||||||
|
|
||||||
|
:: emit-use-conversion ( src preferred required -- new-src' )
|
||||||
|
! If an instruction uses a register with representation 'required',
|
||||||
|
! but the register has preferred representation 'preferred', then
|
||||||
|
! we rename the instruction's input to a new register, which
|
||||||
|
! becomes the output of a conversion instruction.
|
||||||
|
required next-vreg [ src required preferred emit-conversion ] keep ;
|
||||||
|
|
||||||
|
SYMBOLS: renaming-set needs-renaming? ;
|
||||||
|
|
||||||
|
: init-renaming-set ( -- )
|
||||||
|
needs-renaming? off
|
||||||
|
V{ } clone renaming-set set ;
|
||||||
|
|
||||||
|
: no-renaming ( vreg -- )
|
||||||
|
dup 2array renaming-set get push ;
|
||||||
|
|
||||||
|
: record-renaming ( from to -- )
|
||||||
|
2array renaming-set get push needs-renaming? on ;
|
||||||
|
|
||||||
|
:: (compute-renaming-set) ( vreg required quot: ( vreg preferred required -- ) -- )
|
||||||
|
vreg preferred get at :> preferred
|
||||||
|
preferred required eq?
|
||||||
|
[ vreg no-renaming ]
|
||||||
|
[ vreg vreg preferred required quot call record-renaming ] if ; inline
|
||||||
|
|
||||||
|
: compute-renaming-set ( insn -- )
|
||||||
|
! temp vregs don't need conversions since they're always in their
|
||||||
|
! preferred representation
|
||||||
|
init-renaming-set
|
||||||
|
[ [ [ emit-use-conversion ] (compute-renaming-set) ] each-use-rep ]
|
||||||
|
[ , ]
|
||||||
|
[ [ [ emit-def-conversion ] (compute-renaming-set) ] each-def-rep ]
|
||||||
|
tri ;
|
||||||
|
|
||||||
|
: converted-value ( vreg -- vreg' )
|
||||||
|
renaming-set get pop first2 [ assert= ] dip ;
|
||||||
|
|
||||||
|
RENAMING: convert [ converted-value ] [ converted-value ] [ ]
|
||||||
|
|
||||||
|
: perform-renaming ( insn -- )
|
||||||
|
needs-renaming? get [
|
||||||
|
renaming-set get reverse-here
|
||||||
|
[ convert-insn-uses ] [ convert-insn-defs ] bi
|
||||||
|
renaming-set get length 0 assert=
|
||||||
|
] [ drop ] if ;
|
||||||
|
|
||||||
|
GENERIC: conversions-for-insn ( insn -- )
|
||||||
|
|
||||||
|
! Inserting conversions for a phi is done in compiler.cfg.cssa
|
||||||
|
M: ##phi conversions-for-insn , ;
|
||||||
|
|
||||||
|
M: vreg-insn conversions-for-insn
|
||||||
|
[ compute-renaming-set ] [ perform-renaming ] bi ;
|
||||||
|
|
||||||
|
M: insn conversions-for-insn , ;
|
||||||
|
|
||||||
|
: conversions-for-block ( bb -- )
|
||||||
|
dup kill-block? [ drop ] [
|
||||||
|
[
|
||||||
|
[
|
||||||
|
[ conversions-for-insn ] each
|
||||||
|
] V{ } make
|
||||||
|
] change-instructions drop
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: insert-conversions ( cfg -- )
|
||||||
|
[ conversions-for-block ] each-basic-block ;
|
||||||
|
|
||||||
|
: select-representations ( cfg -- cfg' )
|
||||||
|
{
|
||||||
|
[ compute-possibilities ]
|
||||||
|
[ compute-costs ]
|
||||||
|
[ insert-conversions ]
|
||||||
|
[ preferred get [ >>rep drop ] assoc-each ]
|
||||||
|
} cleave ;
|
|
@ -1,22 +1,23 @@
|
||||||
! Copyright (C) 2009 Slava Pestov.
|
! Copyright (C) 2009 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: accessors assocs kernel locals
|
USING: accessors assocs kernel locals fry
|
||||||
cpu.architecture
|
cpu.architecture
|
||||||
compiler.cfg.rpo
|
compiler.cfg.rpo
|
||||||
compiler.cfg.hats
|
|
||||||
compiler.cfg.utilities
|
compiler.cfg.utilities
|
||||||
compiler.cfg.instructions ;
|
compiler.cfg.registers
|
||||||
|
compiler.cfg.instructions
|
||||||
|
compiler.cfg.representations ;
|
||||||
IN: compiler.cfg.ssa.cssa
|
IN: compiler.cfg.ssa.cssa
|
||||||
|
|
||||||
! Convert SSA to conventional SSA.
|
! Convert SSA to conventional SSA.
|
||||||
|
|
||||||
:: insert-copy ( bb src -- bb dst )
|
:: insert-copy ( bb src rep -- bb dst )
|
||||||
i :> dst
|
rep next-vreg :> dst
|
||||||
bb [ dst src int-rep ##copy ] add-instructions
|
bb [ dst src rep src rep>> emit-conversion ] add-instructions
|
||||||
bb dst ;
|
bb dst ;
|
||||||
|
|
||||||
: convert-phi ( ##phi -- )
|
: convert-phi ( ##phi -- )
|
||||||
[ [ insert-copy ] assoc-map ] change-inputs drop ;
|
dup dst>> rep>> '[ [ _ insert-copy ] assoc-map ] change-inputs drop ;
|
||||||
|
|
||||||
: construct-cssa ( cfg -- )
|
: construct-cssa ( cfg -- )
|
||||||
[ [ convert-phi ] each-phi ] each-basic-block ;
|
[ [ convert-phi ] each-phi ] each-basic-block ;
|
|
@ -49,7 +49,10 @@ SYMBOL: copies
|
||||||
: eliminate-copy ( vreg1 vreg2 -- )
|
: eliminate-copy ( vreg1 vreg2 -- )
|
||||||
[ leader ] bi@
|
[ leader ] bi@
|
||||||
2dup eq? [ 2drop ] [
|
2dup eq? [ 2drop ] [
|
||||||
[ update-leaders ] [ merge-classes ] 2bi
|
[ [ rep>> ] bi@ assert= ]
|
||||||
|
[ update-leaders ]
|
||||||
|
[ merge-classes ]
|
||||||
|
2tri
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
: introduce-vreg ( vreg -- )
|
: introduce-vreg ( vreg -- )
|
||||||
|
|
|
@ -9,21 +9,14 @@ IN: compiler.cfg.value-numbering.simplify
|
||||||
! Return value of f means we didn't simplify.
|
! Return value of f means we didn't simplify.
|
||||||
GENERIC: simplify* ( expr -- vn/expr/f )
|
GENERIC: simplify* ( expr -- vn/expr/f )
|
||||||
|
|
||||||
: simplify-unbox ( in boxer -- vn/expr/f )
|
|
||||||
over op>> eq? [ in>> ] [ drop f ] if ; inline
|
|
||||||
|
|
||||||
: simplify-unbox-float ( in -- vn/expr/f )
|
|
||||||
\ ##box-float simplify-unbox ; inline
|
|
||||||
|
|
||||||
: simplify-unbox-alien ( in -- vn/expr/f )
|
: simplify-unbox-alien ( in -- vn/expr/f )
|
||||||
\ ##box-alien simplify-unbox ; inline
|
dup op>> \ ##box-alien eq? [ in>> ] [ drop f ] if ; inline
|
||||||
|
|
||||||
M: unary-expr simplify*
|
M: unary-expr simplify*
|
||||||
#! Note the copy propagation: a copy always simplifies to
|
#! Note the copy propagation: a copy always simplifies to
|
||||||
#! its source VN.
|
#! its source VN.
|
||||||
[ in>> vn>expr ] [ op>> ] bi {
|
[ in>> vn>expr ] [ op>> ] bi {
|
||||||
{ \ ##copy [ ] }
|
{ \ ##copy [ ] }
|
||||||
{ \ ##unbox-float [ simplify-unbox-float ] }
|
|
||||||
{ \ ##unbox-alien [ simplify-unbox-alien ] }
|
{ \ ##unbox-alien [ simplify-unbox-alien ] }
|
||||||
{ \ ##unbox-any-c-ptr [ simplify-unbox-alien ] }
|
{ \ ##unbox-any-c-ptr [ simplify-unbox-alien ] }
|
||||||
[ 2drop f ]
|
[ 2drop f ]
|
||||||
|
|
|
@ -26,8 +26,12 @@ SYMBOL: yield-hook
|
||||||
|
|
||||||
yield-hook [ [ ] ] initialize
|
yield-hook [ [ ] ] initialize
|
||||||
|
|
||||||
: alist-max ( alist -- pair )
|
: alist-most ( alist quot -- pair )
|
||||||
[ ] [ [ [ second ] bi@ > ] most ] map-reduce ;
|
[ [ ] ] dip '[ [ [ second ] bi@ @ ] most ] map-reduce ; inline
|
||||||
|
|
||||||
|
: alist-min ( alist -- pair ) [ before? ] alist-most ;
|
||||||
|
|
||||||
|
: alist-max ( alist -- pair ) [ after? ] alist-most ;
|
||||||
|
|
||||||
: penultimate ( seq -- elt ) [ length 2 - ] keep nth ;
|
: penultimate ( seq -- elt ) [ length 2 - ] keep nth ;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue