compiler.cfg.two-operand: make it work in more cases
parent
423d2996fa
commit
e8cf50ac3e
|
@ -0,0 +1,45 @@
|
||||||
|
IN: compiler.cfg.two-operand.tests
|
||||||
|
USING: compiler.cfg.two-operand compiler.cfg.instructions
|
||||||
|
compiler.cfg.registers cpu.architecture namespaces tools.test ;
|
||||||
|
|
||||||
|
3 vreg-counter set-global
|
||||||
|
|
||||||
|
[
|
||||||
|
V{
|
||||||
|
T{ ##copy f V int-regs 1 V int-regs 2 }
|
||||||
|
T{ ##sub f V int-regs 1 V int-regs 1 V int-regs 3 }
|
||||||
|
}
|
||||||
|
] [
|
||||||
|
{
|
||||||
|
T{ ##sub f V int-regs 1 V int-regs 2 V int-regs 3 }
|
||||||
|
} (convert-two-operand)
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
V{
|
||||||
|
T{ ##sub f V int-regs 1 V int-regs 1 V int-regs 2 }
|
||||||
|
}
|
||||||
|
] [
|
||||||
|
{
|
||||||
|
T{ ##sub f V int-regs 1 V int-regs 1 V int-regs 2 }
|
||||||
|
} (convert-two-operand)
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
V{
|
||||||
|
T{ ##copy f V int-regs 4 V int-regs 2 }
|
||||||
|
T{ ##sub f V int-regs 4 V int-regs 4 V int-regs 1 }
|
||||||
|
T{ ##copy f V int-regs 1 V int-regs 4 }
|
||||||
|
}
|
||||||
|
] [
|
||||||
|
{
|
||||||
|
T{ ##sub f V int-regs 1 V int-regs 2 V int-regs 1 }
|
||||||
|
} (convert-two-operand)
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
! This should never come up after coalescing
|
||||||
|
[
|
||||||
|
V{
|
||||||
|
T{ ##fixnum-add f V int-regs 2 V int-regs 4 V int-regs 2 }
|
||||||
|
} (convert-two-operand)
|
||||||
|
] must-fail
|
|
@ -1,59 +1,104 @@
|
||||||
! Copyright (C) 2008, 2009 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: accessors kernel sequences make compiler.cfg.instructions
|
USING: accessors kernel sequences make combinators
|
||||||
|
compiler.cfg.registers compiler.cfg.instructions
|
||||||
compiler.cfg.rpo cpu.architecture ;
|
compiler.cfg.rpo cpu.architecture ;
|
||||||
IN: compiler.cfg.two-operand
|
IN: compiler.cfg.two-operand
|
||||||
|
|
||||||
! On x86, instructions take the form x = x op y
|
! This pass runs after SSA coalescing and normalizes instructions
|
||||||
! Our SSA IR is x = y op z
|
! to fit the x86 two-address scheme. Possibilities are:
|
||||||
|
|
||||||
|
! 1) x = x op y
|
||||||
|
! 2) x = y op x
|
||||||
|
! 3) x = y op z
|
||||||
|
|
||||||
|
! In case 1, there is nothing to do.
|
||||||
|
|
||||||
|
! In case 2, we convert to
|
||||||
|
! z = y
|
||||||
|
! z = z op x
|
||||||
|
! x = z
|
||||||
|
|
||||||
|
! In case 3, we convert to
|
||||||
|
! x = y
|
||||||
|
! x = x op z
|
||||||
|
|
||||||
|
! In case 2 and case 3, linear scan coalescing will eliminate a
|
||||||
|
! copy if the value y is never used again.
|
||||||
|
|
||||||
! We don't bother with ##add, ##add-imm, ##sub-imm or ##mul-imm
|
! We don't bother with ##add, ##add-imm, ##sub-imm or ##mul-imm
|
||||||
! since x86 has LEA and IMUL instructions which are effectively
|
! since x86 has LEA and IMUL instructions which are effectively
|
||||||
! three-operand addition and multiplication, respectively.
|
! three-operand addition and multiplication, respectively.
|
||||||
|
|
||||||
: convert-two-operand/integer ( insn -- )
|
UNION: two-operand-insn
|
||||||
[ [ dst>> ] [ src1>> ] bi ##copy ]
|
##sub
|
||||||
[ dup dst>> >>src1 , ]
|
##mul
|
||||||
bi ; inline
|
##and
|
||||||
|
##and-imm
|
||||||
: convert-two-operand/float ( insn -- )
|
##or
|
||||||
[ [ dst>> ] [ src1>> ] bi ##copy-float ]
|
##or-imm
|
||||||
[ dup dst>> >>src1 , ]
|
##xor
|
||||||
bi ; inline
|
##xor-imm
|
||||||
|
##shl
|
||||||
|
##shl-imm
|
||||||
|
##shr
|
||||||
|
##shr-imm
|
||||||
|
##sar
|
||||||
|
##sar-imm
|
||||||
|
##fixnum-overflow
|
||||||
|
##add-float
|
||||||
|
##sub-float
|
||||||
|
##mul-float
|
||||||
|
##div-float ;
|
||||||
|
|
||||||
GENERIC: convert-two-operand* ( insn -- )
|
GENERIC: convert-two-operand* ( insn -- )
|
||||||
|
|
||||||
|
: emit-copy ( dst src -- )
|
||||||
|
dup reg-class>> {
|
||||||
|
{ int-regs [ ##copy ] }
|
||||||
|
{ double-float-regs [ ##copy-float ] }
|
||||||
|
} case ; inline
|
||||||
|
|
||||||
|
: case-1? ( insn -- ? ) [ dst>> ] [ src1>> ] bi = ; inline
|
||||||
|
|
||||||
|
: case-1 ( insn -- ) , ; inline
|
||||||
|
|
||||||
|
: case-2? ( insn -- ? ) [ dst>> ] [ src2>> ] bi = ; inline
|
||||||
|
|
||||||
|
ERROR: bad-case-2 insn ;
|
||||||
|
|
||||||
|
: case-2 ( insn -- )
|
||||||
|
! This can't work with a ##fixnum-overflow since it branches
|
||||||
|
dup ##fixnum-overflow? [ bad-case-2 ] when
|
||||||
|
dup dst>> reg-class>> next-vreg
|
||||||
|
[ swap src1>> emit-copy ]
|
||||||
|
[ [ >>src1 ] [ >>dst ] bi , ]
|
||||||
|
[ [ src2>> ] dip emit-copy ]
|
||||||
|
2tri ; inline
|
||||||
|
|
||||||
|
: case-3 ( insn -- )
|
||||||
|
[ [ dst>> ] [ src1>> ] bi emit-copy ]
|
||||||
|
[ dup dst>> >>src1 , ]
|
||||||
|
bi ; inline
|
||||||
|
|
||||||
|
M: two-operand-insn convert-two-operand*
|
||||||
|
{
|
||||||
|
{ [ dup case-1? ] [ case-1 ] }
|
||||||
|
{ [ dup case-2? ] [ case-2 ] }
|
||||||
|
[ case-3 ]
|
||||||
|
} cond ; inline
|
||||||
|
|
||||||
M: ##not convert-two-operand*
|
M: ##not convert-two-operand*
|
||||||
[ [ dst>> ] [ src>> ] bi ##copy ]
|
dup [ dst>> ] [ src>> ] bi = [
|
||||||
[ dup dst>> >>src , ]
|
[ [ dst>> ] [ src>> ] bi ##copy ]
|
||||||
bi ;
|
[ dup dst>> >>src ]
|
||||||
|
bi
|
||||||
M: ##sub convert-two-operand* convert-two-operand/integer ;
|
] unless , ;
|
||||||
M: ##mul convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##and convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##and-imm convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##or convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##or-imm convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##xor convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##xor-imm convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##shl convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##shl-imm convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##shr convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##shr-imm convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##sar convert-two-operand* convert-two-operand/integer ;
|
|
||||||
M: ##sar-imm convert-two-operand* convert-two-operand/integer ;
|
|
||||||
|
|
||||||
M: ##fixnum-overflow convert-two-operand* convert-two-operand/integer ;
|
|
||||||
|
|
||||||
M: ##add-float convert-two-operand* convert-two-operand/float ;
|
|
||||||
M: ##sub-float convert-two-operand* convert-two-operand/float ;
|
|
||||||
M: ##mul-float convert-two-operand* convert-two-operand/float ;
|
|
||||||
M: ##div-float convert-two-operand* convert-two-operand/float ;
|
|
||||||
|
|
||||||
M: insn convert-two-operand* , ;
|
M: insn convert-two-operand* , ;
|
||||||
|
|
||||||
|
: (convert-two-operand) ( cfg -- cfg' )
|
||||||
|
[ [ convert-two-operand* ] each ] V{ } make ;
|
||||||
|
|
||||||
: convert-two-operand ( cfg -- cfg' )
|
: convert-two-operand ( cfg -- cfg' )
|
||||||
two-operand? [
|
two-operand? [ [ (convert-two-operand) ] local-optimization ] when ;
|
||||||
[ [ [ convert-two-operand* ] each ] V{ } make ]
|
|
||||||
local-optimization
|
|
||||||
] when ;
|
|
Loading…
Reference in New Issue