Skip to content

Commit 7949a2a

Browse files
committed
[InstCombine] enhance icmp with sub folds
The new IR with And removes a use of the input variable, which is better for analysis. Fix llvm#60818 Reviewed By: nikic, spatel Differential Revision: https://reviews.llvm.org/D145846
1 parent e2f6ebe commit 7949a2a

File tree

2 files changed

+35
-19
lines changed

2 files changed

+35
-19
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4065,20 +4065,36 @@ Value *InstCombinerImpl::foldMultiplicationOverflowCheck(ICmpInst &I) {
40654065
return Res;
40664066
}
40674067

4068-
static Instruction *foldICmpXNegX(ICmpInst &I) {
4068+
static Instruction *foldICmpXNegX(ICmpInst &I,
4069+
InstCombiner::BuilderTy &Builder) {
40694070
CmpInst::Predicate Pred;
40704071
Value *X;
4071-
if (!match(&I, m_c_ICmp(Pred, m_NSWNeg(m_Value(X)), m_Deferred(X))))
4072-
return nullptr;
4072+
if (match(&I, m_c_ICmp(Pred, m_NSWNeg(m_Value(X)), m_Deferred(X)))) {
40734073

4074-
if (ICmpInst::isSigned(Pred))
4075-
Pred = ICmpInst::getSwappedPredicate(Pred);
4076-
else if (ICmpInst::isUnsigned(Pred))
4077-
Pred = ICmpInst::getSignedPredicate(Pred);
4078-
// else for equality-comparisons just keep the predicate.
4074+
if (ICmpInst::isSigned(Pred))
4075+
Pred = ICmpInst::getSwappedPredicate(Pred);
4076+
else if (ICmpInst::isUnsigned(Pred))
4077+
Pred = ICmpInst::getSignedPredicate(Pred);
4078+
// else for equality-comparisons just keep the predicate.
4079+
4080+
return ICmpInst::Create(Instruction::ICmp, Pred, X,
4081+
Constant::getNullValue(X->getType()), I.getName());
4082+
}
40794083

4080-
return ICmpInst::Create(Instruction::ICmp, Pred, X,
4081-
Constant::getNullValue(X->getType()), I.getName());
4084+
// A value is not equal to its negation unless that value is 0 or
4085+
// MinSignedValue, ie: a != -a --> (a & MaxSignedVal) != 0
4086+
if (match(&I, m_c_ICmp(Pred, m_OneUse(m_Neg(m_Value(X))), m_Deferred(X))) &&
4087+
ICmpInst::isEquality(Pred)) {
4088+
Type *Ty = X->getType();
4089+
uint32_t BitWidth = Ty->getScalarSizeInBits();
4090+
Constant *MaxSignedVal =
4091+
ConstantInt::get(Ty, APInt::getSignedMaxValue(BitWidth));
4092+
Value *And = Builder.CreateAnd(X, MaxSignedVal);
4093+
Constant *Zero = Constant::getNullValue(Ty);
4094+
return CmpInst::Create(Instruction::ICmp, Pred, And, Zero);
4095+
}
4096+
4097+
return nullptr;
40824098
}
40834099

40844100
/// Try to fold icmp (binop), X or icmp X, (binop).
@@ -4096,7 +4112,7 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
40964112
if (!BO0 && !BO1)
40974113
return nullptr;
40984114

4099-
if (Instruction *NewICmp = foldICmpXNegX(I))
4115+
if (Instruction *NewICmp = foldICmpXNegX(I, Builder))
41004116
return NewICmp;
41014117

41024118
const CmpInst::Predicate Pred = I.getPredicate();

llvm/test/Transforms/InstCombine/icmp-sub.ll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,8 @@ bb_exit:
566566
define i1 @PR60818_ne(i32 %a) {
567567
; CHECK-LABEL: @PR60818_ne(
568568
; CHECK-NEXT: entry:
569-
; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]]
570-
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[SUB]], [[A]]
569+
; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[A:%.*]], 2147483647
570+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP0]], 0
571571
; CHECK-NEXT: ret i1 [[CMP]]
572572
;
573573
entry:
@@ -579,8 +579,8 @@ entry:
579579
define i1 @PR60818_eq(i32 %a) {
580580
; CHECK-LABEL: @PR60818_eq(
581581
; CHECK-NEXT: entry:
582-
; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]]
583-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[SUB]], [[A]]
582+
; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[A:%.*]], 2147483647
583+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
584584
; CHECK-NEXT: ret i1 [[CMP]]
585585
;
586586
entry:
@@ -593,8 +593,8 @@ define i1 @PR60818_eq_commuted(i32 %x) {
593593
; CHECK-LABEL: @PR60818_eq_commuted(
594594
; CHECK-NEXT: entry:
595595
; CHECK-NEXT: [[A:%.*]] = mul i32 [[X:%.*]], 43
596-
; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A]]
597-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], [[SUB]]
596+
; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[A]], 2147483647
597+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
598598
; CHECK-NEXT: ret i1 [[CMP]]
599599
;
600600
entry:
@@ -607,8 +607,8 @@ entry:
607607
define <2 x i1> @PR60818_ne_vector(<2 x i32> %a) {
608608
; CHECK-LABEL: @PR60818_ne_vector(
609609
; CHECK-NEXT: entry:
610-
; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> zeroinitializer, [[A:%.*]]
611-
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[SUB]], [[A]]
610+
; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i32> [[A:%.*]], <i32 2147483647, i32 2147483647>
611+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[TMP0]], zeroinitializer
612612
; CHECK-NEXT: ret <2 x i1> [[CMP]]
613613
;
614614
entry:

0 commit comments

Comments
 (0)