xref: /llvm-project/llvm/test/Transforms/GVN/captured-before.ll (revision 383e35048e16c85ab26bc46822d3ceb11fd4d3f2)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
2; RUN: opt -S -passes=gvn < %s | FileCheck %s
3
4declare void @capture(ptr)
5declare void @some_call()
6
7define i32 @test_call_before_capture(ptr %p) {
8; CHECK-LABEL: define i32 @test_call_before_capture(
9; CHECK-SAME: ptr [[P:%.*]]) {
10; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
11; CHECK-NEXT:    store i32 123, ptr [[A]], align 4
12; CHECK-NEXT:    call void @some_call()
13; CHECK-NEXT:    call void @capture(ptr [[A]])
14; CHECK-NEXT:    ret i32 123
15;
16  %a = alloca i32
17  store i32 123, ptr %a
18  call void @some_call()
19  %v = load i32, ptr %a
20  call void @capture(ptr %a)
21  ret i32 %v
22}
23
24define i32 @test_call_after_capture(ptr %p) {
25; CHECK-LABEL: define i32 @test_call_after_capture(
26; CHECK-SAME: ptr [[P:%.*]]) {
27; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
28; CHECK-NEXT:    store i32 123, ptr [[A]], align 4
29; CHECK-NEXT:    call void @capture(ptr [[A]])
30; CHECK-NEXT:    call void @some_call()
31; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[A]], align 4
32; CHECK-NEXT:    ret i32 [[V]]
33;
34  %a = alloca i32
35  store i32 123, ptr %a
36  call void @capture(ptr %a)
37  call void @some_call()
38  %v = load i32, ptr %a
39  ret i32 %v
40}
41
42define i32 @test_store_before_capture(ptr %p) {
43; CHECK-LABEL: define i32 @test_store_before_capture(
44; CHECK-SAME: ptr [[P:%.*]]) {
45; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
46; CHECK-NEXT:    store i32 123, ptr [[A]], align 4
47; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P]], align 8
48; CHECK-NEXT:    store i32 42, ptr [[P2]], align 4
49; CHECK-NEXT:    call void @capture(ptr [[A]])
50; CHECK-NEXT:    ret i32 123
51;
52  %a = alloca i32
53  store i32 123, ptr %a
54  %p2 = load ptr, ptr %p
55  store i32 42, ptr %p2
56  %v = load i32, ptr %a
57  call void @capture(ptr %a)
58  ret i32 %v
59}
60
61define i32 @test_store_after_capture(ptr %p) {
62; CHECK-LABEL: define i32 @test_store_after_capture(
63; CHECK-SAME: ptr [[P:%.*]]) {
64; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
65; CHECK-NEXT:    store i32 123, ptr [[A]], align 4
66; CHECK-NEXT:    call void @capture(ptr [[A]])
67; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P]], align 8
68; CHECK-NEXT:    store i32 42, ptr [[P2]], align 4
69; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[A]], align 4
70; CHECK-NEXT:    ret i32 [[V]]
71;
72  %a = alloca i32
73  store i32 123, ptr %a
74  call void @capture(ptr %a)
75  %p2 = load ptr, ptr %p
76  store i32 42, ptr %p2
77  %v = load i32, ptr %a
78  ret i32 %v
79}
80
81define i32 @test_capture_readonly() {
82; CHECK-LABEL: define i32 @test_capture_readonly() {
83; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
84; CHECK-NEXT:    store i32 123, ptr [[A]], align 4
85; CHECK-NEXT:    call void @capture(ptr readonly [[A]])
86; CHECK-NEXT:    ret i32 123
87;
88  %a = alloca i32
89  store i32 123, ptr %a
90  call void @capture(ptr readonly %a)
91  %v = load i32, ptr %a
92  ret i32 %v
93}
94
95define i32 @test_capture_readonly_with_following_call() {
96; CHECK-LABEL: define i32 @test_capture_readonly_with_following_call() {
97; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
98; CHECK-NEXT:    store i32 123, ptr [[A]], align 4
99; CHECK-NEXT:    call void @capture(ptr readonly [[A]])
100; CHECK-NEXT:    call void @some_call()
101; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[A]], align 4
102; CHECK-NEXT:    ret i32 [[V]]
103;
104  %a = alloca i32
105  store i32 123, ptr %a
106  call void @capture(ptr readonly %a)
107  call void @some_call()
108  %v = load i32, ptr %a
109  ret i32 %v
110}
111
112declare void @use(i32)
113
114define i32 @test_capture_readonly_in_loop() {
115; CHECK-LABEL: define i32 @test_capture_readonly_in_loop() {
116; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
117; CHECK-NEXT:    store i32 123, ptr [[A]], align 4
118; CHECK-NEXT:    br label [[LOOP:%.*]]
119; CHECK:       loop:
120; CHECK-NEXT:    call void @capture(ptr readonly [[A]])
121; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[A]], align 4
122; CHECK-NEXT:    call void @use(i32 [[V]]) #[[ATTR0:[0-9]+]]
123; CHECK-NEXT:    br label [[LOOP]]
124;
125  %a = alloca i32
126  store i32 123, ptr %a
127  br label %loop
128
129loop:
130  call void @capture(ptr readonly %a)
131  %v = load i32, ptr %a
132  call void @use(i32 %v) memory(none)
133  br label %loop
134}
135
136define i32 @test_splat_gep_capture(<1 x i32> %index) {
137; CHECK-LABEL: define i32 @test_splat_gep_capture(
138; CHECK-SAME: <1 x i32> [[INDEX:%.*]]) {
139; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
140; CHECK-NEXT:    store i32 123, ptr [[A]], align 4
141; CHECK-NEXT:    [[PTRS:%.*]] = getelementptr inbounds i32, ptr [[A]], <1 x i32> [[INDEX]]
142; CHECK-NEXT:    call void @some_call(<1 x ptr> [[PTRS]])
143; CHECK-NEXT:    [[RELOAD:%.*]] = load i32, ptr [[A]], align 4
144; CHECK-NEXT:    ret i32 [[RELOAD]]
145;
146  %a = alloca i32
147  store i32 123, ptr %a
148  %ptrs = getelementptr inbounds i32, ptr %a, <1 x i32> %index
149  call void @some_call(<1 x ptr> %ptrs)
150  %reload = load i32, ptr %a
151  ret i32 %reload
152}
153