llvm.org GIT mirror llvm / e8cb2ee
[FastISel][X86] Optimize predicates and fold CMP instructions. This optimizes predicates for certain compares, such as fcmp oeq %x, %x to fcmp ord %x, %x. The latter one is more efficient to generate. The same optimization is applied to conditional branches. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211126 91177308-0d34-0410-b5e6-96231b3b80d8 Juergen Ributzka 5 years ago
3 changed file(s) with 996 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
153153 };
154154
155155 } // end anonymous namespace.
156
157 static CmpInst::Predicate optimizeCmpPredicate(const CmpInst *CI) {
158 // If both operands are the same, then try to optimize or fold the cmp.
159 CmpInst::Predicate Predicate = CI->getPredicate();
160 if (CI->getOperand(0) != CI->getOperand(1))
161 return Predicate;
162
163 switch (Predicate) {
164 default: llvm_unreachable("Invalid predicate!");
165 case CmpInst::FCMP_FALSE: Predicate = CmpInst::FCMP_FALSE; break;
166 case CmpInst::FCMP_OEQ: Predicate = CmpInst::FCMP_ORD; break;
167 case CmpInst::FCMP_OGT: Predicate = CmpInst::FCMP_FALSE; break;
168 case CmpInst::FCMP_OGE: Predicate = CmpInst::FCMP_ORD; break;
169 case CmpInst::FCMP_OLT: Predicate = CmpInst::FCMP_FALSE; break;
170 case CmpInst::FCMP_OLE: Predicate = CmpInst::FCMP_ORD; break;
171 case CmpInst::FCMP_ONE: Predicate = CmpInst::FCMP_FALSE; break;
172 case CmpInst::FCMP_ORD: Predicate = CmpInst::FCMP_ORD; break;
173 case CmpInst::FCMP_UNO: Predicate = CmpInst::FCMP_UNO; break;
174 case CmpInst::FCMP_UEQ: Predicate = CmpInst::FCMP_TRUE; break;
175 case CmpInst::FCMP_UGT: Predicate = CmpInst::FCMP_UNO; break;
176 case CmpInst::FCMP_UGE: Predicate = CmpInst::FCMP_TRUE; break;
177 case CmpInst::FCMP_ULT: Predicate = CmpInst::FCMP_UNO; break;
178 case CmpInst::FCMP_ULE: Predicate = CmpInst::FCMP_TRUE; break;
179 case CmpInst::FCMP_UNE: Predicate = CmpInst::FCMP_UNO; break;
180 case CmpInst::FCMP_TRUE: Predicate = CmpInst::FCMP_TRUE; break;
181
182 case CmpInst::ICMP_EQ: Predicate = CmpInst::FCMP_TRUE; break;
183 case CmpInst::ICMP_NE: Predicate = CmpInst::FCMP_FALSE; break;
184 case CmpInst::ICMP_UGT: Predicate = CmpInst::FCMP_FALSE; break;
185 case CmpInst::ICMP_UGE: Predicate = CmpInst::FCMP_TRUE; break;
186 case CmpInst::ICMP_ULT: Predicate = CmpInst::FCMP_FALSE; break;
187 case CmpInst::ICMP_ULE: Predicate = CmpInst::FCMP_TRUE; break;
188 case CmpInst::ICMP_SGT: Predicate = CmpInst::FCMP_FALSE; break;
189 case CmpInst::ICMP_SGE: Predicate = CmpInst::FCMP_TRUE; break;
190 case CmpInst::ICMP_SLT: Predicate = CmpInst::FCMP_FALSE; break;
191 case CmpInst::ICMP_SLE: Predicate = CmpInst::FCMP_TRUE; break;
192 }
193
194 return Predicate;
195 }
156196
157197 static std::pair
158198 getX86ConditonCode(CmpInst::Predicate Predicate) {
10471087 if (!isTypeLegal(I->getOperand(0)->getType(), VT))
10481088 return false;
10491089
1090 // Try to optimize or fold the cmp.
1091 CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
1092 unsigned ResultReg = 0;
1093 switch (Predicate) {
1094 default: break;
1095 case CmpInst::FCMP_FALSE: {
1096 ResultReg = createResultReg(&X86::GR32RegClass);
1097 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::MOV32r0),
1098 ResultReg);
1099 ResultReg = FastEmitInst_extractsubreg(MVT::i8, ResultReg, /*Kill=*/true,
1100 X86::sub_8bit);
1101 if (!ResultReg)
1102 return false;
1103 break;
1104 }
1105 case CmpInst::FCMP_TRUE: {
1106 ResultReg = createResultReg(&X86::GR8RegClass);
1107 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::MOV8ri),
1108 ResultReg).addImm(1);
1109 break;
1110 }
1111 }
1112
1113 if (ResultReg) {
1114 UpdateValueMap(I, ResultReg);
1115 return true;
1116 }
1117
1118 const Value *LHS = CI->getOperand(0);
1119 const Value *RHS = CI->getOperand(1);
1120
1121 // The optimizer might have replaced fcmp oeq %x, %x with fcmp ord %x, 0.0.
1122 // We don't have to materialize a zero constant for this case and can just use
1123 // %x again on the RHS.
1124 if (Predicate == CmpInst::FCMP_ORD || Predicate == CmpInst::FCMP_UNO) {
1125 const auto *RHSC = dyn_cast(RHS);
1126 if (RHSC && RHSC->isNullValue())
1127 RHS = LHS;
1128 }
1129
10501130 // FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
10511131 static unsigned SETFOpcTable[2][3] = {
10521132 { X86::SETEr, X86::SETNPr, X86::AND8rr },
10531133 { X86::SETNEr, X86::SETPr, X86::OR8rr }
10541134 };
10551135 unsigned *SETFOpc = nullptr;
1056 switch (CI->getPredicate()) {
1136 switch (Predicate) {
10571137 default: break;
10581138 case CmpInst::FCMP_OEQ: SETFOpc = &SETFOpcTable[0][0]; break;
10591139 case CmpInst::FCMP_UNE: SETFOpc = &SETFOpcTable[1][0]; break;
10601140 }
10611141
1062 unsigned ResultReg = createResultReg(&X86::GR8RegClass);
1142 ResultReg = createResultReg(&X86::GR8RegClass);
10631143 if (SETFOpc) {
1064 if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT))
1144 if (!X86FastEmitCompare(LHS, RHS, VT))
10651145 return false;
10661146
10671147 unsigned FlagReg1 = createResultReg(&X86::GR8RegClass);
10771157 }
10781158
10791159 X86::CondCode CC;
1080 bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
1081 std::tie(CC, SwapArgs) = getX86ConditonCode(CI->getPredicate());
1160 bool SwapArgs;
1161 std::tie(CC, SwapArgs) = getX86ConditonCode(Predicate);
10821162 assert(CC <= X86::LAST_VALID_COND && "Unexpected conditon code.");
10831163 unsigned Opc = X86::getSETFromCond(CC);
10841164
1085 const Value *LHS = CI->getOperand(0);
1086 const Value *RHS = CI->getOperand(1);
10871165 if (SwapArgs)
10881166 std::swap(LHS, RHS);
10891167
1090 // Emit a compare of Op0/Op1.
1168 // Emit a compare of LHS/RHS.
10911169 if (!X86FastEmitCompare(LHS, RHS, VT))
10921170 return false;
10931171
11611239 if (CI->hasOneUse() && CI->getParent() == I->getParent()) {
11621240 EVT VT = TLI.getValueType(CI->getOperand(0)->getType());
11631241
1242 // Try to optimize or fold the cmp.
1243 CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
1244 switch (Predicate) {
1245 default: break;
1246 case CmpInst::FCMP_FALSE: FastEmitBranch(FalseMBB, DbgLoc); return true;
1247 case CmpInst::FCMP_TRUE: FastEmitBranch(TrueMBB, DbgLoc); return true;
1248 }
1249
1250 const Value *CmpLHS = CI->getOperand(0);
1251 const Value *CmpRHS = CI->getOperand(1);
1252
1253 // The optimizer might have replaced fcmp oeq %x, %x with fcmp ord %x,
1254 // 0.0.
1255 // We don't have to materialize a zero constant for this case and can just
1256 // use %x again on the RHS.
1257 if (Predicate == CmpInst::FCMP_ORD || Predicate == CmpInst::FCMP_UNO) {
1258 const auto *CmpRHSC = dyn_cast(CmpRHS);
1259 if (CmpRHSC && CmpRHSC->isNullValue())
1260 CmpRHS = CmpLHS;
1261 }
1262
11641263 // Try to take advantage of fallthrough opportunities.
1165 CmpInst::Predicate Predicate = CI->getPredicate();
11661264 if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) {
11671265 std::swap(TrueMBB, FalseMBB);
11681266 Predicate = CmpInst::getInversePredicate(Predicate);
11851283 }
11861284
11871285 X86::CondCode CC;
1188 bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
1189 unsigned BranchOpc; // Opcode to jump on, e.g. "X86::JA"
1286 bool SwapArgs;
1287 unsigned BranchOpc;
11901288 std::tie(CC, SwapArgs) = getX86ConditonCode(Predicate);
11911289 assert(CC <= X86::LAST_VALID_COND && "Unexpected conditon code.");
11921290
11931291 BranchOpc = X86::GetCondBranchFromCond(CC);
1194 const Value *CmpLHS = CI->getOperand(0);
1195 const Value *CmpRHS = CI->getOperand(1);
11961292 if (SwapArgs)
11971293 std::swap(CmpLHS, CmpRHS);
11981294
0 ; RUN: llc < %s -fast-isel -fast-isel-abort -mtriple=x86_64-apple-darwin10 | FileCheck %s
1
2 define i32 @fcmp_oeq1(float %x) {
3 ; CHECK-LABEL: fcmp_oeq1
4 ; CHECK: ucomiss %xmm0, %xmm0
5 ; CHECK-NEXT: jp {{LBB.+_1}}
6 %1 = fcmp oeq float %x, %x
7 br i1 %1, label %bb1, label %bb2
8 bb2:
9 ret i32 1
10 bb1:
11 ret i32 0
12 }
13
14 define i32 @fcmp_oeq2(float %x) {
15 ; CHECK-LABEL: fcmp_oeq2
16 ; CHECK: xorps %xmm1, %xmm1
17 ; CHECK-NEXT: ucomiss %xmm1, %xmm0
18 ; CHECK-NEXT: jne {{LBB.+_1}}
19 ; CHECK-NEXT: jnp {{LBB.+_2}}
20 %1 = fcmp oeq float %x, 0.000000e+00
21 br i1 %1, label %bb1, label %bb2
22 bb2:
23 ret i32 1
24 bb1:
25 ret i32 0
26 }
27
28 define i32 @fcmp_ogt1(float %x) {
29 ; CHECK-LABEL: fcmp_ogt1
30 ; CHECK-NOT: ucomiss
31 ; CHECK: movl $1, %eax
32 %1 = fcmp ogt float %x, %x
33 br i1 %1, label %bb1, label %bb2
34 bb2:
35 ret i32 1
36 bb1:
37 ret i32 0
38 }
39
40 define i32 @fcmp_ogt2(float %x) {
41 ; CHECK-LABEL: fcmp_ogt2
42 ; CHECK: xorps %xmm1, %xmm1
43 ; CHECK-NEXT: ucomiss %xmm1, %xmm0
44 ; CHECK-NEXT: jbe {{LBB.+_1}}
45 %1 = fcmp ogt float %x, 0.000000e+00
46 br i1 %1, label %bb1, label %bb2
47 bb2:
48 ret i32 1
49 bb1:
50 ret i32 0
51 }
52
53 define i32 @fcmp_oge1(float %x) {
54 ; CHECK-LABEL: fcmp_oge1
55 ; CHECK: ucomiss %xmm0, %xmm0
56 ; CHECK-NEXT: jp {{LBB.+_1}}
57 %1 = fcmp oge float %x, %x
58 br i1 %1, label %bb1, label %bb2
59 bb2:
60 ret i32 1
61 bb1:
62 ret i32 0
63 }
64
65 define i32 @fcmp_oge2(float %x) {
66 ; CHECK-LABEL: fcmp_oge2
67 ; CHECK: xorps %xmm1, %xmm1
68 ; CHECK-NEXT: ucomiss %xmm1, %xmm0
69 ; CHECK-NEXT: jb {{LBB.+_1}}
70 %1 = fcmp oge float %x, 0.000000e+00
71 br i1 %1, label %bb1, label %bb2
72 bb2:
73 ret i32 1
74 bb1:
75 ret i32 0
76 }
77
78 define i32 @fcmp_olt1(float %x) {
79 ; CHECK-LABEL: fcmp_olt1
80 ; CHECK-NOT: ucomiss
81 ; CHECK: movl $1, %eax
82 %1 = fcmp olt float %x, %x
83 br i1 %1, label %bb1, label %bb2
84 bb2:
85 ret i32 1
86 bb1:
87 ret i32 0
88 }
89
90 define i32 @fcmp_olt2(float %x) {
91 ; CHECK-LABEL: fcmp_olt2
92 ; CHECK: xorps %xmm1, %xmm1
93 ; CHECK-NEXT: ucomiss %xmm0, %xmm1
94 ; CHECK-NEXT: jbe {{LBB.+_1}}
95 %1 = fcmp olt float %x, 0.000000e+00
96 br i1 %1, label %bb1, label %bb2
97 bb2:
98 ret i32 1
99 bb1:
100 ret i32 0
101 }
102
103 define i32 @fcmp_ole1(float %x) {
104 ; CHECK-LABEL: fcmp_ole1
105 ; CHECK: ucomiss %xmm0, %xmm0
106 ; CHECK-NEXT: jp {{LBB.+_1}}
107 %1 = fcmp ole float %x, %x
108 br i1 %1, label %bb1, label %bb2
109 bb2:
110 ret i32 1
111 bb1:
112 ret i32 0
113 }
114
115 define i32 @fcmp_ole2(float %x) {
116 ; CHECK-LABEL: fcmp_ole2
117 ; CHECK: xorps %xmm1, %xmm1
118 ; CHECK-NEXT: ucomiss %xmm0, %xmm1
119 ; CHECK-NEXT: jb {{LBB.+_1}}
120 %1 = fcmp ole float %x, 0.000000e+00
121 br i1 %1, label %bb1, label %bb2
122 bb2:
123 ret i32 1
124 bb1:
125 ret i32 0
126 }
127
128 define i32 @fcmp_one1(float %x) {
129 ; CHECK-LABEL: fcmp_one1
130 ; CHECK-NOT: ucomiss
131 ; CHECK: movl $1, %eax
132 %1 = fcmp one float %x, %x
133 br i1 %1, label %bb1, label %bb2
134 bb2:
135 ret i32 1
136 bb1:
137 ret i32 0
138 }
139
140 define i32 @fcmp_one2(float %x) {
141 ; CHECK-LABEL: fcmp_one2
142 ; CHECK: xorps %xmm1, %xmm1
143 ; CHECK-NEXT: ucomiss %xmm1, %xmm0
144 ; CHECK-NEXT: je {{LBB.+_1}}
145 %1 = fcmp one float %x, 0.000000e+00
146 br i1 %1, label %bb1, label %bb2
147 bb2:
148 ret i32 1
149 bb1:
150 ret i32 0
151 }
152
153 define i32 @fcmp_ord1(float %x) {
154 ; CHECK-LABEL: fcmp_ord1
155 ; CHECK: ucomiss %xmm0, %xmm0
156 ; CHECK-NEXT: jp {{LBB.+_1}}
157 %1 = fcmp ord float %x, %x
158 br i1 %1, label %bb1, label %bb2
159 bb2:
160 ret i32 1
161 bb1:
162 ret i32 0
163 }
164
165 define i32 @fcmp_ord2(float %x) {
166 ; CHECK-LABEL: fcmp_ord2
167 ; CHECK: ucomiss %xmm0, %xmm0
168 ; CHECK-NEXT: jp {{LBB.+_1}}
169 %1 = fcmp ord float %x, 0.000000e+00
170 br i1 %1, label %bb1, label %bb2
171 bb2:
172 ret i32 1
173 bb1:
174 ret i32 0
175 }
176
177 define i32 @fcmp_uno1(float %x) {
178 ; CHECK-LABEL: fcmp_uno1
179 ; CHECK: ucomiss %xmm0, %xmm0
180 ; CHECK-NEXT: jp {{LBB.+_2}}
181 %1 = fcmp uno float %x, %x
182 br i1 %1, label %bb1, label %bb2
183 bb2:
184 ret i32 1
185 bb1:
186 ret i32 0
187 }
188
189 define i32 @fcmp_uno2(float %x) {
190 ; CHECK-LABEL: fcmp_uno2
191 ; CHECK: ucomiss %xmm0, %xmm0
192 ; CHECK-NEXT: jp {{LBB.+_2}}
193 %1 = fcmp uno float %x, 0.000000e+00
194 br i1 %1, label %bb1, label %bb2
195 bb2:
196 ret i32 1
197 bb1:
198 ret i32 0
199 }
200
201 define i32 @fcmp_ueq1(float %x) {
202 ; CHECK-LABEL: fcmp_ueq1
203 ; CHECK-NOT: ucomiss
204 %1 = fcmp ueq float %x, %x
205 br i1 %1, label %bb1, label %bb2
206 bb2:
207 ret i32 1
208 bb1:
209 ret i32 0
210 }
211
212 define i32 @fcmp_ueq2(float %x) {
213 ; CHECK-LABEL: fcmp_ueq2
214 ; CHECK: xorps %xmm1, %xmm1
215 ; CHECK-NEXT: ucomiss %xmm1, %xmm0
216 ; CHECK-NEXT: je {{LBB.+_2}}
217 %1 = fcmp ueq float %x, 0.000000e+00
218 br i1 %1, label %bb1, label %bb2
219 bb2:
220 ret i32 1
221 bb1:
222 ret i32 0
223 }
224
225 define i32 @fcmp_ugt1(float %x) {
226 ; CHECK-LABEL: fcmp_ugt1
227 ; CHECK: ucomiss %xmm0, %xmm0
228 ; CHECK-NEXT: jnp {{LBB.+_1}}
229 %1 = fcmp ugt float %x, %x
230 br i1 %1, label %bb1, label %bb2
231 bb2:
232 ret i32 1
233 bb1:
234 ret i32 0
235 }
236
237 define i32 @fcmp_ugt2(float %x) {
238 ; CHECK-LABEL: fcmp_ugt2
239 ; CHECK: xorps %xmm1, %xmm1
240 ; CHECK-NEXT: ucomiss %xmm0, %xmm1
241 ; CHECK-NEXT: jae {{LBB.+_1}}
242 %1 = fcmp ugt float %x, 0.000000e+00
243 br i1 %1, label %bb1, label %bb2
244 bb2:
245 ret i32 1
246 bb1:
247 ret i32 0
248 }
249
250 define i32 @fcmp_uge1(float %x) {
251 ; CHECK-LABEL: fcmp_uge1
252 ; CHECK-NOT: ucomiss
253 %1 = fcmp uge float %x, %x
254 br i1 %1, label %bb1, label %bb2
255 bb2:
256 ret i32 1
257 bb1:
258 ret i32 0
259 }
260
261 define i32 @fcmp_uge2(float %x) {
262 ; CHECK-LABEL: fcmp_uge2
263 ; CHECK: xorps %xmm1, %xmm1
264 ; CHECK-NEXT: ucomiss %xmm0, %xmm1
265 ; CHECK-NEXT: ja {{LBB.+_1}}
266 %1 = fcmp uge float %x, 0.000000e+00
267 br i1 %1, label %bb1, label %bb2
268 bb2:
269 ret i32 1
270 bb1:
271 ret i32 0
272 }
273
274 define i32 @fcmp_ult1(float %x) {
275 ; CHECK-LABEL: fcmp_ult1
276 ; CHECK: ucomiss %xmm0, %xmm0
277 ; CHECK-NEXT: jnp {{LBB.+_1}}
278 %1 = fcmp ult float %x, %x
279 br i1 %1, label %bb1, label %bb2
280 bb2:
281 ret i32 1
282 bb1:
283 ret i32 0
284 }
285
286 define i32 @fcmp_ult2(float %x) {
287 ; CHECK-LABEL: fcmp_ult2
288 ; CHECK: xorps %xmm1, %xmm1
289 ; CHECK-NEXT: ucomiss %xmm1, %xmm0
290 ; CHECK-NEXT: jae {{LBB.+_1}}
291 %1 = fcmp ult float %x, 0.000000e+00
292 br i1 %1, label %bb1, label %bb2
293 bb2:
294 ret i32 1
295 bb1:
296 ret i32 0
297 }
298
299 define i32 @fcmp_ule1(float %x) {
300 ; CHECK-LABEL: fcmp_ule1
301 ; CHECK-NOT: ucomiss
302 %1 = fcmp ule float %x, %x
303 br i1 %1, label %bb1, label %bb2
304 bb2:
305 ret i32 1
306 bb1:
307 ret i32 0
308 }
309
310 define i32 @fcmp_ule2(float %x) {
311 ; CHECK-LABEL: fcmp_ule2
312 ; CHECK: xorps %xmm1, %xmm1
313 ; CHECK-NEXT: ucomiss %xmm1, %xmm0
314 ; CHECK-NEXT: ja {{LBB.+_1}}
315 %1 = fcmp ule float %x, 0.000000e+00
316 br i1 %1, label %bb1, label %bb2
317 bb2:
318 ret i32 1
319 bb1:
320 ret i32 0
321 }
322
323 define i32 @fcmp_une1(float %x) {
324 ; CHECK-LABEL: fcmp_une1
325 ; CHECK: ucomiss %xmm0, %xmm0
326 ; CHECK-NEXT: jnp {{LBB.+_1}}
327 %1 = fcmp une float %x, %x
328 br i1 %1, label %bb1, label %bb2
329 bb2:
330 ret i32 1
331 bb1:
332 ret i32 0
333 }
334
335 define i32 @fcmp_une2(float %x) {
336 ; CHECK-LABEL: fcmp_une2
337 ; CHECK: xorps %xmm1, %xmm1
338 ; CHECK-NEXT: ucomiss %xmm1, %xmm0
339 ; CHECK-NEXT: jne {{LBB.+_2}}
340 ; CHECK-NEXT: jp {{LBB.+_2}}
341 ; CHECK-NEXT: jmp {{LBB.+_1}}
342 %1 = fcmp une float %x, 0.000000e+00
343 br i1 %1, label %bb1, label %bb2
344 bb2:
345 ret i32 1
346 bb1:
347 ret i32 0
348 }
349
350 define i32 @icmp_eq(i32 %x) {
351 ; CHECK-LABEL: icmp_eq
352 ; CHECK-NOT: cmpl
353 ; CHECK: movl $0, %eax
354 %1 = icmp eq i32 %x, %x
355 br i1 %1, label %bb1, label %bb2
356 bb2:
357 ret i32 1
358 bb1:
359 ret i32 0
360 }
361
362 define i32 @icmp_ne(i32 %x) {
363 ; CHECK-LABEL: icmp_ne
364 ; CHECK-NOT: cmpl
365 ; CHECK: movl $1, %eax
366 %1 = icmp ne i32 %x, %x
367 br i1 %1, label %bb1, label %bb2
368 bb2:
369 ret i32 1
370 bb1:
371 ret i32 0
372 }
373
374 define i32 @icmp_ugt(i32 %x) {
375 ; CHECK-LABEL: icmp_ugt
376 ; CHECK-NOT: cmpl
377 ; CHECK: movl $1, %eax
378 %1 = icmp ugt i32 %x, %x
379 br i1 %1, label %bb1, label %bb2
380 bb2:
381 ret i32 1
382 bb1:
383 ret i32 0
384 }
385
386 define i32 @icmp_uge(i32 %x) {
387 ; CHECK-LABEL: icmp_uge
388 ; CHECK-NOT: cmpl
389 ; CHECK: movl $0, %eax
390 %1 = icmp uge i32 %x, %x
391 br i1 %1, label %bb1, label %bb2
392 bb2:
393 ret i32 1
394 bb1:
395 ret i32 0
396 }
397
398 define i32 @icmp_ult(i32 %x) {
399 ; CHECK-LABEL: icmp_ult
400 ; CHECK-NOT: cmpl
401 ; CHECK: movl $1, %eax
402 %1 = icmp ult i32 %x, %x
403 br i1 %1, label %bb1, label %bb2
404 bb2:
405 ret i32 1
406 bb1:
407 ret i32 0
408 }
409
410 define i32 @icmp_ule(i32 %x) {
411 ; CHECK-LABEL: icmp_ule
412 ; CHECK-NOT: cmpl
413 ; CHECK: movl $0, %eax
414 %1 = icmp ule i32 %x, %x
415 br i1 %1, label %bb1, label %bb2
416 bb2:
417 ret i32 1
418 bb1:
419 ret i32 0
420 }
421
422 define i32 @icmp_sgt(i32 %x) {
423 ; CHECK-LABEL: icmp_sgt
424 ; CHECK-NOT: cmpl
425 ; CHECK: movl $1, %eax
426 %1 = icmp sgt i32 %x, %x
427 br i1 %1, label %bb1, label %bb2
428 bb2:
429 ret i32 1
430 bb1:
431 ret i32 0
432 }
433
434 define i32 @icmp_sge(i32 %x) {
435 ; CHECK-LABEL: icmp_sge
436 ; CHECK-NOT: cmpl
437 ; CHECK: movl $0, %eax
438 %1 = icmp sge i32 %x, %x
439 br i1 %1, label %bb1, label %bb2
440 bb2:
441 ret i32 1
442 bb1:
443 ret i32 0
444 }
445
446 define i32 @icmp_slt(i32 %x) {
447 ; CHECK-LABEL: icmp_slt
448 ; CHECK-NOT: cmpl
449 ; CHECK: movl $1, %eax
450 %1 = icmp slt i32 %x, %x
451 br i1 %1, label %bb1, label %bb2
452 bb2:
453 ret i32 1
454 bb1:
455 ret i32 0
456 }
457
458 define i32 @icmp_sle(i32 %x) {
459 ; CHECK-LABEL: icmp_sle
460 ; CHECK-NOT: cmpl
461 ; CHECK: movl $0, %eax
462 %1 = icmp sle i32 %x, %x
463 br i1 %1, label %bb1, label %bb2
464 bb2:
465 ret i32 1
466 bb1:
467 ret i32 0
468 }
469
269269 ret i1 %1
270270 }
271271
272 ; Test cmp folding and condition optimization.
273 define zeroext i1 @fcmp_oeq2(float %x) {
274 ; SDAG-LABEL: fcmp_oeq2
275 ; SDAG: ucomiss %xmm0, %xmm0
276 ; SDAG-NEXT: setnp %al
277 ; FAST-LABEL: fcmp_oeq2
278 ; FAST: ucomiss %xmm0, %xmm0
279 ; FAST-NEXT: setnp %al
280 %1 = fcmp oeq float %x, %x
281 ret i1 %1
282 }
283
284 define zeroext i1 @fcmp_oeq3(float %x) {
285 ; SDAG-LABEL: fcmp_oeq3
286 ; SDAG: xorps %xmm1, %xmm1
287 ; SDAG-NEXT: cmpeqss %xmm1, %xmm0
288 ; SDAG-NEXT: movd %xmm0, %eax
289 ; SDAG-NEXT: andl $1, %eax
290 ; FAST-LABEL: fcmp_oeq3
291 ; FAST: xorps %xmm1, %xmm1
292 ; FAST-NEXT: ucomiss %xmm1, %xmm0
293 ; FAST-NEXT: sete %al
294 ; FAST-NEXT: setnp %cl
295 ; FAST-NEXT: andb %al, %cl
296 %1 = fcmp oeq float %x, 0.000000e+00
297 ret i1 %1
298 }
299
300 define zeroext i1 @fcmp_ogt2(float %x) {
301 ; SDAG-LABEL: fcmp_ogt2
302 ; SDAG: xorl %eax, %eax
303 ; FAST-LABEL: fcmp_ogt2
304 ; FAST: xorl %eax, %eax
305 %1 = fcmp ogt float %x, %x
306 ret i1 %1
307 }
308
309 define zeroext i1 @fcmp_ogt3(float %x) {
310 ; SDAG-LABEL: fcmp_ogt3
311 ; SDAG: xorps %xmm1, %xmm1
312 ; SDAG-NEXT: ucomiss %xmm1, %xmm0
313 ; SDAG-NEXT: seta %al
314 ; FAST-LABEL: fcmp_ogt3
315 ; FAST: xorps %xmm1, %xmm1
316 ; FAST-NEXT: ucomiss %xmm1, %xmm0
317 ; FAST-NEXT: seta %al
318 %1 = fcmp ogt float %x, 0.000000e+00
319 ret i1 %1
320 }
321
322 define zeroext i1 @fcmp_oge2(float %x) {
323 ; SDAG-LABEL: fcmp_oge2
324 ; SDAG: ucomiss %xmm0, %xmm0
325 ; SDAG-NEXT: setnp %al
326 ; FAST-LABEL: fcmp_oge2
327 ; FAST: ucomiss %xmm0, %xmm0
328 ; FAST-NEXT: setnp %al
329 %1 = fcmp oge float %x, %x
330 ret i1 %1
331 }
332
333 define zeroext i1 @fcmp_oge3(float %x) {
334 ; SDAG-LABEL: fcmp_oge3
335 ; SDAG: xorps %xmm1, %xmm1
336 ; SDAG-NEXT: ucomiss %xmm1, %xmm0
337 ; SDAG-NEXT: setae %al
338 ; FAST-LABEL: fcmp_oge3
339 ; FAST: xorps %xmm1, %xmm1
340 ; FAST-NEXT: ucomiss %xmm1, %xmm0
341 ; FAST-NEXT: setae %al
342 %1 = fcmp oge float %x, 0.000000e+00
343 ret i1 %1
344 }
345
346 define zeroext i1 @fcmp_olt2(float %x) {
347 ; SDAG-LABEL: fcmp_olt2
348 ; SDAG: xorl %eax, %eax
349 ; FAST-LABEL: fcmp_olt2
350 ; FAST: xorl %eax, %eax
351 %1 = fcmp olt float %x, %x
352 ret i1 %1
353 }
354
355 define zeroext i1 @fcmp_olt3(float %x) {
356 ; SDAG-LABEL: fcmp_olt3
357 ; SDAG: xorps %xmm1, %xmm1
358 ; SDAG-NEXT: ucomiss %xmm0, %xmm1
359 ; SDAG-NEXT: seta %al
360 ; FAST-LABEL: fcmp_olt3
361 ; FAST: xorps %xmm1, %xmm1
362 ; FAST-NEXT: ucomiss %xmm0, %xmm1
363 ; FAST-NEXT: seta %al
364 %1 = fcmp olt float %x, 0.000000e+00
365 ret i1 %1
366 }
367
368 define zeroext i1 @fcmp_ole2(float %x) {
369 ; SDAG-LABEL: fcmp_ole2
370 ; SDAG: ucomiss %xmm0, %xmm0
371 ; SDAG-NEXT: setnp %al
372 ; FAST-LABEL: fcmp_ole2
373 ; FAST: ucomiss %xmm0, %xmm0
374 ; FAST-NEXT: setnp %al
375 %1 = fcmp ole float %x, %x
376 ret i1 %1
377 }
378
379 define zeroext i1 @fcmp_ole3(float %x) {
380 ; SDAG-LABEL: fcmp_ole3
381 ; SDAG: xorps %xmm1, %xmm1
382 ; SDAG-NEXT: ucomiss %xmm0, %xmm1
383 ; SDAG-NEXT: setae %al
384 ; FAST-LABEL: fcmp_ole3
385 ; FAST: xorps %xmm1, %xmm1
386 ; FAST-NEXT: ucomiss %xmm0, %xmm1
387 ; FAST-NEXT: setae %al
388 %1 = fcmp ole float %x, 0.000000e+00
389 ret i1 %1
390 }
391
392 define zeroext i1 @fcmp_one2(float %x) {
393 ; SDAG-LABEL: fcmp_one2
394 ; SDAG: xorl %eax, %eax
395 ; FAST-LABEL: fcmp_one2
396 ; FAST: xorl %eax, %eax
397 %1 = fcmp one float %x, %x
398 ret i1 %1
399 }
400
401 define zeroext i1 @fcmp_one3(float %x) {
402 ; SDAG-LABEL: fcmp_one3
403 ; SDAG: xorps %xmm1, %xmm1
404 ; SDAG-NEXT: ucomiss %xmm1, %xmm0
405 ; SDAG-NEXT: setne %al
406 ; FAST-LABEL: fcmp_one3
407 ; FAST: xorps %xmm1, %xmm1
408 ; FAST-NEXT: ucomiss %xmm1, %xmm0
409 ; FAST-NEXT: setne %al
410 %1 = fcmp one float %x, 0.000000e+00
411 ret i1 %1
412 }
413
414 define zeroext i1 @fcmp_ord2(float %x) {
415 ; SDAG-LABEL: fcmp_ord2
416 ; SDAG: ucomiss %xmm0, %xmm0
417 ; SDAG-NEXT: setnp %al
418 ; FAST-LABEL: fcmp_ord2
419 ; FAST: ucomiss %xmm0, %xmm0
420 ; FAST-NEXT: setnp %al
421 %1 = fcmp ord float %x, %x
422 ret i1 %1
423 }
424
425 define zeroext i1 @fcmp_ord3(float %x) {
426 ; SDAG-LABEL: fcmp_ord3
427 ; SDAG: ucomiss %xmm0, %xmm0
428 ; SDAG-NEXT: setnp %al
429 ; FAST-LABEL: fcmp_ord3
430 ; FAST: ucomiss %xmm0, %xmm0
431 ; FAST-NEXT: setnp %al
432 %1 = fcmp ord float %x, 0.000000e+00
433 ret i1 %1
434 }
435
436 define zeroext i1 @fcmp_uno2(float %x) {
437 ; SDAG-LABEL: fcmp_uno2
438 ; SDAG: ucomiss %xmm0, %xmm0
439 ; SDAG-NEXT: setp %al
440 ; FAST-LABEL: fcmp_uno2
441 ; FAST: ucomiss %xmm0, %xmm0
442 ; FAST-NEXT: setp %al
443 %1 = fcmp uno float %x, %x
444 ret i1 %1
445 }
446
447 define zeroext i1 @fcmp_uno3(float %x) {
448 ; SDAG-LABEL: fcmp_uno3
449 ; SDAG: ucomiss %xmm0, %xmm0
450 ; SDAG-NEXT: setp %al
451 ; FAST-LABEL: fcmp_uno3
452 ; FAST: ucomiss %xmm0, %xmm0
453 ; FAST-NEXT: setp %al
454 %1 = fcmp uno float %x, 0.000000e+00
455 ret i1 %1
456 }
457
458 define zeroext i1 @fcmp_ueq2(float %x) {
459 ; SDAG-LABEL: fcmp_ueq2
460 ; SDAG: movb $1, %al
461 ; FAST-LABEL: fcmp_ueq2
462 ; FAST: movb $1, %al
463 %1 = fcmp ueq float %x, %x
464 ret i1 %1
465 }
466
467 define zeroext i1 @fcmp_ueq3(float %x) {
468 ; SDAG-LABEL: fcmp_ueq3
469 ; SDAG: xorps %xmm1, %xmm1
470 ; SDAG-NEXT: ucomiss %xmm1, %xmm0
471 ; SDAG-NEXT: sete %al
472 ; FAST-LABEL: fcmp_ueq3
473 ; FAST: xorps %xmm1, %xmm1
474 ; FAST-NEXT: ucomiss %xmm1, %xmm0
475 ; FAST-NEXT: sete %al
476 %1 = fcmp ueq float %x, 0.000000e+00
477 ret i1 %1
478 }
479
480 define zeroext i1 @fcmp_ugt2(float %x) {
481 ; SDAG-LABEL: fcmp_ugt2
482 ; SDAG: ucomiss %xmm0, %xmm0
483 ; SDAG-NEXT: setp %al
484 ; FAST-LABEL: fcmp_ugt2
485 ; FAST: ucomiss %xmm0, %xmm0
486 ; FAST-NEXT: setp %al
487 %1 = fcmp ugt float %x, %x
488 ret i1 %1
489 }
490
491 define zeroext i1 @fcmp_ugt3(float %x) {
492 ; SDAG-LABEL: fcmp_ugt3
493 ; SDAG: xorps %xmm1, %xmm1
494 ; SDAG-NEXT: ucomiss %xmm0, %xmm1
495 ; SDAG-NEXT: setb %al
496 ; FAST-LABEL: fcmp_ugt3
497 ; FAST: xorps %xmm1, %xmm1
498 ; FAST-NEXT: ucomiss %xmm0, %xmm1
499 ; FAST-NEXT: setb %al
500 %1 = fcmp ugt float %x, 0.000000e+00
501 ret i1 %1
502 }
503
504 define zeroext i1 @fcmp_uge2(float %x) {
505 ; SDAG-LABEL: fcmp_uge2
506 ; SDAG: movb $1, %al
507 ; FAST-LABEL: fcmp_uge2
508 ; FAST: movb $1, %al
509 %1 = fcmp uge float %x, %x
510 ret i1 %1
511 }
512
513 define zeroext i1 @fcmp_uge3(float %x) {
514 ; SDAG-LABEL: fcmp_uge3
515 ; SDAG: xorps %xmm1, %xmm1
516 ; SDAG-NEXT: ucomiss %xmm0, %xmm1
517 ; SDAG-NEXT: setbe %al
518 ; FAST-LABEL: fcmp_uge3
519 ; FAST: xorps %xmm1, %xmm1
520 ; FAST-NEXT: ucomiss %xmm0, %xmm1
521 ; FAST-NEXT: setbe %al
522 %1 = fcmp uge float %x, 0.000000e+00
523 ret i1 %1
524 }
525
526 define zeroext i1 @fcmp_ult2(float %x) {
527 ; SDAG-LABEL: fcmp_ult2
528 ; SDAG: ucomiss %xmm0, %xmm0
529 ; SDAG-NEXT: setp %al
530 ; FAST-LABEL: fcmp_ult2
531 ; FAST: ucomiss %xmm0, %xmm0
532 ; FAST-NEXT: setp %al
533 %1 = fcmp ult float %x, %x
534 ret i1 %1
535 }
536
537 define zeroext i1 @fcmp_ult3(float %x) {
538 ; SDAG-LABEL: fcmp_ult3
539 ; SDAG: xorps %xmm1, %xmm1
540 ; SDAG-NEXT: ucomiss %xmm1, %xmm0
541 ; SDAG-NEXT: setb %al
542 ; FAST-LABEL: fcmp_ult3
543 ; FAST: xorps %xmm1, %xmm1
544 ; FAST-NEXT: ucomiss %xmm1, %xmm0
545 ; FAST-NEXT: setb %al
546 %1 = fcmp ult float %x, 0.000000e+00
547 ret i1 %1
548 }
549
550 define zeroext i1 @fcmp_ule2(float %x) {
551 ; SDAG-LABEL: fcmp_ule2
552 ; SDAG: movb $1, %al
553 ; FAST-LABEL: fcmp_ule2
554 ; FAST: movb $1, %al
555 %1 = fcmp ule float %x, %x
556 ret i1 %1
557 }
558
559 define zeroext i1 @fcmp_ule3(float %x) {
560 ; SDAG-LABEL: fcmp_ule3
561 ; SDAG: xorps %xmm1, %xmm1
562 ; SDAG-NEXT: ucomiss %xmm1, %xmm0
563 ; SDAG-NEXT: setbe %al
564 ; FAST-LABEL: fcmp_ule3
565 ; FAST: xorps %xmm1, %xmm1
566 ; FAST-NEXT: ucomiss %xmm1, %xmm0
567 ; FAST-NEXT: setbe %al
568 %1 = fcmp ule float %x, 0.000000e+00
569 ret i1 %1
570 }
571
572 define zeroext i1 @fcmp_une2(float %x) {
573 ; SDAG-LABEL: fcmp_une2
574 ; SDAG: ucomiss %xmm0, %xmm0
575 ; SDAG-NEXT: setp %al
576 ; FAST-LABEL: fcmp_une2
577 ; FAST: ucomiss %xmm0, %xmm0
578 ; FAST-NEXT: setp %al
579 %1 = fcmp une float %x, %x
580 ret i1 %1
581 }
582
583 define zeroext i1 @fcmp_une3(float %x) {
584 ; SDAG-LABEL: fcmp_une3
585 ; SDAG: xorps %xmm1, %xmm1
586 ; SDAG-NEXT: cmpneqss %xmm1, %xmm0
587 ; SDAG-NEXT: movd %xmm0, %eax
588 ; SDAG-NEXT: andl $1, %eax
589 ; FAST-LABEL: fcmp_une3
590 ; FAST: xorps %xmm1, %xmm1
591 ; FAST-NEXT: ucomiss %xmm1, %xmm0
592 ; FAST-NEXT: setne %al
593 ; FAST-NEXT: setp %cl
594 ; FAST-NEXT: orb %al, %cl
595 %1 = fcmp une float %x, 0.000000e+00
596 ret i1 %1
597 }
598
599 define zeroext i1 @icmp_eq2(i32 %x) {
600 ; SDAG-LABEL: icmp_eq2
601 ; SDAG: movb $1, %al
602 ; FAST-LABEL: icmp_eq2
603 ; FAST: movb $1, %al
604 %1 = icmp eq i32 %x, %x
605 ret i1 %1
606 }
607
608 define zeroext i1 @icmp_ne2(i32 %x) {
609 ; SDAG-LABEL: icmp_ne2
610 ; SDAG: xorl %eax, %eax
611 ; FAST-LABEL: icmp_ne2
612 ; FAST: xorl %eax, %eax
613 %1 = icmp ne i32 %x, %x
614 ret i1 %1
615 }
616
617 define zeroext i1 @icmp_ugt2(i32 %x) {
618 ; SDAG-LABEL: icmp_ugt2
619 ; SDAG: xorl %eax, %eax
620 ; FAST-LABEL: icmp_ugt2
621 ; FAST: xorl %eax, %eax
622 %1 = icmp ugt i32 %x, %x
623 ret i1 %1
624 }
625
626 define zeroext i1 @icmp_uge2(i32 %x) {
627 ; SDAG-LABEL: icmp_uge2
628 ; SDAG: movb $1, %al
629 ; FAST-LABEL: icmp_uge2
630 ; FAST: movb $1, %al
631 %1 = icmp uge i32 %x, %x
632 ret i1 %1
633 }
634
635 define zeroext i1 @icmp_ult2(i32 %x) {
636 ; SDAG-LABEL: icmp_ult2
637 ; SDAG: xorl %eax, %eax
638 ; FAST-LABEL: icmp_ult2
639 ; FAST: xorl %eax, %eax
640 %1 = icmp ult i32 %x, %x
641 ret i1 %1
642 }
643
644 define zeroext i1 @icmp_ule2(i32 %x) {
645 ; SDAG-LABEL: icmp_ule2
646 ; SDAG: movb $1, %al
647 ; FAST-LABEL: icmp_ule2
648 ; FAST: movb $1, %al
649 %1 = icmp ule i32 %x, %x
650 ret i1 %1
651 }
652
653 define zeroext i1 @icmp_sgt2(i32 %x) {
654 ; SDAG-LABEL: icmp_sgt2
655 ; SDAG: xorl %eax, %eax
656 ; FAST-LABEL: icmp_sgt2
657 ; FAST: xorl %eax, %eax
658 %1 = icmp sgt i32 %x, %x
659 ret i1 %1
660 }
661
662 define zeroext i1 @icmp_sge2(i32 %x) {
663 ; SDAG-LABEL: icmp_sge2
664 ; SDAG: movb $1, %al
665 ; FAST-LABEL: icmp_sge2
666 ; FAST: movb $1, %al
667 %1 = icmp sge i32 %x, %x
668 ret i1 %1
669 }
670
671 define zeroext i1 @icmp_slt2(i32 %x) {
672 ; SDAG-LABEL: icmp_slt2
673 ; SDAG: xorl %eax, %eax
674 ; FAST-LABEL: icmp_slt2
675 ; FAST: xorl %eax, %eax
676 %1 = icmp slt i32 %x, %x
677 ret i1 %1
678 }
679
680 define zeroext i1 @icmp_sle2(i32 %x) {
681 ; SDAG-LABEL: icmp_sle2
682 ; SDAG: movb $1, %al
683 ; FAST-LABEL: icmp_sle2
684 ; FAST: movb $1, %al
685 %1 = icmp sle i32 %x, %x
686 ret i1 %1
687 }
688