6767 br label %loop
6868}
6969
70-
71- ; Hoist ADD and copy NUW if both ops have it. Commutative version .
70+ ; Hoist ADD and copy NUW if both ops have it.
71+ ; Version where operands are commuted .
7272define void @add_nuw_comm (i64 %c1 , i64 %c2 ) {
7373; CHECK-LABEL: @add_nuw_comm(
7474; CHECK-NEXT: entry:
9292 br label %loop
9393}
9494
95+ ; Hoist ADD and copy NUW if both ops have it.
96+ ; Another version where operands are commuted.
97+ define void @add_nuw_comm2 (i64 %c1 , i64 %c2 ) {
98+ ; CHECK-LABEL: @add_nuw_comm2(
99+ ; CHECK-NEXT: entry:
100+ ; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw i64 [[C1:%.*]], [[C2:%.*]]
101+ ; CHECK-NEXT: br label [[LOOP:%.*]]
102+ ; CHECK: loop:
103+ ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
104+ ; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[INDEX]], [[C1]]
105+ ; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
106+ ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]
107+ ; CHECK-NEXT: br label [[LOOP]]
108+ ;
109+ entry:
110+ br label %loop
111+
112+ loop:
113+ %index = phi i64 [ 0 , %entry ], [ %index.next , %loop ]
114+ %step.add = add nuw i64 %index , %c1
115+ call void @use (i64 %step.add )
116+ %index.next = add nuw i64 %c2 , %step.add
117+ br label %loop
118+ }
119+
120+ ; Hoist ADD and copy NUW if both ops have it.
121+ ; Another version where operands are commuted.
122+ define void @add_nuw_comm3 (i64 %c1 , i64 %c2 ) {
123+ ; CHECK-LABEL: @add_nuw_comm3(
124+ ; CHECK-NEXT: entry:
125+ ; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw i64 [[C1:%.*]], [[C2:%.*]]
126+ ; CHECK-NEXT: br label [[LOOP:%.*]]
127+ ; CHECK: loop:
128+ ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
129+ ; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[C1]], [[INDEX]]
130+ ; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
131+ ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]
132+ ; CHECK-NEXT: br label [[LOOP]]
133+ ;
134+ entry:
135+ br label %loop
136+
137+ loop:
138+ %index = phi i64 [ 0 , %entry ], [ %index.next , %loop ]
139+ %step.add = add nuw i64 %c1 , %index
140+ call void @use (i64 %step.add )
141+ %index.next = add nuw i64 %c2 , %step.add
142+ br label %loop
143+ }
144+
145+ ; Hoist ADD and copy NUW if both ops have it.
146+ ; A version where the LHS and RHS of the outer BinOp are BinOps.
147+ define void @add_nuw_twobinops (i64 %c1 , i64 %c2 ) {
148+ ; CHECK-LABEL: @add_nuw_twobinops(
149+ ; CHECK-NEXT: entry:
150+ ; CHECK-NEXT: [[C2_PLUS_2:%.*]] = add nuw i64 [[C2:%.*]], 2
151+ ; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw i64 [[C1:%.*]], [[C2_PLUS_2]]
152+ ; CHECK-NEXT: br label [[LOOP:%.*]]
153+ ; CHECK: loop:
154+ ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
155+ ; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[C1]], [[INDEX]]
156+ ; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
157+ ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]
158+ ; CHECK-NEXT: br label [[LOOP]]
159+ ;
160+ entry:
161+ br label %loop
162+
163+ loop:
164+ %index = phi i64 [ 0 , %entry ], [ %index.next , %loop ]
165+ %step.add = add nuw i64 %c1 , %index
166+ call void @use (i64 %step.add )
167+ %c2.plus.2 = add nuw i64 %c2 , 2
168+ %index.next = add nuw i64 %step.add , %c2.plus.2
169+ br label %loop
170+ }
171+
95172; Hoist MUL and drop NUW even if both ops have it.
96173define void @mul_nuw (i64 %c1 , i64 %c2 ) {
97174; CHECK-LABEL: @mul_nuw(
@@ -116,7 +193,8 @@ loop:
116193 br label %loop
117194}
118195
119- ; Hoist MUL and drop NUW even if both ops have it. Commutative version.
196+ ; Hoist MUL and drop NUW even if both ops have it.
197+ ; Version where operands are commuted.
120198define void @mul_nuw_comm (i64 %c1 , i64 %c2 ) {
121199; CHECK-LABEL: @mul_nuw_comm(
122200; CHECK-NEXT: entry:
@@ -140,6 +218,83 @@ loop:
140218 br label %loop
141219}
142220
221+ ; Hoist MUL and drop NUW even if both ops have it.
222+ ; Another version where operands are commuted.
223+ define void @mul_nuw_comm2 (i64 %c1 , i64 %c2 ) {
224+ ; CHECK-LABEL: @mul_nuw_comm2(
225+ ; CHECK-NEXT: entry:
226+ ; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
227+ ; CHECK-NEXT: br label [[LOOP:%.*]]
228+ ; CHECK: loop:
229+ ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
230+ ; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[INDEX]], [[C1]]
231+ ; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
232+ ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
233+ ; CHECK-NEXT: br label [[LOOP]]
234+ ;
235+ entry:
236+ br label %loop
237+
238+ loop:
239+ %index = phi i64 [ 0 , %entry ], [ %index.next , %loop ]
240+ %step.add = mul nuw i64 %index , %c1
241+ call void @use (i64 %step.add )
242+ %index.next = mul nuw i64 %c2 , %step.add
243+ br label %loop
244+ }
245+
246+ ; Hoist MUL and drop NUW even if both ops have it.
247+ ; Another version where operands are commuted.
248+ define void @mul_nuw_comm3 (i64 %c1 , i64 %c2 ) {
249+ ; CHECK-LABEL: @mul_nuw_comm3(
250+ ; CHECK-NEXT: entry:
251+ ; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
252+ ; CHECK-NEXT: br label [[LOOP:%.*]]
253+ ; CHECK: loop:
254+ ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
255+ ; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[C1]], [[INDEX]]
256+ ; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
257+ ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
258+ ; CHECK-NEXT: br label [[LOOP]]
259+ ;
260+ entry:
261+ br label %loop
262+
263+ loop:
264+ %index = phi i64 [ 0 , %entry ], [ %index.next , %loop ]
265+ %step.add = mul nuw i64 %c1 , %index
266+ call void @use (i64 %step.add )
267+ %index.next = mul nuw i64 %c2 , %step.add
268+ br label %loop
269+ }
270+
271+ ; Hoist MUL and drop NUW even if both ops have it.
272+ ; A version where the LHS and RHS of the outer BinOp are BinOps.
273+ define void @mul_nuw_twobinops (i64 %c1 , i64 %c2 ) {
274+ ; CHECK-LABEL: @mul_nuw_twobinops(
275+ ; CHECK-NEXT: entry:
276+ ; CHECK-NEXT: [[C2_PLUS_2:%.*]] = add nuw i64 [[C2:%.*]], 2
277+ ; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2_PLUS_2]]
278+ ; CHECK-NEXT: br label [[LOOP:%.*]]
279+ ; CHECK: loop:
280+ ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
281+ ; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[C1]], [[INDEX]]
282+ ; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
283+ ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
284+ ; CHECK-NEXT: br label [[LOOP]]
285+ ;
286+ entry:
287+ br label %loop
288+
289+ loop:
290+ %index = phi i64 [ 0 , %entry ], [ %index.next , %loop ]
291+ %step.add = mul nuw i64 %c1 , %index
292+ call void @use (i64 %step.add )
293+ %c2.plus.2 = add nuw i64 %c2 , 2
294+ %index.next = mul nuw i64 %step.add , %c2.plus.2
295+ br label %loop
296+ }
297+
143298; Hoist ADD but don't copy NUW if only one op has it.
144299define void @add_no_nuw (i64 %c1 , i64 %c2 ) {
145300; CHECK-LABEL: @add_no_nuw(
0 commit comments