Skip to content

Commit dfe1d35

Browse files
authored
[InstCombine] Propagate NSW/NUW flags for (X - Y) - Z -> X - (Y + Z) (#72693)
Alive2: https://alive2.llvm.org/ce/z/gqeaVo Related patch: 31d219d
1 parent 5a305ce commit dfe1d35

File tree

2 files changed

+78
-3
lines changed

2 files changed

+78
-3
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,8 +2191,15 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
21912191

21922192
// ((X - Y) - Op1) --> X - (Y + Op1)
21932193
if (match(Op0, m_OneUse(m_Sub(m_Value(X), m_Value(Y))))) {
2194-
Value *Add = Builder.CreateAdd(Y, Op1);
2195-
return BinaryOperator::CreateSub(X, Add);
2194+
OverflowingBinaryOperator *LHSSub = cast<OverflowingBinaryOperator>(Op0);
2195+
bool HasNUW = I.hasNoUnsignedWrap() && LHSSub->hasNoUnsignedWrap();
2196+
bool HasNSW = HasNUW && I.hasNoSignedWrap() && LHSSub->hasNoSignedWrap();
2197+
Value *Add = Builder.CreateAdd(Y, Op1, "", /* HasNUW */ HasNUW,
2198+
/* HasNSW */ HasNSW);
2199+
BinaryOperator *Sub = BinaryOperator::CreateSub(X, Add);
2200+
Sub->setHasNoUnsignedWrap(HasNUW);
2201+
Sub->setHasNoSignedWrap(HasNSW);
2202+
return Sub;
21962203
}
21972204

21982205
// (~X) - (~Y) --> Y - X

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

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,82 @@ define i8 @t0(i8 %x, i8 %y, i8 %z) {
1717
ret i8 %r
1818
}
1919

20-
; No flags are propagated
20+
; NSW/NUW flags are propagated
2121
define i8 @t1_flags(i8 %x, i8 %y, i8 %z) {
2222
; CHECK-LABEL: @t1_flags(
23+
; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i8 [[Y:%.*]], [[Z:%.*]]
24+
; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i8 [[X:%.*]], [[TMP1]]
25+
; CHECK-NEXT: ret i8 [[R]]
26+
;
27+
%o0 = sub nuw nsw i8 %x, %y
28+
%r = sub nuw nsw i8 %o0, %z
29+
ret i8 %r
30+
}
31+
32+
; NUW flags are propagated
33+
define i8 @t1_flags_nuw_only(i8 %x, i8 %y, i8 %z) {
34+
; CHECK-LABEL: @t1_flags_nuw_only(
35+
; CHECK-NEXT: [[TMP1:%.*]] = add nuw i8 [[Y:%.*]], [[Z:%.*]]
36+
; CHECK-NEXT: [[R:%.*]] = sub nuw i8 [[X:%.*]], [[TMP1]]
37+
; CHECK-NEXT: ret i8 [[R]]
38+
;
39+
%o0 = sub nuw i8 %x, %y
40+
%r = sub nuw i8 %o0, %z
41+
ret i8 %r
42+
}
43+
44+
; Negative tests
45+
define i8 @t1_flags_sub_nsw_sub(i8 %x, i8 %y, i8 %z) {
46+
; CHECK-LABEL: @t1_flags_sub_nsw_sub(
47+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
48+
; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
49+
; CHECK-NEXT: ret i8 [[R]]
50+
;
51+
%o0 = sub nsw i8 %x, %y
52+
%r = sub i8 %o0, %z
53+
ret i8 %r
54+
}
55+
56+
define i8 @t1_flags_nuw_first(i8 %x, i8 %y, i8 %z) {
57+
; CHECK-LABEL: @t1_flags_nuw_first(
58+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
59+
; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
60+
; CHECK-NEXT: ret i8 [[R]]
61+
;
62+
%o0 = sub nuw i8 %x, %y
63+
%r = sub i8 %o0, %z
64+
ret i8 %r
65+
}
66+
67+
define i8 @t1_flags_nuw_second(i8 %x, i8 %y, i8 %z) {
68+
; CHECK-LABEL: @t1_flags_nuw_second(
69+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
70+
; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
71+
; CHECK-NEXT: ret i8 [[R]]
72+
;
73+
%o0 = sub i8 %x, %y
74+
%r = sub nuw i8 %o0, %z
75+
ret i8 %r
76+
}
77+
78+
define i8 @t1_flags_nuw_nsw_first(i8 %x, i8 %y, i8 %z) {
79+
; CHECK-LABEL: @t1_flags_nuw_nsw_first(
2380
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
2481
; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
2582
; CHECK-NEXT: ret i8 [[R]]
2683
;
2784
%o0 = sub nuw nsw i8 %x, %y
85+
%r = sub i8 %o0, %z
86+
ret i8 %r
87+
}
88+
89+
define i8 @t1_flags_nuw_nsw_second(i8 %x, i8 %y, i8 %z) {
90+
; CHECK-LABEL: @t1_flags_nuw_nsw_second(
91+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
92+
; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
93+
; CHECK-NEXT: ret i8 [[R]]
94+
;
95+
%o0 = sub i8 %x, %y
2896
%r = sub nuw nsw i8 %o0, %z
2997
ret i8 %r
3098
}

0 commit comments

Comments
 (0)