11; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
22; RUN: opt -S -passes=licm < %s | FileCheck %s
33
4- ; Fold ADD and remove old op if unused.
4+ ; Hoist ADD and remove old op if unused.
55define void @add_one_use (i64 %c1 , i64 %c2 ) {
66; CHECK-LABEL: @add_one_use(
77; CHECK-NEXT: entry:
2222 br label %loop
2323}
2424
25- ; Fold ADD and copy NUW if both ops have it.
26- ; https://alive2.llvm.org/ce/z/bPAT7Z
25+ ; Hoist MUL and remove old op if unused.
26+ define void @mul_one_use (i64 %c1 , i64 %c2 ) {
27+ ; CHECK-LABEL: @mul_one_use(
28+ ; CHECK-NEXT: entry:
29+ ; CHECK-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
30+ ; CHECK-NEXT: br label [[LOOP:%.*]]
31+ ; CHECK: loop:
32+ ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[STEP_ADD_REASS:%.*]], [[LOOP]] ]
33+ ; CHECK-NEXT: [[STEP_ADD_REASS]] = mul i64 [[INDEX]], [[FACTOR_OP_MUL]]
34+ ; CHECK-NEXT: br label [[LOOP]]
35+ ;
36+ entry:
37+ br label %loop
38+
39+ loop:
40+ %index = phi i64 [ 0 , %entry ], [ %index.next , %loop ]
41+ %step.add = mul i64 %index , %c1
42+ %index.next = mul i64 %step.add , %c2
43+ br label %loop
44+ }
45+
46+ ; Hoist ADD and copy NUW if both ops have it.
2747define void @add_nuw (i64 %c1 , i64 %c2 ) {
2848; CHECK-LABEL: @add_nuw(
2949; CHECK-NEXT: entry:
4767 br label %loop
4868}
4969
50- ; Fold ADD but don't copy NUW if only one op has it.
70+ ; Hoist MUL and drop NUW even if both ops have it.
71+ define void @mul_nuw (i64 %c1 , i64 %c2 ) {
72+ ; CHECK-LABEL: @mul_nuw(
73+ ; CHECK-NEXT: entry:
74+ ; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
75+ ; CHECK-NEXT: br label [[LOOP:%.*]]
76+ ; CHECK: loop:
77+ ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
78+ ; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[INDEX]], [[C1]]
79+ ; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
80+ ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
81+ ; CHECK-NEXT: br label [[LOOP]]
82+ ;
83+ entry:
84+ br label %loop
85+
86+ loop:
87+ %index = phi i64 [ 0 , %entry ], [ %index.next , %loop ]
88+ %step.add = mul nuw i64 %index , %c1
89+ call void @use (i64 %step.add )
90+ %index.next = mul nuw i64 %step.add , %c2
91+ br label %loop
92+ }
93+
94+ ; Hoist ADD but don't copy NUW if only one op has it.
5195define void @add_no_nuw (i64 %c1 , i64 %c2 ) {
5296; CHECK-LABEL: @add_no_nuw(
5397; CHECK-NEXT: entry:
71115 br label %loop
72116}
73117
74- ; Fold ADD but don't copy NSW if one op has it.
118+ ; Hoist ADD but don't copy NSW if one op has it.
75119define void @add_no_nsw (i64 %c1 , i64 %c2 ) {
76120; CHECK-LABEL: @add_no_nsw(
77121; CHECK-NEXT: entry:
95139 br label %loop
96140}
97141
98- ; Fold ADD but don't copy NSW even if both ops have it.
142+ ; Hoist ADD but don't copy NSW even if both ops have it.
99143define void @add_no_nsw_2 (i64 %c1 , i64 %c2 ) {
100144; CHECK-LABEL: @add_no_nsw_2(
101145; CHECK-NEXT: entry:
@@ -119,7 +163,31 @@ loop:
119163 br label %loop
120164}
121165
122- ; Don't fold if the ops are different (even if they are both associative).
166+ ; Hoist MUL and drop NSW even if both ops have it.
167+ define void @mul_no_nsw_2 (i64 %c1 , i64 %c2 ) {
168+ ; CHECK-LABEL: @mul_no_nsw_2(
169+ ; CHECK-NEXT: entry:
170+ ; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
171+ ; CHECK-NEXT: br label [[LOOP:%.*]]
172+ ; CHECK: loop:
173+ ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
174+ ; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nsw i64 [[INDEX]], [[C1]]
175+ ; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
176+ ; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
177+ ; CHECK-NEXT: br label [[LOOP]]
178+ ;
179+ entry:
180+ br label %loop
181+
182+ loop:
183+ %index = phi i64 [ 0 , %entry ], [ %index.next , %loop ]
184+ %step.add = mul nsw i64 %index , %c1
185+ call void @use (i64 %step.add )
186+ %index.next = mul nsw i64 %step.add , %c2
187+ br label %loop
188+ }
189+
190+ ; Don't hoist if the ops are different (even if they are both associative).
123191define void @diff_ops (i64 %c1 , i64 %c2 ) {
124192; CHECK-LABEL: @diff_ops(
125193; CHECK-NEXT: entry:
@@ -142,7 +210,7 @@ loop:
142210 br label %loop
143211}
144212
145- ; Don't fold if the ops are not associative.
213+ ; Don't hoist if the ops are not associative.
146214define void @noassoc_ops (i64 %c1 , i64 %c2 ) {
147215; CHECK-LABEL: @noassoc_ops(
148216; CHECK-NEXT: entry:
@@ -165,7 +233,7 @@ loop:
165233 br label %loop
166234}
167235
168- ; Don't fold floating-point ops, even if they are associative. This would be
236+ ; Don't hoist floating-point ops, even if they are associative. This would be
169237; valid, but is currently disabled.
170238define void @fadd (float %c1 , float %c2 ) {
171239; CHECK-LABEL: @fadd(
@@ -189,7 +257,7 @@ loop:
189257 br label %loop
190258}
191259
192- ; Don't fold if the intermediate op has more than two uses. This is an
260+ ; Don't hoist if the intermediate op has more than two uses. This is an
193261; heuristic that can be adjusted if warranted. Currently we are being
194262; conservative to minimise potential impact in code size.
195263define void @not_many_uses (i64 %c1 , i64 %c2 , i64 %c3 ) {
0 commit comments