1 ; RUN: opt < %s -passes=slsr,gvn -S | FileCheck %s
2 ; RUN: opt < %s -passes='slsr,gvn' -S | FileCheck %s
4 target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64-p:64:64:64-p1:32:32:32-p2:128:128:128:32"
16 define void @slsr_gep(ptr %input, i64 %s) {
17 ; CHECK-LABEL: @slsr_gep(
19 call void @foo(ptr %input)
22 %p1 = getelementptr inbounds i32, ptr %input, i64 %s
23 ; CHECK: %p1 = getelementptr inbounds i32, ptr %input, i64 %s
24 call void @foo(ptr %p1)
27 %s2 = shl nsw i64 %s, 1
28 %p2 = getelementptr inbounds i32, ptr %input, i64 %s2
29 ; CHECK: %p2 = getelementptr inbounds i32, ptr %p1, i64 %s
30 call void @foo(ptr %p2)
36 ; foo(input[(long)s]);
37 ; foo(input[(long)(s * 2)]);
45 define void @slsr_gep_sext(ptr %input, i32 %s) {
46 ; CHECK-LABEL: @slsr_gep_sext(
48 call void @foo(ptr %input)
51 %t = sext i32 %s to i64
52 %p1 = getelementptr inbounds i32, ptr %input, i64 %t
53 ; CHECK: %p1 = getelementptr inbounds i32, ptr %input, i64 %t
54 call void @foo(ptr %p1)
57 %s2 = shl nsw i32 %s, 1
58 %t2 = sext i32 %s2 to i64
59 %p2 = getelementptr inbounds i32, ptr %input, i64 %t2
60 ; CHECK: %p2 = getelementptr inbounds i32, ptr %p1, i64 %t
61 call void @foo(ptr %p2)
68 ; foo(input[s * 2][t]);
69 ; foo(input[s * 3][t]);
77 define void @slsr_gep_2d(ptr %input, i64 %s, i64 %t) {
78 ; CHECK-LABEL: @slsr_gep_2d(
80 %p0 = getelementptr inbounds [10 x [5 x i32]], ptr %input, i64 0, i64 %s, i64 %t
81 call void @foo(ptr %p0)
83 ; v1 = input[s * 2][t];
84 %s2 = shl nsw i64 %s, 1
85 ; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 5
86 %p1 = getelementptr inbounds [10 x [5 x i32]], ptr %input, i64 0, i64 %s2, i64 %t
87 ; CHECK: %p1 = getelementptr inbounds i32, ptr %p0, i64 [[BUMP]]
88 call void @foo(ptr %p1)
90 ; v3 = input[s * 3][t];
91 %s3 = mul nsw i64 %s, 3
92 %p2 = getelementptr inbounds [10 x [5 x i32]], ptr %input, i64 0, i64 %s3, i64 %t
93 ; CHECK: %p2 = getelementptr inbounds i32, ptr %p1, i64 [[BUMP]]
94 call void @foo(ptr %p2)
99 %struct.S = type <{ i64, i32 }>
101 ; In this case, the bump
102 ; = (char *)&input[s * 2][t].f1 - (char *)&input[s][t].f1
104 ; which may not be divisible by typeof(input[s][t].f1) = 8. Therefore, we
105 ; rewrite the candidates using byte offset instead of index offset as in
107 define void @slsr_gep_uglygep(ptr %input, i64 %s, i64 %t) {
108 ; CHECK-LABEL: @slsr_gep_uglygep(
109 ; v0 = input[s][t].f1;
110 %p0 = getelementptr inbounds [10 x [5 x %struct.S]], ptr %input, i64 0, i64 %s, i64 %t, i32 0
111 call void @bar(ptr %p0)
113 ; v1 = input[s * 2][t].f1;
114 %s2 = shl nsw i64 %s, 1
115 ; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 60
116 %p1 = getelementptr inbounds [10 x [5 x %struct.S]], ptr %input, i64 0, i64 %s2, i64 %t, i32 0
117 ; CHECK: %p1 = getelementptr inbounds i8, ptr %p0, i64 [[BUMP]]
118 call void @bar(ptr %p1)
120 ; v2 = input[s * 3][t].f1;
121 %s3 = mul nsw i64 %s, 3
122 %p2 = getelementptr inbounds [10 x [5 x %struct.S]], ptr %input, i64 0, i64 %s3, i64 %t, i32 0
123 ; CHECK: %p2 = getelementptr inbounds i8, ptr %p1, i64 [[BUMP]]
124 call void @bar(ptr %p2)
129 define void @slsr_out_of_bounds_gep(ptr %input, i32 %s) {
130 ; CHECK-LABEL: @slsr_out_of_bounds_gep(
132 call void @foo(ptr %input)
134 ; v1 = input[(long)s];
135 %t = sext i32 %s to i64
136 %p1 = getelementptr i32, ptr %input, i64 %t
137 ; CHECK: %p1 = getelementptr i32, ptr %input, i64 %t
138 call void @foo(ptr %p1)
140 ; v2 = input[(long)(s * 2)];
141 %s2 = shl nsw i32 %s, 1
142 %t2 = sext i32 %s2 to i64
143 %p2 = getelementptr i32, ptr %input, i64 %t2
144 ; CHECK: %p2 = getelementptr i32, ptr %p1, i64 %t
145 call void @foo(ptr %p2)
150 define void @slsr_gep_128bit_index(ptr %input, i128 %s) {
151 ; CHECK-LABEL: @slsr_gep_128bit_index(
153 call void @foo(ptr %input)
155 ; p1 = &input[s << 125]
156 %s125 = shl nsw i128 %s, 125
157 %p1 = getelementptr inbounds i32, ptr %input, i128 %s125
158 ; CHECK: %p1 = getelementptr inbounds i32, ptr %input, i128 %s125
159 call void @foo(ptr %p1)
161 ; p2 = &input[s << 126]
162 %s126 = shl nsw i128 %s, 126
163 %p2 = getelementptr inbounds i32, ptr %input, i128 %s126
164 ; CHECK: %p2 = getelementptr inbounds i32, ptr %input, i128 %s126
165 call void @foo(ptr %p2)
170 define void @slsr_gep_32bit_pointer(ptr addrspace(1) %input, i64 %s) {
171 ; CHECK-LABEL: @slsr_gep_32bit_pointer(
173 %p1 = getelementptr inbounds i32, ptr addrspace(1) %input, i64 %s
174 call void @baz(ptr addrspace(1) %p1)
177 %s2 = mul nsw i64 %s, 2
178 %p2 = getelementptr inbounds i32, ptr addrspace(1) %input, i64 %s2
179 ; %s2 is wider than the pointer size of addrspace(1), so do not factor it.
180 ; CHECK: %p2 = getelementptr inbounds i32, ptr addrspace(1) %input, i64 %s2
181 call void @baz(ptr addrspace(1) %p2)
186 define void @slsr_gep_fat_pointer(ptr addrspace(2) %input, i32 %s) {
188 %p1 = getelementptr inbounds i32, ptr addrspace(2) %input, i32 %s
189 call void @baz2(ptr addrspace(2) %p1)
192 %s2 = mul nsw i32 %s, 2
193 %p2 = getelementptr inbounds i32, ptr addrspace(2) %input, i32 %s2
194 ; CHECK: %p2 = getelementptr inbounds i32, ptr addrspace(2) %p1, i32 %s
195 ; Use index bitwidth, not pointer size (i128)
196 call void @baz2(ptr addrspace(2) %p2)
202 declare void @foo(ptr)
203 declare void @bar(ptr)
204 declare void @baz(ptr addrspace(1))
205 declare void @baz2(ptr addrspace(2))