1; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
2target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
3
4@G1 = external global i32
5
6declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1)
7declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1)
8declare void @llvm.experimental.deoptimize.void(...)
9declare void @unknown_but_readonly() readonly
10
11define void @test1(i8* %p) {
12  call void(...) @llvm.experimental.deoptimize.void() [ "deopt"() ]
13  ret void
14
15; CHECK-LABEL: Function: test1:
16; CHECK:  Just Ref: Ptr: i8* %p <-> call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
17}
18
19; By specification calls with deopt bundles reads through all operands and entire heap.
20; Check that global G1 is reported as Ref by memcpy/memmove calls.
21define i32 @test_memcpy_with_deopt() {
22; CHECK-LABEL: Function: test_memcpy_with_deopt:
23; CHECK: Just Mod:  Ptr: i8* %A	<->  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
24; CHECK: Just Ref:  Ptr: i8* %B	<->  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
25; CHECK: Just Ref:  Ptr: i32* @G1	<->  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
26
27  %A = alloca i8
28  %B = alloca i8
29
30  store i32 2, i32* @G1  ;; Not referenced by semantics of memcpy but still may be read due to "deopt"
31
32  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
33
34  %C = load i32, i32* @G1
35  ret i32 %C
36}
37
38define i32 @test_memmove_with_deopt() {
39; CHECK-LABEL: Function: test_memmove_with_deopt:
40; CHECK: Just Mod:  Ptr: i8* %A	<->  call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
41; CHECK: Just Ref:  Ptr: i8* %B	<->  call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
42; CHECK: Just Ref:  Ptr: i32* @G1	<->  call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
43
44  %A = alloca i8
45  %B = alloca i8
46
47  store i32 2, i32* @G1  ;; Not referenced by semantics of memcpy but still may be read due to "deopt"
48
49  call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
50
51  %C = load i32, i32* @G1
52  ret i32 %C
53}
54