Skip to content

Commit 435e3f9

Browse files
committed
Addressed review comments. Added commutative cases.
1 parent 55f236a commit 435e3f9

File tree

3 files changed

+116
-63
lines changed

3 files changed

+116
-63
lines changed

llvm/include/llvm/IR/PatternMatch.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,14 @@ m_NSWAdd(const LHS &L, const RHS &R) {
13231323
R);
13241324
}
13251325
template <typename LHS, typename RHS>
1326+
inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Add,
1327+
OverflowingBinaryOperator::NoSignedWrap, true>
1328+
m_c_NSWAdd(const LHS &L, const RHS &R) {
1329+
return OverflowingBinaryOp_match<LHS, RHS, Instruction::Add,
1330+
OverflowingBinaryOperator::NoSignedWrap,
1331+
true>(L, R);
1332+
}
1333+
template <typename LHS, typename RHS>
13261334
inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub,
13271335
OverflowingBinaryOperator::NoSignedWrap>
13281336
m_NSWSub(const LHS &L, const RHS &R) {

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2810,22 +2810,18 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
28102810
// (sub[ nsw][ nuw] (sext (add nsw (X, Y)), sext (X))) --> (sext (Y))
28112811
{
28122812
Value *Add0;
2813-
if (match(Op0, m_SExt(m_Value(Add0))) &&
2814-
match(Add0, m_Add(m_Value(X), m_Value(Y))) &&
2815-
match(Op1, m_SExt(m_Specific(X)))) {
2816-
auto *OBO0 = cast<OverflowingBinaryOperator>(Add0);
2817-
if (OBO0->hasNoSignedWrap()) {
2818-
// Non-constant Y requires new SExt.
2819-
unsigned numOfNewInstrs = !isa<Constant>(Y) ? 1 : 0;
2820-
// Check if we can trade some of the old instructions for the new ones.
2821-
unsigned numOfDeadInstrs = 0;
2822-
numOfDeadInstrs += Op0->hasOneUse() ? 1 : 0;
2823-
numOfDeadInstrs += Op1->hasOneUse() ? 1 : 0;
2824-
numOfDeadInstrs += Add0->hasOneUse() ? 1 : 0;
2825-
if (numOfDeadInstrs >= numOfNewInstrs) {
2826-
Value *SExtY = Builder.CreateSExt(Y, I.getType());
2827-
return replaceInstUsesWith(I, SExtY);
2828-
}
2813+
if (match(Op1, m_SExt(m_Value(X))) && match(Op0, m_SExt(m_Value(Add0))) &&
2814+
match(Add0, m_c_NSWAdd(m_Specific(X), m_Value(Y)))) {
2815+
// Non-constant Y requires new SExt.
2816+
unsigned NumOfNewInstrs = !isa<Constant>(Y) ? 1 : 0;
2817+
// Check if we can trade some of the old instructions for the new ones.
2818+
unsigned NumOfDeadInstrs = 0;
2819+
NumOfDeadInstrs += Op0->hasOneUse() ? 1 : 0;
2820+
NumOfDeadInstrs += Op1->hasOneUse() ? 1 : 0;
2821+
NumOfDeadInstrs += Add0->hasOneUse() ? 1 : 0;
2822+
if (NumOfDeadInstrs >= NumOfNewInstrs) {
2823+
Value *SExtY = Builder.CreateSExt(Y, I.getType());
2824+
return replaceInstUsesWith(I, SExtY);
28292825
}
28302826
}
28312827
}
@@ -2835,30 +2831,28 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
28352831
{
28362832
Value *Z, *Add0, *Add1;
28372833
if (match(Op0, m_SExt(m_Value(Add0))) &&
2838-
match(Add0, m_Add(m_Value(X), m_Value(Y))) &&
28392834
match(Op1, m_SExt(m_Value(Add1))) &&
2840-
match(Add1, m_Add(m_Specific(X), m_Value(Z)))) {
2841-
auto *OBO0 = cast<OverflowingBinaryOperator>(Add0);
2842-
auto *OBO1 = cast<OverflowingBinaryOperator>(Add1);
2843-
if (OBO0->hasNoSignedWrap() && OBO1->hasNoSignedWrap()) {
2844-
unsigned numOfNewInstrs = 0;
2845-
// Non-constant Y, Z require new SExt.
2846-
numOfNewInstrs += !isa<Constant>(Y) ? 1 : 0;
2847-
numOfNewInstrs += !isa<Constant>(Z) ? 1 : 0;
2848-
// Check if we can trade some of the old instructions for the new ones.
2849-
unsigned numOfDeadInstrs = 0;
2850-
numOfDeadInstrs += Op0->hasOneUse() ? 1 : 0;
2851-
numOfDeadInstrs += Op1->hasOneUse() ? 1 : 0;
2852-
numOfDeadInstrs += Add0->hasOneUse() ? 1 : 0;
2853-
numOfDeadInstrs += Add1->hasOneUse() ? 1 : 0;
2854-
if (numOfDeadInstrs >= numOfNewInstrs) {
2855-
Value *SExtY = Builder.CreateSExt(Y, I.getType());
2856-
Value *SExtZ = Builder.CreateSExt(Z, I.getType());
2857-
Value *Sub = Builder.CreateSub(SExtY, SExtZ, "",
2858-
/* HasNUW */ false,
2859-
/* HasNSW */ I.hasNoSignedWrap());
2860-
return replaceInstUsesWith(I, Sub);
2861-
}
2835+
((match(Add0, m_NSWAdd(m_Value(X), m_Value(Y))) &&
2836+
match(Add1, m_c_NSWAdd(m_Specific(X), m_Value(Z)))) ||
2837+
(match(Add0, m_NSWAdd(m_Value(Y), m_Value(X))) &&
2838+
match(Add1, m_c_NSWAdd(m_Specific(X), m_Value(Z)))))) {
2839+
unsigned NumOfNewInstrs = 0;
2840+
// Non-constant Y, Z require new SExt.
2841+
NumOfNewInstrs += !isa<Constant>(Y) ? 1 : 0;
2842+
NumOfNewInstrs += !isa<Constant>(Z) ? 1 : 0;
2843+
// Check if we can trade some of the old instructions for the new ones.
2844+
unsigned NumOfDeadInstrs = 0;
2845+
NumOfDeadInstrs += Op0->hasOneUse() ? 1 : 0;
2846+
NumOfDeadInstrs += Op1->hasOneUse() ? 1 : 0;
2847+
NumOfDeadInstrs += Add0->hasOneUse() ? 1 : 0;
2848+
NumOfDeadInstrs += Add1->hasOneUse() ? 1 : 0;
2849+
if (NumOfDeadInstrs >= NumOfNewInstrs) {
2850+
Value *SExtY = Builder.CreateSExt(Y, I.getType());
2851+
Value *SExtZ = Builder.CreateSExt(Z, I.getType());
2852+
Value *Sub = Builder.CreateSub(SExtY, SExtZ, "",
2853+
/* HasNUW */ false,
2854+
/* HasNSW */ I.hasNoSignedWrap());
2855+
return replaceInstUsesWith(I, Sub);
28622856
}
28632857
}
28642858
}

llvm/test/Transforms/InstCombine/sub-sext-add.ll

Lines changed: 75 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
22
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
33

4-
define i64 @src_2add_2sext_sub(i32 %x, i32 %y, i32 %z) {
5-
; CHECK-LABEL: define i64 @src_2add_2sext_sub(
6-
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
7-
; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[Y]] to i64
8-
; CHECK-NEXT: [[SEXT2:%.*]] = sext i32 [[Z]] to i64
9-
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[SEXT1]], [[SEXT2]]
4+
define i64 @src_2add_2sext_sub_1(i32 %x, i32 %y, i32 %z) {
5+
; CHECK-LABEL: @src_2add_2sext_sub_1(
6+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y:%.*]] to i64
7+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z:%.*]] to i64
8+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
109
; CHECK-NEXT: ret i64 [[SUB]]
1110
;
1211
%add1 = add nsw i32 %x, %y
@@ -17,11 +16,55 @@ define i64 @src_2add_2sext_sub(i32 %x, i32 %y, i32 %z) {
1716
ret i64 %sub
1817
}
1918

19+
define i64 @src_2add_2sext_sub_2(i32 %x, i32 %y, i32 %z) {
20+
; CHECK-LABEL: @src_2add_2sext_sub_2(
21+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y:%.*]] to i64
22+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z:%.*]] to i64
23+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
24+
; CHECK-NEXT: ret i64 [[SUB]]
25+
;
26+
%add1 = add nsw i32 %x, %y
27+
%add2 = add nsw i32 %z, %x
28+
%sext1 = sext i32 %add1 to i64
29+
%sext2 = sext i32 %add2 to i64
30+
%sub = sub i64 %sext1, %sext2
31+
ret i64 %sub
32+
}
33+
34+
define i64 @src_2add_2sext_sub_3(i32 %x, i32 %y, i32 %z) {
35+
; CHECK-LABEL: @src_2add_2sext_sub_3(
36+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y:%.*]] to i64
37+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z:%.*]] to i64
38+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
39+
; CHECK-NEXT: ret i64 [[SUB]]
40+
;
41+
%add1 = add nsw i32 %y, %x
42+
%add2 = add nsw i32 %z, %x
43+
%sext1 = sext i32 %add1 to i64
44+
%sext2 = sext i32 %add2 to i64
45+
%sub = sub i64 %sext1, %sext2
46+
ret i64 %sub
47+
}
48+
49+
define i64 @src_2add_2sext_sub_4(i32 %x, i32 %y, i32 %z) {
50+
; CHECK-LABEL: @src_2add_2sext_sub_4(
51+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y:%.*]] to i64
52+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z:%.*]] to i64
53+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
54+
; CHECK-NEXT: ret i64 [[SUB]]
55+
;
56+
%add1 = add nsw i32 %y, %x
57+
%add2 = add nsw i32 %x, %z
58+
%sext1 = sext i32 %add1 to i64
59+
%sext2 = sext i32 %add2 to i64
60+
%sub = sub i64 %sext1, %sext2
61+
ret i64 %sub
62+
}
63+
2064
define i64 @src_2add_2sext_sub_nsw(i32 %x, i32 %y, i32 %z) {
21-
; CHECK-LABEL: define i64 @src_2add_2sext_sub_nsw(
22-
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
23-
; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[Y]] to i64
24-
; CHECK-NEXT: [[SEXT2:%.*]] = sext i32 [[Z]] to i64
65+
; CHECK-LABEL: @src_2add_2sext_sub_nsw(
66+
; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[Y:%.*]] to i64
67+
; CHECK-NEXT: [[SEXT2:%.*]] = sext i32 [[Z:%.*]] to i64
2568
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[SEXT1]], [[SEXT2]]
2669
; CHECK-NEXT: ret i64 [[SUB]]
2770
;
@@ -34,10 +77,9 @@ define i64 @src_2add_2sext_sub_nsw(i32 %x, i32 %y, i32 %z) {
3477
}
3578

