1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -instcombine -S %s | FileCheck %s
3
4define i32 @reassoc_add_nuw(i32 %x) {
5; CHECK-LABEL: @reassoc_add_nuw(
6; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i32 [[X:%.*]], 68
7; CHECK-NEXT:    ret i32 [[ADD1]]
8;
9  %add0 = add nuw i32 %x, 4
10  %add1 = add nuw i32 %add0, 64
11  ret i32 %add1
12}
13
14; This does the wrong thing because the sub is turned into an add of a
15; negative constant first which drops the nuw.
16define i32 @reassoc_sub_nuw(i32 %x) {
17; CHECK-LABEL: @reassoc_sub_nuw(
18; CHECK-NEXT:    [[SUB1:%.*]] = add i32 [[X:%.*]], -68
19; CHECK-NEXT:    ret i32 [[SUB1]]
20;
21  %sub0 = sub nuw i32 %x, 4
22  %sub1 = sub nuw i32 %sub0, 64
23  ret i32 %sub1
24}
25
26define i32 @reassoc_mul_nuw(i32 %x) {
27; CHECK-LABEL: @reassoc_mul_nuw(
28; CHECK-NEXT:    [[MUL1:%.*]] = mul nuw i32 [[X:%.*]], 260
29; CHECK-NEXT:    ret i32 [[MUL1]]
30;
31  %mul0 = mul nuw i32 %x, 4
32  %mul1 = mul nuw i32 %mul0, 65
33  ret i32 %mul1
34}
35
36define i32 @no_reassoc_add_nuw_none(i32 %x) {
37; CHECK-LABEL: @no_reassoc_add_nuw_none(
38; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[X:%.*]], 68
39; CHECK-NEXT:    ret i32 [[ADD1]]
40;
41  %add0 = add i32 %x, 4
42  %add1 = add nuw i32 %add0, 64
43  ret i32 %add1
44}
45
46define i32 @no_reassoc_add_none_nuw(i32 %x) {
47; CHECK-LABEL: @no_reassoc_add_none_nuw(
48; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[X:%.*]], 68
49; CHECK-NEXT:    ret i32 [[ADD1]]
50;
51  %add0 = add nuw i32 %x, 4
52  %add1 = add i32 %add0, 64
53  ret i32 %add1
54}
55
56define i32 @reassoc_x2_add_nuw(i32 %x, i32 %y) {
57; CHECK-LABEL: @reassoc_x2_add_nuw(
58; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i32 [[X:%.*]], [[Y:%.*]]
59; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i32 [[ADD1]], 12
60; CHECK-NEXT:    ret i32 [[ADD2]]
61;
62  %add0 = add nuw i32 %x, 4
63  %add1 = add nuw i32 %y, 8
64  %add2 = add nuw i32 %add0, %add1
65  ret i32 %add2
66}
67
68define i32 @reassoc_x2_mul_nuw(i32 %x, i32 %y) {
69; CHECK-LABEL: @reassoc_x2_mul_nuw(
70; CHECK-NEXT:    [[MUL1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
71; CHECK-NEXT:    [[MUL2:%.*]] = mul nuw i32 [[MUL1]], 45
72; CHECK-NEXT:    ret i32 [[MUL2]]
73;
74  %mul0 = mul nuw i32 %x, 5
75  %mul1 = mul nuw i32 %y, 9
76  %mul2 = mul nuw i32 %mul0, %mul1
77  ret i32 %mul2
78}
79
80define i32 @reassoc_x2_sub_nuw(i32 %x, i32 %y) {
81; CHECK-LABEL: @reassoc_x2_sub_nuw(
82; CHECK-NEXT:    [[SUB0:%.*]] = add i32 [[X:%.*]], -4
83; CHECK-NEXT:    [[SUB1:%.*]] = add i32 [[Y:%.*]], -8
84; CHECK-NEXT:    [[SUB2:%.*]] = sub nuw i32 [[SUB0]], [[SUB1]]
85; CHECK-NEXT:    ret i32 [[SUB2]]
86;
87  %sub0 = sub nuw i32 %x, 4
88  %sub1 = sub nuw i32 %y, 8
89  %sub2 = sub nuw i32 %sub0, %sub1
90  ret i32 %sub2
91}
92
93define i32 @tryFactorization_add_nuw_mul_nuw(i32 %x) {
94; CHECK-LABEL: @tryFactorization_add_nuw_mul_nuw(
95; CHECK-NEXT:    [[ADD2:%.*]] = shl nuw i32 [[X:%.*]], 2
96; CHECK-NEXT:    ret i32 [[ADD2]]
97;
98  %mul1 = mul nuw i32 %x, 3
99  %add2 = add nuw i32 %mul1, %x
100  ret i32 %add2
101}
102
103define i32 @tryFactorization_add_nuw_mul_nuw_int_max(i32 %x) {
104; CHECK-LABEL: @tryFactorization_add_nuw_mul_nuw_int_max(
105; CHECK-NEXT:    [[ADD2:%.*]] = shl nuw i32 [[X:%.*]], 31
106; CHECK-NEXT:    ret i32 [[ADD2]]
107;
108  %mul1 = mul nuw i32 %x, 2147483647
109  %add2 = add nuw i32 %mul1, %x
110  ret i32 %add2
111}
112
113define i32 @tryFactorization_add_mul_nuw(i32 %x) {
114; CHECK-LABEL: @tryFactorization_add_mul_nuw(
115; CHECK-NEXT:    [[ADD2:%.*]] = shl i32 [[X:%.*]], 2
116; CHECK-NEXT:    ret i32 [[ADD2]]
117;
118  %mul1 = mul i32 %x, 3
119  %add2 = add nuw i32 %mul1, %x
120  ret i32 %add2
121}
122
123define i32 @tryFactorization_add_nuw_mul(i32 %x) {
124; CHECK-LABEL: @tryFactorization_add_nuw_mul(
125; CHECK-NEXT:    [[ADD2:%.*]] = shl i32 [[X:%.*]], 2
126; CHECK-NEXT:    ret i32 [[ADD2]]
127;
128  %mul1 = mul nuw i32 %x, 3
129  %add2 = add i32 %mul1, %x
130  ret i32 %add2
131}
132
133define i32 @tryFactorization_add_nuw_mul_nuw_mul_nuw_var(i32 %x, i32 %y, i32 %z) {
134; CHECK-LABEL: @tryFactorization_add_nuw_mul_nuw_mul_nuw_var(
135; CHECK-NEXT:    [[MUL21:%.*]] = add i32 [[Y:%.*]], [[Z:%.*]]
136; CHECK-NEXT:    [[ADD1:%.*]] = mul nuw i32 [[MUL21]], [[X:%.*]]
137; CHECK-NEXT:    ret i32 [[ADD1]]
138;
139  %mul1 = mul nuw i32 %x, %y
140  %mul2 = mul nuw i32 %x, %z
141  %add1 = add nuw i32 %mul1, %mul2
142  ret i32 %add1
143}
144
145define i32 @tryFactorization_add_nuw_mul_mul_nuw_var(i32 %x, i32 %y, i32 %z) {
146; CHECK-LABEL: @tryFactorization_add_nuw_mul_mul_nuw_var(
147; CHECK-NEXT:    [[MUL21:%.*]] = add i32 [[Y:%.*]], [[Z:%.*]]
148; CHECK-NEXT:    [[ADD1:%.*]] = mul i32 [[MUL21]], [[X:%.*]]
149; CHECK-NEXT:    ret i32 [[ADD1]]
150;
151  %mul1 = mul i32 %x, %y
152  %mul2 = mul nuw i32 %x, %z
153  %add1 = add nuw i32 %mul1, %mul2
154  ret i32 %add1
155}
156
157define i32 @tryFactorization_add_nuw_mul_nuw_mul_var(i32 %x, i32 %y, i32 %z) {
158; CHECK-LABEL: @tryFactorization_add_nuw_mul_nuw_mul_var(
159; CHECK-NEXT:    [[MUL21:%.*]] = add i32 [[Y:%.*]], [[Z:%.*]]
160; CHECK-NEXT:    [[ADD1:%.*]] = mul i32 [[MUL21]], [[X:%.*]]
161; CHECK-NEXT:    ret i32 [[ADD1]]
162;
163  %mul1 = mul nuw i32 %x, %y
164  %mul2 = mul i32 %x, %z
165  %add1 = add nuw i32 %mul1, %mul2
166  ret i32 %add1
167}
168
169define i32 @tryFactorization_add_mul_nuw_mul_var(i32 %x, i32 %y, i32 %z) {
170; CHECK-LABEL: @tryFactorization_add_mul_nuw_mul_var(
171; CHECK-NEXT:    [[MUL21:%.*]] = add i32 [[Y:%.*]], [[Z:%.*]]
172; CHECK-NEXT:    [[ADD1:%.*]] = mul i32 [[MUL21]], [[X:%.*]]
173; CHECK-NEXT:    ret i32 [[ADD1]]
174;
175  %mul1 = mul nuw i32 %x, %y
176  %mul2 = mul nuw i32 %x, %z
177  %add1 = add i32 %mul1, %mul2
178  ret i32 %add1
179}
180