[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / test / Transforms / StraightLineStrengthReduce / slsr-gep.ll
blobb9bb4faf1b41486f10460f2569d41803939ce362
1 ; RUN: opt < %s -slsr -gvn -S | FileCheck %s
3 target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64-p:64:64:64-p1:32:32:32"
5 ; foo(input[0]);
6 ; foo(input[s]);
7 ; foo(input[s * 2]);
8 ;   =>
9 ; p0 = &input[0];
10 ; foo(*p);
11 ; p1 = p0 + s;
12 ; foo(*p1);
13 ; p2 = p1 + s;
14 ; foo(*p2);
15 define void @slsr_gep(i32* %input, i64 %s) {
16 ; CHECK-LABEL: @slsr_gep(
17   ; v0 = input[0];
18   %p0 = getelementptr inbounds i32, i32* %input, i64 0
19   call void @foo(i32* %p0)
21   ; v1 = input[s];
22   %p1 = getelementptr inbounds i32, i32* %input, i64 %s
23 ; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i64 %s
24   call void @foo(i32* %p1)
26   ; v2 = input[s * 2];
27   %s2 = shl nsw i64 %s, 1
28   %p2 = getelementptr inbounds i32, i32* %input, i64 %s2
29 ; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 %s
30   call void @foo(i32* %p2)
32   ret void
35 ; foo(input[0]);
36 ; foo(input[(long)s]);
37 ; foo(input[(long)(s * 2)]);
38 ;   =>
39 ; p0 = &input[0];
40 ; foo(*p);
41 ; p1 = p0 + (long)s;
42 ; foo(*p1);
43 ; p2 = p1 + (long)s;
44 ; foo(*p2);
45 define void @slsr_gep_sext(i32* %input, i32 %s) {
46 ; CHECK-LABEL: @slsr_gep_sext(
47   ; v0 = input[0];
48   %p0 = getelementptr inbounds i32, i32* %input, i64 0
49   call void @foo(i32* %p0)
51   ; v1 = input[s];
52   %t = sext i32 %s to i64
53   %p1 = getelementptr inbounds i32, i32* %input, i64 %t
54 ; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i64 %t
55   call void @foo(i32* %p1)
57   ; v2 = input[s * 2];
58   %s2 = shl nsw i32 %s, 1
59   %t2 = sext i32 %s2 to i64
60   %p2 = getelementptr inbounds i32, i32* %input, i64 %t2
61 ; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 %t
62   call void @foo(i32* %p2)
64   ret void
67 ; int input[10][5];
68 ; foo(input[s][t]);
69 ; foo(input[s * 2][t]);
70 ; foo(input[s * 3][t]);
71 ;   =>
72 ; p0 = &input[s][t];
73 ; foo(*p0);
74 ; p1 = p0 + 5s;
75 ; foo(*p1);
76 ; p2 = p1 + 5s;
77 ; foo(*p2);
78 define void @slsr_gep_2d([10 x [5 x i32]]* %input, i64 %s, i64 %t) {
79 ; CHECK-LABEL: @slsr_gep_2d(
80   ; v0 = input[s][t];
81   %p0 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s, i64 %t
82   call void @foo(i32* %p0)
84   ; v1 = input[s * 2][t];
85   %s2 = shl nsw i64 %s, 1
86 ; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 5
87   %p1 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s2, i64 %t
88 ; CHECK: %p1 = getelementptr inbounds i32, i32* %p0, i64 [[BUMP]]
89   call void @foo(i32* %p1)
91   ; v3 = input[s * 3][t];
92   %s3 = mul nsw i64 %s, 3
93   %p2 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s3, i64 %t
94 ; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 [[BUMP]]
95   call void @foo(i32* %p2)
97   ret void
100 %struct.S = type <{ i64, i32 }>
102 ; In this case, the bump
103 ;     = (char *)&input[s * 2][t].f1 - (char *)&input[s][t].f1
104 ;     = 60 * s
105 ; which may not be divisible by typeof(input[s][t].f1) = 8. Therefore, we
106 ; rewrite the candidates using byte offset instead of index offset as in
107 ; @slsr_gep_2d.
108 define void @slsr_gep_uglygep([10 x [5 x %struct.S]]* %input, i64 %s, i64 %t) {
109 ; CHECK-LABEL: @slsr_gep_uglygep(
110   ; v0 = input[s][t].f1;
111   %p0 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s, i64 %t, i32 0
112   call void @bar(i64* %p0)
114   ; v1 = input[s * 2][t].f1;
115   %s2 = shl nsw i64 %s, 1
116 ; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 60
117   %p1 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s2, i64 %t, i32 0
118 ; CHECK: getelementptr inbounds i8, i8* %{{[0-9]+}}, i64 [[BUMP]]
119   call void @bar(i64* %p1)
121   ; v2 = input[s * 3][t].f1;
122   %s3 = mul nsw i64 %s, 3
123   %p2 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s3, i64 %t, i32 0
124 ; CHECK: getelementptr inbounds i8, i8* %{{[0-9]+}}, i64 [[BUMP]]
125   call void @bar(i64* %p2)
127   ret void
130 define void @slsr_out_of_bounds_gep(i32* %input, i32 %s) {
131 ; CHECK-LABEL: @slsr_out_of_bounds_gep(
132   ; v0 = input[0];
133   %p0 = getelementptr i32, i32* %input, i64 0
134   call void @foo(i32* %p0)
136   ; v1 = input[(long)s];
137   %t = sext i32 %s to i64
138   %p1 = getelementptr i32, i32* %input, i64 %t
139 ; CHECK: %p1 = getelementptr i32, i32* %input, i64 %t
140   call void @foo(i32* %p1)
142   ; v2 = input[(long)(s * 2)];
143   %s2 = shl nsw i32 %s, 1
144   %t2 = sext i32 %s2 to i64
145   %p2 = getelementptr i32, i32* %input, i64 %t2
146 ; CHECK: %p2 = getelementptr i32, i32* %p1, i64 %t
147   call void @foo(i32* %p2)
149   ret void
152 define void @slsr_gep_128bit_index(i32* %input, i128 %s) {
153 ; CHECK-LABEL: @slsr_gep_128bit_index(
154   ; p0 = &input[0]
155   %p0 = getelementptr inbounds i32, i32* %input, i128 0
156   call void @foo(i32* %p0)
158   ; p1 = &input[s << 125]
159   %s125 = shl nsw i128 %s, 125
160   %p1 = getelementptr inbounds i32, i32* %input, i128 %s125
161 ; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i128 %s125
162   call void @foo(i32* %p1)
164   ; p2 = &input[s << 126]
165   %s126 = shl nsw i128 %s, 126
166   %p2 = getelementptr inbounds i32, i32* %input, i128 %s126
167 ; CHECK: %p2 = getelementptr inbounds i32, i32* %input, i128 %s126
168   call void @foo(i32* %p2)
170   ret void
173 define void @slsr_gep_32bit_pointer(i32 addrspace(1)* %input, i64 %s) {
174 ; CHECK-LABEL: @slsr_gep_32bit_pointer(
175   ; p1 = &input[s]
176   %p1 = getelementptr inbounds i32, i32 addrspace(1)* %input, i64 %s
177   call void @baz(i32 addrspace(1)* %p1)
179   ; p2 = &input[s * 2]
180   %s2 = mul nsw i64 %s, 2
181   %p2 = getelementptr inbounds i32, i32 addrspace(1)* %input, i64 %s2
182   ; %s2 is wider than the pointer size of addrspace(1), so do not factor it.
183 ; CHECK: %p2 = getelementptr inbounds i32, i32 addrspace(1)* %input, i64 %s2
184   call void @baz(i32 addrspace(1)* %p2)
186   ret void
189 declare void @foo(i32*)
190 declare void @bar(i64*)
191 declare void @baz(i32 addrspace(1)*)