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"
15 define void @slsr_gep(i32* %input, i64 %s) {
16 ; CHECK-LABEL: @slsr_gep(
18 %p0 = getelementptr inbounds i32, i32* %input, i64 0
19 call void @foo(i32* %p0)
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)
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)
36 ; foo(input[(long)s]);
37 ; foo(input[(long)(s * 2)]);
45 define void @slsr_gep_sext(i32* %input, i32 %s) {
46 ; CHECK-LABEL: @slsr_gep_sext(
48 %p0 = getelementptr inbounds i32, i32* %input, i64 0
49 call void @foo(i32* %p0)
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)
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)
69 ; foo(input[s * 2][t]);
70 ; foo(input[s * 3][t]);
78 define void @slsr_gep_2d([10 x [5 x i32]]* %input, i64 %s, i64 %t) {
79 ; CHECK-LABEL: @slsr_gep_2d(
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)
100 %struct.S = type <{ i64, i32 }>
102 ; In this case, the bump
103 ; = (char *)&input[s * 2][t].f1 - (char *)&input[s][t].f1
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
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)
130 define void @slsr_out_of_bounds_gep(i32* %input, i32 %s) {
131 ; CHECK-LABEL: @slsr_out_of_bounds_gep(
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)
152 define void @slsr_gep_128bit_index(i32* %input, i128 %s) {
153 ; CHECK-LABEL: @slsr_gep_128bit_index(
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)
173 define void @slsr_gep_32bit_pointer(i32 addrspace(1)* %input, i64 %s) {
174 ; CHECK-LABEL: @slsr_gep_32bit_pointer(
176 %p1 = getelementptr inbounds i32, i32 addrspace(1)* %input, i64 %s
177 call void @baz(i32 addrspace(1)* %p1)
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)
189 declare void @foo(i32*)
190 declare void @bar(i64*)
191 declare void @baz(i32 addrspace(1)*)