Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 1ca1d27

Browse files
committed
[InstCombine] move icmp transforms that might be recognized as min/max and inf-loop (PR31751)
This is a minimal patch to avoid the infinite loop in: https://llvm.org/bugs/show_bug.cgi?id=31751 But the general problem is bigger: we're not canonicalizing all of the min/max forms reported by value tracking's matchSelectPattern(), and we don't define min/max consistently. Some code uses matchSelectPattern(), other code uses matchers like m_Umax, and others have their own inline definitions which may be subtly different from any of the above. The reason that the test cases in this patch need a cast op to trigger is because we don't (yet) canonicalize all min/max forms based on matchSelectPattern() in canonicalizeMinMaxWithConstant(), but we do make min/max+cast transforms based on matchSelectPattern() in visitSelectInst(). The location of the icmp transforms that trigger the inf-loop seems arbitrary at best, so I'm moving those behind the min/max fence in visitICmpInst() as the quick fix. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293345 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent fbd6014 commit 1ca1d27

File tree

2 files changed

+103
-10
lines changed

2 files changed

+103
-10
lines changed

lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4088,11 +4088,6 @@ Instruction *InstCombiner::foldICmpUsingKnownBits(ICmpInst &I) {
40884088
Constant *CMinus1 = ConstantInt::get(Op0->getType(), *CmpC - 1);
40894089
return new ICmpInst(ICmpInst::ICMP_EQ, Op0, CMinus1);
40904090
}
4091-
// (x <u 2147483648) -> (x >s -1) -> true if sign bit clear
4092-
if (CmpC->isMinSignedValue()) {
4093-
Constant *AllOnes = Constant::getAllOnesValue(Op0->getType());
4094-
return new ICmpInst(ICmpInst::ICMP_SGT, Op0, AllOnes);
4095-
}
40964091
}
40974092
break;
40984093
}
@@ -4112,11 +4107,6 @@ Instruction *InstCombiner::foldICmpUsingKnownBits(ICmpInst &I) {
41124107
if (*CmpC == Op0Max - 1)
41134108
return new ICmpInst(ICmpInst::ICMP_EQ, Op0,
41144109
ConstantInt::get(Op1->getType(), *CmpC + 1));
4115-
4116-
// (x >u 2147483647) -> (x <s 0) -> true if sign bit set
4117-
if (CmpC->isMaxSignedValue())
4118-
return new ICmpInst(ICmpInst::ICMP_SLT, Op0,
4119-
Constant::getNullValue(Op0->getType()));
41204110
}
41214111
break;
41224112
}
@@ -4348,6 +4338,27 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
43484338
(SI->getOperand(2) == Op0 && SI->getOperand(1) == Op1))
43494339
return nullptr;
43504340

4341+
// FIXME: We only do this after checking for min/max to prevent infinite
4342+
// looping caused by a reverse canonicalization of these patterns for min/max.
4343+
// FIXME: The organization of folds is a mess. These would naturally go into
4344+
// canonicalizeCmpWithConstant(), but we can't move all of the above folds
4345+
// down here after the min/max restriction.
4346+
ICmpInst::Predicate Pred = I.getPredicate();
4347+
const APInt *C;
4348+
if (match(Op1, m_APInt(C))) {
4349+
// For i32: x >u 2147483647 -> x <s 0 -> true if sign bit set
4350+
if (Pred == ICmpInst::ICMP_UGT && C->isMaxSignedValue()) {
4351+
Constant *Zero = Constant::getNullValue(Op0->getType());
4352+
return new ICmpInst(ICmpInst::ICMP_SLT, Op0, Zero);
4353+
}
4354+
4355+
// For i32: x <u 2147483648 -> x >s -1 -> true if sign bit clear
4356+
if (Pred == ICmpInst::ICMP_ULT && C->isMinSignedValue()) {
4357+
Constant *AllOnes = Constant::getAllOnesValue(Op0->getType());
4358+
return new ICmpInst(ICmpInst::ICMP_SGT, Op0, AllOnes);
4359+
}
4360+
}
4361+
43514362
if (Instruction *Res = foldICmpInstWithConstant(I))
43524363
return Res;
43534364

