CellSPU:
[oota-llvm.git] / lib / Target / CellSPU / SPU64InstrInfo.td
1 //====--- SPU64InstrInfo.td - Cell SPU 64-bit operations -*- tablegen -*--====//
2 //
3 //                     Cell SPU 64-bit operations
4 //
5 // Primary author: Scott Michel (scottm@aero.org)
6 //===----------------------------------------------------------------------===//
7
8 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
9 // 64-bit comparisons:
10 //
11 // 1. The instruction sequences for vector vice scalar differ by a
12 //    constant. In the scalar case, we're only interested in the
13 //    top two 32-bit slots, whereas we're interested in an exact
14 //    all-four-slot match in the vector case.
15 //
16 // 2. There are no "immediate" forms, since loading 64-bit constants
17 //    could be a constant pool load.
18 //
19 // 3. i64 setcc results are i32, which are subsequently converted to a FSM
20 //    mask when used in a select pattern.
21 //
22 // 4. v2i64 setcc results are v4i32, which can be converted to a FSM mask (TODO)
23 //    [Note: this may be moot, since gb produces v4i32 or r32.]
24 //
25 // 5. The code sequences for r64 and v2i64 are probably overly conservative,
26 //    compared to the code that gcc produces.
27 //
28 // M00$E B!tes Kan be Pretty N@sTi!!!!! (appologies to Monty!)
29 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
30
31 // selb instruction definition for i64. Note that the selection mask is
32 // a vector, produced by various forms of FSM:
33 def SELBr64_cond:
34    SELBInst<(outs R64C:$rT), (ins R64C:$rA, R64C:$rB, VECREG:$rC),
35             [/* no pattern */]>;
36
37 // select the negative condition:
38 class I64SELECTNegCond<PatFrag cond, CodeFrag compare>:
39   Pat<(select (i32 (cond R64C:$rA, R64C:$rB)), R64C:$rTrue, R64C:$rFalse),
40       (SELBr64_cond R64C:$rTrue, R64C:$rFalse, (FSMr32 compare.Fragment))>;
41
42 // setcc the negative condition:
43 class I64SETCCNegCond<PatFrag cond, CodeFrag compare>:
44   Pat<(cond R64C:$rA, R64C:$rB),
45       (XORIr32 compare.Fragment, -1)>;
46
47 // The generic i64 select pattern, which assumes that the comparison result
48 // is in a 32-bit register that contains a select mask pattern (i.e., gather
49 // bits result):
50
51 def : Pat<(select R32C:$rC, R64C:$rB, R64C:$rA),
52           (SELBr64_cond R64C:$rA, R64C:$rB, (FSMr32 R32C:$rC))>;
53
54 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
55 // The i64 seteq fragment that does the scalar->vector conversion and
56 // comparison:
57 def CEQr64compare:
58     CodeFrag<(CGTIv4i32 (GBv4i32 (CEQv4i32 (ORv2i64_i64 R64C:$rA),
59                                            (ORv2i64_i64 R64C:$rB))), 0xb)>;
60
61 // The i64 seteq fragment that does the vector comparison
62 def CEQv2i64compare:
63     CodeFrag<(CEQIv4i32 (GBv4i32 (CEQv4i32 VECREG:$rA, VECREG:$rB)), 0xf)>;
64
65 // i64 seteq (equality): the setcc result is i32, which is converted to a
66 // vector FSM mask when used in a select pattern.
67 //
68 // v2i64 seteq (equality): the setcc result is v4i32
69 multiclass CompareEqual64 {
70   // Plain old comparison, converts back to i32 scalar
71   def r64: CodeFrag<(ORi32_v4i32 CEQr64compare.Fragment)>;
72   def v2i64: CodeFrag<(ORi32_v4i32 CEQv2i64compare.Fragment)>;
73
74   // SELB mask from FSM:
75   def r64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CEQr64compare.Fragment))>;
76   def v2i64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CEQv2i64compare.Fragment))>;
77 }
78
79 defm I64EQ: CompareEqual64;
80
81 def : Pat<(seteq R64C:$rA, R64C:$rB), I64EQr64.Fragment>;
82 def : Pat<(seteq (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)), I64EQv2i64.Fragment>;
83
84 // i64 setne:
85 def : I64SETCCNegCond<setne, I64EQr64>;
86 def : I64SELECTNegCond<setne, I64EQr64>;
87
88 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
89 // i64 setugt/setule:
90 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
91
92 def CLGTr64ugt:
93     CodeFrag<(CLGTv4i32 (ORv2i64_i64 R64C:$rA), (ORv2i64_i64 R64C:$rB))>;
94
95 def CLGTr64eq:
96     CodeFrag<(CEQv4i32 (ORv2i64_i64 R64C:$rA), (ORv2i64_i64 R64C:$rB))>;
97     
98 def CLGTr64compare:
99     CodeFrag<(SELBv2i64 CLGTr64ugt.Fragment,
100                         (XSWDv2i64 CLGTr64ugt.Fragment),
101                         CLGTr64eq.Fragment)>;
102
103 def CLGTv2i64ugt:
104     CodeFrag<(CLGTv4i32 VECREG:$rA, VECREG:$rB)>;
105
106 def CLGTv2i64eq:
107     CodeFrag<(CEQv4i32 VECREG:$rA, VECREG:$rB)>;
108     
109 def CLGTv2i64compare:
110     CodeFrag<(SELBv2i64 CLGTv2i64ugt.Fragment,
111                         (XSWDv2i64 CLGTr64ugt.Fragment),
112                         CLGTv2i64eq.Fragment)>;
113
114 multiclass CompareLogicalGreaterThan64 {
115   // Plain old comparison, converts back to i32 scalar
116   def r64: CodeFrag<(ORi32_v4i32 CLGTr64compare.Fragment)>;
117   def v2i64: CodeFrag<CLGTv2i64compare.Fragment>;
118
119   // SELB mask from FSM:
120   def r64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CLGTr64compare.Fragment))>;
121   def v2i64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CLGTv2i64compare.Fragment))>;
122 }
123
124 defm I64LGT: CompareLogicalGreaterThan64;
125
126 def : Pat<(setugt R64C:$rA, R64C:$rB), I64LGTr64.Fragment>;
127 def : Pat<(setugt (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)),
128                   I64LGTv2i64.Fragment>;
129
130 // i64 setult:
131 def : I64SETCCNegCond<setule, I64LGTr64>;
132 def : I64SELECTNegCond<setule, I64LGTr64>;
133
134 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
135 // i64 setuge/setult:
136 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
137
138 def CLGEr64compare:
139     CodeFrag<(CGTIv4i32 (GBv4i32 (ORv4i32 CLGTr64ugt.Fragment,
140                                           CLGTr64eq.Fragment)), 0xb)>;
141
142 def CLGEv2i64compare:
143     CodeFrag<(CEQIv4i32 (GBv4i32 (ORv4i32 CLGTv2i64ugt.Fragment,
144                                           CLGTv2i64eq.Fragment)), 0xf)>;
145
146 multiclass CompareLogicalGreaterEqual64 {
147   // Plain old comparison, converts back to i32 scalar
148   def r64: CodeFrag<(ORi32_v4i32 CLGEr64compare.Fragment)>;
149   def v2i64: CodeFrag<CLGEv2i64compare.Fragment>;
150
151   // SELB mask from FSM:
152   def r64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CLGEr64compare.Fragment))>;
153   def v2i64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CLGEv2i64compare.Fragment))>;
154 }
155
156 defm I64LGE: CompareLogicalGreaterEqual64;
157
158 def : Pat<(setuge R64C:$rA, R64C:$rB), I64LGEr64.Fragment>;
159 def : Pat<(setuge (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)),
160                   I64LGEv2i64.Fragment>;
161
162 // i64 setult:
163 def : I64SETCCNegCond<setult, I64LGEr64>;
164 def : I64SELECTNegCond<setult, I64LGEr64>;
165
166 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
167 // i64 setgt/setle:
168 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
169
170 def CGTr64sgt:
171     CodeFrag<(CGTv4i32 (ORv2i64_i64 R64C:$rA), (ORv2i64_i64 R64C:$rB))>;
172
173 def CGTr64eq:
174     CodeFrag<(CEQv4i32 (ORv2i64_i64 R64C:$rA), (ORv2i64_i64 R64C:$rB))>;
175     
176 def CGTr64compare:
177     CodeFrag<(SELBv2i64 CGTr64sgt.Fragment,
178                         (XSWDv2i64 CGTr64sgt.Fragment),
179                         CGTr64eq.Fragment)>;
180
181 def CGTv2i64sgt:
182     CodeFrag<(CGTv4i32 VECREG:$rA, VECREG:$rB)>;
183
184 def CGTv2i64eq:
185     CodeFrag<(CEQv4i32 VECREG:$rA, VECREG:$rB)>;
186     
187 def CGTv2i64compare:
188     CodeFrag<(SELBv2i64 CGTv2i64sgt.Fragment,
189                         (XSWDv2i64 CGTr64sgt.Fragment),
190                         CGTv2i64eq.Fragment)>;
191
192 multiclass CompareGreaterThan64 {
193   // Plain old comparison, converts back to i32 scalar
194   def r64: CodeFrag<(ORi32_v4i32 CGTr64compare.Fragment)>;
195   def v2i64: CodeFrag<CGTv2i64compare.Fragment>;
196
197   // SELB mask from FSM:
198   def r64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CGTr64compare.Fragment))>;
199   def v2i64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CGTv2i64compare.Fragment))>;
200 }
201
202 defm I64GT: CompareLogicalGreaterThan64;
203
204 def : Pat<(setgt R64C:$rA, R64C:$rB), I64GTr64.Fragment>;
205 def : Pat<(setgt (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)),
206                   I64GTv2i64.Fragment>;
207
208 // i64 setult:
209 def : I64SETCCNegCond<setle, I64GTr64>;
210 def : I64SELECTNegCond<setle, I64GTr64>;
211
212 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
213 // i64 setge/setlt:
214 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
215     
216 def CGEr64compare:
217     CodeFrag<(CGTIv4i32 (GBv4i32 (ORv4i32 CGTr64sgt.Fragment,
218                                           CGTr64eq.Fragment)), 0xb)>;
219
220 def CGEv2i64compare:
221     CodeFrag<(CEQIv4i32 (GBv4i32 (ORv4i32 CGTv2i64sgt.Fragment,
222                                           CGTv2i64eq.Fragment)), 0xf)>;
223
224 multiclass CompareGreaterEqual64 {
225   // Plain old comparison, converts back to i32 scalar
226   def r64: CodeFrag<(ORi32_v4i32 CGEr64compare.Fragment)>;
227   def v2i64: CodeFrag<CGEv2i64compare.Fragment>;
228
229   // SELB mask from FSM:
230   def r64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CGEr64compare.Fragment))>;
231   def v2i64mask: CodeFrag<(ORi32_v4i32 (FSMv4i32 CGEv2i64compare.Fragment))>;
232 }
233
234 defm I64GE: CompareGreaterEqual64;
235
236 def : Pat<(setge R64C:$rA, R64C:$rB), I64GEr64.Fragment>;
237 def : Pat<(setge (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)),
238                   I64GEv2i64.Fragment>;
239
240 // i64 setult:
241 def : I64SETCCNegCond<setlt, I64GEr64>;
242 def : I64SELECTNegCond<setlt, I64GEr64>;