[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / AArch64 / stack-tagging.ll
blob244a0a1edbb25bc70e69bd1f5579aa14f673730d
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 @use8(i8*)
7 declare void @use32(i32*)
8 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
9 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
11 define void @OneVar() sanitize_memtag {
12 entry:
13   %x = alloca i32, align 4
14   call void @use32(i32* %x)
15   ret void
18 ; CHECK-LABEL: define void @OneVar(
19 ; CHECK:  [[BASE:%.*]] = call i8* @llvm.aarch64.irg.sp(i64 0)
20 ; CHECK:  [[X:%.*]] = alloca { i32, [12 x i8] }, align 16
21 ; CHECK:  [[TX:%.*]] = call { i32, [12 x i8] }* @llvm.aarch64.tagp.{{.*}}({ i32, [12 x i8] }* [[X]], i8* [[BASE]], i64 0)
22 ; CHECK:  [[TX8:%.*]] = bitcast { i32, [12 x i8] }* [[TX]] to i8*
23 ; CHECK:  call void @llvm.aarch64.settag(i8* [[TX8]], i64 16)
24 ; CHECK:  [[GEP32:%.*]] = bitcast { i32, [12 x i8] }* [[TX]] to i32*
25 ; CHECK:  call void @use32(i32* [[GEP32]])
26 ; CHECK:  [[GEP8:%.*]] = bitcast { i32, [12 x i8] }* [[X]] to i8*
27 ; CHECK:  call void @llvm.aarch64.settag(i8* [[GEP8]], i64 16)
28 ; CHECK:  ret void
31 define void @ManyVars() sanitize_memtag {
32 entry:
33   %x1 = alloca i32, align 4
34   %x2 = alloca i8, align 4
35   %x3 = alloca i32, i32 11, align 4
36   call void @use32(i32* %x1)
37   call void @use8(i8* %x2)
38   call void @use32(i32* %x3)
39   ret void
42 ; CHECK-LABEL: define void @ManyVars(
43 ; CHECK:  alloca { i32, [12 x i8] }, align 16
44 ; CHECK:  call { i32, [12 x i8] }* @llvm.aarch64.tagp.{{.*}}({ i32, [12 x i8] }* {{.*}}, i64 0)
45 ; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)
46 ; CHECK:  alloca { i8, [15 x i8] }, align 16
47 ; CHECK:  call { i8, [15 x i8] }* @llvm.aarch64.tagp.{{.*}}({ i8, [15 x i8] }* {{.*}}, i64 1)
48 ; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)
49 ; CHECK:  alloca { [11 x i32], [4 x i8] }, align 16
50 ; CHECK:  call { [11 x i32], [4 x i8] }* @llvm.aarch64.tagp.{{.*}}({ [11 x i32], [4 x i8] }* {{.*}}, i64 2)
51 ; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 48)
53 ; CHECK:  call void @use32(
54 ; CHECK:  call void @use8(
55 ; CHECK:  call void @use32(
57 ; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)
58 ; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)
59 ; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 48)
60 ; CHECK-NEXT:  ret void
63 define void @Scope(i32 %b) sanitize_memtag {
64 entry:
65   %x = alloca i32, align 4
66   %tobool = icmp eq i32 %b, 0
67   br i1 %tobool, label %if.end, label %if.then
69 if.then:
70   %0 = bitcast i32* %x to i8*
71   call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)
72   call void @use8(i8* %0) #3
73   call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)
74   br label %if.end
76 if.end:
77   ret void
80 ; CHECK-LABEL: define void @Scope(
81 ; CHECK:  br i1
82 ; CHECK:  call void @llvm.lifetime.start.p0i8(
83 ; CHECK:  call void @llvm.aarch64.settag(
84 ; CHECK:  call void @use8(
85 ; CHECK:  call void @llvm.aarch64.settag(
86 ; CHECK:  call void @llvm.lifetime.end.p0i8(
87 ; CHECK:  br label
88 ; CHECK:  ret void
91 ; Spooked by the multiple lifetime ranges, StackTagging remove all of them and sets tags on entry and exit.
92 define void @BadScope(i32 %b) sanitize_memtag {
93 entry:
94   %x = alloca i32, align 4
95   %tobool = icmp eq i32 %b, 0
96   br i1 %tobool, label %if.end, label %if.then
98 if.then:
99   %0 = bitcast i32* %x to i8*
100   call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)
101   call void @use8(i8* %0) #3
102   call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)
104   call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)
105   call void @use8(i8* %0) #3
106   call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)
107   br label %if.end
109 if.end:
110   ret void
113 ; CHECK-LABEL: define void @BadScope(
114 ; CHECK:       call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)
115 ; CHECK:       br i1
116 ; CHECK:       call void @use8(i8*
117 ; CHECK-NEXT:  call void @use8(i8*
118 ; CHECK:       br label
119 ; CHECK:       call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)
120 ; CHECK-NEXT:  ret void
122 define void @DynamicAllocas(i32 %cnt) sanitize_memtag {
123 entry:
124   %x = alloca i32, i32 %cnt, align 4
125   br label %l
127   %y = alloca i32, align 4
128   call void @use32(i32* %x)
129   call void @use32(i32* %y)
130   ret void
133 ; CHECK-LABEL: define void @DynamicAllocas(
134 ; CHECK-NOT: @llvm.aarch64.irg.sp
135 ; CHECK:     %x = alloca i32, i32 %cnt, align 4
136 ; CHECK-NOT: @llvm.aarch64.irg.sp
137 ; CHECK:     alloca i32, align 4
138 ; CHECK-NOT: @llvm.aarch64.irg.sp
139 ; CHECK:     ret void
141 ; If we can't trace one of the lifetime markers to a single alloca, fall back
142 ; to poisoning all allocas at the beginning of the function.
143 ; Each alloca must be poisoned only once.
144 define void @UnrecognizedLifetime(i8 %v) sanitize_memtag {
145 entry:
146   %x = alloca i32, align 4
147   %y = alloca i32, align 4
148   %z = alloca i32, align 4
149   %cx = bitcast i32* %x to i8*
150   %cy = bitcast i32* %y to i8*
151   %cz = bitcast i32* %z to i8*
152   %tobool = icmp eq i8 %v, 0
153   %xy = select i1 %tobool, i32* %x, i32* %y
154   %cxcy = select i1 %tobool, i8* %cx, i8* %cy
155   br label %another_bb
157 another_bb:
158   call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %cz)
159   store i32 7, i32* %z
160   call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %cz)
161   call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %cz)
162   store i32 7, i32* %z
163   call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %cz)
164   call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %cxcy)
165   store i32 8, i32* %xy
166   call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %cxcy)
167   ret void
170 ; CHECK-LABEL: define void @UnrecognizedLifetime(
171 ; CHECK: call i8* @llvm.aarch64.irg.sp(i64 0)
172 ; CHECK: alloca { i32, [12 x i8] }, align 16
173 ; CHECK: call { i32, [12 x i8] }* @llvm.aarch64.tagp
174 ; CHECK: call void @llvm.aarch64.settag(
175 ; CHECK: alloca { i32, [12 x i8] }, align 16
176 ; CHECK: call { i32, [12 x i8] }* @llvm.aarch64.tagp
177 ; CHECK: call void @llvm.aarch64.settag(
178 ; CHECK: alloca { i32, [12 x i8] }, align 16
179 ; CHECK: call { i32, [12 x i8] }* @llvm.aarch64.tagp
180 ; CHECK: call void @llvm.aarch64.settag(
181 ; CHECK: store i32
182 ; CHECK: store i32
183 ; CHECK: store i32
184 ; CHECK: call void @llvm.aarch64.settag(
185 ; CHECK: call void @llvm.aarch64.settag(
186 ; CHECK: call void @llvm.aarch64.settag(
187 ; CHECK: ret void