Skip to content

Commit 8cedff8

Browse files
committed
[InstCombine] Extend foldICmpBinOp to add-like or.
InstCombine canonicalizes `add` to `or` when possible, but this makes some optimizations applicable to `add` to be missed because they don't realize that the `or` is equivalent to `add`. In this patch we generalize `foldICmpBinOp` to handle such cases.
1 parent 69bc371 commit 8cedff8

File tree

2 files changed

+48
-31
lines changed

2 files changed

+48
-31
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4629,31 +4629,38 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
46294629
}
46304630

46314631
bool NoOp0WrapProblem = false, NoOp1WrapProblem = false;
4632-
if (BO0 && isa<OverflowingBinaryOperator>(BO0))
4633-
NoOp0WrapProblem =
4634-
ICmpInst::isEquality(Pred) ||
4635-
(CmpInst::isUnsigned(Pred) && BO0->hasNoUnsignedWrap()) ||
4636-
(CmpInst::isSigned(Pred) && BO0->hasNoSignedWrap());
4637-
if (BO1 && isa<OverflowingBinaryOperator>(BO1))
4638-
NoOp1WrapProblem =
4639-
ICmpInst::isEquality(Pred) ||
4640-
(CmpInst::isUnsigned(Pred) && BO1->hasNoUnsignedWrap()) ||
4641-
(CmpInst::isSigned(Pred) && BO1->hasNoSignedWrap());
4642-
4632+
bool Op0HasNUW = false, Op1HasNUW = false;
4633+
bool Op0HasNSW = false, Op1HasNSW = false;
46434634
// Analyze the case when either Op0 or Op1 is an add instruction.
46444635
// Op0 = A + B (or A and B are null); Op1 = C + D (or C and D are null).
46454636
Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr;
4646-
if (BO0 && BO0->getOpcode() == Instruction::Add) {
4647-
A = BO0->getOperand(0);
4648-
B = BO0->getOperand(1);
4637+
auto hasNoWrapProblem = [&](const BinaryOperator &BO, const Value *X,
4638+
const Value *Y, bool &HasNSW,
4639+
bool &HasNUW) -> bool {
4640+
if (isa<OverflowingBinaryOperator>(BO)) {
4641+
HasNUW = BO.hasNoUnsignedWrap();
4642+
HasNSW = BO.hasNoSignedWrap();
4643+
return ICmpInst::isEquality(Pred) ||
4644+
(CmpInst::isUnsigned(Pred) && HasNUW) ||
4645+
(CmpInst::isSigned(Pred) && HasNSW);
4646+
} else if (BO0->getOpcode() == Instruction::Or) {
4647+
HasNUW = true;
4648+
HasNSW = true;
4649+
return true;
4650+
} else {
4651+
return false;
4652+
}
4653+
};
4654+
4655+
if (BO0) {
4656+
match(BO0, m_AddLike(m_Value(A), m_Value(B)));
4657+
NoOp0WrapProblem = hasNoWrapProblem(*BO0, A, B, Op0HasNSW, Op0HasNUW);
46494658
}
4650-
if (BO1 && BO1->getOpcode() == Instruction::Add) {
4651-
C = BO1->getOperand(0);
4652-
D = BO1->getOperand(1);
4659+
if (BO1) {
4660+
match(BO1, m_AddLike(m_Value(C), m_Value(D)));
4661+
NoOp1WrapProblem = hasNoWrapProblem(*BO1, C, D, Op1HasNSW, Op1HasNUW);
46534662
}
46544663

4655-
// icmp (A+B), A -> icmp B, 0 for equalities or if there is no overflow.
4656-
// icmp (A+B), B -> icmp A, 0 for equalities or if there is no overflow.
46574664
if ((A == Op1 || B == Op1) && NoOp0WrapProblem)
46584665
return new ICmpInst(Pred, A == Op1 ? B : A,
46594666
Constant::getNullValue(Op1->getType()));
@@ -4769,17 +4776,15 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
47694776
APInt AP2Abs = AP2->abs();
47704777
if (AP1Abs.uge(AP2Abs)) {
47714778
APInt Diff = *AP1 - *AP2;
4772-
bool HasNUW = BO0->hasNoUnsignedWrap() && Diff.ule(*AP1);
4773-
bool HasNSW = BO0->hasNoSignedWrap();
47744779
Constant *C3 = Constant::getIntegerValue(BO0->getType(), Diff);
4775-
Value *NewAdd = Builder.CreateAdd(A, C3, "", HasNUW, HasNSW);
4780+
Value *NewAdd = Builder.CreateAdd(
4781+
A, C3, "", Op0HasNUW && Diff.ule(*AP1), Op0HasNSW);
47764782
return new ICmpInst(Pred, NewAdd, C);
47774783
} else {
47784784
APInt Diff = *AP2 - *AP1;
4779-
bool HasNUW = BO1->hasNoUnsignedWrap() && Diff.ule(*AP2);
4780-
bool HasNSW = BO1->hasNoSignedWrap();
47814785
Constant *C3 = Constant::getIntegerValue(BO0->getType(), Diff);
4782-
Value *NewAdd = Builder.CreateAdd(C, C3, "", HasNUW, HasNSW);
4786+
Value *NewAdd = Builder.CreateAdd(
4787+
C, C3, "", Op1HasNUW && Diff.ule(*AP1), Op1HasNSW);
47834788
return new ICmpInst(Pred, A, NewAdd);
47844789
}
47854790
}
@@ -4873,16 +4878,14 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
48734878
isKnownNonZero(Z, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT);
48744879
// if Z != 0 and nsw(X * Z) and nsw(Y * Z)
48754880
// X * Z eq/ne Y * Z -> X eq/ne Y
4876-
if (NonZero && BO0 && BO1 && BO0->hasNoSignedWrap() &&
4877-
BO1->hasNoSignedWrap())
4881+
if (NonZero && BO0 && BO1 && Op0HasNUW && Op1HasNSW)
48784882
return new ICmpInst(Pred, X, Y);
48794883
} else
48804884
NonZero = isKnownNonZero(Z, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT);
48814885

48824886
// If Z != 0 and nuw(X * Z) and nuw(Y * Z)
48834887
// X * Z u{lt/le/gt/ge}/eq/ne Y * Z -> X u{lt/le/gt/ge}/eq/ne Y
4884-
if (NonZero && BO0 && BO1 && BO0->hasNoUnsignedWrap() &&
4885-
BO1->hasNoUnsignedWrap())
4888+
if (NonZero && BO0 && BO1 && Op0HasNUW && Op1HasNUW)
48864889
return new ICmpInst(Pred, X, Y);
48874890
}
48884891
}
@@ -4982,8 +4985,8 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
49824985
return new ICmpInst(Pred, BO0->getOperand(0), BO1->getOperand(0));
49834986

49844987
case Instruction::Shl: {
4985-
bool NUW = BO0->hasNoUnsignedWrap() && BO1->hasNoUnsignedWrap();
4986-
bool NSW = BO0->hasNoSignedWrap() && BO1->hasNoSignedWrap();
4988+
bool NUW = Op0HasNUW && Op1HasNUW;
4989+
bool NSW = Op0HasNSW && Op1HasNSW;
49874990
if (!NUW && !NSW)
49884991
break;
49894992
if (!NSW && I.isSigned())
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3+
4+
define i1 @simplify_icmp(i32 %x, i32 %y) {
5+
; CHECK-LABEL: define i1 @simplify_icmp(
6+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
7+
; CHECK-NEXT: [[ICMP_:%.*]] = icmp sle i32 [[X]], [[Y]]
8+
; CHECK-NEXT: ret i1 [[ICMP_]]
9+
;
10+
%add0_ = or disjoint i32 %x, 1
11+
%add1_ = add nsw i32 %y, 1
12+
%icmp_ = icmp sle i32 %add0_, %add1_
13+
ret i1 %icmp_
14+
}

0 commit comments

Comments
 (0)