1
1
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2
2
; RUN: opt -S -passes=licm < %s | FileCheck %s
3
3
4
- ; Fold ADD and remove old op if unused.
4
+ ; Hoist ADD and remove old op if unused.
5
5
define void @add_one_use (i64 %c1 , i64 %c2 ) {
6
6
; CHECK-LABEL: @add_one_use(
7
7
; CHECK-NEXT: entry:
22
22
br label %loop
23
23
}
24
24
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.
27
47
define void @add_nuw (i64 %c1 , i64 %c2 ) {
28
48
; CHECK-LABEL: @add_nuw(
29
49
; CHECK-NEXT: entry:
47
67
br label %loop
48
68
}
49
69
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.
51
95
define void @add_no_nuw (i64 %c1 , i64 %c2 ) {
52
96
; CHECK-LABEL: @add_no_nuw(
53
97
; CHECK-NEXT: entry:
71
115
br label %loop
72
116
}
73
117
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.
75
119
define void @add_no_nsw (i64 %c1 , i64 %c2 ) {
76
120
; CHECK-LABEL: @add_no_nsw(
77
121
; CHECK-NEXT: entry:
95
139
br label %loop
96
140
}
97
141
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.
99
143
define void @add_no_nsw_2 (i64 %c1 , i64 %c2 ) {
100
144
; CHECK-LABEL: @add_no_nsw_2(
101
145
; CHECK-NEXT: entry:
@@ -119,7 +163,31 @@ loop:
119
163
br label %loop
120
164
}
121
165
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).
123
191
define void @diff_ops (i64 %c1 , i64 %c2 ) {
124
192
; CHECK-LABEL: @diff_ops(
125
193
; CHECK-NEXT: entry:
@@ -142,7 +210,7 @@ loop:
142
210
br label %loop
143
211
}
144
212
145
- ; Don't fold if the ops are not associative.
213
+ ; Don't hoist if the ops are not associative.
146
214
define void @noassoc_ops (i64 %c1 , i64 %c2 ) {
147
215
; CHECK-LABEL: @noassoc_ops(
148
216
; CHECK-NEXT: entry:
@@ -165,7 +233,7 @@ loop:
165
233
br label %loop
166
234
}
167
235
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
169
237
; valid, but is currently disabled.
170
238
define void @fadd (float %c1 , float %c2 ) {
171
239
; CHECK-LABEL: @fadd(
@@ -189,7 +257,7 @@ loop:
189
257
br label %loop
190
258
}
191
259
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
193
261
; heuristic that can be adjusted if warranted. Currently we are being
194
262
; conservative to minimise potential impact in code size.
195
263
define void @not_many_uses (i64 %c1 , i64 %c2 , i64 %c3 ) {
0 commit comments