[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / AArch64 / stack-tagging-initializer-merge.ll
blob5c4be4354ea7b5db30b8c6b516c3541678f33896
1 ; RUN: opt < %s -stack-tagging -S -o - | FileCheck %s
3 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
4 target triple = "aarch64--linux-android"
6 declare void @use(i8*)
7 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
8 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
9 declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg)
11 define void @OneVarNoInit() sanitize_memtag {
12 entry:
13   %x = alloca i32, align 4
14   %0 = bitcast i32* %x to i8*
15   call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)
16   call void @use(i8* nonnull %0)
17   call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)
18   ret void
21 ; CHECK-LABEL: define void @OneVarNoInit(
22 ; CHECK-DAG:  [[X:%.*]] = alloca { i32, [12 x i8] }, align 16
23 ; CHECK-DAG:  [[TX:%.*]] = call { i32, [12 x i8] }* @llvm.aarch64.tagp.{{.*}}({ i32, [12 x i8] }* [[X]], {{.*}}, i64 0)
24 ; CHECK-DAG:  [[TX32:%.*]] = bitcast { i32, [12 x i8] }* [[TX]] to i32*
25 ; CHECK-DAG:  [[TX8:%.*]] = bitcast i32* [[TX32]] to i8*
26 ; CHECK-DAG:  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull [[TX8]])
27 ; CHECK-DAG:  call void @llvm.aarch64.settag(i8* [[TX8]], i64 16)
28 ; CHECK-DAG:  call void @use(i8* nonnull [[TX8]])
29 ; CHECK-DAG:  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[TX8]])
31 define void @OneVarInitConst() sanitize_memtag {
32 entry:
33   %x = alloca i32, align 4
34   %0 = bitcast i32* %x to i8*
35   call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)
36   store i32 42, i32* %x, align 4
37   call void @use(i8* nonnull %0)
38   call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)
39   ret void
42 ; CHECK-LABEL: define void @OneVarInitConst(
43 ; CHECK:  [[TX:%.*]] = call { i32, [12 x i8] }* @llvm.aarch64.tagp
44 ; CHECK:  [[TX32:%.*]] = bitcast { i32, [12 x i8] }* [[TX]] to i32*
45 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX32]] to i8*
46 ; CHECK-NOT: aarch64.settag
47 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8]], i64 42, i64 0)
48 ; Untagging before lifetime.end:
49 ; CHECK:  call void @llvm.aarch64.settag(
50 ; CHECK-NOT: aarch64.settag
51 ; CHECK:  ret void
53 define void @ArrayInitConst() sanitize_memtag {
54 entry:
55   %x = alloca i32, i32 16, align 4
56   %0 = bitcast i32* %x to i8*
57   call void @llvm.lifetime.start.p0i8(i64 64, i8* nonnull %0)
58   store i32 42, i32* %x, align 4
59   call void @use(i8* nonnull %0)
60   call void @llvm.lifetime.end.p0i8(i64 64, i8* nonnull %0)
61   ret void
64 ; CHECK-LABEL: define void @ArrayInitConst(
65 ; CHECK:  [[TX:%.*]] = call i32* @llvm.aarch64.tagp.
66 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX]] to i8*
67 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8]], i64 42, i64 0)
68 ; CHECK:  [[TX8_16:%.*]] = getelementptr i8, i8* [[TX8]], i32 16
69 ; CHECK:  call void @llvm.aarch64.settag.zero(i8* [[TX8_16]], i64 48)
70 ; CHECK:  ret void
72 define void @ArrayInitConst2() sanitize_memtag {
73 entry:
74   %x = alloca i32, i32 16, align 4
75   %0 = bitcast i32* %x to i8*
76   call void @llvm.lifetime.start.p0i8(i64 64, i8* nonnull %0)
77   store i32 42, i32* %x, align 4
78   %1 = getelementptr i32, i32* %x, i32 1
79   store i32 43, i32* %1, align 4
80   %2 = getelementptr i32, i32* %x, i32 2
81   %3 = bitcast i32* %2 to i64*
82   store i64 -1, i64* %3, align 4
83   call void @use(i8* nonnull %0)
84   call void @llvm.lifetime.end.p0i8(i64 64, i8* nonnull %0)
85   ret void
88 ; CHECK-LABEL: define void @ArrayInitConst2(
89 ; CHECK:  [[TX:%.*]] = call i32* @llvm.aarch64.tagp.
90 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX]] to i8*
91 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8]], i64 184683593770, i64 -1)
92 ; CHECK:  [[TX8_16:%.*]] = getelementptr i8, i8* [[TX8]], i32 16
93 ; CHECK:  call void @llvm.aarch64.settag.zero(i8* [[TX8_16]], i64 48)
94 ; CHECK:  ret void
96 define void @ArrayInitConstSplit() sanitize_memtag {
97 entry:
98   %x = alloca i32, i32 16, align 4
99   %0 = bitcast i32* %x to i8*
100   call void @llvm.lifetime.start.p0i8(i64 64, i8* nonnull %0)
101   %1 = getelementptr i32, i32* %x, i32 1
102   %2 = bitcast i32* %1 to i64*
103   store i64 -1, i64* %2, align 4
104   call void @use(i8* nonnull %0)
105   call void @llvm.lifetime.end.p0i8(i64 64, i8* nonnull %0)
106   ret void
109 ; CHECK-LABEL: define void @ArrayInitConstSplit(
110 ; CHECK:  [[TX:%.*]] = call i32* @llvm.aarch64.tagp.
111 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX]] to i8*
112 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8]], i64 -4294967296, i64 4294967295)
113 ; CHECK:  ret void
115 define void @ArrayInitConstWithHoles() sanitize_memtag {
116 entry:
117   %x = alloca i32, i32 32, align 4
118   %0 = bitcast i32* %x to i8*
119   call void @llvm.lifetime.start.p0i8(i64 128, i8* nonnull %0)
120   %1 = getelementptr i32, i32* %x, i32 5
121   store i32 42, i32* %1, align 4
122   %2 = getelementptr i32, i32* %x, i32 14
123   store i32 43, i32* %2, align 4
124   call void @use(i8* nonnull %0)
125   call void @llvm.lifetime.end.p0i8(i64 128, i8* nonnull %0)
126   ret void
129 ; CHECK-LABEL: define void @ArrayInitConstWithHoles(
130 ; CHECK:  [[TX:%.*]] = call i32* @llvm.aarch64.tagp.
131 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX]] to i8*
132 ; CHECK:  call void @llvm.aarch64.settag.zero(i8* [[TX8]], i64 16)
133 ; CHECK:  [[TX8_16:%.*]] = getelementptr i8, i8* %0, i32 16
134 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8_16]], i64 180388626432, i64 0)
135 ; CHECK:  [[TX8_32:%.*]] = getelementptr i8, i8* %0, i32 32
136 ; CHECK:  call void @llvm.aarch64.settag.zero(i8* [[TX8_32]], i64 16)
137 ; CHECK:  [[TX8_48:%.*]] = getelementptr i8, i8* %0, i32 48
138 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8_48]], i64 0, i64 43)
139 ; CHECK:  [[TX8_64:%.*]] = getelementptr i8, i8* %0, i32 64
140 ; CHECK:  call void @llvm.aarch64.settag.zero(i8* [[TX8_64]], i64 64)
141 ; CHECK:  ret void
143 define void @InitNonConst(i32 %v) sanitize_memtag {
144 entry:
145   %x = alloca i32, align 4
146   %0 = bitcast i32* %x to i8*
147   call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)
148   store i32 %v, i32* %x, align 4
149   call void @use(i8* nonnull %0)
150   call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)
151   ret void
154 ; CHECK-LABEL: define void @InitNonConst(
155 ; CHECK:  [[TX:%.*]] = call { i32, [12 x i8] }* @llvm.aarch64.tagp
156 ; CHECK:  [[TX32:%.*]] = bitcast { i32, [12 x i8] }* [[TX]] to i32*
157 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX32]] to i8*
158 ; CHECK:  [[V:%.*]] = zext i32 %v to i64
159 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8]], i64 [[V]], i64 0)
160 ; CHECK:  ret void
162 define void @InitNonConst2(i32 %v, i32 %w) sanitize_memtag {
163 entry:
164   %x = alloca i32, i32 4, align 4
165   %0 = bitcast i32* %x to i8*
166   call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %0)
167   store i32 %v, i32* %x, align 4
168   %1 = getelementptr i32, i32* %x, i32 1
169   store i32 %w, i32* %1, align 4
170   call void @use(i8* nonnull %0)
171   call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %0)
172   ret void
175 ; CHECK-LABEL: define void @InitNonConst2(
176 ; CHECK:  [[TX:%.*]] = call i32* @llvm.aarch64.tagp
177 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX]] to i8*
178 ; CHECK:  [[V:%.*]] = zext i32 %v to i64
179 ; CHECK:  [[W:%.*]] = zext i32 %w to i64
180 ; CHECK:  [[WS:%.*]] = shl i64 [[W]], 32
181 ; CHECK:  [[VW:%.*]] = or i64 [[V]], [[WS]]
182 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8]], i64 [[VW]], i64 0)
183 ; CHECK:  ret void
185 define void @InitVector() sanitize_memtag {
186 entry:
187   %x = alloca i32, i32 4, align 4
188   %0 = bitcast i32* %x to i8*
189   call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %0)
190   %1 = bitcast i32* %x to <2 x i32>*
191   store <2 x i32> <i32 1, i32 2>, <2 x i32>* %1, align 4
192   call void @use(i8* nonnull %0)
193   call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %0)
194   ret void
197 ; CHECK-LABEL: define void @InitVector(
198 ; CHECK:  [[TX:%.*]] = call i32* @llvm.aarch64.tagp
199 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX]] to i8*
200 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8]], i64 bitcast (<2 x i32> <i32 1, i32 2> to i64), i64 0)
201 ; CHECK:  ret void
203 define void @InitVectorPtr(i32* %p) sanitize_memtag {
204 entry:
205   %s = alloca <4 x i32*>, align 8
206   %v0 = insertelement <4 x i32*> undef, i32* %p, i32 0
207   %v1 = shufflevector <4 x i32*> %v0, <4 x i32*> undef, <4 x i32> zeroinitializer
208   store <4 x i32*> %v1, <4 x i32*>* %s
209   %0 = bitcast <4 x i32*>* %s to i8*
210   call void @use(i8* nonnull %0)
211   ret void
214 ; CHECK-LABEL: define void @InitVectorPtr(
215 ; CHECK:  call <4 x i32*>* @llvm.aarch64.tagp
216 ; CHECK:  [[V1:%.*]] = shufflevector
217 ; CHECK:  [[V2:%.*]] = ptrtoint <4 x i32*> [[V1]] to <4 x i64>
218 ; CHECK:  [[V3:%.*]] = bitcast <4 x i64> [[V2]] to i256
219 ; CHECK:  [[A1:%.*]] = trunc i256 [[V3]] to i64
220 ; CHECK:  [[A2_:%.*]] = lshr i256 [[V3]], 64
221 ; CHECK:  [[A2:%.*]] = trunc i256 [[A2_]] to i64
222 ; CHECK:  [[A3_:%.*]] = lshr i256 [[V3]], 128
223 ; CHECK:  [[A3:%.*]] = trunc i256 [[A3_]] to i64
224 ; CHECK:  [[A4_:%.*]] = lshr i256 [[V3]], 192
225 ; CHECK:  [[A4:%.*]] = trunc i256 [[A4_]] to i64
226 ; CHECK:  call void @llvm.aarch64.stgp({{.*}}, i64 [[A1]], i64 [[A2]])
227 ; CHECK:  call void @llvm.aarch64.stgp({{.*}}, i64 [[A3]], i64 [[A4]])
228 ; CHECK:  ret void
230 define void @InitVectorSplit() sanitize_memtag {
231 entry:
232   %x = alloca i32, i32 4, align 4
233   %0 = bitcast i32* %x to i8*
234   call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %0)
235   %1 = getelementptr i32, i32* %x, i32 1
236   %2 = bitcast i32* %1 to <2 x i32>*
237   store <2 x i32> <i32 1, i32 2>, <2 x i32>* %2, align 4
238   call void @use(i8* nonnull %0)
239   call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %0)
240   ret void
243 ; CHECK-LABEL: define void @InitVectorSplit(
244 ; CHECK:  [[TX:%.*]] = call i32* @llvm.aarch64.tagp
245 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX]] to i8*
246 ; CHECK:  call void @llvm.aarch64.stgp(i8* [[TX8]], i64 shl (i64 bitcast (<2 x i32> <i32 1, i32 2> to i64), i64 32), i64 lshr (i64 bitcast (<2 x i32> <i32 1, i32 2> to i64), i64 32))
247 ; CHECK:  ret void
249 define void @MemSetZero() sanitize_memtag {
250 entry:
251   %x = alloca i32, i32 8, align 16
252   %0 = bitcast i32* %x to i8*
253   call void @llvm.memset.p0i8.i64(i8* nonnull align 16 %0, i8 0, i64 32, i1 false)
254   call void @use(i8* nonnull %0)
255   ret void
258 ; CHECK-LABEL: define void @MemSetZero(
259 ; CHECK:  [[TX:%.*]] = call i32* @llvm.aarch64.tagp
260 ; CHECK:  [[TX8:%.*]] = bitcast i32* [[TX]] to i8*
261 ; CHECK:  call void @llvm.aarch64.settag.zero(i8* [[TX8]], i64 32)
262 ; CHECK:  ret void
265 define void @MemSetNonZero() sanitize_memtag {
266 entry:
267   %x = alloca i32, i32 8, align 16
268   %0 = bitcast i32* %x to i8*
269   call void @llvm.memset.p0i8.i64(i8* nonnull align 16 %0, i8 42, i64 32, i1 false)
270   call void @use(i8* nonnull %0)
271   ret void
274 ; CHECK-LABEL: define void @MemSetNonZero(
275 ; CHECK:  call void @llvm.aarch64.stgp(i8* {{.*}}, i64 3038287259199220266, i64 3038287259199220266)
276 ; CHECK:  call void @llvm.aarch64.stgp(i8* {{.*}}, i64 3038287259199220266, i64 3038287259199220266)
277 ; CHECK:  ret void
280 define void @MemSetNonZero2() sanitize_memtag {
281 entry:
282   %x = alloca [32 x i8], align 16
283   %0 = getelementptr inbounds [32 x i8], [32 x i8]* %x, i64 0, i64 2
284   call void @llvm.memset.p0i8.i64(i8* nonnull %0, i8 42, i64 28, i1 false)
285   call void @use(i8* nonnull %0)
286   ret void
289 ; CHECK-LABEL: define void @MemSetNonZero2(
290 ; CHECK:  call void @llvm.aarch64.stgp(i8* {{.*}}, i64 3038287259199209472, i64 3038287259199220266)
291 ; CHECK:  call void @llvm.aarch64.stgp(i8* {{.*}}, i64 3038287259199220266, i64 46360584399402)
292 ; CHECK:  ret void
294 define void @MemSetNonZero3() sanitize_memtag {
295 entry:
296   %x = alloca [32 x i8], align 16
297   %0 = getelementptr inbounds [32 x i8], [32 x i8]* %x, i64 0, i64 2
298   call void @llvm.memset.p0i8.i64(i8* nonnull %0, i8 42, i64 4, i1 false)
299   %1 = getelementptr inbounds [32 x i8], [32 x i8]* %x, i64 0, i64 24
300   call void @llvm.memset.p0i8.i64(i8* nonnull %1, i8 42, i64 8, i1 false)
301   call void @use(i8* nonnull %0)
302   ret void
305 ; CHECK-LABEL: define void @MemSetNonZero3(
306 ; CHECK:  call void @llvm.aarch64.stgp(i8* {{.*}}, i64 46360584388608, i64 0)
307 ; CHECK:  call void @llvm.aarch64.stgp(i8* {{.*}}, i64 0, i64 3038287259199220266)
308 ; CHECK:  ret void