Skip to content

Commit 84560f7

Browse files
committed
[InstCombine] Fold usub_sat((sub nuw C1, A), C2) to usub_sat(C1 - C2, A) or 0
1 parent e03339a commit 84560f7

File tree

2 files changed

+23
-22
lines changed

2 files changed

+23
-22
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2139,8 +2139,22 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
21392139
}
21402140
}
21412141

2142+
// usub_sat((sub nuw C, A), C1) -> usub_sat(usub_sat(C, C1), A)
2143+
// which after that:
2144+
// usub_sat((sub nuw C, A), C1) -> usub_sat(C - C1, A) if C1 u< C
2145+
// usub_sat((sub nuw C, A), C1) -> 0 otherwise
2146+
Constant *C, *C1;
2147+
Value *A;
2148+
if (IID == Intrinsic::usub_sat &&
2149+
match(Arg0, m_NUWSub(m_ImmConstant(C), m_Value(A))) &&
2150+
match(Arg1, m_ImmConstant(C1))) {
2151+
auto *NewC = Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, C, C1);
2152+
auto *NewSub =
2153+
Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, NewC, A);
2154+
return replaceInstUsesWith(*SI, NewSub);
2155+
}
2156+
21422157
// ssub.sat(X, C) -> sadd.sat(X, -C) if C != MIN
2143-
Constant *C;
21442158
if (IID == Intrinsic::ssub_sat && match(Arg1, m_Constant(C)) &&
21452159
C->isNotMinSignedValue()) {
21462160
Value *NegVal = ConstantExpr::getNeg(C);

llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ declare void @usei1(i1)
1111
; usub_sat((sub nuw C1, A), C2) to usub_sat(usub_sat(C1 - C2), A)
1212
define i32 @usub_sat_C1_C2(i32 %a){
1313
; CHECK-LABEL: @usub_sat_C1_C2(
14-
; CHECK-NEXT: [[ADD:%.*]] = sub nuw i32 64, [[A:%.*]]
15-
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[ADD]], i32 14)
14+
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.usub.sat.i32(i32 50, i32 [[A:%.*]])
1615
; CHECK-NEXT: ret i32 [[COND]]
1716
;
1817
%add = sub nuw i32 64, %a
@@ -22,9 +21,7 @@ define i32 @usub_sat_C1_C2(i32 %a){
2221

2322
define i32 @usub_sat_C1_C2_produce_0(i32 %a){
2423
; CHECK-LABEL: @usub_sat_C1_C2_produce_0(
25-
; CHECK-NEXT: [[ADD:%.*]] = sub nuw i32 14, [[A:%.*]]
26-
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[ADD]], i32 14)
27-
; CHECK-NEXT: ret i32 [[COND]]
24+
; CHECK-NEXT: ret i32 0
2825
;
2926
%add = sub nuw i32 14, %a
3027
%cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
@@ -33,9 +30,7 @@ define i32 @usub_sat_C1_C2_produce_0(i32 %a){
3330

3431
define i32 @usub_sat_C1_C2_produce_0_too(i32 %a){
3532
; CHECK-LABEL: @usub_sat_C1_C2_produce_0_too(
36-
; CHECK-NEXT: [[ADD:%.*]] = sub nuw i32 12, [[A:%.*]]
37-
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[ADD]], i32 14)
38-
; CHECK-NEXT: ret i32 [[COND]]
33+
; CHECK-NEXT: ret i32 0
3934
;
4035
%add = sub nuw i32 12, %a
4136
%cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
@@ -45,8 +40,7 @@ define i32 @usub_sat_C1_C2_produce_0_too(i32 %a){
4540
; vector tests
4641
define <2 x i16> @usub_sat_C1_C2_splat(<2 x i16> %a) {
4742
; CHECK-LABEL: @usub_sat_C1_C2_splat(
48-
; CHECK-NEXT: [[ADD:%.*]] = sub nuw <2 x i16> <i16 64, i16 64>, [[A:%.*]]
49-
; CHECK-NEXT: [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> [[ADD]], <2 x i16> <i16 14, i16 14>)
43+
; CHECK-NEXT: [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> <i16 50, i16 50>, <2 x i16> [[A:%.*]])
5044
; CHECK-NEXT: ret <2 x i16> [[COND]]
5145
;
5246
%add = sub nuw <2 x i16> <i16 64, i16 64>, %a
@@ -56,8 +50,7 @@ define <2 x i16> @usub_sat_C1_C2_splat(<2 x i16> %a) {
5650

5751
define <2 x i16> @usub_sat_C1_C2_non_splat(<2 x i16> %a) {
5852
; CHECK-LABEL: @usub_sat_C1_C2_non_splat(
59-
; CHECK-NEXT: [[ADD:%.*]] = sub nuw <2 x i16> <i16 50, i16 64>, [[A:%.*]]
60-
; CHECK-NEXT: [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> [[ADD]], <2 x i16> <i16 20, i16 14>)
53+
; CHECK-NEXT: [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> <i16 30, i16 50>, <2 x i16> [[A:%.*]])
6154
; CHECK-NEXT: ret <2 x i16> [[COND]]
6255
;
6356
%add = sub nuw <2 x i16> <i16 50, i16 64>, %a
@@ -67,9 +60,7 @@ define <2 x i16> @usub_sat_C1_C2_non_splat(<2 x i16> %a) {
6760

6861
define <2 x i16> @usub_sat_C1_C2_splat_produce_0(<2 x i16> %a){
6962
; CHECK-LABEL: @usub_sat_C1_C2_splat_produce_0(
70-
; CHECK-NEXT: [[ADD:%.*]] = sub nuw <2 x i16> <i16 14, i16 14>, [[A:%.*]]
71-
; CHECK-NEXT: [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> [[ADD]], <2 x i16> <i16 14, i16 14>)
72-
; CHECK-NEXT: ret <2 x i16> [[COND]]
63+
; CHECK-NEXT: ret <2 x i16> zeroinitializer
7364
;
7465
%add = sub nuw <2 x i16> <i16 14, i16 14>, %a
7566
%cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> <i16 14, i16 14>)
@@ -78,9 +69,7 @@ define <2 x i16> @usub_sat_C1_C2_splat_produce_0(<2 x i16> %a){
7869

7970
define <2 x i16> @usub_sat_C1_C2_splat_produce_0_too(<2 x i16> %a){
8071
; CHECK-LABEL: @usub_sat_C1_C2_splat_produce_0_too(
81-
; CHECK-NEXT: [[ADD:%.*]] = sub nuw <2 x i16> <i16 12, i16 12>, [[A:%.*]]
82-
; CHECK-NEXT: [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> [[ADD]], <2 x i16> <i16 14, i16 14>)
83-
; CHECK-NEXT: ret <2 x i16> [[COND]]
72+
; CHECK-NEXT: ret <2 x i16> zeroinitializer
8473
;
8574
%add = sub nuw <2 x i16> <i16 12, i16 12>, %a
8675
%cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> <i16 14, i16 14>)
@@ -89,9 +78,7 @@ define <2 x i16> @usub_sat_C1_C2_splat_produce_0_too(<2 x i16> %a){
8978

9079
define <2 x i16> @usub_sat_C1_C2_non_splat_produce_0_too(<2 x i16> %a){
9180
; CHECK-LABEL: @usub_sat_C1_C2_non_splat_produce_0_too(
92-
; CHECK-NEXT: [[ADD:%.*]] = sub nuw <2 x i16> <i16 12, i16 13>, [[A:%.*]]
93-
; CHECK-NEXT: [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> [[ADD]], <2 x i16> <i16 14, i16 15>)
94-
; CHECK-NEXT: ret <2 x i16> [[COND]]
81+
; CHECK-NEXT: ret <2 x i16> zeroinitializer
9582
;
9683
%add = sub nuw <2 x i16> <i16 12, i16 13>, %a
9784
%cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> <i16 14, i16 15>)

0 commit comments

Comments
 (0)