xref: /llvm-project/llvm/test/Analysis/GlobalsModRef/nosync_nocallback.ll (revision 9dc7da3f9cb48ed7ba6c4806f4519d997f6671b5)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
2; RUN: opt -aa-pipeline=basic-aa,globals-aa -passes='require<globals-aa>,gvn' -S < %s | FileCheck %s
3
4; Make sure we do not hoist the load before the intrinsic, unknown function, or
5; optnone function except if we know the unknown function is nosync and nocallback.
6
7@G1 = internal global i32 undef
8@G2 = internal global i32 undef
9@G3 = internal global i32 undef
10@G4 = internal global i32 undef
11
12define void @test_barrier(i1 %c) {
13; CHECK-LABEL: define {{[^@]+}}@test_barrier
14; CHECK-SAME: (i1 [[C:%.*]]) {
15; CHECK-NEXT:    br i1 [[C]], label [[INIT:%.*]], label [[CHECK:%.*]]
16; CHECK:       init:
17; CHECK-NEXT:    store i32 0, ptr @G1, align 4
18; CHECK-NEXT:    br label [[CHECK]]
19; CHECK:       check:
20; CHECK-NEXT:    call void @llvm.amdgcn.s.barrier()
21; CHECK-NEXT:    [[V:%.*]] = load i32, ptr @G1, align 4
22; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[V]], 0
23; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
24; CHECK-NEXT:    ret void
25;
26  br i1 %c, label %init, label %check
27init:
28  store i32 0, ptr @G1
29  br label %check
30check:
31  call void @llvm.amdgcn.s.barrier()
32  %v = load i32, ptr @G1
33  %cmp = icmp eq i32 %v, 0
34  call void @llvm.assume(i1 %cmp)
35  ret void
36}
37
38define void @test_unknown(i1 %c) {
39; CHECK-LABEL: define {{[^@]+}}@test_unknown
40; CHECK-SAME: (i1 [[C:%.*]]) {
41; CHECK-NEXT:    br i1 [[C]], label [[INIT:%.*]], label [[CHECK:%.*]]
42; CHECK:       init:
43; CHECK-NEXT:    store i32 0, ptr @G2, align 4
44; CHECK-NEXT:    br label [[CHECK]]
45; CHECK:       check:
46; CHECK-NEXT:    call void @unknown()
47; CHECK-NEXT:    [[V:%.*]] = load i32, ptr @G2, align 4
48; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[V]], 0
49; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
50; CHECK-NEXT:    ret void
51;
52  br i1 %c, label %init, label %check
53init:
54  store i32 0, ptr @G2
55  br label %check
56check:
57  call void @unknown()
58  %v = load i32, ptr @G2
59  %cmp = icmp eq i32 %v, 0
60  call void @llvm.assume(i1 %cmp)
61  ret void
62}
63
64define void @test_optnone(i1 %c) {
65; CHECK-LABEL: define {{[^@]+}}@test_optnone
66; CHECK-SAME: (i1 [[C:%.*]]) {
67; CHECK-NEXT:    br i1 [[C]], label [[INIT:%.*]], label [[CHECK:%.*]]
68; CHECK:       init:
69; CHECK-NEXT:    store i32 0, ptr @G3, align 4
70; CHECK-NEXT:    br label [[CHECK]]
71; CHECK:       check:
72; CHECK-NEXT:    call void @optnone()
73; CHECK-NEXT:    [[V:%.*]] = load i32, ptr @G3, align 4
74; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[V]], 0
75; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
76; CHECK-NEXT:    ret void
77;
78  br i1 %c, label %init, label %check
79init:
80  store i32 0, ptr @G3
81  br label %check
82check:
83  call void @optnone()
84  %v = load i32, ptr @G3
85  %cmp = icmp eq i32 %v, 0
86  call void @llvm.assume(i1 %cmp)
87  ret void
88}
89
90define void @optnone() optnone nosync nocallback noinline {
91; CHECK: Function Attrs: nocallback noinline nosync optnone
92; CHECK-LABEL: define {{[^@]+}}@optnone
93; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
94; CHECK-NEXT:    ret void
95;
96  ret void
97}
98
99; Here hoisting is legal and we use it to verify it will happen.
100define void @test_unknown_annotated(i1 %c) {
101; CHECK-LABEL: define {{[^@]+}}@test_unknown_annotated
102; CHECK-SAME: (i1 [[C:%.*]]) {
103; CHECK-NEXT:    br i1 [[C]], label [[INIT:%.*]], label [[DOTCHECK_CRIT_EDGE:%.*]]
104; CHECK:       .check_crit_edge:
105; CHECK-NEXT:    [[V_PRE:%.*]] = load i32, ptr @G4, align 4
106; CHECK-NEXT:    br label [[CHECK:%.*]]
107; CHECK:       init:
108; CHECK-NEXT:    store i32 0, ptr @G4, align 4
109; CHECK-NEXT:    br label [[CHECK]]
110; CHECK:       check:
111; CHECK-NEXT:    [[V:%.*]] = phi i32 [ [[V_PRE]], [[DOTCHECK_CRIT_EDGE]] ], [ 0, [[INIT]] ]
112; CHECK-NEXT:    call void @unknown_nosync_nocallback()
113; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[V]], 0
114; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
115; CHECK-NEXT:    ret void
116;
117  br i1 %c, label %init, label %check
118init:
119  store i32 0, ptr @G4
120  br label %check
121check:
122  call void @unknown_nosync_nocallback()
123  %v = load i32, ptr @G4
124  %cmp = icmp eq i32 %v, 0
125  call void @llvm.assume(i1 %cmp)
126  ret void
127}
128
129declare void @unknown()
130declare void @unknown_nosync_nocallback() nosync nocallback
131declare void @llvm.amdgcn.s.barrier()
132declare void @llvm.assume(i1 noundef)
133
134