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