Skip to content

Commit aa80ea8

Browse files
committed
[IndVarSimplify] Add test requiring ashr expansion.
Add test cases showing large ashr expansion during IndVarSimplify after ec54867.
1 parent a0898f0 commit aa80ea8

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -indvars -S %s | FileCheck %s
3+
4+
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
5+
6+
define float @ashr_expansion_valid(i64 %x, float* %ptr) {
7+
; CHECK-LABEL: @ashr_expansion_valid(
8+
; CHECK-NEXT: entry:
9+
; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[X:%.*]], i64 -1)
10+
; CHECK-NEXT: [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 1)
11+
; CHECK-NEXT: [[TMP0:%.*]] = sub i64 0, [[X]]
12+
; CHECK-NEXT: [[SMAX1:%.*]] = call i64 @llvm.smax.i64(i64 [[X]], i64 [[TMP0]])
13+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[SMAX1]], 4
14+
; CHECK-NEXT: [[TMP2:%.*]] = mul nsw i64 [[SMIN]], [[TMP1]]
15+
; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 1)
16+
; CHECK-NEXT: br label [[LOOP:%.*]]
17+
; CHECK: loop:
18+
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
19+
; CHECK-NEXT: [[RED:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP]] ]
20+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr float, float* [[PTR:%.*]], i64 [[IV]]
21+
; CHECK-NEXT: [[LV:%.*]] = load float, float* [[GEP]], align 4
22+
; CHECK-NEXT: [[RED_NEXT]] = fadd float [[LV]], [[RED]]
23+
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1
24+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[UMAX]]
25+
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
26+
; CHECK: exit:
27+
; CHECK-NEXT: [[LCSSA_RED_NEXT:%.*]] = phi float [ [[RED_NEXT]], [[LOOP]] ]
28+
; CHECK-NEXT: ret float [[LCSSA_RED_NEXT]]
29+
;
30+
entry:
31+
%bound = ashr exact i64 %x, 4
32+
br label %loop
33+
34+
loop:
35+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
36+
%red = phi float [ 0.0, %entry ], [ %red.next, %loop ]
37+
%gep = getelementptr float, float* %ptr, i64 %iv
38+
%lv = load float, float* %gep
39+
%red.next = fadd float %lv, %red
40+
%iv.next = add nuw i64 %iv, 1
41+
%cond = icmp ult i64 %iv.next, %bound
42+
br i1 %cond, label %loop, label %exit
43+
44+
exit: ; preds = %bb135
45+
%lcssa.red.next = phi float [ %red.next, %loop ]
46+
ret float %lcssa.red.next
47+
}
48+
49+
; No explicit ashr, but a chain of operations that can be replaced by ashr.
50+
define float @ashr_equivalent_expansion(i64 %x, float* %ptr) {
51+
; CHECK-LABEL: @ashr_equivalent_expansion(
52+
; CHECK-NEXT: entry:
53+
; CHECK-NEXT: [[ABS_X:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 false)
54+
; CHECK-NEXT: [[T0:%.*]] = call i64 @llvm.smax.i64(i64 [[X]], i64 -1)
55+
; CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.smin.i64(i64 [[T0]], i64 1)
56+
; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[ABS_X]], 4
57+
; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[T1]], [[TMP0]]
58+
; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP1]], i64 1)
59+
; CHECK-NEXT: br label [[LOOP:%.*]]
60+
; CHECK: loop:
61+
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
62+
; CHECK-NEXT: [[RED:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP]] ]
63+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr float, float* [[PTR:%.*]], i64 [[IV]]
64+
; CHECK-NEXT: [[LV:%.*]] = load float, float* [[GEP]], align 4
65+
; CHECK-NEXT: [[RED_NEXT]] = fadd float [[LV]], [[RED]]
66+
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1
67+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[UMAX]]
68+
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
69+
; CHECK: exit:
70+
; CHECK-NEXT: [[LCSSA_RED_NEXT:%.*]] = phi float [ [[RED_NEXT]], [[LOOP]] ]
71+
; CHECK-NEXT: ret float [[LCSSA_RED_NEXT]]
72+
;
73+
entry:
74+
%abs_x = call i64 @llvm.abs.i64(i64 %x, i1 false)
75+
%div = udiv exact i64 %abs_x, 16
76+
%t0 = call i64 @llvm.smax.i64(i64 %x, i64 -1)
77+
%t1 = call i64 @llvm.smin.i64(i64 %t0, i64 1)
78+
%bound = mul nsw i64 %div, %t1
79+
br label %loop
80+
81+
loop:
82+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
83+
%red = phi float [ 0.0, %entry ], [ %red.next, %loop ]
84+
%gep = getelementptr float, float* %ptr, i64 %iv
85+
%lv = load float, float* %gep
86+
%red.next = fadd float %lv, %red
87+
%iv.next = add nuw i64 %iv, 1
88+
%cond = icmp ult i64 %iv.next, %bound
89+
br i1 %cond, label %loop, label %exit
90+
91+
exit: ; preds = %bb135
92+
%lcssa.red.next = phi float [ %red.next, %loop ]
93+
ret float %lcssa.red.next
94+
}
95+
96+
; Chain of operations that *cannot* be replaced by ashr, because the udiv is
97+
; missing exact.
98+
define float @no_ashr_due_to_missing_exact_udiv(i64 %x, float* %ptr) {
99+
; CHECK-LABEL: @no_ashr_due_to_missing_exact_udiv(
100+
; CHECK-NEXT: entry:
101+
; CHECK-NEXT: [[ABS_X:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 false)
102+
; CHECK-NEXT: [[DIV:%.*]] = udiv i64 [[ABS_X]], 16
103+
; CHECK-NEXT: [[T0:%.*]] = call i64 @llvm.smax.i64(i64 [[X]], i64 -1)
104+
; CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.smin.i64(i64 [[T0]], i64 1)
105+
; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[T1]], [[DIV]]
106+
; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP0]], i64 1)
107+
; CHECK-NEXT: br label [[LOOP:%.*]]
108+
; CHECK: loop:
109+
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
110+
; CHECK-NEXT: [[RED:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP]] ]
111+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr float, float* [[PTR:%.*]], i64 [[IV]]
112+
; CHECK-NEXT: [[LV:%.*]] = load float, float* [[GEP]], align 4
113+
; CHECK-NEXT: [[RED_NEXT]] = fadd float [[LV]], [[RED]]
114+
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1
115+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[UMAX]]
116+
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
117+
; CHECK: exit:
118+
; CHECK-NEXT: [[LCSSA_RED_NEXT:%.*]] = phi float [ [[RED_NEXT]], [[LOOP]] ]
119+
; CHECK-NEXT: ret float [[LCSSA_RED_NEXT]]
120+
;
121+
entry:
122+
%abs_x = call i64 @llvm.abs.i64(i64 %x, i1 false)
123+
%div = udiv i64 %abs_x, 16
124+
%t0 = call i64 @llvm.smax.i64(i64 %x, i64 -1)
125+
%t1 = call i64 @llvm.smin.i64(i64 %t0, i64 1)
126+
%bound = mul nsw i64 %div, %t1
127+
br label %loop
128+
129+
loop:
130+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
131+
%red = phi float [ 0.0, %entry ], [ %red.next, %loop ]
132+
%gep = getelementptr float, float* %ptr, i64 %iv
133+
%lv = load float, float* %gep
134+
%red.next = fadd float %lv, %red
135+
%iv.next = add nuw i64 %iv, 1
136+
%cond = icmp ult i64 %iv.next, %bound
137+
br i1 %cond, label %loop, label %exit
138+
139+
exit: ; preds = %bb135
140+
%lcssa.red.next = phi float [ %red.next, %loop ]
141+
ret float %lcssa.red.next
142+
}
143+
144+
; Chain of operations that *cannot* be replaced by ashr, because abs and
145+
; signum have different operands.
146+
define float @no_ashr_due_to_different_ops(i64 %x, i64 %y, float* %ptr) {
147+
; CHECK-LABEL: @no_ashr_due_to_different_ops(
148+
; CHECK-NEXT: entry:
149+
; CHECK-NEXT: [[ABS_X:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 false)
150+
; CHECK-NEXT: [[DIV:%.*]] = udiv i64 [[ABS_X]], 16
151+
; CHECK-NEXT: [[T0:%.*]] = call i64 @llvm.smax.i64(i64 [[Y:%.*]], i64 -1)
152+
; CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.smin.i64(i64 [[T0]], i64 1)
153+
; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[T1]], [[DIV]]
154+
; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP0]], i64 1)
155+
; CHECK-NEXT: br label [[LOOP:%.*]]
156+
; CHECK: loop:
157+
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
158+
; CHECK-NEXT: [[RED:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP]] ]
159+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr float, float* [[PTR:%.*]], i64 [[IV]]
160+
; CHECK-NEXT: [[LV:%.*]] = load float, float* [[GEP]], align 4
161+
; CHECK-NEXT: [[RED_NEXT]] = fadd float [[LV]], [[RED]]
162+
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1
163+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[UMAX]]
164+
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
165+
; CHECK: exit:
166+
; CHECK-NEXT: [[LCSSA_RED_NEXT:%.*]] = phi float [ [[RED_NEXT]], [[LOOP]] ]
167+
; CHECK-NEXT: ret float [[LCSSA_RED_NEXT]]
168+
;
169+
entry:
170+
%abs_x = call i64 @llvm.abs.i64(i64 %x, i1 false)
171+
%div = udiv i64 %abs_x, 16
172+
%t0 = call i64 @llvm.smax.i64(i64 %y, i64 -1)
173+
%t1 = call i64 @llvm.smin.i64(i64 %t0, i64 1)
174+
%bound = mul nsw i64 %div, %t1
175+
br label %loop
176+
177+
loop:
178+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
179+
%red = phi float [ 0.0, %entry ], [ %red.next, %loop ]
180+
%gep = getelementptr float, float* %ptr, i64 %iv
181+
%lv = load float, float* %gep
182+
%red.next = fadd float %lv, %red
183+
%iv.next = add nuw i64 %iv, 1
184+
%cond = icmp ult i64 %iv.next, %bound
185+
br i1 %cond, label %loop, label %exit
186+
187+
exit: ; preds = %bb135
188+
%lcssa.red.next = phi float [ %red.next, %loop ]
189+
ret float %lcssa.red.next
190+
}
191+
192+
declare i64 @llvm.abs.i64(i64, i1)
193+
194+
declare i64 @llvm.smax.i64(i64, i64)
195+
196+
declare i64 @llvm.smin.i64(i64, i64)

0 commit comments

Comments
 (0)