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
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.
7 @G1 = internal global i32 undef
8 @G2 = internal global i32 undef
9 @G3 = internal global i32 undef
10 @G4 = internal global i32 undef
12 define 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:%.*]]
17 ; CHECK-NEXT: store i32 0, ptr @G1, align 4
18 ; CHECK-NEXT: br label [[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
26 br i1 %c, label %init, label %check
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)
38 define 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:%.*]]
43 ; CHECK-NEXT: store i32 0, ptr @G2, align 4
44 ; CHECK-NEXT: br label [[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
52 br i1 %c, label %init, label %check
58 %v = load i32, ptr @G2
59 %cmp = icmp eq i32 %v, 0
60 call void @llvm.assume(i1 %cmp)
64 define 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:%.*]]
69 ; CHECK-NEXT: store i32 0, ptr @G3, align 4
70 ; CHECK-NEXT: br label [[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
78 br i1 %c, label %init, label %check
84 %v = load i32, ptr @G3
85 %cmp = icmp eq i32 %v, 0
86 call void @llvm.assume(i1 %cmp)
90 define 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
99 ; Here hoisting is legal and we use it to verify it will happen.
100 define 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:%.*]]
108 ; CHECK-NEXT: store i32 0, ptr @G4, align 4
109 ; CHECK-NEXT: br label [[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
117 br i1 %c, label %init, label %check
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)
129 declare void @unknown()
130 declare void @unknown_nosync_nocallback() nosync nocallback
131 declare void @llvm.amdgcn.s.barrier()
132 declare void @llvm.assume(i1 noundef)