1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S < %s | FileCheck %s
4 target datalayout = "e-i64:64-f80:128-n8:16:32:64"
5 target triple = "x86_64-unknown-linux-gnu"
7 %A__vtbl = type { i8*, i32 (%A*)* }
8 %A = type { %A__vtbl* }
11 @A__vtblZ = constant %A__vtbl { i8* null, i32 (%A*)* @A.foo }
13 declare i32 @A.foo(%A* nocapture %this)
15 define void @storeA(%A* %a.ptr) {
16 ; CHECK-LABEL: @storeA(
17 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[A:%.*]], %A* [[A_PTR:%.*]], i64 0, i32 0
18 ; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
19 ; CHECK-NEXT: ret void
21 store %A { %A__vtbl* @A__vtblZ }, %A* %a.ptr, align 8
25 define void @storeB(%B* %b.ptr) {
26 ; CHECK-LABEL: @storeB(
27 ; CHECK-NEXT: [[B_PTR_REPACK:%.*]] = getelementptr inbounds [[B:%.*]], %B* [[B_PTR:%.*]], i64 0, i32 0
28 ; CHECK-NEXT: store i8* null, i8** [[B_PTR_REPACK]], align 8
29 ; CHECK-NEXT: [[B_PTR_REPACK1:%.*]] = getelementptr inbounds [[B]], %B* [[B_PTR]], i64 0, i32 1
30 ; CHECK-NEXT: store i64 42, i64* [[B_PTR_REPACK1]], align 8
31 ; CHECK-NEXT: ret void
33 store %B { i8* null, i64 42 }, %B* %b.ptr, align 8
37 define void @storeStructOfA({ %A }* %sa.ptr) {
38 ; CHECK-LABEL: @storeStructOfA(
39 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [[A:%.*]] }, { [[A]] }* [[SA_PTR:%.*]], i64 0, i32 0, i32 0
40 ; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
41 ; CHECK-NEXT: ret void
43 store { %A } { %A { %A__vtbl* @A__vtblZ } }, { %A }* %sa.ptr, align 8
47 define void @storeArrayOfA([1 x %A]* %aa.ptr) {
48 ; CHECK-LABEL: @storeArrayOfA(
49 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [1 x %A], [1 x %A]* [[AA_PTR:%.*]], i64 0, i64 0, i32 0
50 ; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
51 ; CHECK-NEXT: ret void
53 store [1 x %A] [%A { %A__vtbl* @A__vtblZ }], [1 x %A]* %aa.ptr, align 8
58 define void @storeLargeArrayOfA([2000 x %A]* %aa.ptr) {
59 ; CHECK-LABEL: @storeLargeArrayOfA(
60 ; CHECK-NEXT: store [2000 x %A]
61 ; CHECK-NEXT: ret void
63 %i1 = insertvalue [2000 x %A] undef, %A { %A__vtbl* @A__vtblZ }, 1
64 store [2000 x %A] %i1, [2000 x %A]* %aa.ptr, align 8
69 define void @storeStructOfArrayOfA({ [1 x %A] }* %saa.ptr) {
70 ; CHECK-LABEL: @storeStructOfArrayOfA(
71 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [1 x %A] }, { [1 x %A] }* [[SAA_PTR:%.*]], i64 0, i32 0, i64 0, i32 0
72 ; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
73 ; CHECK-NEXT: ret void
75 store { [1 x %A] } { [1 x %A] [%A { %A__vtbl* @A__vtblZ }] }, { [1 x %A] }* %saa.ptr, align 8
79 define void @storeArrayOfB([2 x %B]* %ab.ptr, [2 x %B] %ab) {
80 ; CHECK-LABEL: @storeArrayOfB(
81 ; CHECK-NEXT: [[AB_ELT:%.*]] = extractvalue [2 x %B] [[AB:%.*]], 0
82 ; CHECK-NEXT: [[AB_PTR_REPACK_REPACK:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR:%.*]], i64 0, i64 0, i32 0
83 ; CHECK-NEXT: [[AB_ELT_ELT:%.*]] = extractvalue [[B:%.*]] [[AB_ELT]], 0
84 ; CHECK-NEXT: store i8* [[AB_ELT_ELT]], i8** [[AB_PTR_REPACK_REPACK]], align 8
85 ; CHECK-NEXT: [[AB_PTR_REPACK_REPACK3:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 0, i32 1
86 ; CHECK-NEXT: [[AB_ELT_ELT4:%.*]] = extractvalue [[B]] [[AB_ELT]], 1
87 ; CHECK-NEXT: store i64 [[AB_ELT_ELT4]], i64* [[AB_PTR_REPACK_REPACK3]], align 8
88 ; CHECK-NEXT: [[AB_ELT2:%.*]] = extractvalue [2 x %B] [[AB]], 1
89 ; CHECK-NEXT: [[AB_PTR_REPACK1_REPACK:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 1, i32 0
90 ; CHECK-NEXT: [[AB_ELT2_ELT:%.*]] = extractvalue [[B]] [[AB_ELT2]], 0
91 ; CHECK-NEXT: store i8* [[AB_ELT2_ELT]], i8** [[AB_PTR_REPACK1_REPACK]], align 8
92 ; CHECK-NEXT: [[AB_PTR_REPACK1_REPACK5:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 1, i32 1
93 ; CHECK-NEXT: [[AB_ELT2_ELT6:%.*]] = extractvalue [[B]] [[AB_ELT2]], 1
94 ; CHECK-NEXT: store i64 [[AB_ELT2_ELT6]], i64* [[AB_PTR_REPACK1_REPACK5]], align 8
95 ; CHECK-NEXT: ret void
97 store [2 x %B] %ab, [2 x %B]* %ab.ptr, align 8
101 define %A @loadA(%A* %a.ptr) {
102 ; CHECK-LABEL: @loadA(
103 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[A:%.*]], %A* [[A_PTR:%.*]], i64 0, i32 0
104 ; CHECK-NEXT: [[DOTUNPACK:%.*]] = load %A__vtbl*, %A__vtbl** [[TMP1]], align 8
105 ; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[A]] undef, %A__vtbl* [[DOTUNPACK]], 0
106 ; CHECK-NEXT: ret [[A]] [[TMP2]]
108 %1 = load %A, %A* %a.ptr, align 8
112 define %B @loadB(%B* %b.ptr) {
113 ; CHECK-LABEL: @loadB(
114 ; CHECK-NEXT: [[DOTELT:%.*]] = getelementptr inbounds [[B:%.*]], %B* [[B_PTR:%.*]], i64 0, i32 0
115 ; CHECK-NEXT: [[DOTUNPACK:%.*]] = load i8*, i8** [[DOTELT]], align 8
116 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[B]] undef, i8* [[DOTUNPACK]], 0
117 ; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds [[B]], %B* [[B_PTR]], i64 0, i32 1
118 ; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load i64, i64* [[DOTELT1]], align 8
119 ; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[B]] [[TMP1]], i64 [[DOTUNPACK2]], 1
120 ; CHECK-NEXT: ret [[B]] [[TMP2]]
122 %1 = load %B, %B* %b.ptr, align 8
126 define { %A } @loadStructOfA({ %A }* %sa.ptr) {
127 ; CHECK-LABEL: @loadStructOfA(
128 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [[A:%.*]] }, { [[A]] }* [[SA_PTR:%.*]], i64 0, i32 0, i32 0
129 ; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load %A__vtbl*, %A__vtbl** [[TMP1]], align 8
130 ; CHECK-NEXT: [[DOTUNPACK1:%.*]] = insertvalue [[A]] undef, %A__vtbl* [[DOTUNPACK_UNPACK]], 0
131 ; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { [[A]] } undef, [[A]] [[DOTUNPACK1]], 0
132 ; CHECK-NEXT: ret { [[A]] } [[TMP2]]
134 %1 = load { %A }, { %A }* %sa.ptr, align 8
138 define [1 x %A] @loadArrayOfA([1 x %A]* %aa.ptr) {
139 ; CHECK-LABEL: @loadArrayOfA(
140 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [1 x %A], [1 x %A]* [[AA_PTR:%.*]], i64 0, i64 0, i32 0
141 ; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load %A__vtbl*, %A__vtbl** [[TMP1]], align 8
142 ; CHECK-NEXT: [[DOTUNPACK1:%.*]] = insertvalue [[A:%.*]] undef, %A__vtbl* [[DOTUNPACK_UNPACK]], 0
143 ; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [1 x %A] undef, [[A]] [[DOTUNPACK1]], 0
144 ; CHECK-NEXT: ret [1 x %A] [[TMP2]]
146 %1 = load [1 x %A], [1 x %A]* %aa.ptr, align 8
150 define { [1 x %A] } @loadStructOfArrayOfA({ [1 x %A] }* %saa.ptr) {
151 ; CHECK-LABEL: @loadStructOfArrayOfA(
152 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [1 x %A] }, { [1 x %A] }* [[SAA_PTR:%.*]], i64 0, i32 0, i64 0, i32 0
153 ; CHECK-NEXT: [[DOTUNPACK_UNPACK_UNPACK:%.*]] = load %A__vtbl*, %A__vtbl** [[TMP1]], align 8
154 ; CHECK-NEXT: [[DOTUNPACK_UNPACK2:%.*]] = insertvalue [[A:%.*]] undef, %A__vtbl* [[DOTUNPACK_UNPACK_UNPACK]], 0
155 ; CHECK-NEXT: [[DOTUNPACK1:%.*]] = insertvalue [1 x %A] undef, [[A]] [[DOTUNPACK_UNPACK2]], 0
156 ; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { [1 x %A] } undef, [1 x %A] [[DOTUNPACK1]], 0
157 ; CHECK-NEXT: ret { [1 x %A] } [[TMP2]]
159 %1 = load { [1 x %A] }, { [1 x %A] }* %saa.ptr, align 8
163 define { %A } @structOfA({ %A }* %sa.ptr) {
164 ; CHECK-LABEL: @structOfA(
165 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [[A:%.*]] }, { [[A]] }* [[SA_PTR:%.*]], i64 0, i32 0, i32 0
166 ; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
167 ; CHECK-NEXT: ret { [[A]] } { [[A]] { %A__vtbl* @A__vtblZ } }
169 store { %A } { %A { %A__vtbl* @A__vtblZ } }, { %A }* %sa.ptr, align 8
170 %1 = load { %A }, { %A }* %sa.ptr, align 8
174 define %B @structB(%B* %b.ptr) {
175 ; CHECK-LABEL: @structB(
176 ; CHECK-NEXT: [[B_PTR_REPACK:%.*]] = getelementptr inbounds [[B:%.*]], %B* [[B_PTR:%.*]], i64 0, i32 0
177 ; CHECK-NEXT: store i8* null, i8** [[B_PTR_REPACK]], align 8
178 ; CHECK-NEXT: [[B_PTR_REPACK1:%.*]] = getelementptr inbounds [[B]], %B* [[B_PTR]], i64 0, i32 1
179 ; CHECK-NEXT: store i64 42, i64* [[B_PTR_REPACK1]], align 8
180 ; CHECK-NEXT: ret [[B]] { i8* null, i64 42 }
182 store %B { i8* null, i64 42 }, %B* %b.ptr, align 8
183 %1 = load %B, %B* %b.ptr, align 8
187 define [2 x %B] @loadArrayOfB([2 x %B]* %ab.ptr) {
188 ; CHECK-LABEL: @loadArrayOfB(
189 ; CHECK-NEXT: [[DOTUNPACK_ELT:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR:%.*]], i64 0, i64 0, i32 0
190 ; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load i8*, i8** [[DOTUNPACK_ELT]], align 8
191 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[B:%.*]] undef, i8* [[DOTUNPACK_UNPACK]], 0
192 ; CHECK-NEXT: [[DOTUNPACK_ELT3:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 0, i32 1
193 ; CHECK-NEXT: [[DOTUNPACK_UNPACK4:%.*]] = load i64, i64* [[DOTUNPACK_ELT3]], align 8
194 ; CHECK-NEXT: [[DOTUNPACK5:%.*]] = insertvalue [[B]] [[TMP1]], i64 [[DOTUNPACK_UNPACK4]], 1
195 ; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [2 x %B] undef, [[B]] [[DOTUNPACK5]], 0
196 ; CHECK-NEXT: [[DOTUNPACK2_ELT:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 1, i32 0
197 ; CHECK-NEXT: [[DOTUNPACK2_UNPACK:%.*]] = load i8*, i8** [[DOTUNPACK2_ELT]], align 8
198 ; CHECK-NEXT: [[TMP3:%.*]] = insertvalue [[B]] undef, i8* [[DOTUNPACK2_UNPACK]], 0
199 ; CHECK-NEXT: [[DOTUNPACK2_ELT6:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 1, i32 1
200 ; CHECK-NEXT: [[DOTUNPACK2_UNPACK7:%.*]] = load i64, i64* [[DOTUNPACK2_ELT6]], align 8
201 ; CHECK-NEXT: [[DOTUNPACK28:%.*]] = insertvalue [[B]] [[TMP3]], i64 [[DOTUNPACK2_UNPACK7]], 1
202 ; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [2 x %B] [[TMP2]], [[B]] [[DOTUNPACK28]], 1
203 ; CHECK-NEXT: ret [2 x %B] [[TMP4]]
205 %1 = load [2 x %B], [2 x %B]* %ab.ptr, align 8
209 define [2000 x %B] @loadLargeArrayOfB([2000 x %B]* %ab.ptr) {
210 ; CHECK-LABEL: @loadLargeArrayOfB(
211 ; CHECK-NEXT: [[TMP1:%.*]] = load [2000 x %B], [2000 x %B]* [[AB_PTR:%.*]], align 8
212 ; CHECK-NEXT: ret [2000 x %B] [[TMP1]]
214 %1 = load [2000 x %B], [2000 x %B]* %ab.ptr, align 8
218 %struct.S = type <{ i8, %struct.T }>
219 %struct.T = type { i32, i32 }
221 ; Make sure that we do not increase alignment of packed struct element
222 define i32 @packed_alignment(%struct.S* dereferenceable(9) %s) {
223 ; CHECK-LABEL: @packed_alignment(
224 ; CHECK-NEXT: [[TV_ELT1:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], %struct.S* [[S:%.*]], i64 0, i32 1, i32 1
225 ; CHECK-NEXT: [[TV_UNPACK2:%.*]] = load i32, i32* [[TV_ELT1]], align 1
226 ; CHECK-NEXT: ret i32 [[TV_UNPACK2]]
228 %t = getelementptr inbounds %struct.S, %struct.S* %s, i32 0, i32 1
229 %tv = load %struct.T, %struct.T* %t, align 1
230 %v = extractvalue %struct.T %tv, 1
234 %struct.U = type {i8, i8, i8, i8, i8, i8, i8, i8, i64}
236 define void @check_alignment(%struct.U* %u, %struct.U* %v) {
237 ; CHECK-LABEL: @check_alignment(
238 ; CHECK-NEXT: [[DOTELT:%.*]] = getelementptr inbounds [[STRUCT_U:%.*]], %struct.U* [[U:%.*]], i64 0, i32 0
239 ; CHECK-NEXT: [[DOTUNPACK:%.*]] = load i8, i8* [[DOTELT]], align 8
240 ; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 1
241 ; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load i8, i8* [[DOTELT1]], align 1
242 ; CHECK-NEXT: [[DOTELT3:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 2
243 ; CHECK-NEXT: [[DOTUNPACK4:%.*]] = load i8, i8* [[DOTELT3]], align 2
244 ; CHECK-NEXT: [[DOTELT5:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 3
245 ; CHECK-NEXT: [[DOTUNPACK6:%.*]] = load i8, i8* [[DOTELT5]], align 1
246 ; CHECK-NEXT: [[DOTELT7:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 4
247 ; CHECK-NEXT: [[DOTUNPACK8:%.*]] = load i8, i8* [[DOTELT7]], align 4
248 ; CHECK-NEXT: [[DOTELT9:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 5
249 ; CHECK-NEXT: [[DOTUNPACK10:%.*]] = load i8, i8* [[DOTELT9]], align 1
250 ; CHECK-NEXT: [[DOTELT11:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 6
251 ; CHECK-NEXT: [[DOTUNPACK12:%.*]] = load i8, i8* [[DOTELT11]], align 2
252 ; CHECK-NEXT: [[DOTELT13:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 7
253 ; CHECK-NEXT: [[DOTUNPACK14:%.*]] = load i8, i8* [[DOTELT13]], align 1
254 ; CHECK-NEXT: [[DOTELT15:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 8
255 ; CHECK-NEXT: [[DOTUNPACK16:%.*]] = load i64, i64* [[DOTELT15]], align 8
256 ; CHECK-NEXT: [[V_REPACK:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V:%.*]], i64 0, i32 0
257 ; CHECK-NEXT: store i8 [[DOTUNPACK]], i8* [[V_REPACK]], align 8
258 ; CHECK-NEXT: [[V_REPACK18:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 1
259 ; CHECK-NEXT: store i8 [[DOTUNPACK2]], i8* [[V_REPACK18]], align 1
260 ; CHECK-NEXT: [[V_REPACK20:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 2
261 ; CHECK-NEXT: store i8 [[DOTUNPACK4]], i8* [[V_REPACK20]], align 2
262 ; CHECK-NEXT: [[V_REPACK22:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 3
263 ; CHECK-NEXT: store i8 [[DOTUNPACK6]], i8* [[V_REPACK22]], align 1
264 ; CHECK-NEXT: [[V_REPACK24:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 4
265 ; CHECK-NEXT: store i8 [[DOTUNPACK8]], i8* [[V_REPACK24]], align 4
266 ; CHECK-NEXT: [[V_REPACK26:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 5
267 ; CHECK-NEXT: store i8 [[DOTUNPACK10]], i8* [[V_REPACK26]], align 1
268 ; CHECK-NEXT: [[V_REPACK28:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 6
269 ; CHECK-NEXT: store i8 [[DOTUNPACK12]], i8* [[V_REPACK28]], align 2
270 ; CHECK-NEXT: [[V_REPACK30:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 7
271 ; CHECK-NEXT: store i8 [[DOTUNPACK14]], i8* [[V_REPACK30]], align 1
272 ; CHECK-NEXT: [[V_REPACK32:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 8
273 ; CHECK-NEXT: store i64 [[DOTUNPACK16]], i64* [[V_REPACK32]], align 8
274 ; CHECK-NEXT: ret void
276 %1 = load %struct.U, %struct.U* %u
277 store %struct.U %1, %struct.U* %v