3679
define i64 @src_2add_2sext_sub_nuw(i32 %x, i32 %y, i32 %z) {
37-
; CHECK-LABEL: define i64 @src_2add_2sext_sub_nuw(
38-
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
39-
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y]] to i64
40-
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z]] to i64
80+
; CHECK-LABEL: @src_2add_2sext_sub_nuw(
81+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y:%.*]] to i64
82+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z:%.*]] to i64
4183
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
4284
; CHECK-NEXT: ret i64 [[SUB]]
4385
;
@@ -49,10 +91,9 @@ define i64 @src_2add_2sext_sub_nuw(i32 %x, i32 %y, i32 %z) {
4991
ret i64 %sub
5092
}
5193

52-
define i64 @src_x_add_2sext_sub(i32 %x, i32 %y) {
53-
; CHECK-LABEL: define i64 @src_x_add_2sext_sub(
54-
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
55-
; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[Y]] to i64
94+
define i64 @src_x_add_2sext_sub_1(i32 %x, i32 %y) {
95+
; CHECK-LABEL: @src_x_add_2sext_sub_1(
96+
; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[Y:%.*]] to i64
5697
; CHECK-NEXT: ret i64 [[SUB]]
5798
;
5899
%add1 = add nsw i32 %x, %y
@@ -62,10 +103,21 @@ define i64 @src_x_add_2sext_sub(i32 %x, i32 %y) {
62103
ret i64 %sub
63104
}
64105

106+
define i64 @src_x_add_2sext_sub_2(i32 %x, i32 %y) {
107+
; CHECK-LABEL: @src_x_add_2sext_sub_2(
108+
; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[Y:%.*]] to i64
109+
; CHECK-NEXT: ret i64 [[SUB]]
110+
;
111+
%add1 = add nsw i32 %y, %x
112+
%sext1 = sext i32 %add1 to i64
113+
%sext2 = sext i32 %x to i64
114+
%sub = sub i64 %sext1, %sext2
115+
ret i64 %sub
116+
}
117+
65118
define i64 @src_x_add_2sext_sub_nsw(i32 %x, i32 %y) {
66-
; CHECK-LABEL: define i64 @src_x_add_2sext_sub_nsw(
67-
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
68-
; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[Y]] to i64
119+
; CHECK-LABEL: @src_x_add_2sext_sub_nsw(
120+
; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[Y:%.*]] to i64
69121
; CHECK-NEXT: ret i64 [[SUB]]
70122
;
71123
%add1 = add nsw i32 %x, %y
@@ -76,9 +128,8 @@ define i64 @src_x_add_2sext_sub_nsw(i32 %x, i32 %y) {
76128
}
77129

78130
define i64 @src_x_add_2sext_sub_nuw(i32 %x, i32 %y) {
79-
; CHECK-LABEL: define i64 @src_x_add_2sext_sub_nuw(
80-
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
81-
; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[Y]] to i64
131+
; CHECK-LABEL: @src_x_add_2sext_sub_nuw(
132+
; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[Y:%.*]] to i64
82133
; CHECK-NEXT: ret i64 [[SUB]]
83134
;
84135
%add1 = add nsw i32 %x, %y

0 commit comments

Comments
 (0)