llvm.org GIT mirror llvm / 36bc2b7
[EarlyCSE] detect equivalence of selects with inverse conditions and commuted operands (PR41101) This is 1 of the problems discussed in the post-commit thread for: rL355741 / http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20190311/635516.html and filed as: https://bugs.llvm.org/show_bug.cgi?id=41101 Instcombine tries to canonicalize some of these cases (and there's room for improvement there independently of this patch), but it can't always do that because of extra uses. So we need to recognize these commuted operand patterns here in EarlyCSE. This is similar to how we detect commuted compares and commuted min/max/abs. Differential Revision: https://reviews.llvm.org/D60723 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358523 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 5 months ago
2 changed file(s) with 71 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
129129
130130 } // end namespace llvm
131131
132 /// Match a 'select' including an optional 'not' of the condition.
133 static bool matchSelectWithOptionalNotCond(Value *V, Value *&Cond,
134 Value *&T, Value *&F) {
135 if (match(V, m_Select(m_Value(Cond), m_Value(T), m_Value(F)))) {
136 // Look through a 'not' of the condition operand by swapping true/false.
137 Value *CondNot;
138 if (match(Cond, m_Not(m_Value(CondNot)))) {
139 Cond = CondNot;
140 std::swap(T, F);
141 }
142 return true;
143 }
144 return false;
145 }
146
132147 unsigned DenseMapInfo::getHashValue(SimpleValue Val) {
133148 Instruction *Inst = Val.Inst;
134149 // Hash in all of the operands as pointers.
170185 return hash_combine(Inst->getOpcode(), SPF, A, B);
171186 }
172187
188 // Hash general selects to allow matching commuted true/false operands.
189 Value *Cond, *TVal, *FVal;
190 if (matchSelectWithOptionalNotCond(Inst, Cond, TVal, FVal)) {
191 // If we do not have a compare as the condition, just hash in the condition.
192 CmpInst::Predicate Pred;
193 Value *X, *Y;
194 if (!match(Cond, m_Cmp(Pred, m_Value(X), m_Value(Y))))
195 return hash_combine(Inst->getOpcode(), Cond, TVal, FVal);
196
197 // Similar to cmp normalization (above) - canonicalize the predicate value:
198 // select (icmp Pred, X, Y), T, F --> select (icmp InvPred, X, Y), F, T
199 if (CmpInst::getInversePredicate(Pred) < Pred) {
200 Pred = CmpInst::getInversePredicate(Pred);
201 std::swap(TVal, FVal);
202 }
203 return hash_combine(Inst->getOpcode(), Pred, X, Y, TVal, FVal);
204 }
205
173206 if (CastInst *CI = dyn_cast(Inst))
174207 return hash_combine(CI->getOpcode(), CI->getType(), CI->getOperand(0));
175208
182215 IVI->getOperand(1),
183216 hash_combine_range(IVI->idx_begin(), IVI->idx_end()));
184217
185 assert((isa(Inst) || isa(Inst) ||
186 isa(Inst) || isaInst>(Inst) ||
218 assert((isa(Inst) || isaInst>(Inst) ||
187219 isa(Inst) || isa(Inst) ||
188220 isa(Inst)) &&
189221 "Invalid/unknown instruction");
244276 return LHSA == RHSA && LHSB == RHSB;
245277 return ((LHSA == RHSA && LHSB == RHSB) ||
246278 (LHSA == RHSB && LHSB == RHSA));
279 }
280 }
281
282 // Selects can be non-trivially equivalent via inverted conditions and swaps.
283 Value *CondL, *CondR, *TrueL, *TrueR, *FalseL, *FalseR;
284 if (matchSelectWithOptionalNotCond(LHSI, CondL, TrueL, FalseL) &&
285 matchSelectWithOptionalNotCond(RHSI, CondR, TrueR, FalseR)) {
286 // select Cond, T, F <--> select not(Cond), F, T
287 if (CondL == CondR && TrueL == TrueR && FalseL == FalseR)
288 return true;
289
290 // If the true/false operands are swapped and the conditions are compares
291 // with inverted predicates, the selects are equal:
292 // select (icmp Pred, X, Y), T, F <--> select (icmp InvPred, X, Y), F, T
293 //
294 // This also handles patterns with a double-negation because we looked
295 // through a 'not' in the matching function and swapped T/F:
296 // select (cmp Pred, X, Y), T, F <--> select (not (cmp InvPred, X, Y)), T, F
297 if (TrueL == FalseR && FalseL == TrueR) {
298 CmpInst::Predicate PredL, PredR;
299 Value *X, *Y;
300 if (match(CondL, m_Cmp(PredL, m_Value(X), m_Value(Y))) &&
301 match(CondR, m_Cmp(PredR, m_Specific(X), m_Specific(Y))) &&
302 CmpInst::getInversePredicate(PredL) == PredR)
303 return true;
247304 }
248305 }
249306
289289 }
290290
291291 ; https://bugs.llvm.org/show_bug.cgi?id=41101
292 ; TODO: Detect equivalence of selects with commuted operands: 'not' cond.
292 ; Detect equivalence of selects with commuted operands: 'not' cond.
293293
294294 define i32 @select_not_cond(i1 %cond, i32 %t, i32 %f) {
295295 ; CHECK-LABEL: @select_not_cond(
296296 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true
297297 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
298 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[F]], i32 [[T]]
299 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
300 ; CHECK-NEXT: ret i32 [[R]]
298 ; CHECK-NEXT: ret i32 0
301299 ;
302300 %not = xor i1 %cond, -1
303301 %m1 = select i1 %cond, i32 %t, i32 %f
306304 ret i32 %r
307305 }
308306
309 ; TODO: Detect equivalence of selects with commuted operands: 'not' cond with vector select.
307 ; Detect equivalence of selects with commuted operands: 'not' cond with vector select.
310308
311309 define <2 x double> @select_not_cond_commute_vec(<2 x i1> %cond, <2 x double> %t, <2 x double> %f) {
312310 ; CHECK-LABEL: @select_not_cond_commute_vec(
313311 ; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[COND:%.*]],
314312 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[COND]], <2 x double> [[T:%.*]], <2 x double> [[F:%.*]]
315 ; CHECK-NEXT: [[M2:%.*]] = select <2 x i1> [[NOT]], <2 x double> [[F]], <2 x double> [[T]]
316 ; CHECK-NEXT: [[R:%.*]] = fdiv nnan <2 x double> [[M1]], [[M2]]
317 ; CHECK-NEXT: ret <2 x double> [[R]]
313 ; CHECK-NEXT: ret <2 x double>
318314 ;
319315 %not = xor <2 x i1> %cond,
320316 %m1 = select <2 x i1> %cond, <2 x double> %t, <2 x double> %f
356352 ret i32 %r
357353 }
358354
359 ; TODO: Detect equivalence of selects with commuted operands: inverted pred with fcmps.
355 ; Detect equivalence of selects with commuted operands: inverted pred with fcmps.
360356
361357 define i32 @select_invert_pred_cond(float %x, i32 %t, i32 %f) {
362358 ; CHECK-LABEL: @select_invert_pred_cond(
363359 ; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
364360 ; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01
365361 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
366 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
367 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
368 ; CHECK-NEXT: ret i32 [[R]]
362 ; CHECK-NEXT: ret i32 0
369363 ;
370364 %cond = fcmp ueq float %x, 42.0
371365 %invcond = fcmp one float %x, 42.0
375369 ret i32 %r
376370 }
377371
378 ; TODO: Detect equivalence of selects with commuted operands: inverted pred with icmps and vectors.
372 ; Detect equivalence of selects with commuted operands: inverted pred with icmps and vectors.
379373
380374 define <2 x i32> @select_invert_pred_cond_commute_vec(<2 x i8> %x, <2 x i32> %t, <2 x i32> %f) {
381375 ; CHECK-LABEL: @select_invert_pred_cond_commute_vec(
382376 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt <2 x i8> [[X:%.*]],
383377 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp sle <2 x i8> [[X]],
384378 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[T:%.*]], <2 x i32> [[F:%.*]]
385 ; CHECK-NEXT: [[M2:%.*]] = select <2 x i1> [[INVCOND]], <2 x i32> [[F]], <2 x i32> [[T]]
386 ; CHECK-NEXT: [[R:%.*]] = xor <2 x i32> [[M1]], [[M2]]
387 ; CHECK-NEXT: ret <2 x i32> [[R]]
379 ; CHECK-NEXT: ret <2 x i32> zeroinitializer
388380 ;
389381 %cond = icmp sgt <2 x i8> %x,
390382 %invcond = icmp sle <2 x i8> %x,
451443 ret i32 %r
452444 }
453445
454 ; TODO: If we have both an inverted predicate and a 'not' op, recognize the double-negation.
446 ; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
455447
456448 define i32 @select_not_invert_pred_cond(i8 %x, i32 %t, i32 %f) {
457449 ; CHECK-LABEL: @select_not_invert_pred_cond(
459451 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X]], 42
460452 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
461453 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
462 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T]], i32 [[F]]
463 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[M1]], [[M2]]
464 ; CHECK-NEXT: ret i32 [[R]]
454 ; CHECK-NEXT: ret i32 0
465455 ;
466456 %cond = icmp ugt i8 %x, 42
467457 %invcond = icmp ule i8 %x, 42
472462 ret i32 %r
473463 }
474464
475 ; TODO: If we have both an inverted predicate and a 'not' op, recognize the double-negation.
465 ; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
476466
477467 define i32 @select_not_invert_pred_cond_commute(i8 %x, i8 %y, i32 %t, i32 %f) {
478468 ; CHECK-LABEL: @select_not_invert_pred_cond_commute(
480470 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
481471 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
482472 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
483 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]
484 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]
485 ; CHECK-NEXT: ret i32 [[R]]
473 ; CHECK-NEXT: ret i32 0
486474 ;
487475 %invcond = icmp ule i8 %x, %y
488476 %not = xor i1 %invcond, -1