test/Transforms/InstCombine/minmax-fold.ll

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,3 +410,85 @@ define i32 @clamp_unsigned2(i32 %x) {
410410
ret i32 %r
411411
}
412412

413+
; The next 3 min tests should canonicalize to the same form...and not infinite loop.
414+
415+
define double @PR31751_umin1(i32 %x) {
416+
; CHECK-LABEL: @PR31751_umin1(
417+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 %x, 2147483647
418+
; CHECK-NEXT: [[CONV1:%.*]] = select i1 [[TMP1]], i32 %x, i32 2147483647
419+
; CHECK-NEXT: [[TMP2:%.*]] = sitofp i32 [[CONV1]] to double
420+
; CHECK-NEXT: ret double [[TMP2]]
421+
;
422+
%cmp = icmp slt i32 %x, 0
423+
%sel = select i1 %cmp, i32 2147483647, i32 %x
424+
%conv = sitofp i32 %sel to double
425+
ret double %conv
426+
}
427+
428+
define double @PR31751_umin2(i32 %x) {
429+
; CHECK-LABEL: @PR31751_umin2(
430+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 %x, 2147483647
431+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 %x, i32 2147483647
432+
; CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[SEL]] to double
433+
; CHECK-NEXT: ret double [[CONV]]
434+
;
435+
%cmp = icmp ult i32 %x, 2147483647
436+
%sel = select i1 %cmp, i32 %x, i32 2147483647
437+
%conv = sitofp i32 %sel to double
438+
ret double %conv
439+
}
440+
441+
define double @PR31751_umin3(i32 %x) {
442+
; CHECK-LABEL: @PR31751_umin3(
443+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 %x, 2147483647
444+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP1]], i32 %x, i32 2147483647
445+
; CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[SEL]] to double
446+
; CHECK-NEXT: ret double [[CONV]]
447+
;
448+
%cmp = icmp ugt i32 %x, 2147483647
449+
%sel = select i1 %cmp, i32 2147483647, i32 %x
450+
%conv = sitofp i32 %sel to double
451+
ret double %conv
452+
}
453+
454+
; The next 3 max tests should canonicalize to the same form...and not infinite loop.
455+
456+
define double @PR31751_umax1(i32 %x) {
457+
; CHECK-LABEL: @PR31751_umax1(
458+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 %x, -2147483648
459+
; CHECK-NEXT: [[CONV1:%.*]] = select i1 [[TMP1]], i32 %x, i32 -2147483648
460+
; CHECK-NEXT: [[TMP2:%.*]] = sitofp i32 [[CONV1]] to double
461+
; CHECK-NEXT: ret double [[TMP2]]
462+
;
463+
%cmp = icmp sgt i32 %x, -1
464+
%sel = select i1 %cmp, i32 2147483648, i32 %x
465+
%conv = sitofp i32 %sel to double
466+
ret double %conv
467+
}
468+
469+
define double @PR31751_umax2(i32 %x) {
470+
; CHECK-LABEL: @PR31751_umax2(
471+
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 %x, -2147483648
472+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 %x, i32 -2147483648
473+
; CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[SEL]] to double
474+
; CHECK-NEXT: ret double [[CONV]]
475+
;
476+
%cmp = icmp ugt i32 %x, 2147483648
477+
%sel = select i1 %cmp, i32 %x, i32 2147483648
478+
%conv = sitofp i32 %sel to double
479+
ret double %conv
480+
}
481+
482+
define double @PR31751_umax3(i32 %x) {
483+
; CHECK-LABEL: @PR31751_umax3(
484+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 %x, -2147483648
485+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP1]], i32 %x, i32 -2147483648
486+
; CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[SEL]] to double
487+
; CHECK-NEXT: ret double [[CONV]]
488+
;
489+
%cmp = icmp ult i32 %x, 2147483648
490+
%sel = select i1 %cmp, i32 2147483648, i32 %x
491+
%conv = sitofp i32 %sel to double
492+
ret double %conv
493+
}
494+

0 commit comments

Comments
 (0)