aboutsummaryrefslogtreecommitdiff
path: root/llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll
blob: 24ad14be42bee56de0db9833cfeeb4b0618fcf82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
; RUN: opt < %s -aa-pipeline=basic-aa,globals-aa -passes='require<globals-aa>,gvn' -S | FileCheck %s
;
; This tests the safe no-alias conclusions of GMR -- when there is
; a non-escaping global as one indentified underlying object and some pointer
; that would inherently have escaped any other function as the other underlying
; pointer of an alias query.

@g1 = internal global i32 0

define i32 @test1(ptr %param) {
; Ensure that we can fold a store to a load of a global across a store to
; a parameter when the global is non-escaping.
;
; CHECK-LABEL: @test1(
; CHECK: store i32 42, ptr @g1
; CHECK-NOT: load i32
; CHECK: ret i32 42
entry:
  store i32 42, ptr @g1
  store i32 7, ptr %param
  %v = load i32, ptr @g1
  ret i32 %v
}

@g1_tls = internal thread_local global i32 0

define i32 @test1_tls(ptr %param) {
; Ensure that we can fold a store to a load of a global across a store to
; a parameter when the global is non-escaping.
;
; CHECK-LABEL: define i32 @test1_tls(
; CHECK-SAME: ptr [[PARAM:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[P:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @g1_tls)
; CHECK-NEXT:    store i32 42, ptr [[P]], align 4
; CHECK-NEXT:    store i32 7, ptr [[PARAM]], align 4
; CHECK-NEXT:    ret i32 42
;
entry:
  %p = call ptr @llvm.threadlocal.address(ptr @g1_tls)
  store i32 42, ptr %p
  store i32 7, ptr %param
  %p2 = call ptr @llvm.threadlocal.address(ptr @g1_tls)
  %v = load i32, ptr %p2
  ret i32 %v
}

define ptr @test1_tls_noopt(ptr %coro, ptr %param) presplitcoroutine {
; CHECK-LABEL: define ptr @test1_tls_noopt(
; CHECK-SAME: ptr [[CORO:%.*]], ptr [[PARAM:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[P:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @g1_tls)
; CHECK-NEXT:    store i32 42, ptr [[P]], align 4
; CHECK-NEXT:    [[TMP0:%.*]] = call i8 @llvm.coro.suspend(token none, i1 false)
; CHECK-NEXT:    switch i8 [[TMP0]], label [[SUSPEND:%.*]] [
; CHECK-NEXT:      i8 0, label [[RESUME:%.*]]
; CHECK-NEXT:      i8 1, label [[SUSPEND]]
; CHECK-NEXT:    ]
; CHECK:       resume:
; CHECK-NEXT:    [[P2:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @g1_tls)
; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P2]], align 4
; CHECK-NEXT:    store i32 [[V]], ptr [[PARAM]], align 4
; CHECK-NEXT:    ret ptr [[CORO]]
; CHECK:       suspend:
; CHECK-NEXT:    [[TMP1:%.*]] = call i1 @llvm.coro.end(ptr [[CORO]], i1 false, token none)
; CHECK-NEXT:    ret ptr [[CORO]]
;
entry:
  %p = call ptr @llvm.threadlocal.address(ptr @g1_tls)
  store i32 42, ptr %p

  %0 = call i8 @llvm.coro.suspend(token none, i1 false)
  switch i8 %0, label %suspend [i8 0, label %resume
  i8 1, label %suspend]
resume:
  %p2 = call ptr @llvm.threadlocal.address(ptr @g1_tls)
  %v = load i32, ptr %p2
  store i32 %v, ptr %param, align 4
  ret ptr %coro

suspend:
  call i1 @llvm.coro.end(ptr %coro, i1 0)
  ret ptr %coro
}

declare ptr @f()

define i32 @test2() {
; Ensure that we can fold a store to a load of a global across a store to
; the pointer returned by a function call. Since the global could not escape,
; this function cannot be returning its address.
;
; CHECK-LABEL: @test2(
; CHECK: store i32 42, ptr @g1
; CHECK-NOT: load i32
; CHECK: ret i32 42
entry:
  %ptr = call ptr @f() readnone
  store i32 42, ptr @g1
  store i32 7, ptr %ptr
  %v = load i32, ptr @g1
  ret i32 %v
}

@g2 = external global ptr

define i32 @test3() {
; Ensure that we can fold a store to a load of a global across a store to
; the pointer loaded from that global. Because the global does not escape, it
; cannot alias a pointer loaded out of a global.
;
; CHECK-LABEL: @test3(
; CHECK: store i32 42, ptr @g1
; CHECK: store i32 7, ptr
; CHECK-NOT: load i32
; CHECK: ret i32 42
entry:
  store i32 42, ptr @g1
  %ptr1 = load ptr, ptr @g2
  store i32 7, ptr %ptr1
  %v = load i32, ptr @g1
  ret i32 %v
}

@g3 = internal global i32 1
@g4 = internal global [10 x ptr] zeroinitializer

define i32 @test4(ptr %param, i32 %n, i1 %c1, i1 %c2, i1 %c3) {
; Ensure that we can fold a store to a load of a global across a store to
; the pointer loaded from that global even when the load is behind PHIs and
; selects, and there is a mixture of a load and another global or argument.
; Note that we can't eliminate the load here because it is used in a PHI and
; GVN doesn't try to do real DCE. The store is still forwarded by GVN though.
;
; CHECK-LABEL: @test4(
; CHECK: store i32 42, ptr @g1
; CHECK: store i32 7, ptr
; CHECK: ret i32 42
entry:
  %call = call ptr @f()
  store i32 42, ptr @g1
  %ptr1 = load ptr, ptr @g2
  %ptr2 = select i1 %c1, ptr %ptr1, ptr %param
  %ptr3 = select i1 %c3, ptr %ptr2, ptr @g3
  br label %loop

loop:
  %iv = phi i32 [ 0, %entry ], [ %inc, %loop ]
  %ptr = phi ptr [ %ptr3, %entry ], [ %ptr5, %loop ]
  store i32 7, ptr %ptr
  %ptr4 = load ptr, ptr getelementptr ([10 x ptr], ptr @g4, i32 0, i32 1)
  %ptr5 = select i1 %c2, ptr %ptr4, ptr %call
  %inc = add i32 %iv, 1
  %test = icmp slt i32 %inc, %n
  br i1 %test, label %loop, label %exit

exit:
  %v = load i32, ptr @g1
  ret i32 %v
}

define i32 @test5(ptr %param) {
; Ensure that we can fold a store to a load of a global across a store to
; a parameter that has been dereferenced when the global is non-escaping.
;
; CHECK-LABEL: @test5(
; CHECK: %p = load ptr
; CHECK: store i32 42, ptr @g1
; CHECK-NOT: load i32
; CHECK: ret i32 42
entry:
  %p = load ptr, ptr %param
  store i32 42, ptr @g1
  store i32 7, ptr %p
  %v = load i32, ptr @g1
  ret i32 %v
}