Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 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 | |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 8 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
| 9 | // 64-bit comparisons: |
| 10 | // |
| 11 | // 1. The instruction sequences for vector vice scalar differ by a |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 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. |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 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 | // |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 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.] |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 24 | // |
Scott Michel | e0168c1 | 2009-01-05 01:34:35 +0000 | [diff] [blame] | 25 | // 5. The code sequences for r64 and v2i64 are probably overly conservative, |
| 26 | // compared to the code that gcc produces. |
| 27 | // |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 28 | // M00$E B!tes Kan be Pretty N@sTi!!!!! (appologies to Monty!) |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 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 | |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 37 | // select the negative condition: |
| 38 | class I64SELECTNegCond<PatFrag cond, CodeFrag compare>: |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 39 | Pat<(select (i32 (cond R64C:$rA, R64C:$rB)), R64C:$rTrue, R64C:$rFalse), |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 40 | (SELBr64_cond R64C:$rTrue, R64C:$rFalse, (FSMr32 compare.Fragment))>; |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 41 | |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 42 | // setcc the negative condition: |
| 43 | class I64SETCCNegCond<PatFrag cond, CodeFrag compare>: |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 44 | Pat<(cond R64C:$rA, R64C:$rB), |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 45 | (XORIr32 compare.Fragment, -1)>; |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 46 | |
Scott Michel | e0168c1 | 2009-01-05 01:34:35 +0000 | [diff] [blame] | 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 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 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), |
Scott Michel | e0168c1 | 2009-01-05 01:34:35 +0000 | [diff] [blame] | 59 | (ORv2i64_i64 R64C:$rB))), 0xb)>; |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 60 | |
| 61 | // The i64 seteq fragment that does the vector comparison |
| 62 | def CEQv2i64compare: |
Scott Michel | e0168c1 | 2009-01-05 01:34:35 +0000 | [diff] [blame] | 63 | CodeFrag<(CEQIv4i32 (GBv4i32 (CEQv4i32 VECREG:$rA, VECREG:$rB)), 0xf)>; |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 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>; |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 82 | def : Pat<(seteq (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)), I64EQv2i64.Fragment>; |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 83 | |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 84 | // i64 setne: |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 85 | def : I64SETCCNegCond<setne, I64EQr64>; |
Scott Michel | 4d07fb7 | 2008-12-30 23:28:25 +0000 | [diff] [blame] | 86 | def : I64SELECTNegCond<setne, I64EQr64>; |
Scott Michel | 06eabde | 2008-12-27 04:51:36 +0000 | [diff] [blame] | 87 | |
Scott Michel | e0168c1 | 2009-01-05 01:34:35 +0000 | [diff] [blame] | 88 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
Scott Michel | 0e2532a | 2009-01-05 04:05:53 +0000 | [diff] [blame^] | 89 | // i64 setugt/setule: |
Scott Michel | e0168c1 | 2009-01-05 01:34:35 +0000 | [diff] [blame] | 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>; |
Scott Michel | 0e2532a | 2009-01-05 04:05:53 +0000 | [diff] [blame^] | 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>; |