]> gitweb.factorcode.org Git - factor.git/blob - basis/compiler/cfg/two-operand/two-operand.factor
Solution to Project Euler problem 65
[factor.git] / basis / compiler / cfg / two-operand / two-operand.factor
1 ! Copyright (C) 2008, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors kernel sequences make combinators
4 compiler.cfg.registers compiler.cfg.instructions
5 compiler.cfg.rpo cpu.architecture ;
6 IN: compiler.cfg.two-operand
7
8 ! This pass runs before SSA coalescing and normalizes instructions
9 ! to fit the x86 two-address scheme. Since the input is in SSA,
10 ! it suffices to convert
11 !
12 ! x = y op z
13 !
14 ! to
15 !
16 ! x = y
17 ! x = x op z
18 !
19 ! We don't bother with ##add, ##add-imm, ##sub-imm or ##mul-imm
20 ! since x86 has LEA and IMUL instructions which are effectively
21 ! three-operand addition and multiplication, respectively.
22
23 UNION: two-operand-insn
24     ##sub
25     ##mul
26     ##and
27     ##and-imm
28     ##or
29     ##or-imm
30     ##xor
31     ##xor-imm
32     ##shl
33     ##shl-imm
34     ##shr
35     ##shr-imm
36     ##sar
37     ##sar-imm
38     ##min
39     ##max
40     ##fixnum-add
41     ##fixnum-sub
42     ##fixnum-mul
43     ##add-float
44     ##sub-float
45     ##mul-float
46     ##div-float
47     ##min-float
48     ##max-float
49     ##add-vector
50     ##sub-vector
51     ##mul-vector
52     ##div-vector
53     ##min-vector
54     ##max-vector ;
55
56 GENERIC: convert-two-operand* ( insn -- )
57
58 : emit-copy ( dst src -- )
59     dup rep-of ##copy ; inline
60
61 M: two-operand-insn convert-two-operand*
62     [ [ dst>> ] [ src1>> ] bi emit-copy ]
63     [
64         dup [ src1>> ] [ src2>> ] bi = [ dup dst>> >>src2 ] when
65         dup dst>> >>src1 ,
66     ] bi ;
67
68 M: ##not convert-two-operand*
69     [ [ dst>> ] [ src>> ] bi emit-copy ]
70     [ dup dst>> >>src , ]
71     bi ;
72
73 M: insn convert-two-operand* , ;
74
75 : (convert-two-operand) ( insns -- insns' )
76     dup first kill-vreg-insn? [
77         [ [ convert-two-operand* ] each ] V{ } make
78     ] unless ;
79
80 : convert-two-operand ( cfg -- cfg' )
81     two-operand? [ [ (convert-two-operand) ] local-optimization ] when ;