compiler: combine ##load-constant followed by ##alien-double into a ##load-double on x86-32, saving an integer register
parent
8f0739197e
commit
2517b2fc2b
|
@ -57,7 +57,7 @@ gc
|
||||||
|
|
||||||
curry compose uncurry
|
curry compose uncurry
|
||||||
|
|
||||||
array-nth set-array-nth length>>
|
array-nth set-array-nth
|
||||||
|
|
||||||
wrap probe
|
wrap probe
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,10 @@ INSN: ##load-constant
|
||||||
def: dst/int-rep
|
def: dst/int-rep
|
||||||
constant: obj ;
|
constant: obj ;
|
||||||
|
|
||||||
|
INSN: ##load-double
|
||||||
|
def: dst/double-rep
|
||||||
|
constant: val ;
|
||||||
|
|
||||||
INSN: ##peek
|
INSN: ##peek
|
||||||
def: dst/int-rep
|
def: dst/int-rep
|
||||||
literal: loc ;
|
literal: loc ;
|
||||||
|
|
|
@ -68,23 +68,23 @@ PRIVATE>
|
||||||
tri
|
tri
|
||||||
] with-compilation-unit
|
] with-compilation-unit
|
||||||
|
|
||||||
: each-def-rep ( ... insn vreg-quot: ( ... vreg rep -- ... ) -- ... )
|
: each-def-rep ( insn vreg-quot: ( vreg rep -- ) -- )
|
||||||
[ [ defs-vreg ] [ defs-vreg-rep ] bi ] dip with when* ; inline
|
[ [ defs-vreg ] [ defs-vreg-rep ] bi ] dip with when* ; inline
|
||||||
|
|
||||||
: each-use-rep ( ... insn vreg-quot: ( ... vreg rep -- ... ) -- ... )
|
: each-use-rep ( insn vreg-quot: ( vreg rep -- ) -- )
|
||||||
[ [ uses-vregs ] [ uses-vreg-reps ] bi ] dip 2each ; inline
|
[ [ uses-vregs ] [ uses-vreg-reps ] bi ] dip 2each ; inline
|
||||||
|
|
||||||
: each-temp-rep ( ... insn vreg-quot: ( ... vreg rep -- ... ) -- ... )
|
: each-temp-rep ( insn vreg-quot: ( vreg rep -- ) -- )
|
||||||
[ [ temp-vregs ] [ temp-vreg-reps ] bi ] dip 2each ; inline
|
[ [ temp-vregs ] [ temp-vreg-reps ] bi ] dip 2each ; inline
|
||||||
|
|
||||||
|
: each-rep ( insn vreg-quot: ( vreg rep -- ) -- )
|
||||||
|
[ each-def-rep ] [ each-use-rep ] [ each-temp-rep ] 2tri ; inline
|
||||||
|
|
||||||
: with-vreg-reps ( ..a cfg vreg-quot: ( ..a vreg rep -- ..b ) -- ..b )
|
: with-vreg-reps ( ..a cfg vreg-quot: ( ..a vreg rep -- ..b ) -- ..b )
|
||||||
'[
|
'[
|
||||||
[ basic-block set ] [
|
[ basic-block set ] [
|
||||||
[
|
[
|
||||||
_
|
_ each-rep
|
||||||
[ each-def-rep ]
|
|
||||||
[ each-use-rep ]
|
|
||||||
[ each-temp-rep ] 2tri
|
|
||||||
] each-non-phi
|
] each-non-phi
|
||||||
] bi
|
] bi
|
||||||
] each-basic-block ; inline
|
] each-basic-block ; inline
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
USING: tools.test cpu.architecture
|
USING: accessors compiler.cfg compiler.cfg.debugger
|
||||||
compiler.cfg.registers compiler.cfg.instructions
|
compiler.cfg.instructions compiler.cfg.registers
|
||||||
compiler.cfg.representations.preferred ;
|
compiler.cfg.representations.preferred cpu.architecture kernel
|
||||||
|
namespaces tools.test sequences arrays system ;
|
||||||
IN: compiler.cfg.representations
|
IN: compiler.cfg.representations
|
||||||
|
|
||||||
[ { double-rep double-rep } ] [
|
[ { double-rep double-rep } ] [
|
||||||
|
@ -17,3 +18,110 @@ IN: compiler.cfg.representations
|
||||||
{ src 3 }
|
{ src 3 }
|
||||||
} defs-vreg-rep
|
} defs-vreg-rep
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
: test-representations ( -- )
|
||||||
|
cfg new 0 get >>entry dup cfg set select-representations drop ;
|
||||||
|
|
||||||
|
! Make sure cost calculation isn't completely wrong
|
||||||
|
V{
|
||||||
|
T{ ##prologue }
|
||||||
|
T{ ##branch }
|
||||||
|
} 0 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##peek f 1 D 0 }
|
||||||
|
T{ ##peek f 2 D 1 }
|
||||||
|
T{ ##add-float f 3 1 2 }
|
||||||
|
T{ ##replace f 3 D 0 }
|
||||||
|
T{ ##replace f 3 D 1 }
|
||||||
|
T{ ##replace f 3 D 2 }
|
||||||
|
T{ ##branch }
|
||||||
|
} 1 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##epilogue }
|
||||||
|
T{ ##return }
|
||||||
|
} 2 test-bb
|
||||||
|
|
||||||
|
0 1 edge
|
||||||
|
1 2 edge
|
||||||
|
|
||||||
|
[ ] [ test-representations ] unit-test
|
||||||
|
|
||||||
|
[ 1 ] [ 1 get instructions>> [ ##allot? ] count ] unit-test
|
||||||
|
|
||||||
|
cpu x86.32? [
|
||||||
|
|
||||||
|
! Make sure load-constant is converted into load-double
|
||||||
|
V{
|
||||||
|
T{ ##prologue }
|
||||||
|
T{ ##branch }
|
||||||
|
} 0 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##peek f 1 D 0 }
|
||||||
|
T{ ##load-constant f 2 0.5 }
|
||||||
|
T{ ##add-float f 3 1 2 }
|
||||||
|
T{ ##replace f 3 D 0 }
|
||||||
|
T{ ##branch }
|
||||||
|
} 1 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##epilogue }
|
||||||
|
T{ ##return }
|
||||||
|
} 2 test-bb
|
||||||
|
|
||||||
|
0 1 edge
|
||||||
|
1 2 edge
|
||||||
|
|
||||||
|
[ ] [ test-representations ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ 1 get instructions>> second ##load-double? ] unit-test
|
||||||
|
|
||||||
|
! Make sure phi nodes are handled in a sane way
|
||||||
|
V{
|
||||||
|
T{ ##prologue }
|
||||||
|
T{ ##branch }
|
||||||
|
} 0 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##peek f 1 D 0 }
|
||||||
|
T{ ##compare-imm-branch f 1 2 }
|
||||||
|
} 1 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##load-constant f 2 1.5 }
|
||||||
|
T{ ##branch }
|
||||||
|
} 2 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##load-constant f 3 2.5 }
|
||||||
|
T{ ##branch }
|
||||||
|
} 3 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##phi f 4 }
|
||||||
|
T{ ##peek f 5 D 0 }
|
||||||
|
T{ ##add-float f 6 4 5 }
|
||||||
|
T{ ##replace f 6 D 0 }
|
||||||
|
} 4 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##epilogue }
|
||||||
|
T{ ##return }
|
||||||
|
} 5 test-bb
|
||||||
|
|
||||||
|
test-diamond
|
||||||
|
4 5 edge
|
||||||
|
|
||||||
|
2 get 2 2array
|
||||||
|
3 get 3 2array 2array 4 get instructions>> first (>>inputs)
|
||||||
|
|
||||||
|
[ ] [ test-representations ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ 2 get instructions>> first ##load-double? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ 3 get instructions>> first ##load-double? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ 4 get instructions>> first ##phi? ] unit-test
|
||||||
|
] when
|
|
@ -1,4 +1,4 @@
|
||||||
! Copyright (C) 2009 Slava Pestov
|
! Copyright (C) 2009, 2010 Slava Pestov
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel fry accessors sequences assocs sets namespaces
|
USING: kernel fry accessors sequences assocs sets namespaces
|
||||||
arrays combinators combinators.short-circuit math make locals
|
arrays combinators combinators.short-circuit math make locals
|
||||||
|
@ -91,8 +91,8 @@ SYMBOL: possibilities
|
||||||
: possible ( vreg -- reps ) possibilities get at ;
|
: possible ( vreg -- reps ) possibilities get at ;
|
||||||
|
|
||||||
: compute-possibilities ( cfg -- )
|
: compute-possibilities ( cfg -- )
|
||||||
H{ } clone [ '[ swap _ conjoin-at ] with-vreg-reps ] keep
|
H{ } clone [ '[ swap _ adjoin-at ] with-vreg-reps ] keep
|
||||||
[ keys ] assoc-map possibilities set ;
|
[ members ] assoc-map possibilities set ;
|
||||||
|
|
||||||
! Compute vregs which must remain tagged for their lifetime.
|
! Compute vregs which must remain tagged for their lifetime.
|
||||||
SYMBOL: always-boxed
|
SYMBOL: always-boxed
|
||||||
|
@ -119,15 +119,18 @@ SYMBOL: always-boxed
|
||||||
SYMBOL: costs
|
SYMBOL: costs
|
||||||
|
|
||||||
: init-costs ( -- )
|
: init-costs ( -- )
|
||||||
possibilities get [ [ 0 ] H{ } map>assoc ] assoc-map costs set ;
|
possibilities get [ drop H{ } clone ] assoc-map costs set ;
|
||||||
|
|
||||||
|
: record-possibility ( rep vreg -- )
|
||||||
|
costs get at [ 0 or ] change-at ;
|
||||||
|
|
||||||
: increase-cost ( rep vreg -- )
|
: increase-cost ( rep vreg -- )
|
||||||
! Increase cost of keeping vreg in rep, making a choice of rep less
|
! Increase cost of keeping vreg in rep, making a choice of rep less
|
||||||
! likely.
|
! likely.
|
||||||
[ basic-block get loop-nesting-at ] 2dip costs get at at+ ;
|
costs get at [ 0 or basic-block get loop-nesting-at 1 + + ] change-at ;
|
||||||
|
|
||||||
: maybe-increase-cost ( possible vreg preferred -- )
|
: maybe-increase-cost ( possible vreg preferred -- )
|
||||||
pick eq? [ 2drop ] [ increase-cost ] if ;
|
pick eq? [ record-possibility ] [ increase-cost ] if ;
|
||||||
|
|
||||||
: representation-cost ( vreg preferred -- )
|
: representation-cost ( vreg preferred -- )
|
||||||
! 'preferred' is a representation that the instruction can accept with no cost.
|
! 'preferred' is a representation that the instruction can accept with no cost.
|
||||||
|
@ -137,11 +140,29 @@ SYMBOL: costs
|
||||||
[ '[ _ _ maybe-increase-cost ] ]
|
[ '[ _ _ maybe-increase-cost ] ]
|
||||||
2bi each ;
|
2bi each ;
|
||||||
|
|
||||||
|
GENERIC: compute-insn-costs ( insn -- )
|
||||||
|
|
||||||
|
M: ##load-constant compute-insn-costs
|
||||||
|
! There's no cost to unboxing the result of a ##load-constant
|
||||||
|
drop ;
|
||||||
|
|
||||||
|
M: insn compute-insn-costs [ representation-cost ] each-rep ;
|
||||||
|
|
||||||
: compute-costs ( cfg -- costs )
|
: compute-costs ( cfg -- costs )
|
||||||
init-costs [ representation-cost ] with-vreg-reps costs get ;
|
init-costs
|
||||||
|
[
|
||||||
|
[ basic-block set ]
|
||||||
|
[
|
||||||
|
[
|
||||||
|
compute-insn-costs
|
||||||
|
] each-non-phi
|
||||||
|
] bi
|
||||||
|
] each-basic-block
|
||||||
|
costs get ;
|
||||||
|
|
||||||
! For every vreg, compute preferred representation, that minimizes costs.
|
! For every vreg, compute preferred representation, that minimizes costs.
|
||||||
: minimize-costs ( costs -- representations )
|
: minimize-costs ( costs -- representations )
|
||||||
|
[ nip assoc-empty? not ] assoc-filter
|
||||||
[ >alist alist-min first ] assoc-map ;
|
[ >alist alist-min first ] assoc-map ;
|
||||||
|
|
||||||
: compute-representations ( cfg -- )
|
: compute-representations ( cfg -- )
|
||||||
|
@ -150,6 +171,54 @@ SYMBOL: costs
|
||||||
bi assoc-union
|
bi assoc-union
|
||||||
representations set ;
|
representations set ;
|
||||||
|
|
||||||
|
! PHI nodes require special treatment
|
||||||
|
! If the output of a phi instruction is only used as the input to another
|
||||||
|
! phi instruction, then we want to use the same representation for both
|
||||||
|
! if possible.
|
||||||
|
SYMBOL: phis
|
||||||
|
|
||||||
|
: collect-phis ( cfg -- )
|
||||||
|
H{ } clone phis set
|
||||||
|
[
|
||||||
|
phis get
|
||||||
|
'[ [ inputs>> values ] [ dst>> ] bi _ set-at ] each-phi
|
||||||
|
] each-basic-block ;
|
||||||
|
|
||||||
|
SYMBOL: work-list
|
||||||
|
|
||||||
|
: add-to-work-list ( vregs -- )
|
||||||
|
work-list get push-all-front ;
|
||||||
|
|
||||||
|
: rep-assigned ( vregs -- vregs' )
|
||||||
|
representations get '[ _ key? ] filter ;
|
||||||
|
|
||||||
|
: rep-not-assigned ( vregs -- vregs' )
|
||||||
|
representations get '[ _ key? not ] filter ;
|
||||||
|
|
||||||
|
: add-ready-phis ( -- )
|
||||||
|
phis get keys rep-assigned add-to-work-list ;
|
||||||
|
|
||||||
|
: process-phi ( dst -- )
|
||||||
|
! If dst = phi(src1,src2,...) and dst's representation has been
|
||||||
|
! determined, assign that representation to each one of src1,...
|
||||||
|
! that does not have a representation yet, and process those, too.
|
||||||
|
dup phis get at* [
|
||||||
|
[ rep-of ] [ rep-not-assigned ] bi*
|
||||||
|
[ [ set-rep-of ] with each ] [ add-to-work-list ] bi
|
||||||
|
] [ 2drop ] if ;
|
||||||
|
|
||||||
|
: remaining-phis ( -- )
|
||||||
|
phis get keys rep-not-assigned { } assert-sequence= ;
|
||||||
|
|
||||||
|
: process-phis ( -- )
|
||||||
|
<hashed-dlist> work-list set
|
||||||
|
add-ready-phis
|
||||||
|
work-list get [ process-phi ] slurp-deque
|
||||||
|
remaining-phis ;
|
||||||
|
|
||||||
|
: compute-phi-representations ( cfg -- )
|
||||||
|
collect-phis process-phis ;
|
||||||
|
|
||||||
! Insert conversions. This introduces new temporaries, so we need
|
! Insert conversions. This introduces new temporaries, so we need
|
||||||
! to rename opearands too.
|
! to rename opearands too.
|
||||||
|
|
||||||
|
@ -188,7 +257,7 @@ SYMBOLS: renaming-set needs-renaming? ;
|
||||||
: record-renaming ( from to -- )
|
: record-renaming ( from to -- )
|
||||||
2array renaming-set get push needs-renaming? on ;
|
2array renaming-set get push needs-renaming? on ;
|
||||||
|
|
||||||
:: (compute-renaming-set) ( ..a vreg required quot: ( ..a vreg preferred required -- ..b ) -- ..b )
|
:: (compute-renaming-set) ( vreg required quot: ( vreg preferred required -- new-vreg ) -- )
|
||||||
vreg rep-of :> preferred
|
vreg rep-of :> preferred
|
||||||
preferred required eq?
|
preferred required eq?
|
||||||
[ vreg no-renaming ]
|
[ vreg no-renaming ]
|
||||||
|
@ -217,15 +286,16 @@ RENAMING: convert [ converted-value ] [ converted-value ] [ ]
|
||||||
|
|
||||||
GENERIC: conversions-for-insn ( insn -- )
|
GENERIC: conversions-for-insn ( insn -- )
|
||||||
|
|
||||||
SYMBOL: phi-mappings
|
M: ##phi conversions-for-insn , ;
|
||||||
|
|
||||||
! compiler.cfg.cssa inserts conversions which convert phi inputs into
|
! When a float is unboxed, we replace the ##load-constant with a ##load-double
|
||||||
! the representation of the output. However, we still have to do some
|
! if the architecture supports it
|
||||||
! processing here, because if the only node that uses the output of
|
: convert-to-load-double? ( insn -- ? )
|
||||||
! the phi instruction is another phi instruction then this phi node's
|
{
|
||||||
! output won't have a representation assigned.
|
[ drop load-double? ]
|
||||||
M: ##phi conversions-for-insn
|
[ dst>> rep-of double-rep? ]
|
||||||
[ , ] [ [ inputs>> values ] [ dst>> ] bi phi-mappings get set-at ] bi ;
|
[ obj>> float? ]
|
||||||
|
} 1&& ;
|
||||||
|
|
||||||
! When a literal zeroes/ones vector is unboxed, we replace the ##load-reference
|
! When a literal zeroes/ones vector is unboxed, we replace the ##load-reference
|
||||||
! with a ##zero-vector or ##fill-vector instruction since this is more efficient.
|
! with a ##zero-vector or ##fill-vector instruction since this is more efficient.
|
||||||
|
@ -234,17 +304,25 @@ M: ##phi conversions-for-insn
|
||||||
[ dst>> rep-of vector-rep? ]
|
[ dst>> rep-of vector-rep? ]
|
||||||
[ obj>> B{ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } = ]
|
[ obj>> B{ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } = ]
|
||||||
} 1&& ;
|
} 1&& ;
|
||||||
|
|
||||||
: convert-to-fill-vector? ( insn -- ? )
|
: convert-to-fill-vector? ( insn -- ? )
|
||||||
{
|
{
|
||||||
[ dst>> rep-of vector-rep? ]
|
[ dst>> rep-of vector-rep? ]
|
||||||
[ obj>> B{ 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 } = ]
|
[ obj>> B{ 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 } = ]
|
||||||
} 1&& ;
|
} 1&& ;
|
||||||
|
|
||||||
|
: (convert-to-load-double) ( insn -- dst val )
|
||||||
|
[ dst>> ] [ obj>> ] bi ; inline
|
||||||
|
|
||||||
: (convert-to-zero/fill-vector) ( insn -- dst rep )
|
: (convert-to-zero/fill-vector) ( insn -- dst rep )
|
||||||
dst>> dup rep-of ; inline
|
dst>> dup rep-of ; inline
|
||||||
|
|
||||||
: conversions-for-load-insn ( insn -- ?insn )
|
: conversions-for-load-insn ( insn -- ?insn )
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
[ dup convert-to-load-double? ]
|
||||||
|
[ (convert-to-load-double) ##load-double f ]
|
||||||
|
}
|
||||||
{
|
{
|
||||||
[ dup convert-to-zero-vector? ]
|
[ dup convert-to-zero-vector? ]
|
||||||
[ (convert-to-zero/fill-vector) ##zero-vector f ]
|
[ (convert-to-zero/fill-vector) ##zero-vector f ]
|
||||||
|
@ -277,46 +355,8 @@ M: insn conversions-for-insn , ;
|
||||||
] change-instructions drop
|
] change-instructions drop
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
! If the output of a phi instruction is only used as the input to another
|
|
||||||
! phi instruction, then we want to use the same representation for both
|
|
||||||
! if possible.
|
|
||||||
SYMBOL: work-list
|
|
||||||
|
|
||||||
: add-to-work-list ( vregs -- )
|
|
||||||
work-list get push-all-front ;
|
|
||||||
|
|
||||||
: rep-assigned ( vregs -- vregs' )
|
|
||||||
representations get '[ _ key? ] filter ;
|
|
||||||
|
|
||||||
: rep-not-assigned ( vregs -- vregs' )
|
|
||||||
representations get '[ _ key? not ] filter ;
|
|
||||||
|
|
||||||
: add-ready-phis ( -- )
|
|
||||||
phi-mappings get keys rep-assigned add-to-work-list ;
|
|
||||||
|
|
||||||
: process-phi-mapping ( dst -- )
|
|
||||||
! If dst = phi(src1,src2,...) and dst's representation has been
|
|
||||||
! determined, assign that representation to each one of src1,...
|
|
||||||
! that does not have a representation yet, and process those, too.
|
|
||||||
dup phi-mappings get at* [
|
|
||||||
[ rep-of ] [ rep-not-assigned ] bi*
|
|
||||||
[ [ set-rep-of ] with each ] [ add-to-work-list ] bi
|
|
||||||
] [ 2drop ] if ;
|
|
||||||
|
|
||||||
: remaining-phi-mappings ( -- )
|
|
||||||
phi-mappings get keys rep-not-assigned
|
|
||||||
[ [ int-rep ] dip set-rep-of ] each ;
|
|
||||||
|
|
||||||
: process-phi-mappings ( -- )
|
|
||||||
<hashed-dlist> work-list set
|
|
||||||
add-ready-phis
|
|
||||||
work-list get [ process-phi-mapping ] slurp-deque
|
|
||||||
remaining-phi-mappings ;
|
|
||||||
|
|
||||||
: insert-conversions ( cfg -- )
|
: insert-conversions ( cfg -- )
|
||||||
H{ } clone phi-mappings set
|
[ conversions-for-block ] each-basic-block ;
|
||||||
[ conversions-for-block ] each-basic-block
|
|
||||||
process-phi-mappings ;
|
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
|
@ -326,6 +366,7 @@ PRIVATE>
|
||||||
{
|
{
|
||||||
[ compute-possibilities ]
|
[ compute-possibilities ]
|
||||||
[ compute-representations ]
|
[ compute-representations ]
|
||||||
|
[ compute-phi-representations ]
|
||||||
[ insert-conversions ]
|
[ insert-conversions ]
|
||||||
[ ]
|
[ ]
|
||||||
} cleave
|
} cleave
|
||||||
|
|
|
@ -81,6 +81,7 @@ SYNTAX: CODEGEN:
|
||||||
CODEGEN: ##load-immediate %load-immediate
|
CODEGEN: ##load-immediate %load-immediate
|
||||||
CODEGEN: ##load-reference %load-reference
|
CODEGEN: ##load-reference %load-reference
|
||||||
CODEGEN: ##load-constant %load-reference
|
CODEGEN: ##load-constant %load-reference
|
||||||
|
CODEGEN: ##load-double %load-double
|
||||||
CODEGEN: ##peek %peek
|
CODEGEN: ##peek %peek
|
||||||
CODEGEN: ##replace %replace
|
CODEGEN: ##replace %replace
|
||||||
CODEGEN: ##inc-d %inc-d
|
CODEGEN: ##inc-d %inc-d
|
||||||
|
|
|
@ -70,9 +70,12 @@ MEMO: cached-string>symbol ( symbol -- obj ) string>symbol ;
|
||||||
: rel-word-pic-tail ( word class -- )
|
: rel-word-pic-tail ( word class -- )
|
||||||
[ add-literal ] dip rt-entry-point-pic-tail rel-fixup ;
|
[ add-literal ] dip rt-entry-point-pic-tail rel-fixup ;
|
||||||
|
|
||||||
: rel-immediate ( literal class -- )
|
: rel-literal ( literal class -- )
|
||||||
[ add-literal ] dip rt-literal rel-fixup ;
|
[ add-literal ] dip rt-literal rel-fixup ;
|
||||||
|
|
||||||
|
: rel-float ( literal class -- )
|
||||||
|
[ add-literal ] dip rt-float rel-fixup ;
|
||||||
|
|
||||||
: rel-this ( class -- )
|
: rel-this ( class -- )
|
||||||
rt-this rel-fixup ;
|
rt-this rel-fixup ;
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,8 @@ C-ENUM: f
|
||||||
rt-vm
|
rt-vm
|
||||||
rt-cards-offset
|
rt-cards-offset
|
||||||
rt-decks-offset
|
rt-decks-offset
|
||||||
rt-exception-handler ;
|
rt-exception-handler
|
||||||
|
rt-float ;
|
||||||
|
|
||||||
: rc-absolute? ( n -- ? )
|
: rc-absolute? ( n -- ? )
|
||||||
${
|
${
|
||||||
|
|
|
@ -8,7 +8,7 @@ IN: compiler.tree.propagation.recursive.tests
|
||||||
integer generalize-counter-interval
|
integer generalize-counter-interval
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ T{ interval f { 0 t } { $[ most-positive-fixnum ] t } } ] [
|
[ T{ interval f { 0 t } { $[ max-array-capacity ] t } } ] [
|
||||||
T{ interval f { 1 t } { 1 t } }
|
T{ interval f { 1 t } { 1 t } }
|
||||||
T{ interval f { 0 t } { 0 t } }
|
T{ interval f { 0 t } { 0 t } }
|
||||||
fixnum generalize-counter-interval
|
fixnum generalize-counter-interval
|
||||||
|
|
|
@ -202,8 +202,9 @@ M: ulonglong-2-rep scalar-rep-of drop ulonglong-scalar-rep ;
|
||||||
! Mapping from register class to machine registers
|
! Mapping from register class to machine registers
|
||||||
HOOK: machine-registers cpu ( -- assoc )
|
HOOK: machine-registers cpu ( -- assoc )
|
||||||
|
|
||||||
HOOK: %load-immediate cpu ( reg obj -- )
|
HOOK: %load-immediate cpu ( reg val -- )
|
||||||
HOOK: %load-reference cpu ( reg obj -- )
|
HOOK: %load-reference cpu ( reg obj -- )
|
||||||
|
HOOK: %load-double cpu ( reg val -- )
|
||||||
|
|
||||||
HOOK: %peek cpu ( vreg loc -- )
|
HOOK: %peek cpu ( vreg loc -- )
|
||||||
HOOK: %replace cpu ( vreg loc -- )
|
HOOK: %replace cpu ( vreg loc -- )
|
||||||
|
@ -496,6 +497,11 @@ M: reg-class param-reg param-regs nth ;
|
||||||
|
|
||||||
M: stack-params param-reg 2drop ;
|
M: stack-params param-reg 2drop ;
|
||||||
|
|
||||||
|
! Does this architecture support %load-double?
|
||||||
|
HOOK: load-double? cpu ( -- ? )
|
||||||
|
|
||||||
|
M: object load-double? f ;
|
||||||
|
|
||||||
! Can this value be an immediate operand for %add-imm, %sub-imm,
|
! Can this value be an immediate operand for %add-imm, %sub-imm,
|
||||||
! or %mul-imm?
|
! or %mul-imm?
|
||||||
HOOK: immediate-arithmetic? cpu ( n -- ? )
|
HOOK: immediate-arithmetic? cpu ( n -- ? )
|
||||||
|
|
|
@ -47,7 +47,7 @@ CONSTANT: fp-scratch-reg 30
|
||||||
M: ppc %load-immediate ( reg n -- ) swap LOAD ;
|
M: ppc %load-immediate ( reg n -- ) swap LOAD ;
|
||||||
|
|
||||||
M: ppc %load-reference ( reg obj -- )
|
M: ppc %load-reference ( reg obj -- )
|
||||||
[ 0 swap LOAD32 ] [ rc-absolute-ppc-2/2 rel-immediate ] bi* ;
|
[ 0 swap LOAD32 ] [ rc-absolute-ppc-2/2 rel-literal ] bi* ;
|
||||||
|
|
||||||
M: ppc %alien-global ( register symbol dll -- )
|
M: ppc %alien-global ( register symbol dll -- )
|
||||||
[ 0 swap LOAD32 ] 2dip rc-absolute-ppc-2/2 rel-dlsym ;
|
[ 0 swap LOAD32 ] 2dip rc-absolute-ppc-2/2 rel-dlsym ;
|
||||||
|
|
|
@ -12,9 +12,6 @@ cpu.x86.assembler.operands cpu.x86 cpu.architecture vm ;
|
||||||
FROM: layouts => cell ;
|
FROM: layouts => cell ;
|
||||||
IN: cpu.x86.32
|
IN: cpu.x86.32
|
||||||
|
|
||||||
M: x86.32 immediate-comparand? ( n -- ? )
|
|
||||||
[ call-next-method ] [ word? ] bi or ;
|
|
||||||
|
|
||||||
M: x86.32 machine-registers
|
M: x86.32 machine-registers
|
||||||
{
|
{
|
||||||
{ int-regs { EAX ECX EDX EBP EBX } }
|
{ int-regs { EAX ECX EDX EBP EBX } }
|
||||||
|
@ -27,6 +24,14 @@ M: x86.32 stack-reg ESP ;
|
||||||
M: x86.32 frame-reg EBP ;
|
M: x86.32 frame-reg EBP ;
|
||||||
M: x86.32 temp-reg ECX ;
|
M: x86.32 temp-reg ECX ;
|
||||||
|
|
||||||
|
M: x86.32 immediate-comparand? ( n -- ? )
|
||||||
|
[ call-next-method ] [ word? ] bi or ;
|
||||||
|
|
||||||
|
M: x86.32 load-double? ( -- ? ) t ;
|
||||||
|
|
||||||
|
M: x86.32 %load-double ( dst val -- )
|
||||||
|
[ 0 [] MOVSD ] dip rc-absolute rel-float ;
|
||||||
|
|
||||||
M: x86.32 %mov-vm-ptr ( reg -- )
|
M: x86.32 %mov-vm-ptr ( reg -- )
|
||||||
0 MOV 0 rc-absolute-cell rel-vm ;
|
0 MOV 0 rc-absolute-cell rel-vm ;
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ HOOK: pic-tail-reg cpu ( -- reg )
|
||||||
|
|
||||||
M: x86 %load-immediate dup 0 = [ drop dup XOR ] [ MOV ] if ;
|
M: x86 %load-immediate dup 0 = [ drop dup XOR ] [ MOV ] if ;
|
||||||
|
|
||||||
M: x86 %load-reference swap 0 MOV rc-absolute-cell rel-immediate ;
|
M: x86 %load-reference swap 0 MOV rc-absolute-cell rel-literal ;
|
||||||
|
|
||||||
HOOK: ds-reg cpu ( -- reg )
|
HOOK: ds-reg cpu ( -- reg )
|
||||||
HOOK: rs-reg cpu ( -- reg )
|
HOOK: rs-reg cpu ( -- reg )
|
||||||
|
@ -493,7 +493,7 @@ M: x86 %epilogue ( n -- ) cell - incr-stack-reg ;
|
||||||
|
|
||||||
:: (%boolean) ( dst temp insn -- )
|
:: (%boolean) ( dst temp insn -- )
|
||||||
dst \ f type-number MOV
|
dst \ f type-number MOV
|
||||||
temp 0 MOV \ t rc-absolute-cell rel-immediate
|
temp 0 MOV \ t rc-absolute-cell rel-literal
|
||||||
dst temp insn execute ; inline
|
dst temp insn execute ; inline
|
||||||
|
|
||||||
: %boolean ( dst cc temp -- )
|
: %boolean ( dst cc temp -- )
|
||||||
|
@ -514,7 +514,7 @@ M:: x86 %compare ( dst src1 src2 cc temp -- )
|
||||||
[ register? ] [ 0 = ] [ { cc= cc/= } member? ] tri* and and ;
|
[ register? ] [ 0 = ] [ { cc= cc/= } member? ] tri* and and ;
|
||||||
|
|
||||||
: (%compare-tagged) ( src1 src2 -- )
|
: (%compare-tagged) ( src1 src2 -- )
|
||||||
[ HEX: ffffffff CMP ] dip rc-absolute rel-immediate ;
|
[ HEX: ffffffff CMP ] dip rc-absolute rel-literal ;
|
||||||
|
|
||||||
: (%compare-imm) ( src1 src2 cc -- )
|
: (%compare-imm) ( src1 src2 cc -- )
|
||||||
{
|
{
|
||||||
|
|
|
@ -265,6 +265,9 @@ struct initial_code_block_visitor {
|
||||||
case RT_LITERAL:
|
case RT_LITERAL:
|
||||||
op.store_value(next_literal());
|
op.store_value(next_literal());
|
||||||
break;
|
break;
|
||||||
|
case RT_FLOAT:
|
||||||
|
op.store_float(next_literal());
|
||||||
|
break;
|
||||||
case RT_ENTRY_POINT:
|
case RT_ENTRY_POINT:
|
||||||
op.store_value(parent->compute_entry_point_address(next_literal()));
|
op.store_value(parent->compute_entry_point_address(next_literal()));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -111,6 +111,9 @@ struct code_block_compaction_relocation_visitor {
|
||||||
case RT_LITERAL:
|
case RT_LITERAL:
|
||||||
op.store_value(slot_forwarder.visit_pointer(op.load_value(old_offset)));
|
op.store_value(slot_forwarder.visit_pointer(op.load_value(old_offset)));
|
||||||
break;
|
break;
|
||||||
|
case RT_FLOAT:
|
||||||
|
op.store_float(slot_forwarder.visit_pointer(op.load_float(old_offset)));
|
||||||
|
break;
|
||||||
case RT_ENTRY_POINT:
|
case RT_ENTRY_POINT:
|
||||||
case RT_ENTRY_POINT_PIC:
|
case RT_ENTRY_POINT_PIC:
|
||||||
case RT_ENTRY_POINT_PIC_TAIL:
|
case RT_ENTRY_POINT_PIC_TAIL:
|
||||||
|
|
|
@ -185,6 +185,9 @@ struct code_block_fixup_relocation_visitor {
|
||||||
case RT_LITERAL:
|
case RT_LITERAL:
|
||||||
op.store_value(data_visitor.visit_pointer(op.load_value(old_offset)));
|
op.store_value(data_visitor.visit_pointer(op.load_value(old_offset)));
|
||||||
break;
|
break;
|
||||||
|
case RT_FLOAT:
|
||||||
|
op.store_float(data_visitor.visit_pointer(op.load_float(old_offset)));
|
||||||
|
break;
|
||||||
case RT_ENTRY_POINT:
|
case RT_ENTRY_POINT:
|
||||||
case RT_ENTRY_POINT_PIC:
|
case RT_ENTRY_POINT_PIC:
|
||||||
case RT_ENTRY_POINT_PIC_TAIL:
|
case RT_ENTRY_POINT_PIC_TAIL:
|
||||||
|
|
|
@ -62,6 +62,16 @@ fixnum instruction_operand::load_value()
|
||||||
return load_value(pointer);
|
return load_value(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cell instruction_operand::load_float()
|
||||||
|
{
|
||||||
|
return (cell)load_value() - boxed_float_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell instruction_operand::load_float(cell pointer)
|
||||||
|
{
|
||||||
|
return (cell)load_value(pointer) - boxed_float_offset;
|
||||||
|
}
|
||||||
|
|
||||||
code_block *instruction_operand::load_code_block(cell relative_to)
|
code_block *instruction_operand::load_code_block(cell relative_to)
|
||||||
{
|
{
|
||||||
return ((code_block *)load_value(relative_to) - 1);
|
return ((code_block *)load_value(relative_to) - 1);
|
||||||
|
@ -135,6 +145,11 @@ void instruction_operand::store_value(fixnum absolute_value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void instruction_operand::store_float(cell value)
|
||||||
|
{
|
||||||
|
store_value((fixnum)value + boxed_float_offset);
|
||||||
|
}
|
||||||
|
|
||||||
void instruction_operand::store_code_block(code_block *compiled)
|
void instruction_operand::store_code_block(code_block *compiled)
|
||||||
{
|
{
|
||||||
store_value((cell)compiled->entry_point());
|
store_value((cell)compiled->entry_point());
|
||||||
|
|
|
@ -30,6 +30,9 @@ enum relocation_type {
|
||||||
type since its used in a situation where relocation arguments cannot
|
type since its used in a situation where relocation arguments cannot
|
||||||
be passed in, and so RT_DLSYM is inappropriate (Windows only) */
|
be passed in, and so RT_DLSYM is inappropriate (Windows only) */
|
||||||
RT_EXCEPTION_HANDLER,
|
RT_EXCEPTION_HANDLER,
|
||||||
|
/* pointer to a float's payload */
|
||||||
|
RT_FLOAT,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum relocation_class {
|
enum relocation_class {
|
||||||
|
@ -112,6 +115,7 @@ struct relocation_entry {
|
||||||
case RT_CARDS_OFFSET:
|
case RT_CARDS_OFFSET:
|
||||||
case RT_DECKS_OFFSET:
|
case RT_DECKS_OFFSET:
|
||||||
case RT_EXCEPTION_HANDLER:
|
case RT_EXCEPTION_HANDLER:
|
||||||
|
case RT_FLOAT:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
critical_error("Bad rel type",rel_type());
|
critical_error("Bad rel type",rel_type());
|
||||||
|
@ -152,12 +156,15 @@ struct instruction_operand {
|
||||||
fixnum load_value_masked(cell mask, cell bits, cell shift);
|
fixnum load_value_masked(cell mask, cell bits, cell shift);
|
||||||
fixnum load_value(cell relative_to);
|
fixnum load_value(cell relative_to);
|
||||||
fixnum load_value();
|
fixnum load_value();
|
||||||
|
cell load_float(cell relative_to);
|
||||||
|
cell load_float();
|
||||||
code_block *load_code_block(cell relative_to);
|
code_block *load_code_block(cell relative_to);
|
||||||
code_block *load_code_block();
|
code_block *load_code_block();
|
||||||
|
|
||||||
void store_value_2_2(fixnum value);
|
void store_value_2_2(fixnum value);
|
||||||
void store_value_masked(fixnum value, cell mask, cell shift);
|
void store_value_masked(fixnum value, cell mask, cell shift);
|
||||||
void store_value(fixnum value);
|
void store_value(fixnum value);
|
||||||
|
void store_float(cell value);
|
||||||
void store_code_block(code_block *compiled);
|
void store_code_block(code_block *compiled);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -246,6 +246,8 @@ struct wrapper : public object {
|
||||||
cell object;
|
cell object;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fixnum boxed_float_offset = 8 - FLOAT_TYPE;
|
||||||
|
|
||||||
/* Assembly code makes assumptions about the layout of this struct */
|
/* Assembly code makes assumptions about the layout of this struct */
|
||||||
struct boxed_float : object {
|
struct boxed_float : object {
|
||||||
static const cell type_number = FLOAT_TYPE;
|
static const cell type_number = FLOAT_TYPE;
|
||||||
|
|
|
@ -192,8 +192,17 @@ struct literal_references_visitor {
|
||||||
|
|
||||||
void operator()(instruction_operand op)
|
void operator()(instruction_operand op)
|
||||||
{
|
{
|
||||||
if(op.rel_type() == RT_LITERAL)
|
switch(op.rel_type())
|
||||||
|
{
|
||||||
|
case RT_LITERAL:
|
||||||
op.store_value(visitor->visit_pointer(op.load_value()));
|
op.store_value(visitor->visit_pointer(op.load_value()));
|
||||||
|
break;
|
||||||
|
case RT_FLOAT:
|
||||||
|
op.store_float(visitor->visit_pointer(op.load_float()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue