Skip to content

Commit 406f607

Browse files
committed
1. A more concise implementation of the original swap code
2. looser equality constraints, such as nsw/nuw combinations, can be folded
1 parent 23585d3 commit 406f607

File tree

2 files changed

+28
-34
lines changed

2 files changed

+28
-34
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7728,36 +7728,41 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
77287728
}
77297729
}
77307730

7731-
// In case of a comparison with add/sub instructions having the same operands,
7732-
// check whether cmp operands have same signed no wrap. If so, just compare
7733-
// the sub's second operand and zero.
7734-
// For example:
7735-
// %tmp1 = sub nsw i8 %x, %y
7736-
// %tmp2 = add nsw i8 %x, %y
7737-
// %cmp = icmp sgt i8 %tmp1, %tmp2
7738-
// transform this into:
7739-
// %cmp = icmp slt i32 %y, 0
7731+
// When comparing results of sub and add instructions with identical operands,
7732+
// optimization is valid when the comparison type and overflow flags satisfy:
7733+
// - Signed comparisons (slt/sgt/sle/sge) require 'nsw' flags
7734+
// - Unsigned comparisons (ult/ugt/ule/uge) require 'nuw' flags
7735+
// - Equality comparisons (eq/ne) accept either 'nsw' or 'nuw'
7736+
//
7737+
// If conditions are met, the comparison simplifies to a zero comparison on
7738+
// the second operand of the sub instruction with the swapped predicate.
7739+
// Example transformation for signed comparison:
7740+
// %sub = sub nsw i8 %x, %y
7741+
// %add = add nsw i8 %x, %y
7742+
// %cmp = icmp sgt i8 %sub, %add // (x - y) > (x + y)
7743+
// becomes:
7744+
// %cmp = icmp slt i8 %y, 0 // y < 0
7745+
//
77407746
// This handles similar cases to transform.
77417747
{
77427748
Value *A, *B;
77437749
auto *I0 = dyn_cast<OverflowingBinaryOperator>(Op0);
77447750
auto *I1 = dyn_cast<OverflowingBinaryOperator>(Op1);
7745-
bool UnsignedCmp = ICmpInst::isUnsigned(Pred);
7746-
bool SignedCmp = ICmpInst::isSigned(Pred);
7747-
bool EqualityCmp = ICmpInst::isEquality(Pred);
7748-
77497751
if (I0 && I1) {
77507752
bool I0NUW = I0->hasNoUnsignedWrap();
77517753
bool I1NUW = I1->hasNoUnsignedWrap();
77527754
bool I0NSW = I0->hasNoSignedWrap();
77537755
bool I1NSW = I1->hasNoSignedWrap();
7756+
bool UnsignedCmp = ICmpInst::isUnsigned(Pred);
7757+
bool SignedCmp = ICmpInst::isSigned(Pred);
7758+
bool EqualityCmp = ICmpInst::isEquality(Pred);
7759+
CmpPredicate CmpPred;
77547760
if ((UnsignedCmp && I0NUW && I1NUW) || (SignedCmp && I0NSW && I1NSW) ||
7755-
(EqualityCmp && ((I0NUW && I1NUW) || (I0NSW && I1NSW)))) {
7756-
if (match(I0, m_Sub(m_Value(A), m_Value(B))) &&
7757-
match(I1, m_Add(m_Specific(A), m_Specific(B)))) {
7758-
return new ICmpInst(I.getSwappedPredicate(), B,
7761+
(EqualityCmp && ((I0NUW || I0NSW) && (I1NUW || I1NSW)))) {
7762+
if (match(&I, m_c_ICmp(CmpPred, m_Sub(m_Value(A), m_Value(B)),
7763+
m_c_Add(m_Deferred(A), m_Deferred(B)))))
7764+
return new ICmpInst(CmpPredicate::getSwapped(CmpPred), B,
77597765
ConstantInt::get(Op0->getType(), 0));
7760-
}
77617766
}
77627767
}
77637768
}

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

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ define i1 @test-same-operands-sub-add-nsw-nuw-icmp-eq(i8 %a, i8 %b) {
4343
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[B]], 0
4444
; CHECK-NEXT: ret i1 [[CMP]]
4545
;
46-
%sub = sub nuw nsw i8 %a, %b
47-
%add = add nuw nsw i8 %a, %b
46+
%sub = sub nsw i8 %a, %b
47+
%add = add nuw i8 %a, %b
4848
%cmp = icmp eq i8 %sub, %add
4949
ret i1 %cmp
5050
}
@@ -61,13 +61,10 @@ define i1 @test-same-operands-sub-add-nsw-icmp-eq(i8 %a, i8 %b) {
6161
ret i1 %cmp
6262
}
6363

64-
; Should floded by foldICmpCommutative in the future
6564
define i1 @test-add-sub-nsw-icmp-sgt(i8 %a, i8 %b) {
6665
; CHECK-LABEL: define i1 @test-add-sub-nsw-icmp-sgt(
6766
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
68-
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[A]], [[B]]
69-
; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[A]], [[B]]
70-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[ADD]], [[SUB]]
67+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[B]], 0
7168
; CHECK-NEXT: ret i1 [[CMP]]
7269
;
7370
%sub = sub nsw i8 %a, %b
@@ -76,14 +73,10 @@ define i1 @test-add-sub-nsw-icmp-sgt(i8 %a, i8 %b) {
7673
ret i1 %cmp
7774
}
7875

79-
; Should floded by foldICmpCommutative in the future
8076
define i1 @test-add-sub-nuw-icmp-uge(i8 %a, i8 %b) {
8177
; CHECK-LABEL: define i1 @test-add-sub-nuw-icmp-uge(
8278
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
83-
; CHECK-NEXT: [[SUB:%.*]] = sub nuw i8 [[A]], [[B]]
84-
; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[A]], [[B]]
85-
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[ADD]], [[SUB]]
86-
; CHECK-NEXT: ret i1 [[CMP]]
79+
; CHECK-NEXT: ret i1 true
8780
;
8881
%sub = sub nuw i8 %a, %b
8982
%add = add nuw i8 %a, %b
@@ -106,14 +99,10 @@ define i1 @test-add-sub-nuw-icmp-sge(i8 %a, i8 %b) {
10699
ret i1 %cmp
107100
}
108101

109-
; Should floded by foldICmpCommutative in the future
110102
define i1 @test-add-swap-sub-nuw-icmp-uge(i8 %a, i8 %b) {
111103
; CHECK-LABEL: define i1 @test-add-swap-sub-nuw-icmp-uge(
112104
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
113-
; CHECK-NEXT: [[SUB:%.*]] = sub nuw i8 [[A]], [[B]]
114-
; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[B]], [[A]]
115-
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[ADD]], [[SUB]]
116-
; CHECK-NEXT: ret i1 [[CMP]]
105+
; CHECK-NEXT: ret i1 true
117106
;
118107
%sub = sub nuw i8 %a, %b
119108
%add = add nuw i8 %b, %a

0 commit comments

Comments
 (0)