SYMBOLS: local-def-indices local-kill-indices ;
-: record-def ( n vreg -- )
+: record-def ( n insn -- )
! We allow multiple defs of a vreg as long as they're
! all in the same basic block
- dup [
+ defs-vreg dup [
local-def-indices get 2dup key?
[ 3drop ] [ set-at ] if
] [ 2drop ] if ;
-: record-uses ( n vregs -- )
- local-kill-indices get '[ _ set-at ] with each ;
+: record-uses ( n insn -- )
+ ! Record live intervals so that all but the first input interfere
+ ! with the output. This lets us coalesce the output with the
+ ! first input.
+ [ uses-vregs ] [ def-is-use-insn? ] bi over empty? [ 3drop ] [
+ [ [ first local-kill-indices get set-at ] [ rest-slice ] 2bi ] unless
+ [ 1 + ] dip [ local-kill-indices get set-at ] with each
+ ] if ;
: visit-insn ( insn n -- )
- ! Instructions are numbered 2 apart. If the instruction requires
- ! that outputs are in different registers than the inputs, then
- ! a use will be registered for every output immediately after
- ! this instruction and before the next one, ensuring that outputs
- ! interfere with inputs.
- 2 *
- [ swap defs-vreg record-def ]
- [ swap uses-vregs record-uses ]
- [ over def-is-use-insn? [ 1 + swap defs-vreg 1array record-uses ] [ 2drop ] if ]
- 2tri ;
+ 2 * swap [ record-def ] [ record-uses ] 2bi ;
SYMBOLS: def-indices kill-indices ;
+++ /dev/null
-! Copyright (C) 2008, 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors kernel sequences make combinators
-compiler.cfg.registers compiler.cfg.instructions
-compiler.cfg.rpo cpu.architecture ;
-IN: compiler.cfg.two-operand
-
-! This pass runs before SSA coalescing and normalizes instructions
-! to fit the x86 two-address scheme. Since the input is in SSA,
-! it suffices to convert
-!
-! x = y op z
-!
-! to
-!
-! x = y
-! x = x op z
-!
-! We don't bother with ##add, ##add-imm, ##sub-imm or ##mul-imm
-! since x86 has LEA and IMUL instructions which are effectively
-! three-operand addition and multiplication, respectively.
-
-UNION: two-operand-insn
- ##sub
- ##mul
- ##and
- ##and-imm
- ##or
- ##or-imm
- ##xor
- ##xor-imm
- ##shl
- ##shl-imm
- ##shr
- ##shr-imm
- ##sar
- ##sar-imm
- ##min
- ##max
- ##fixnum-add
- ##fixnum-sub
- ##fixnum-mul
- ##add-float
- ##sub-float
- ##mul-float
- ##div-float
- ##min-float
- ##max-float
- ##add-vector
- ##saturated-add-vector
- ##add-sub-vector
- ##sub-vector
- ##saturated-sub-vector
- ##mul-vector
- ##saturated-mul-vector
- ##div-vector
- ##min-vector
- ##max-vector
- ##and-vector
- ##or-vector
- ##xor-vector
- ##shl-vector
- ##shr-vector ;
-
-GENERIC: convert-two-operand* ( insn -- )
-
-: emit-copy ( dst src -- )
- dup rep-of ##copy ; inline
-
-M: two-operand-insn convert-two-operand*
- [ [ dst>> ] [ src1>> ] bi emit-copy ]
- [
- dup [ src1>> ] [ src2>> ] bi = [ dup dst>> >>src2 ] when
- dup dst>> >>src1 ,
- ] bi ;
-
-M: ##not convert-two-operand*
- [ [ dst>> ] [ src>> ] bi emit-copy ]
- [ dup dst>> >>src , ]
- bi ;
-
-M: insn convert-two-operand* , ;
-
-: (convert-two-operand) ( insns -- insns' )
- dup first kill-vreg-insn? [
- [ [ convert-two-operand* ] each ] V{ } make
- ] unless ;
-
-: convert-two-operand ( cfg -- cfg' )
- two-operand? [ [ (convert-two-operand) ] local-optimization ] when ;
\ No newline at end of file
M: label JMP 0 JMP rc-relative label-fixup ;
M: label JUMPcc [ 0 ] dip JUMPcc rc-relative label-fixup ;
-M: x86 two-operand? t ;
-
M: x86 vector-regs float-regs ;
HOOK: stack-reg cpu ( -- reg )
M: x86 %set-slot ( src obj slot -- ) [+] swap MOV ;
M: x86 %set-slot-imm ( src obj slot tag -- ) (%slot-imm) swap MOV ;
+:: two-operand ( dst src1 src2 rep -- dst src )
+ dst src2 eq? [ "Cannot handle this case" throw ] when
+ dst src1 rep %copy
+ dst src2 ; inline
+
+:: one-operand ( dst src rep -- dst )
+ dst src rep %copy
+ dst ; inline
+
M: x86 %add 2over eq? [ nip ADD ] [ [+] LEA ] if ;
M: x86 %add-imm 2over eq? [ nip ADD ] [ [+] LEA ] if ;
-M: x86 %sub nip SUB ;
+M: x86 %sub int-rep two-operand SUB ;
M: x86 %sub-imm 2over eq? [ nip SUB ] [ neg [+] LEA ] if ;
-M: x86 %mul nip swap IMUL2 ;
+M: x86 %mul int-rep two-operand swap IMUL2 ;
M: x86 %mul-imm IMUL3 ;
-M: x86 %and nip AND ;
-M: x86 %and-imm nip AND ;
-M: x86 %or nip OR ;
-M: x86 %or-imm nip OR ;
-M: x86 %xor nip XOR ;
-M: x86 %xor-imm nip XOR ;
-M: x86 %shl-imm nip SHL ;
-M: x86 %shr-imm nip SHR ;
-M: x86 %sar-imm nip SAR ;
-
-M: x86 %min nip [ CMP ] [ CMOVG ] 2bi ;
-M: x86 %max nip [ CMP ] [ CMOVL ] 2bi ;
-
-M: x86 %not drop NOT ;
+M: x86 %and int-rep two-operand AND ;
+M: x86 %and-imm int-rep two-operand AND ;
+M: x86 %or int-rep two-operand OR ;
+M: x86 %or-imm int-rep two-operand OR ;
+M: x86 %xor int-rep two-operand XOR ;
+M: x86 %xor-imm int-rep two-operand XOR ;
+M: x86 %shl-imm int-rep two-operand SHL ;
+M: x86 %shr-imm int-rep two-operand SHR ;
+M: x86 %sar-imm int-rep two-operand SAR ;
+
+M: x86 %min int-rep two-operand [ CMP ] [ CMOVG ] 2bi ;
+M: x86 %max int-rep two-operand [ CMP ] [ CMOVL ] 2bi ;
+
+M: x86 %not int-rep one-operand NOT ;
M: x86 %log2 BSR ;
GENERIC: copy-register* ( dst src rep -- )
M: x86 %copy ( dst src rep -- )
2over eq? [ 3drop ] [ copy-register* ] if ;
-:: overflow-template ( label dst src1 src2 insn -- )
- src1 src2 insn call
- label JO ; inline
-
M: x86 %fixnum-add ( label dst src1 src2 -- )
- [ ADD ] overflow-template ;
+ int-rep two-operand ADD JO ;
M: x86 %fixnum-sub ( label dst src1 src2 -- )
- [ SUB ] overflow-template ;
+ int-rep two-operand SUB JO ;
M: x86 %fixnum-mul ( label dst src1 src2 -- )
- [ swap IMUL2 ] overflow-template ;
+ int-rep two-operand swap IMUL2 JO ;
: bignum@ ( reg n -- op )
cells bignum tag-number - [+] ; inline
"end" resolve-label
] with-scope ;
-M: x86 %add-float nip ADDSD ;
-M: x86 %sub-float nip SUBSD ;
-M: x86 %mul-float nip MULSD ;
-M: x86 %div-float nip DIVSD ;
-M: x86 %min-float nip MINSD ;
-M: x86 %max-float nip MAXSD ;
+M: x86 %add-float double-rep two-operand ADDSD ;
+M: x86 %sub-float double-rep two-operand SUBSD ;
+M: x86 %mul-float double-rep two-operand MULSD ;
+M: x86 %div-float double-rep two-operand DIVSD ;
+M: x86 %min-float double-rep two-operand MINSD ;
+M: x86 %max-float double-rep two-operand MAXSD ;
M: x86 %sqrt SQRTSD ;
M: x86 %single>double-float CVTSS2SD ;
} available-reps ;
M: x86 %add-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ float-4-rep [ ADDPS ] }
{ double-2-rep [ ADDPD ] }
{ uint-4-rep [ PADDD ] }
{ longlong-2-rep [ PADDQ ] }
{ ulonglong-2-rep [ PADDQ ] }
- } case drop ;
+ } case ;
M: x86 %add-vector-reps
{
} available-reps ;
M: x86 %saturated-add-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ char-16-rep [ PADDSB ] }
{ uchar-16-rep [ PADDUSB ] }
{ short-8-rep [ PADDSW ] }
{ ushort-8-rep [ PADDUSW ] }
- } case drop ;
+ } case ;
M: x86 %saturated-add-vector-reps
{
} available-reps ;
M: x86 %add-sub-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ float-4-rep [ ADDSUBPS ] }
{ double-2-rep [ ADDSUBPD ] }
- } case drop ;
+ } case ;
M: x86 %add-sub-vector-reps
{
} available-reps ;
M: x86 %sub-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ float-4-rep [ SUBPS ] }
{ double-2-rep [ SUBPD ] }
{ uint-4-rep [ PSUBD ] }
{ longlong-2-rep [ PSUBQ ] }
{ ulonglong-2-rep [ PSUBQ ] }
- } case drop ;
+ } case ;
M: x86 %sub-vector-reps
{
} available-reps ;
M: x86 %saturated-sub-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ char-16-rep [ PSUBSB ] }
{ uchar-16-rep [ PSUBUSB ] }
{ short-8-rep [ PSUBSW ] }
{ ushort-8-rep [ PSUBUSW ] }
- } case drop ;
+ } case ;
M: x86 %saturated-sub-vector-reps
{
} available-reps ;
M: x86 %mul-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ float-4-rep [ MULPS ] }
{ double-2-rep [ MULPD ] }
{ ushort-8-rep [ PMULLW ] }
{ int-4-rep [ PMULLD ] }
{ uint-4-rep [ PMULLD ] }
- } case drop ;
+ } case ;
M: x86 %mul-vector-reps
{
{ } ;
M: x86 %div-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ float-4-rep [ DIVPS ] }
{ double-2-rep [ DIVPD ] }
- } case drop ;
+ } case ;
M: x86 %div-vector-reps
{
} available-reps ;
M: x86 %min-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ char-16-rep [ PMINSB ] }
{ uchar-16-rep [ PMINUB ] }
{ uint-4-rep [ PMINUD ] }
{ float-4-rep [ MINPS ] }
{ double-2-rep [ MINPD ] }
- } case drop ;
+ } case ;
M: x86 %min-vector-reps
{
} available-reps ;
M: x86 %max-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ char-16-rep [ PMAXSB ] }
{ uchar-16-rep [ PMAXUB ] }
{ uint-4-rep [ PMAXUD ] }
{ float-4-rep [ MAXPS ] }
{ double-2-rep [ MAXPD ] }
- } case drop ;
+ } case ;
M: x86 %max-vector-reps
{
} available-reps ;
M: x86 %and-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ float-4-rep [ ANDPS ] }
{ double-2-rep [ ANDPD ] }
[ drop PAND ]
- } case drop ;
+ } case ;
M: x86 %and-vector-reps
{
} available-reps ;
M: x86 %or-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ float-4-rep [ ORPS ] }
{ double-2-rep [ ORPD ] }
[ drop POR ]
- } case drop ;
+ } case ;
M: x86 %or-vector-reps
{
} available-reps ;
M: x86 %xor-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ float-4-rep [ XORPS ] }
{ double-2-rep [ XORPD ] }
[ drop PXOR ]
- } case drop ;
+ } case ;
M: x86 %xor-vector-reps
{
} available-reps ;
M: x86 %shl-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ short-8-rep [ PSLLW ] }
{ ushort-8-rep [ PSLLW ] }
{ uint-4-rep [ PSLLD ] }
{ longlong-2-rep [ PSLLQ ] }
{ ulonglong-2-rep [ PSLLQ ] }
- } case drop ;
+ } case ;
M: x86 %shl-vector-reps
{
} available-reps ;
M: x86 %shr-vector ( dst src1 src2 rep -- )
+ [ two-operand ] keep
{
{ short-8-rep [ PSRAW ] }
{ ushort-8-rep [ PSRLW ] }
{ int-4-rep [ PSRAD ] }
{ uint-4-rep [ PSRLD ] }
{ ulonglong-2-rep [ PSRLQ ] }
- } case drop ;
+ } case ;
M: x86 %shr-vector-reps
{