1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2 ; Test memory sanitizer instrumentation for Arm NEON VST instructions, with
3 ; origin tracking. These tests are deliberately shorter than neon_vst.ll, due
4 ; to the verbosity of the output.
6 ; RUN: opt < %s -passes=msan -msan-track-origins=2 -S | FileCheck %s
8 ; Forked from llvm/test/CodeGen/AArch64/arm64-st1.ll
10 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
11 target triple = "aarch64--linux-android9001"
13 ; -----------------------------------------------------------------------------------------------------------------------------------------------
15 define void @st2_16b(<16 x i8> %A, <16 x i8> %B, ptr %P) nounwind sanitize_memory {
18 ; CHECK-LABEL: define void @st2_16b
19 ; CHECK-SAME: (<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] {
20 ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 32) to ptr), align 8
21 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 32) to ptr), align 4
22 ; CHECK-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr @__msan_param_tls, align 8
23 ; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr @__msan_param_origin_tls, align 4
24 ; CHECK-NEXT: [[TMP5:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
25 ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 16) to ptr), align 4
26 ; CHECK-NEXT: call void @llvm.donothing()
27 ; CHECK-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[P]] to i64
28 ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576
29 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr
30 ; CHECK-NEXT: [[TMP10:%.*]] = add i64 [[TMP8]], 35184372088832
31 ; CHECK-NEXT: [[TMP11:%.*]] = and i64 [[TMP10]], -4
32 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr
33 ; CHECK-NEXT: call void @llvm.aarch64.neon.st2.v16i8.p0(<16 x i8> [[TMP3]], <16 x i8> [[TMP5]], ptr [[TMP9]])
34 ; CHECK-NEXT: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP5]] to i128
35 ; CHECK-NEXT: [[TMP14:%.*]] = icmp ne i128 [[TMP13]], 0
36 ; CHECK-NEXT: [[TMP15:%.*]] = select i1 [[TMP14]], i32 [[TMP6]], i32 [[TMP4]]
37 ; CHECK-NEXT: store i32 [[TMP15]], ptr [[TMP12]], align 4
38 ; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i32, ptr [[TMP12]], i32 1
39 ; CHECK-NEXT: store i32 [[TMP15]], ptr [[TMP16]], align 4
40 ; CHECK-NEXT: [[TMP17:%.*]] = getelementptr i32, ptr [[TMP12]], i32 2
41 ; CHECK-NEXT: store i32 [[TMP15]], ptr [[TMP17]], align 4
42 ; CHECK-NEXT: [[TMP18:%.*]] = getelementptr i32, ptr [[TMP12]], i32 3
43 ; CHECK-NEXT: store i32 [[TMP15]], ptr [[TMP18]], align 4
44 ; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i32, ptr [[TMP12]], i32 4
45 ; CHECK-NEXT: store i32 [[TMP15]], ptr [[TMP19]], align 4
46 ; CHECK-NEXT: [[TMP20:%.*]] = getelementptr i32, ptr [[TMP12]], i32 5
47 ; CHECK-NEXT: store i32 [[TMP15]], ptr [[TMP20]], align 4
48 ; CHECK-NEXT: [[TMP21:%.*]] = getelementptr i32, ptr [[TMP12]], i32 6
49 ; CHECK-NEXT: store i32 [[TMP15]], ptr [[TMP21]], align 4
50 ; CHECK-NEXT: [[TMP22:%.*]] = getelementptr i32, ptr [[TMP12]], i32 7
51 ; CHECK-NEXT: store i32 [[TMP15]], ptr [[TMP22]], align 4
52 ; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP1]], 0
53 ; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP23:%.*]], label [[TMP24:%.*]], !prof [[PROF0:![0-9]+]]
55 ; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP2]]) #[[ATTR4:[0-9]+]]
56 ; CHECK-NEXT: unreachable
58 ; CHECK-NEXT: call void @llvm.aarch64.neon.st2.v16i8.p0(<16 x i8> [[A]], <16 x i8> [[B]], ptr [[P]])
59 ; CHECK-NEXT: ret void
61 call void @llvm.aarch64.neon.st2.v16i8.p0(<16 x i8> %A, <16 x i8> %B, ptr %P)
65 define void @st3_16b(<16 x i8> %A, <16 x i8> %B, <16 x i8> %C, ptr %P) nounwind sanitize_memory {
68 ; CHECK-LABEL: define void @st3_16b
69 ; CHECK-SAME: (<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], <16 x i8> [[C:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
70 ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 48) to ptr), align 8
71 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 48) to ptr), align 4
72 ; CHECK-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr @__msan_param_tls, align 8
73 ; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr @__msan_param_origin_tls, align 4
74 ; CHECK-NEXT: [[TMP5:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
75 ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 16) to ptr), align 4
76 ; CHECK-NEXT: [[TMP7:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 32) to ptr), align 8
77 ; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 32) to ptr), align 4
78 ; CHECK-NEXT: call void @llvm.donothing()
79 ; CHECK-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[P]] to i64
80 ; CHECK-NEXT: [[TMP10:%.*]] = xor i64 [[TMP9]], 193514046488576
81 ; CHECK-NEXT: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr
82 ; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[TMP10]], 35184372088832
83 ; CHECK-NEXT: [[TMP13:%.*]] = and i64 [[TMP12]], -4
84 ; CHECK-NEXT: [[TMP14:%.*]] = inttoptr i64 [[TMP13]] to ptr
85 ; CHECK-NEXT: call void @llvm.aarch64.neon.st3.v16i8.p0(<16 x i8> [[TMP3]], <16 x i8> [[TMP5]], <16 x i8> [[TMP7]], ptr [[TMP11]])
86 ; CHECK-NEXT: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP5]] to i128
87 ; CHECK-NEXT: [[TMP16:%.*]] = icmp ne i128 [[TMP15]], 0
88 ; CHECK-NEXT: [[TMP17:%.*]] = select i1 [[TMP16]], i32 [[TMP6]], i32 [[TMP4]]
89 ; CHECK-NEXT: [[TMP18:%.*]] = bitcast <16 x i8> [[TMP7]] to i128
90 ; CHECK-NEXT: [[TMP19:%.*]] = icmp ne i128 [[TMP18]], 0
91 ; CHECK-NEXT: [[TMP20:%.*]] = select i1 [[TMP19]], i32 [[TMP8]], i32 [[TMP17]]
92 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP14]], align 4
93 ; CHECK-NEXT: [[TMP21:%.*]] = getelementptr i32, ptr [[TMP14]], i32 1
94 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP21]], align 4
95 ; CHECK-NEXT: [[TMP22:%.*]] = getelementptr i32, ptr [[TMP14]], i32 2
96 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP22]], align 4
97 ; CHECK-NEXT: [[TMP23:%.*]] = getelementptr i32, ptr [[TMP14]], i32 3
98 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP23]], align 4
99 ; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i32, ptr [[TMP14]], i32 4
100 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP24]], align 4
101 ; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i32, ptr [[TMP14]], i32 5
102 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP25]], align 4
103 ; CHECK-NEXT: [[TMP26:%.*]] = getelementptr i32, ptr [[TMP14]], i32 6
104 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP26]], align 4
105 ; CHECK-NEXT: [[TMP27:%.*]] = getelementptr i32, ptr [[TMP14]], i32 7
106 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP27]], align 4
107 ; CHECK-NEXT: [[TMP28:%.*]] = getelementptr i32, ptr [[TMP14]], i32 8
108 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP28]], align 4
109 ; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i32, ptr [[TMP14]], i32 9
110 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP29]], align 4
111 ; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i32, ptr [[TMP14]], i32 10
112 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP30]], align 4
113 ; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i32, ptr [[TMP14]], i32 11
114 ; CHECK-NEXT: store i32 [[TMP20]], ptr [[TMP31]], align 4
115 ; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP1]], 0
116 ; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP32:%.*]], label [[TMP33:%.*]], !prof [[PROF0]]
118 ; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP2]]) #[[ATTR4]]
119 ; CHECK-NEXT: unreachable
121 ; CHECK-NEXT: call void @llvm.aarch64.neon.st3.v16i8.p0(<16 x i8> [[A]], <16 x i8> [[B]], <16 x i8> [[C]], ptr [[P]])
122 ; CHECK-NEXT: ret void
124 call void @llvm.aarch64.neon.st3.v16i8.p0(<16 x i8> %A, <16 x i8> %B, <16 x i8> %C, ptr %P)
128 define void @st4_16b(<16 x i8> %A, <16 x i8> %B, <16 x i8> %C, <16 x i8> %D, ptr %P) nounwind sanitize_memory {
131 ; CHECK-LABEL: define void @st4_16b
132 ; CHECK-SAME: (<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], <16 x i8> [[C:%.*]], <16 x i8> [[D:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
133 ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 64) to ptr), align 8
134 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 64) to ptr), align 4
135 ; CHECK-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr @__msan_param_tls, align 8
136 ; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr @__msan_param_origin_tls, align 4
137 ; CHECK-NEXT: [[TMP5:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
138 ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 16) to ptr), align 4
139 ; CHECK-NEXT: [[TMP7:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 32) to ptr), align 8
140 ; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 32) to ptr), align 4
141 ; CHECK-NEXT: [[TMP9:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 48) to ptr), align 8
142 ; CHECK-NEXT: [[TMP10:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 48) to ptr), align 4
143 ; CHECK-NEXT: call void @llvm.donothing()
144 ; CHECK-NEXT: [[TMP11:%.*]] = ptrtoint ptr [[P]] to i64
145 ; CHECK-NEXT: [[TMP12:%.*]] = xor i64 [[TMP11]], 193514046488576
146 ; CHECK-NEXT: [[TMP13:%.*]] = inttoptr i64 [[TMP12]] to ptr
147 ; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[TMP12]], 35184372088832
148 ; CHECK-NEXT: [[TMP15:%.*]] = and i64 [[TMP14]], -4
149 ; CHECK-NEXT: [[TMP16:%.*]] = inttoptr i64 [[TMP15]] to ptr
150 ; CHECK-NEXT: call void @llvm.aarch64.neon.st4.v16i8.p0(<16 x i8> [[TMP3]], <16 x i8> [[TMP5]], <16 x i8> [[TMP7]], <16 x i8> [[TMP9]], ptr [[TMP13]])
151 ; CHECK-NEXT: [[TMP17:%.*]] = bitcast <16 x i8> [[TMP5]] to i128
152 ; CHECK-NEXT: [[TMP18:%.*]] = icmp ne i128 [[TMP17]], 0
153 ; CHECK-NEXT: [[TMP19:%.*]] = select i1 [[TMP18]], i32 [[TMP6]], i32 [[TMP4]]
154 ; CHECK-NEXT: [[TMP20:%.*]] = bitcast <16 x i8> [[TMP7]] to i128
155 ; CHECK-NEXT: [[TMP21:%.*]] = icmp ne i128 [[TMP20]], 0
156 ; CHECK-NEXT: [[TMP22:%.*]] = select i1 [[TMP21]], i32 [[TMP8]], i32 [[TMP19]]
157 ; CHECK-NEXT: [[TMP23:%.*]] = bitcast <16 x i8> [[TMP9]] to i128
158 ; CHECK-NEXT: [[TMP24:%.*]] = icmp ne i128 [[TMP23]], 0
159 ; CHECK-NEXT: [[TMP25:%.*]] = select i1 [[TMP24]], i32 [[TMP10]], i32 [[TMP22]]
160 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP16]], align 4
161 ; CHECK-NEXT: [[TMP26:%.*]] = getelementptr i32, ptr [[TMP16]], i32 1
162 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP26]], align 4
163 ; CHECK-NEXT: [[TMP27:%.*]] = getelementptr i32, ptr [[TMP16]], i32 2
164 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP27]], align 4
165 ; CHECK-NEXT: [[TMP28:%.*]] = getelementptr i32, ptr [[TMP16]], i32 3
166 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP28]], align 4
167 ; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i32, ptr [[TMP16]], i32 4
168 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP29]], align 4
169 ; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i32, ptr [[TMP16]], i32 5
170 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP30]], align 4
171 ; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i32, ptr [[TMP16]], i32 6
172 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP31]], align 4
173 ; CHECK-NEXT: [[TMP32:%.*]] = getelementptr i32, ptr [[TMP16]], i32 7
174 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP32]], align 4
175 ; CHECK-NEXT: [[TMP33:%.*]] = getelementptr i32, ptr [[TMP16]], i32 8
176 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP33]], align 4
177 ; CHECK-NEXT: [[TMP34:%.*]] = getelementptr i32, ptr [[TMP16]], i32 9
178 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP34]], align 4
179 ; CHECK-NEXT: [[TMP35:%.*]] = getelementptr i32, ptr [[TMP16]], i32 10
180 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP35]], align 4
181 ; CHECK-NEXT: [[TMP36:%.*]] = getelementptr i32, ptr [[TMP16]], i32 11
182 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP36]], align 4
183 ; CHECK-NEXT: [[TMP37:%.*]] = getelementptr i32, ptr [[TMP16]], i32 12
184 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP37]], align 4
185 ; CHECK-NEXT: [[TMP38:%.*]] = getelementptr i32, ptr [[TMP16]], i32 13
186 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP38]], align 4
187 ; CHECK-NEXT: [[TMP39:%.*]] = getelementptr i32, ptr [[TMP16]], i32 14
188 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP39]], align 4
189 ; CHECK-NEXT: [[TMP40:%.*]] = getelementptr i32, ptr [[TMP16]], i32 15
190 ; CHECK-NEXT: store i32 [[TMP25]], ptr [[TMP40]], align 4
191 ; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP1]], 0
192 ; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP41:%.*]], label [[TMP42:%.*]], !prof [[PROF0]]
194 ; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP2]]) #[[ATTR4]]
195 ; CHECK-NEXT: unreachable
197 ; CHECK-NEXT: call void @llvm.aarch64.neon.st4.v16i8.p0(<16 x i8> [[A]], <16 x i8> [[B]], <16 x i8> [[C]], <16 x i8> [[D]], ptr [[P]])
198 ; CHECK-NEXT: ret void
200 call void @llvm.aarch64.neon.st4.v16i8.p0(<16 x i8> %A, <16 x i8> %B, <16 x i8> %C, <16 x i8> %D, ptr %P)
204 declare void @llvm.aarch64.neon.st2.v16i8.p0(<16 x i8>, <16 x i8>, ptr) nounwind sanitize_memory readonly
205 declare void @llvm.aarch64.neon.st3.v16i8.p0(<16 x i8>, <16 x i8>, <16 x i8>, ptr) nounwind sanitize_memory readonly
206 declare void @llvm.aarch64.neon.st4.v16i8.p0(<16 x i8>, <16 x i8>, <16 x i8>, <16 x i8>, ptr) nounwind sanitize_memory readonly