]> gitweb.factorcode.org Git - factor.git/commitdiff
compiler.cfg.two-operand: make it work in more cases
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Tue, 28 Jul 2009 03:28:29 +0000 (22:28 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Tue, 28 Jul 2009 03:28:29 +0000 (22:28 -0500)
basis/compiler/cfg/two-operand/two-operand-tests.factor [new file with mode: 0644]
basis/compiler/cfg/two-operand/two-operand.factor

diff --git a/basis/compiler/cfg/two-operand/two-operand-tests.factor b/basis/compiler/cfg/two-operand/two-operand-tests.factor
new file mode 100644 (file)
index 0000000..0d0c57e
--- /dev/null
@@ -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
index 0a52aa7c1a582c460daf1adfbf1fff9588919ba2..db3462bf0df8f10d8adb614a687255fb68914941 100644 (file)
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! 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 ;
 IN: compiler.cfg.two-operand
 
-! On x86, instructions take the form x = x op y
-! Our SSA IR is x = y op z
+! This pass runs after SSA coalescing and normalizes instructions
+! 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
 ! since x86 has LEA and IMUL instructions which are effectively
 ! three-operand addition and multiplication, respectively.
 
-: convert-two-operand/integer ( insn -- )
-    [ [ dst>> ] [ src1>> ] bi ##copy ]
-    [ dup dst>> >>src1 , ]
-    bi ; inline
+UNION: two-operand-insn
+    ##sub
+    ##mul
+    ##and
+    ##and-imm
+    ##or
+    ##or-imm
+    ##xor
+    ##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 -- )
 
-: convert-two-operand/float ( insn -- )
-    [ [ dst>> ] [ src1>> ] bi ##copy-float ]
+: 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
 
-GENERIC: convert-two-operand* ( insn -- )
+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*
-    [ [ dst>> ] [ src>> ] bi ##copy ]
-    [ dup dst>> >>src , ]
-    bi ;
-
-M: ##sub convert-two-operand* convert-two-operand/integer ;
-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 ;
+    dup [ dst>> ] [ src>> ] bi = [
+        [ [ dst>> ] [ src>> ] bi ##copy ]
+        [ dup dst>> >>src ]
+        bi
+    ] unless , ;
 
 M: insn convert-two-operand* , ;
 
+: (convert-two-operand) ( cfg -- cfg' )
+    [ [ convert-two-operand* ] each ] V{ } make ;
+
 : convert-two-operand ( cfg -- cfg' )
-    two-operand? [
-        [ [ [ convert-two-operand* ] each ] V{ } make ]
-        local-optimization
-    ] when ;
+    two-operand? [ [ (convert-two-operand) ] local-optimization ] when ;
\ No newline at end of file