[Frontend] Remove unused includes (NFC) (#116927)
[llvm-project.git] / llvm / test / Instrumentation / AddressSanitizer / hoist-argument-init-insts.ll
blob5ecd4dc7fb9430f7ad39ada6499fc98b7c7642ae
1 ; RUN: opt < %s -passes=asan -asan-use-after-scope -asan-use-stack-safety=1 -S | FileCheck %s
3 ; Source (-O0 -fsanitize=address -fsanitize-address-use-after-scope):
4 ;; struct S { int x, y; };
5 ;; void swap(S *a, S *b, bool doit) {
6 ;;   if (!doit)
7 ;;     return;
8 ;;   auto tmp = *a;
9 ;;   *a = *b;
10 ;;   *b = tmp;
11 ;; }
13 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
14 target triple = "x86_64-apple-macosx10.14.0"
16 %struct.S = type { i32, i32 }
18 ; CHECK-LABEL: define {{.*}} @_Z4swapP1SS0_b(
20 ; First come the argument allocas.
21 ; CHECK:      %a.addr = alloca ptr, align 8
22 ; CHECK-NEXT: %b.addr = alloca ptr, align 8
23 ; CHECK-NEXT: %doit.addr = alloca i8, align 1
25 ; Next, the stores into the argument allocas.
26 ; CHECK-NEXT: store ptr {{.*}}, ptr %a.addr
27 ; CHECK-NEXT: store ptr {{.*}}, ptr %b.addr
28 ; CHECK-NEXT: [[frombool:%.*]] = zext i1 {{.*}} to i8
29 ; CHECK-NEXT: store i8 %frombool, ptr %doit.addr, align 1
30 ; CHECK-NEXT: [[stack_base:%.*]] = alloca i64, align 8
32 define void @_Z4swapP1SS0_b(ptr %a, ptr %b, i1 zeroext %doit) sanitize_address {
33 entry:
34   %a.addr = alloca ptr, align 8
35   %b.addr = alloca ptr, align 8
36   %doit.addr = alloca i8, align 1
37   %tmp = alloca %struct.S, align 4
38   store ptr %a, ptr %a.addr, align 8
39   store ptr %b, ptr %b.addr, align 8
40   %frombool = zext i1 %doit to i8
41   store i8 %frombool, ptr %doit.addr, align 1
42   %0 = load i8, ptr %doit.addr, align 1
43   %tobool = trunc i8 %0 to i1
44   br i1 %tobool, label %if.end, label %if.then
46 if.then:                                          ; preds = %entry
47   br label %return
49 if.end:                                           ; preds = %entry
50   %1 = load ptr, ptr %a.addr, align 8
51   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %1, i64 8, i1 false)
52   %2 = load ptr, ptr %b.addr, align 8
53   %3 = load ptr, ptr %a.addr, align 8
54   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %3, ptr align 4 %2, i64 8, i1 false)
55   %4 = load ptr, ptr %b.addr, align 8
56   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %4, ptr align 4 %tmp, i64 8, i1 false)
57   br label %return
59 return:                                           ; preds = %if.end, %if.then
60   ret void
63 ; Synthetic test case, meant to check that we do not reorder instructions past
64 ; a load when attempting to hoist argument init insts.
65 ; CHECK-LABEL: define {{.*}} @func_with_load_in_arginit_sequence
66 ; CHECK:      [[argA:%.*]] = alloca ptr,
67 ; CHECK-NEXT: [[argB:%.*]] = alloca ptr,
68 ; CHECK-NEXT: [[argDoit:%.*]] = alloca i8,
69 ; CHECK-NEXT: %tmp = alloca %struct.S, align 4
70 ; CHECK-NEXT: store ptr {{.*}}, ptr [[argA]]
71 ; CHECK-NEXT: store ptr {{.*}}, ptr [[argB]]
72 ; CHECK-NEXT: %0 = load i8, ptr %doit.addr, align 1
73 ; CHECK-NEXT: %frombool = zext i1 %doit to i8
74 ; CHECK-NEXT: store i8 %frombool, ptr %doit.addr, align 1
75 define void @func_with_load_in_arginit_sequence(ptr %a, ptr %b, i1 zeroext %doit) sanitize_address {
76 entry:
77   %a.addr = alloca ptr, align 8
78   %b.addr = alloca ptr, align 8
79   %doit.addr = alloca i8, align 1
80   %tmp = alloca %struct.S, align 4
81   store ptr %a, ptr %a.addr, align 8
82   store ptr %b, ptr %b.addr, align 8
84   ; This load prevents the next argument init sequence from being moved.
85   %0 = load i8, ptr %doit.addr, align 1 
87   %frombool = zext i1 %doit to i8
88   store i8 %frombool, ptr %doit.addr, align 1
89   %tobool = trunc i8 %0 to i1
90   br i1 %tobool, label %if.end, label %if.then
92 if.then:                                          ; preds = %entry
93   br label %return
95 if.end:                                           ; preds = %entry
96   %1 = load ptr, ptr %a.addr, align 8
97   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %1, i64 8, i1 false)
98   %2 = load ptr, ptr %b.addr, align 8
99   %3 = load ptr, ptr %a.addr, align 8
100   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %3, ptr align 4 %2, i64 8, i1 false)
101   %4 = load ptr, ptr %b.addr, align 8
102   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %4, ptr align 4 %tmp, i64 8, i1 false)
103   br label %return
105 return:                                           ; preds = %if.end, %if.then
106   ret void
109 ; Synthetic test case, meant to check that we can handle functions with more
110 ; than one interesting alloca.
111 ; CHECK-LABEL: define {{.*}} @func_with_multiple_interesting_allocas
112 ; CHECK:      [[argA:%.*]] = alloca ptr,
113 ; CHECK-NEXT: [[argB:%.*]] = alloca ptr,
114 ; CHECK-NEXT: [[argDoit:%.*]] = alloca i8,
115 ; CHECK-NEXT: %tmp = alloca %struct.S, align 4
116 ; CHECK-NEXT: %tmp2 = alloca %struct.S, align 4
117 ; CHECK-NEXT: store ptr {{.*}}, ptr [[argA]]
118 ; CHECK-NEXT: store ptr {{.*}}, ptr [[argB]]
119 ; CHECK-NEXT: [[frombool:%.*]] = zext i1 {{.*}} to i8
120 ; CHECK-NEXT: store i8 [[frombool]], ptr [[argDoit]]
121 ; CHECK-NEXT: %0 = load i8, ptr %doit.addr, align 1
122 define void @func_with_multiple_interesting_allocas(ptr %a, ptr %b, i1 zeroext %doit) sanitize_address {
123 entry:
124   %a.addr = alloca ptr, align 8
125   %b.addr = alloca ptr, align 8
126   %doit.addr = alloca i8, align 1
127   %tmp = alloca %struct.S, align 4
128   %tmp2 = alloca %struct.S, align 4
129   store ptr %a, ptr %a.addr, align 8
130   store ptr %b, ptr %b.addr, align 8
131   %frombool = zext i1 %doit to i8
132   store i8 %frombool, ptr %doit.addr, align 1
133   %0 = load i8, ptr %doit.addr, align 1
134   %tobool = trunc i8 %0 to i1
135   br i1 %tobool, label %if.end, label %if.then
137 if.then:                                          ; preds = %entry
138   br label %return
140 if.end:                                           ; preds = %entry
141   %1 = load ptr, ptr %a.addr, align 8
142   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %1, i64 8, i1 false)
143   %2 = load ptr, ptr %b.addr, align 8
144   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp2, ptr align 4 %2, i64 8, i1 false)
145   %3 = load ptr, ptr %b.addr, align 8
146   %4 = load ptr, ptr %a.addr, align 8
147   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %4, ptr align 4 %3, i64 8, i1 false)
148   %5 = load ptr, ptr %b.addr, align 8
149   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %5, ptr align 4 %tmp, i64 8, i1 false)
150   %6 = load ptr, ptr %a.addr, align 8
151   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %6, ptr align 4 %tmp2, i64 8, i1 false)
152   br label %return
154 return:                                           ; preds = %if.end, %if.then
155   ret void
158 declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)