[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / test / Instrumentation / MemorySanitizer / msan_basic.ll
blobfe7637918524d13f05cbdb22a176de40337e06bc
1 ; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CHECK,NOORIGINS --implicit-check-not="call void @__msan_warning"
2 ; RUN: opt < %s --passes='module(msan)' -msan-check-access-address=0 -S | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CHECK,NOORIGINS --implicit-check-not="call void @__msan_warning"
3 ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,ORIGINS %s --implicit-check-not="call void @__msan_warning"
4 ; RUN: opt < %s -passes='module(msan)' -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,ORIGINS %s --implicit-check-not="call void @__msan_warning"
5 ; RUN: opt < %s -passes='module(msan)' -msan-instrumentation-with-call-threshold=0 -msan-track-origins=1 -S | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK-CALLS %s --implicit-check-not="call void @__msan_warning"
7 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
8 target triple = "x86_64-unknown-linux-gnu"
10 ; CHECK: @llvm.used = appending global [1 x ptr] [ptr @msan.module_ctor]
11 ; CHECK: @llvm.global_ctors {{.*}} { i32 0, ptr @msan.module_ctor, ptr null }
13 ; Check the presence and the linkage type of __msan_track_origins and
14 ; other interface symbols.
15 ; CHECK-NOT: @__msan_track_origins
16 ; ORIGINS: @__msan_track_origins = weak_odr constant i32 1
17 ; CHECK-NOT: @__msan_keep_going = weak_odr constant i32 0
18 ; CHECK: @__msan_retval_tls = external thread_local(initialexec) global [{{.*}}]
19 ; CHECK: @__msan_retval_origin_tls = external thread_local(initialexec) global i32
20 ; CHECK: @__msan_param_tls = external thread_local(initialexec) global [{{.*}}]
21 ; CHECK: @__msan_param_origin_tls = external thread_local(initialexec) global [{{.*}}]
22 ; CHECK: @__msan_va_arg_tls = external thread_local(initialexec) global [{{.*}}]
23 ; CHECK: @__msan_va_arg_overflow_size_tls = external thread_local(initialexec) global i64
26 ; Check instrumentation of stores
28 define void @Store(ptr nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
29 entry:
30   store i32 %x, ptr %p, align 4
31   ret void
34 ; CHECK-LABEL: @Store
35 ; CHECK: load {{.*}} @__msan_param_tls
36 ; ORIGINS: load {{.*}} @__msan_param_origin_tls
37 ; CHECK: store
38 ; ORIGINS: icmp
39 ; ORIGINS: br i1
40 ; ORIGINS: {{^[0-9]+}}:
41 ; ORIGINS: store
42 ; ORIGINS: br label
43 ; ORIGINS: {{^[0-9]+}}:
44 ; CHECK: store
45 ; CHECK: ret void
48 ; Check instrumentation of aligned stores
49 ; Shadow store has the same alignment as the original store; origin store
50 ; does not specify explicit alignment.
52 define void @AlignedStore(ptr nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
53 entry:
54   store i32 %x, ptr %p, align 32
55   ret void
58 ; CHECK-LABEL: @AlignedStore
59 ; CHECK: load {{.*}} @__msan_param_tls
60 ; ORIGINS: load {{.*}} @__msan_param_origin_tls
61 ; CHECK: store {{.*}} align 32
62 ; ORIGINS: icmp
63 ; ORIGINS: br i1
64 ; ORIGINS: {{^[0-9]+}}:
65 ; ORIGINS: store {{.*}} align 32
66 ; ORIGINS: br label
67 ; ORIGINS: {{^[0-9]+}}:
68 ; CHECK: store {{.*}} align 32
69 ; CHECK: ret void
72 ; load followed by cmp: check that we load the shadow and call __msan_warning_with_origin.
73 define void @LoadAndCmp(ptr nocapture %a) nounwind uwtable sanitize_memory {
74 entry:
75   %0 = load i32, ptr %a, align 4
76   %tobool = icmp eq i32 %0, 0
77   br i1 %tobool, label %if.end, label %if.then
79 if.then:                                          ; preds = %entry
80   tail call void (...) @foo() nounwind
81   br label %if.end
83 if.end:                                           ; preds = %entry, %if.then
84   ret void
87 declare void @foo(...)
89 ; CHECK-LABEL: @LoadAndCmp
90 ; CHECK: %0 = load i32,
91 ; CHECK: = load
92 ; ORIGINS: %[[ORIGIN:.*]] = load
93 ; NOORIGINS: call void @__msan_warning_noreturn()
94 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32 %[[ORIGIN]])
95 ; CHECK-CONT:
96 ; CHECK-NEXT: unreachable
97 ; CHECK: br i1 %tobool
98 ; CHECK: ret void
100 ; Check that we store the shadow for the retval.
101 define i32 @ReturnInt() nounwind uwtable readnone sanitize_memory {
102 entry:
103   ret i32 123
106 ; CHECK-LABEL: @ReturnInt
107 ; CHECK: store i32 0,{{.*}}__msan_retval_tls
108 ; CHECK: ret i32
110 ; Check that we get the shadow for the retval.
111 define void @CopyRetVal(ptr nocapture %a) nounwind uwtable sanitize_memory {
112 entry:
113   %call = tail call i32 @ReturnInt() nounwind
114   store i32 %call, ptr %a, align 4
115   ret void
118 ; CHECK-LABEL: @CopyRetVal
119 ; CHECK: load{{.*}}__msan_retval_tls
120 ; CHECK: store
121 ; CHECK: store
122 ; CHECK: ret void
125 ; Check that we generate PHIs for shadow.
126 define void @FuncWithPhi(ptr nocapture %a, ptr %b, ptr nocapture %c) nounwind uwtable sanitize_memory {
127 entry:
128   %tobool = icmp eq ptr %b, null
129   br i1 %tobool, label %if.else, label %if.then
131   if.then:                                          ; preds = %entry
132   %0 = load i32, ptr %b, align 4
133   br label %if.end
135   if.else:                                          ; preds = %entry
136   %1 = load i32, ptr %c, align 4
137   br label %if.end
139   if.end:                                           ; preds = %if.else, %if.then
140   %t.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ]
141   store i32 %t.0, ptr %a, align 4
142   ret void
145 ; CHECK-LABEL: @FuncWithPhi
146 ; NOORIGINS: call void @__msan_warning_noreturn()
147 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32
148 ; CHECK: = phi
149 ; CHECK-NEXT: = phi
150 ; CHECK: store
151 ; CHECK: store
152 ; CHECK: ret void
154 ; Compute shadow for "x << 10"
155 define void @ShlConst(ptr nocapture %x) nounwind uwtable sanitize_memory {
156 entry:
157   %0 = load i32, ptr %x, align 4
158   %1 = shl i32 %0, 10
159   store i32 %1, ptr %x, align 4
160   ret void
163 ; CHECK-LABEL: @ShlConst
164 ; CHECK: = load
165 ; CHECK: = load
166 ; CHECK: shl
167 ; CHECK: shl
168 ; CHECK: store
169 ; CHECK: store
170 ; CHECK: ret void
172 ; Compute shadow for "10 << x": it should have 'sext i1'.
173 define void @ShlNonConst(ptr nocapture %x) nounwind uwtable sanitize_memory {
174 entry:
175   %0 = load i32, ptr %x, align 4
176   %1 = shl i32 10, %0
177   store i32 %1, ptr %x, align 4
178   ret void
181 ; CHECK-LABEL: @ShlNonConst
182 ; CHECK: = load
183 ; CHECK: = load
184 ; CHECK: = sext i1
185 ; CHECK: store
186 ; CHECK: store
187 ; CHECK: ret void
189 ; SExt
190 define void @SExt(ptr nocapture %a, ptr nocapture %b) nounwind uwtable sanitize_memory {
191 entry:
192   %0 = load i16, ptr %b, align 2
193   %1 = sext i16 %0 to i32
194   store i32 %1, ptr %a, align 4
195   ret void
198 ; CHECK-LABEL: @SExt
199 ; CHECK: = load
200 ; CHECK: = load
201 ; CHECK: = sext
202 ; CHECK: = sext
203 ; CHECK: store
204 ; CHECK: store
205 ; CHECK: ret void
208 ; memset
209 define void @MemSet(ptr nocapture %x) nounwind uwtable sanitize_memory {
210 entry:
211   call void @llvm.memset.p0.i64(ptr %x, i8 42, i64 10, i1 false)
212   ret void
215 declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
217 ; CHECK-LABEL: @MemSet
218 ; CHECK: call ptr @__msan_memset
219 ; CHECK: ret void
222 ; memcpy
223 define void @MemCpy(ptr nocapture %x, ptr nocapture %y) nounwind uwtable sanitize_memory {
224 entry:
225   call void @llvm.memcpy.p0.p0.i64(ptr %x, ptr %y, i64 10, i1 false)
226   ret void
229 declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
231 ; CHECK-LABEL: @MemCpy
232 ; CHECK: call ptr @__msan_memcpy
233 ; CHECK: ret void
235 ; memset.inline
236 define void @MemSetInline(ptr nocapture %x) nounwind uwtable sanitize_memory {
237 entry:
238   call void @llvm.memset.inline.p0.i64(ptr %x, i8 42, i64 10, i1 false)
239   ret void
242 declare void @llvm.memset.inline.p0.i64(ptr nocapture, i8, i64, i1) nounwind
244 ; CHECK-LABEL: @MemSetInline
245 ; CHECK: call ptr @__msan_memset
246 ; CHECK: ret void
248 ; memcpy.inline
249 define void @MemCpyInline(ptr nocapture %x, ptr nocapture %y) nounwind uwtable sanitize_memory {
250 entry:
251   call void @llvm.memcpy.inline.p0.p0.i64(ptr %x, ptr %y, i64 10, i1 false)
252   ret void
255 declare void @llvm.memcpy.inline.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
257 ; CHECK-LABEL: @MemCpyInline
258 ; CHECK: call ptr @__msan_memcpy
259 ; CHECK: ret void
261 ; memmove is lowered to a call
262 define void @MemMove(ptr nocapture %x, ptr nocapture %y) nounwind uwtable sanitize_memory {
263 entry:
264   call void @llvm.memmove.p0.p0.i64(ptr %x, ptr %y, i64 10, i1 false)
265   ret void
268 declare void @llvm.memmove.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
270 ; CHECK-LABEL: @MemMove
271 ; CHECK: call ptr @__msan_memmove
272 ; CHECK: ret void
274 ;; ------------
275 ;; Placeholder tests that will fail once element atomic @llvm.mem[cpy|move|set] intrinsics have
276 ;; been added to the MemIntrinsic class hierarchy. These will act as a reminder to
277 ;; verify that MSAN handles these intrinsics properly once they have been
278 ;; added to that class hierarchy.
279 declare void @llvm.memset.element.unordered.atomic.p0.i64(ptr nocapture writeonly, i8, i64, i32) nounwind
280 declare void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i32) nounwind
281 declare void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i32) nounwind
283 define void @atomic_memcpy(ptr nocapture %x, ptr nocapture %y) nounwind {
284   ; CHECK-LABEL: atomic_memcpy
285   ; CHECK-NEXT: call void @llvm.donothing
286   ; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %x, ptr align 2 %y, i64 16, i32 1)
287   ; CHECK-NEXT: ret void
288   call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %x, ptr align 2 %y, i64 16, i32 1)
289   ret void
292 define void @atomic_memmove(ptr nocapture %x, ptr nocapture %y) nounwind {
293   ; CHECK-LABEL: atomic_memmove
294   ; CHECK-NEXT: call void @llvm.donothing
295   ; CHECK-NEXT: call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %x, ptr align 2 %y, i64 16, i32 1)
296   ; CHECK-NEXT: ret void
297   call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %x, ptr align 2 %y, i64 16, i32 1)
298   ret void
301 define void @atomic_memset(ptr nocapture %x) nounwind {
302   ; CHECK-LABEL: atomic_memset
303   ; CHECK-NEXT: call void @llvm.donothing
304   ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 1 %x, i8 88, i64 16, i32 1)
305   ; CHECK-NEXT: ret void
306   call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 1 %x, i8 88, i64 16, i32 1)
307   ret void
310 ;; ------------
313 ; Check that we propagate shadow for "select"
315 define i32 @Select(i32 %a, i32 %b, i1 %c) nounwind uwtable readnone sanitize_memory {
316 entry:
317   %cond = select i1 %c, i32 %a, i32 %b
318   ret i32 %cond
321 ; CHECK-LABEL: @Select
322 ; CHECK: select i1
323 ; CHECK-DAG: or i32
324 ; CHECK-DAG: xor i32
325 ; CHECK: or i32
326 ; CHECK-DAG: select i1
327 ; ORIGINS-DAG: select
328 ; ORIGINS-DAG: select
329 ; CHECK-DAG: select i1
330 ; CHECK: store i32{{.*}}@__msan_retval_tls
331 ; ORIGINS: store i32{{.*}}@__msan_retval_origin_tls
332 ; CHECK: ret i32
335 ; Check that we propagate origin for "select" with vector condition.
336 ; Select condition is flattened to i1, which is then used to select one of the
337 ; argument origins.
339 define <8 x i16> @SelectVector(<8 x i16> %a, <8 x i16> %b, <8 x i1> %c) nounwind uwtable readnone sanitize_memory {
340 entry:
341   %cond = select <8 x i1> %c, <8 x i16> %a, <8 x i16> %b
342   ret <8 x i16> %cond
345 ; CHECK-LABEL: @SelectVector
346 ; CHECK: select <8 x i1>
347 ; CHECK-DAG: or <8 x i16>
348 ; CHECK-DAG: xor <8 x i16>
349 ; CHECK: or <8 x i16>
350 ; CHECK-DAG: select <8 x i1>
351 ; ORIGINS-DAG: select
352 ; ORIGINS-DAG: select
353 ; CHECK-DAG: select <8 x i1>
354 ; CHECK: store <8 x i16>{{.*}}@__msan_retval_tls
355 ; ORIGINS: store i32{{.*}}@__msan_retval_origin_tls
356 ; CHECK: ret <8 x i16>
359 ; Check that we propagate origin for "select" with scalar condition and vector
360 ; arguments. Select condition shadow is sign-extended to the vector type and
361 ; mixed into the result shadow.
363 define <8 x i16> @SelectVector2(<8 x i16> %a, <8 x i16> %b, i1 %c) nounwind uwtable readnone sanitize_memory {
364 entry:
365   %cond = select i1 %c, <8 x i16> %a, <8 x i16> %b
366   ret <8 x i16> %cond
369 ; CHECK-LABEL: @SelectVector2
370 ; CHECK: select i1
371 ; CHECK-DAG: or <8 x i16>
372 ; CHECK-DAG: xor <8 x i16>
373 ; CHECK: or <8 x i16>
374 ; CHECK-DAG: select i1
375 ; ORIGINS-DAG: select i1
376 ; ORIGINS-DAG: select i1
377 ; CHECK-DAG: select i1
378 ; CHECK: ret <8 x i16>
381 define { i64, i64 } @SelectStruct(i1 zeroext %x, { i64, i64 } %a, { i64, i64 } %b) readnone sanitize_memory {
382 entry:
383   %c = select i1 %x, { i64, i64 } %a, { i64, i64 } %b
384   ret { i64, i64 } %c
387 ; CHECK-LABEL: @SelectStruct
388 ; CHECK: select i1 {{.*}}, { i64, i64 }
389 ; CHECK-NEXT: select i1 {{.*}}, { i64, i64 } { i64 -1, i64 -1 }, { i64, i64 }
390 ; ORIGINS: select i1
391 ; ORIGINS: select i1
392 ; CHECK-NEXT: select i1 {{.*}}, { i64, i64 }
393 ; CHECK: ret { i64, i64 }
396 define { ptr, double } @SelectStruct2(i1 zeroext %x, { ptr, double } %a, { ptr, double } %b) readnone sanitize_memory {
397 entry:
398   %c = select i1 %x, { ptr, double } %a, { ptr, double } %b
399   ret { ptr, double } %c
402 ; CHECK-LABEL: @SelectStruct2
403 ; CHECK: select i1 {{.*}}, { i64, i64 }
404 ; CHECK-NEXT: select i1 {{.*}}, { i64, i64 } { i64 -1, i64 -1 }, { i64, i64 }
405 ; ORIGINS: select i1
406 ; ORIGINS: select i1
407 ; CHECK-NEXT: select i1 {{.*}}, { ptr, double }
408 ; CHECK: ret { ptr, double }
411 define ptr @IntToPtr(i64 %x) nounwind uwtable readnone sanitize_memory {
412 entry:
413   %0 = inttoptr i64 %x to ptr
414   ret ptr %0
417 ; CHECK-LABEL: @IntToPtr
418 ; CHECK: load i64, ptr{{.*}}__msan_param_tls
419 ; ORIGINS-NEXT: load i32, ptr{{.*}}__msan_param_origin_tls
420 ; CHECK-NEXT: call void @llvm.donothing
421 ; CHECK-NEXT: inttoptr
422 ; CHECK-NEXT: store i64{{.*}}__msan_retval_tls
423 ; CHECK: ret ptr
426 define ptr @IntToPtr_ZExt(i16 %x) nounwind uwtable readnone sanitize_memory {
427 entry:
428   %0 = inttoptr i16 %x to ptr
429   ret ptr %0
432 ; CHECK-LABEL: @IntToPtr_ZExt
433 ; CHECK: load i16, ptr{{.*}}__msan_param_tls
434 ; CHECK: zext
435 ; CHECK-NEXT: inttoptr
436 ; CHECK-NEXT: store i64{{.*}}__msan_retval_tls
437 ; CHECK: ret ptr
440 ; Check that we insert exactly one check on udiv
441 ; (2nd arg shadow is checked, 1st arg shadow is propagated)
443 define i32 @Div(i32 %a, i32 %b) nounwind uwtable readnone sanitize_memory {
444 entry:
445   %div = udiv i32 %a, %b
446   ret i32 %div
449 ; CHECK-LABEL: @Div
450 ; CHECK: icmp
451 ; NOORIGINS: call void @__msan_warning_noreturn()
452 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32
453 ; CHECK-NOT: icmp
454 ; CHECK: udiv
455 ; CHECK-NOT: icmp
456 ; CHECK: ret i32
458 ; Check that fdiv, unlike udiv, simply propagates shadow.
460 define float @FDiv(float %a, float %b) nounwind uwtable readnone sanitize_memory {
461 entry:
462   %c = fdiv float %a, %b
463   ret float %c
466 ; CHECK-LABEL: @FDiv
467 ; CHECK: %[[SA:.*]] = load i32,{{.*}}@__msan_param_tls
468 ; CHECK: %[[SB:.*]] = load i32,{{.*}}@__msan_param_tls
469 ; CHECK: %[[SC:.*]] = or i32 %[[SA]], %[[SB]]
470 ; CHECK: = fdiv float
471 ; CHECK: store i32 %[[SC]], ptr {{.*}}@__msan_retval_tls
472 ; CHECK: ret float
474 ; Check that fneg simply propagates shadow.
476 define float @FNeg(float %a) nounwind uwtable readnone sanitize_memory {
477 entry:
478   %c = fneg float %a
479   ret float %c
482 ; CHECK-LABEL: @FNeg
483 ; CHECK: %[[SA:.*]] = load i32,{{.*}}@__msan_param_tls
484 ; ORIGINS: %[[SB:.*]] = load i32,{{.*}}@__msan_param_origin_tls
485 ; CHECK: = fneg float
486 ; CHECK: store i32 %[[SA]], ptr {{.*}}@__msan_retval_tls
487 ; ORIGINS: store i32{{.*}}@__msan_retval_origin_tls
488 ; CHECK: ret float
490 ; Check that we propagate shadow for x<0, x>=0, etc (i.e. sign bit tests)
492 define zeroext i1 @ICmpSLTZero(i32 %x) nounwind uwtable readnone sanitize_memory {
493   %1 = icmp slt i32 %x, 0
494   ret i1 %1
497 ; CHECK-LABEL: @ICmpSLTZero
498 ; CHECK: icmp slt
499 ; CHECK-NOT: call void @__msan_warning
500 ; CHECK: icmp slt
501 ; CHECK-NOT: call void @__msan_warning
502 ; CHECK: ret i1
504 define zeroext i1 @ICmpSGEZero(i32 %x) nounwind uwtable readnone sanitize_memory {
505   %1 = icmp sge i32 %x, 0
506   ret i1 %1
509 ; CHECK-LABEL: @ICmpSGEZero
510 ; CHECK: icmp slt
511 ; CHECK-NOT: call void @__msan_warning
512 ; CHECK: icmp sge
513 ; CHECK-NOT: call void @__msan_warning
514 ; CHECK: ret i1
516 define zeroext i1 @ICmpSGTZero(i32 %x) nounwind uwtable readnone sanitize_memory {
517   %1 = icmp sgt i32 0, %x
518   ret i1 %1
521 ; CHECK-LABEL: @ICmpSGTZero
522 ; CHECK: icmp slt
523 ; CHECK-NOT: call void @__msan_warning
524 ; CHECK: icmp sgt
525 ; CHECK-NOT: call void @__msan_warning
526 ; CHECK: ret i1
528 define zeroext i1 @ICmpSLEZero(i32 %x) nounwind uwtable readnone sanitize_memory {
529   %1 = icmp sle i32 0, %x
530   ret i1 %1
533 ; CHECK-LABEL: @ICmpSLEZero
534 ; CHECK: icmp slt
535 ; CHECK-NOT: call void @__msan_warning
536 ; CHECK: icmp sle
537 ; CHECK-NOT: call void @__msan_warning
538 ; CHECK: ret i1
541 ; Check that we propagate shadow for x<=-1, x>-1, etc (i.e. sign bit tests)
543 define zeroext i1 @ICmpSLTAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
544   %1 = icmp slt i32 -1, %x
545   ret i1 %1
548 ; CHECK-LABEL: @ICmpSLTAllOnes
549 ; CHECK: icmp slt
550 ; CHECK-NOT: call void @__msan_warning
551 ; CHECK: icmp slt
552 ; CHECK-NOT: call void @__msan_warning
553 ; CHECK: ret i1
555 define zeroext i1 @ICmpSGEAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
556   %1 = icmp sge i32 -1, %x
557   ret i1 %1
560 ; CHECK-LABEL: @ICmpSGEAllOnes
561 ; CHECK: icmp slt
562 ; CHECK-NOT: call void @__msan_warning
563 ; CHECK: icmp sge
564 ; CHECK-NOT: call void @__msan_warning
565 ; CHECK: ret i1
567 define zeroext i1 @ICmpSGTAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
568   %1 = icmp sgt i32 %x, -1
569   ret i1 %1
572 ; CHECK-LABEL: @ICmpSGTAllOnes
573 ; CHECK: icmp slt
574 ; CHECK-NOT: call void @__msan_warning
575 ; CHECK: icmp sgt
576 ; CHECK-NOT: call void @__msan_warning
577 ; CHECK: ret i1
579 define zeroext i1 @ICmpSLEAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
580   %1 = icmp sle i32 %x, -1
581   ret i1 %1
584 ; CHECK-LABEL: @ICmpSLEAllOnes
585 ; CHECK: icmp slt
586 ; CHECK-NOT: call void @__msan_warning
587 ; CHECK: icmp sle
588 ; CHECK-NOT: call void @__msan_warning
589 ; CHECK: ret i1
592 ; Check that we propagate shadow for x<0, x>=0, etc (i.e. sign bit tests)
593 ; of the vector arguments.
595 define <2 x i1> @ICmpSLT_vector_Zero(<2 x ptr> %x) nounwind uwtable readnone sanitize_memory {
596   %1 = icmp slt <2 x ptr> %x, zeroinitializer
597   ret <2 x i1> %1
600 ; CHECK-LABEL: @ICmpSLT_vector_Zero
601 ; CHECK: icmp slt <2 x i64>
602 ; CHECK-NOT: call void @__msan_warning
603 ; CHECK: icmp slt <2 x ptr>
604 ; CHECK-NOT: call void @__msan_warning
605 ; CHECK: ret <2 x i1>
607 ; Check that we propagate shadow for x<=-1, x>0, etc (i.e. sign bit tests)
608 ; of the vector arguments.
610 define <2 x i1> @ICmpSLT_vector_AllOnes(<2 x i32> %x) nounwind uwtable readnone sanitize_memory {
611   %1 = icmp slt <2 x i32> <i32 -1, i32 -1>, %x
612   ret <2 x i1> %1
615 ; CHECK-LABEL: @ICmpSLT_vector_AllOnes
616 ; CHECK: icmp slt <2 x i32>
617 ; CHECK-NOT: call void @__msan_warning
618 ; CHECK: icmp slt <2 x i32>
619 ; CHECK-NOT: call void @__msan_warning
620 ; CHECK: ret <2 x i1>
623 ; Check that we propagate shadow for unsigned relational comparisons with
624 ; constants
626 define zeroext i1 @ICmpUGTConst(i32 %x) nounwind uwtable readnone sanitize_memory {
627 entry:
628   %cmp = icmp ugt i32 %x, 7
629   ret i1 %cmp
632 ; CHECK-LABEL: @ICmpUGTConst
633 ; CHECK: icmp ugt i32
634 ; CHECK-NOT: call void @__msan_warning
635 ; CHECK: icmp ugt i32
636 ; CHECK-NOT: call void @__msan_warning
637 ; CHECK: icmp ugt i32
638 ; CHECK-NOT: call void @__msan_warning
639 ; CHECK: ret i1
642 ; Check that loads of shadow have the same alignment as the original loads.
643 ; Check that loads of origin have the alignment of max(4, original alignment).
645 define i32 @ShadowLoadAlignmentLarge() nounwind uwtable sanitize_memory {
646   %y = alloca i32, align 64
647   %1 = load volatile i32, ptr %y, align 64
648   ret i32 %1
651 ; CHECK-LABEL: @ShadowLoadAlignmentLarge
652 ; CHECK: load volatile i32, ptr {{.*}} align 64
653 ; CHECK: load i32, ptr {{.*}} align 64
654 ; CHECK: ret i32
656 define i32 @ShadowLoadAlignmentSmall() nounwind uwtable sanitize_memory {
657   %y = alloca i32, align 2
658   %1 = load volatile i32, ptr %y, align 2
659   ret i32 %1
662 ; CHECK-LABEL: @ShadowLoadAlignmentSmall
663 ; CHECK: load volatile i32, ptr {{.*}} align 2
664 ; CHECK: load i32, ptr {{.*}} align 2
665 ; ORIGINS: load i32, ptr {{.*}} align 4
666 ; CHECK: ret i32
669 ; Test vector manipulation instructions.
670 ; Check that the same bit manipulation is applied to the shadow values.
671 ; Check that there is a zero test of the shadow of %idx argument, where present.
673 define i32 @ExtractElement(<4 x i32> %vec, i32 %idx) sanitize_memory {
674   %x = extractelement <4 x i32> %vec, i32 %idx
675   ret i32 %x
678 ; CHECK-LABEL: @ExtractElement
679 ; CHECK: extractelement
680 ; NOORIGINS: call void @__msan_warning_noreturn()
681 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32
682 ; CHECK: extractelement
683 ; CHECK: ret i32
685 define <4 x i32> @InsertElement(<4 x i32> %vec, i32 %idx, i32 %x) sanitize_memory {
686   %vec1 = insertelement <4 x i32> %vec, i32 %x, i32 %idx
687   ret <4 x i32> %vec1
690 ; CHECK-LABEL: @InsertElement
691 ; CHECK: insertelement
692 ; NOORIGINS: call void @__msan_warning_noreturn()
693 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32
694 ; CHECK: insertelement
695 ; CHECK: ret <4 x i32>
697 define <4 x i32> @ShuffleVector(<4 x i32> %vec, <4 x i32> %vec1) sanitize_memory {
698   %vec2 = shufflevector <4 x i32> %vec, <4 x i32> %vec1,
699                         <4 x i32> <i32 0, i32 4, i32 1, i32 5>
700   ret <4 x i32> %vec2
703 ; CHECK-LABEL: @ShuffleVector
704 ; CHECK: shufflevector
705 ; CHECK-NOT: call void @__msan_warning
706 ; CHECK: shufflevector
707 ; CHECK: ret <4 x i32>
710 ; Test bswap intrinsic instrumentation
711 define i32 @BSwap(i32 %x) nounwind uwtable readnone sanitize_memory {
712   %y = tail call i32 @llvm.bswap.i32(i32 %x)
713   ret i32 %y
716 declare i32 @llvm.bswap.i32(i32) nounwind readnone
718 ; CHECK-LABEL: @BSwap
719 ; CHECK-NOT: call void @__msan_warning
720 ; CHECK: @llvm.bswap.i32
721 ; CHECK-NOT: call void @__msan_warning
722 ; CHECK: @llvm.bswap.i32
723 ; CHECK-NOT: call void @__msan_warning
724 ; CHECK: ret i32
726 ; Test handling of vectors of pointers.
727 ; Check that shadow of such vector is a vector of integers.
729 define <8 x ptr> @VectorOfPointers(ptr %p) nounwind uwtable sanitize_memory {
730   %x = load <8 x ptr>, ptr %p
731   ret <8 x ptr> %x
734 ; CHECK-LABEL: @VectorOfPointers
735 ; CHECK: load <8 x ptr>, ptr
736 ; CHECK: load <8 x i64>, ptr
737 ; CHECK: store <8 x i64> {{.*}} @__msan_retval_tls
738 ; CHECK: ret <8 x ptr>
740 ; Test handling of va_copy.
742 declare void @llvm.va_copy(ptr, ptr) nounwind
744 define void @VACopy(ptr %p1, ptr %p2) nounwind uwtable sanitize_memory {
745   call void @llvm.va_copy(ptr %p1, ptr %p2) nounwind
746   ret void
749 ; CHECK-LABEL: @VACopy
750 ; CHECK: call void @llvm.memset.p0.i64({{.*}}, i8 0, i64 24, i1 false)
751 ; CHECK: ret void
754 ; Test that va_start instrumentation does not use va_arg_tls*.
755 ; It should work with a local stack copy instead.
757 %struct.__va_list_tag = type { i32, i32, ptr, ptr }
758 declare void @llvm.va_start(ptr) nounwind
760 ; Function Attrs: nounwind uwtable
761 define void @VAStart(i32 %x, ...) sanitize_memory {
762 entry:
763   %x.addr = alloca i32, align 4
764   %va = alloca [1 x %struct.__va_list_tag], align 16
765   store i32 %x, ptr %x.addr, align 4
766   call void @llvm.va_start(ptr %va)
767   ret void
770 ; CHECK-LABEL: @VAStart
771 ; CHECK: call void @llvm.va_start
772 ; CHECK-NOT: @__msan_va_arg_tls
773 ; CHECK-NOT: @__msan_va_arg_overflow_size_tls
774 ; CHECK: ret void
777 ; Test handling of volatile stores.
778 ; Check that MemorySanitizer does not add a check of the value being stored.
780 define void @VolatileStore(ptr nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
781 entry:
782   store volatile i32 %x, ptr %p, align 4
783   ret void
786 ; CHECK-LABEL: @VolatileStore
787 ; CHECK-NOT: @__msan_warning_with_origin
788 ; CHECK: ret void
791 ; Test that checks are omitted and returned value is always initialized if
792 ; sanitize_memory attribute is missing.
794 define i32 @NoSanitizeMemory(i32 %x) uwtable {
795 entry:
796   %tobool = icmp eq i32 %x, 0
797   br i1 %tobool, label %if.end, label %if.then
799 if.then:                                          ; preds = %entry
800   tail call void @bar()
801   br label %if.end
803 if.end:                                           ; preds = %entry, %if.then
804   ret i32 %x
807 declare void @bar()
809 ; CHECK-LABEL: @NoSanitizeMemory
810 ; CHECK-NOT: @__msan_warning_with_origin
811 ; CHECK: store i32 0, {{.*}} @__msan_retval_tls
812 ; CHECK-NOT: @__msan_warning_with_origin
813 ; CHECK: ret i32
816 ; Test that stack allocations are unpoisoned in functions missing
817 ; sanitize_memory attribute
819 define i32 @NoSanitizeMemoryAlloca() {
820 entry:
821   %p = alloca i32, align 4
822   %x = call i32 @NoSanitizeMemoryAllocaHelper(ptr %p)
823   ret i32 %x
826 declare i32 @NoSanitizeMemoryAllocaHelper(ptr %p)
828 ; CHECK-LABEL: @NoSanitizeMemoryAlloca
829 ; CHECK: call void @llvm.memset.p0.i64(ptr align 4 {{.*}}, i8 0, i64 4, i1 false)
830 ; CHECK: call i32 @NoSanitizeMemoryAllocaHelper(ptr
831 ; CHECK: ret i32
834 ; Test that undef is unpoisoned in functions missing
835 ; sanitize_memory attribute
837 define i32 @NoSanitizeMemoryUndef() {
838 entry:
839   %x = call i32 @NoSanitizeMemoryUndefHelper(i32 undef)
840   ret i32 %x
843 declare i32 @NoSanitizeMemoryUndefHelper(i32 %x)
845 ; CHECK-LABEL: @NoSanitizeMemoryUndef
846 ; CHECK: store i32 0, ptr @__msan_param_tls
847 ; CHECK: call i32 @NoSanitizeMemoryUndefHelper(i32 undef)
848 ; CHECK: ret i32
851 ; Test PHINode instrumentation in ignorelisted functions
853 define i32 @NoSanitizeMemoryPHI(i32 %x) {
854 entry:
855   %tobool = icmp ne i32 %x, 0
856   br i1 %tobool, label %cond.true, label %cond.false
858 cond.true:                                        ; preds = %entry
859   br label %cond.end
861 cond.false:                                       ; preds = %entry
862   br label %cond.end
864 cond.end:                                         ; preds = %cond.false, %cond.true
865   %cond = phi i32 [ undef, %cond.true ], [ undef, %cond.false ]
866   ret i32 %cond
869 ; CHECK: [[A:%.*]] = phi i32 [ undef, %cond.true ], [ undef, %cond.false ]
870 ; CHECK: store i32 0, ptr @__msan_retval_tls
871 ; CHECK: ret i32 [[A]]
874 ; Test that there are no __msan_param_origin_tls stores when
875 ; argument shadow is a compile-time zero constant (which is always the case
876 ; in functions missing sanitize_memory attribute).
878 define i32 @NoSanitizeMemoryParamTLS(ptr nocapture readonly %x) {
879 entry:
880   %0 = load i32, ptr %x, align 4
881   %call = tail call i32 @NoSanitizeMemoryParamTLSHelper(i32 %0)
882   ret i32 %call
885 declare i32 @NoSanitizeMemoryParamTLSHelper(i32 %x)
887 ; CHECK-LABEL: define i32 @NoSanitizeMemoryParamTLS(
888 ; CHECK-NOT: __msan_param_origin_tls
889 ; CHECK: ret i32
892 ; Test argument shadow alignment
894 define <2 x i64> @ArgumentShadowAlignment(i64 %a, <2 x i64> %b) sanitize_memory {
895 entry:
896   ret <2 x i64> %b
899 ; CHECK-LABEL: @ArgumentShadowAlignment
900 ; CHECK: load <2 x i64>, ptr {{.*}} @__msan_param_tls {{.*}}, align 8
901 ; CHECK: store <2 x i64> {{.*}}, ptr @__msan_retval_tls, align 8
902 ; CHECK: ret <2 x i64>
905 ; Test origin propagation for insertvalue
907 define { i64, i32 } @make_pair_64_32(i64 %x, i32 %y) sanitize_memory {
908 entry:
909   %a = insertvalue { i64, i32 } undef, i64 %x, 0
910   %b = insertvalue { i64, i32 } %a, i32 %y, 1
911   ret { i64, i32 } %b
914 ; ORIGINS: @make_pair_64_32
915 ; First element shadow
916 ; ORIGINS: insertvalue { i64, i32 } { i64 -1, i32 -1 }, i64 {{.*}}, 0
917 ; First element origin
918 ; ORIGINS: icmp ne i64
919 ; ORIGINS: select i1
920 ; First element app value
921 ; ORIGINS: insertvalue { i64, i32 } undef, i64 {{.*}}, 0
922 ; Second element shadow
923 ; ORIGINS: insertvalue { i64, i32 } {{.*}}, i32 {{.*}}, 1
924 ; Second element origin
925 ; ORIGINS: icmp ne i32
926 ; ORIGINS: select i1
927 ; Second element app value
928 ; ORIGINS: insertvalue { i64, i32 } {{.*}}, i32 {{.*}}, 1
929 ; ORIGINS: ret { i64, i32 }
932 ; Test shadow propagation for aggregates passed through ellipsis.
934 %struct.StructByVal = type { i32, i32, i32, i32 }
936 declare void @VAArgStructFn(i32 %guard, ...)
938 define void @VAArgStruct(ptr nocapture %s) sanitize_memory {
939 entry:
940   %agg.tmp2 = alloca %struct.StructByVal, align 8
941   %agg.tmp.sroa.0.0.copyload = load i64, ptr %s, align 4
942   %agg.tmp.sroa.2.0..sroa_idx = getelementptr inbounds %struct.StructByVal, ptr %s, i64 0, i32 2
943   %agg.tmp.sroa.2.0.copyload = load i64, ptr %agg.tmp.sroa.2.0..sroa_idx, align 4
944   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %s, i64 16, i1 false)
945   call void (i32, ...) @VAArgStructFn(i32 undef, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, ptr byval(%struct.StructByVal) align 8 %agg.tmp2)
946   ret void
949 ; "undef" and the first 2 structs go to general purpose registers;
950 ; the third struct goes to the overflow area byval
952 ; CHECK-LABEL: @VAArgStruct
953 ; undef not stored to __msan_va_arg_tls - it's a fixed argument
954 ; first struct through general purpose registers
955 ; CHECK: store i64 {{.*}}, ptr {{.*}}@__msan_va_arg_tls{{.*}}, i64 8){{.*}}, align 8
956 ; CHECK: store i64 {{.*}}, ptr {{.*}}@__msan_va_arg_tls{{.*}}, i64 16){{.*}}, align 8
957 ; second struct through general purpose registers
958 ; CHECK: store i64 {{.*}}, ptr {{.*}}@__msan_va_arg_tls{{.*}}, i64 24){{.*}}, align 8
959 ; CHECK: store i64 {{.*}}, ptr {{.*}}@__msan_va_arg_tls{{.*}}, i64 32){{.*}}, align 8
960 ; third struct through the overflow area byval
961 ; CHECK: ptrtoint ptr {{.*}} to i64
962 ; CHECK: call void @llvm.memcpy.p0.p0.i64{{.*}}@__msan_va_arg_tls {{.*}}, i64 176
963 ; CHECK: store i64 16, ptr @__msan_va_arg_overflow_size_tls
964 ; CHECK: call void (i32, ...) @VAArgStructFn
965 ; CHECK: ret void
967 ; Same code compiled without SSE (see attributes below).
968 ; The register save area is only 48 bytes instead of 176.
969 define void @VAArgStructNoSSE(ptr nocapture %s) sanitize_memory #0 {
970 entry:
971   %agg.tmp2 = alloca %struct.StructByVal, align 8
972   %agg.tmp.sroa.0.0.copyload = load i64, ptr %s, align 4
973   %agg.tmp.sroa.2.0..sroa_idx = getelementptr inbounds %struct.StructByVal, ptr %s, i64 0, i32 2
974   %agg.tmp.sroa.2.0.copyload = load i64, ptr %agg.tmp.sroa.2.0..sroa_idx, align 4
975   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %s, i64 16, i1 false)
976   call void (i32, ...) @VAArgStructFn(i32 undef, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, ptr byval(%struct.StructByVal) align 8 %agg.tmp2)
977   ret void
980 attributes #0 = { "target-features"="+fxsr,+x87,-sse" }
982 ; CHECK: call void @llvm.memcpy.p0.p0.i64{{.*}}@__msan_va_arg_tls {{.*}}, i64 48
984 declare i32 @InnerTailCall(i32 %a)
986 define void @MismatchedReturnTypeTailCall(i32 %a) sanitize_memory {
987   %b = tail call i32 @InnerTailCall(i32 %a)
988   ret void
991 ; We used to strip off the 'tail' modifier, but now that we unpoison return slot
992 ; shadow before the call, we don't need to anymore.
994 ; CHECK-LABEL: define void @MismatchedReturnTypeTailCall
995 ; CHECK: tail call i32 @InnerTailCall
996 ; CHECK: ret void
999 declare i32 @MustTailCall(i32 %a)
1001 define i32 @CallMustTailCall(i32 %a) sanitize_memory {
1002   %b = musttail call i32 @MustTailCall(i32 %a)
1003   ret i32 %b
1006 ; For "musttail" calls we can not insert any shadow manipulating code between
1007 ; call and the return instruction. And we don't need to, because everything is
1008 ; taken care of in the callee.
1010 ; CHECK-LABEL: define i32 @CallMustTailCall
1011 ; CHECK: musttail call i32 @MustTailCall
1012 ; No instrumentation between call and ret.
1013 ; CHECK-NEXT: ret i32
1015 declare ptr @MismatchingMustTailCall(i32 %a)
1017 define ptr @MismatchingCallMustTailCall(i32 %a) sanitize_memory {
1018   %b = musttail call ptr @MismatchingMustTailCall(i32 %a)
1019   ret ptr %b
1022 ; For "musttail" calls we can not insert any shadow manipulating code between
1023 ; call and the return instruction. And we don't need to, because everything is
1024 ; taken care of in the callee.
1026 ; CHECK-LABEL: define ptr @MismatchingCallMustTailCall
1027 ; CHECK: musttail call ptr @MismatchingMustTailCall
1028 ; No instrumentation between call and ret.
1029 ; CHECK-NEXT: ret ptr
1032 ; CHECK-LABEL: define internal void @msan.module_ctor() #[[#ATTR:]] {
1033 ; CHECK: call void @__msan_init()
1035 ; CHECK-CALLS: declare void @__msan_maybe_warning_1(i8, i32)
1036 ; CHECK-CALLS: declare void @__msan_maybe_store_origin_1(i8, ptr, i32)
1037 ; CHECK-CALLS: declare void @__msan_maybe_warning_2(i16, i32)
1038 ; CHECK-CALLS: declare void @__msan_maybe_store_origin_2(i16, ptr, i32)
1039 ; CHECK-CALLS: declare void @__msan_maybe_warning_4(i32, i32)
1040 ; CHECK-CALLS: declare void @__msan_maybe_store_origin_4(i32, ptr, i32)
1041 ; CHECK-CALLS: declare void @__msan_maybe_warning_8(i64, i32)
1042 ; CHECK-CALLS: declare void @__msan_maybe_store_origin_8(i64, ptr, i32)
1044 ; CHECK:       attributes #[[#ATTR]] = { nounwind }