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