xref: /llvm-project/llvm/test/Transforms/LICM/AMDGPU/buffer-rsrc-ptrs.ll (revision 23098bd4542e76b897696f1d542a26caa5c25020)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt < %s -aa-pipeline=basic-aa,scoped-noalias-aa -passes=licm -S | FileCheck %s
3
4target triple = "amdgcn-amd-amdhsa"
5
6define void @hoistable_noalias(ptr addrspace(8) noalias %p, ptr addrspace(8) noalias %q, i32 %bound) {
7; CHECK-LABEL: define void @hoistable_noalias
8; CHECK-SAME: (ptr addrspace(8) noalias [[P:%.*]], ptr addrspace(8) noalias [[Q:%.*]], i32 [[BOUND:%.*]]) {
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    [[HOISTABLE:%.*]] = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) [[Q]], i32 0, i32 0, i32 0, i32 0)
11; CHECK-NEXT:    br label [[LOOP:%.*]]
12; CHECK:       loop:
13; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
14; CHECK-NEXT:    [[ORIG:%.*]] = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0)
15; CHECK-NEXT:    [[INC:%.*]] = add i32 [[HOISTABLE]], [[ORIG]]
16; CHECK-NEXT:    call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 [[INC]], ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0)
17; CHECK-NEXT:    [[NEXT]] = add i32 [[I]], 1
18; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[NEXT]], [[BOUND]]
19; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[TAIL:%.*]]
20; CHECK:       tail:
21; CHECK-NEXT:    ret void
22;
23entry:
24  br label %loop
25loop:
26  %i = phi i32 [0, %entry], [%next, %loop]
27
28  %hoistable = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) %q, i32 0, i32 0, i32 0, i32 0)
29  %orig = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) %p, i32 %i, i32 0, i32 0)
30  %inc = add i32 %hoistable, %orig
31  call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 %inc, ptr addrspace(8) %p, i32 %i, i32 0, i32 0)
32
33  %next = add i32 %i, 1
34  %cond = icmp ult i32 %next, %bound
35  br i1 %cond, label %loop, label %tail
36tail:
37  ret void
38}
39
40define void @not_hoistable_may_alias(ptr addrspace(8) %p, ptr addrspace(8) %q, i32 %bound) {
41; CHECK-LABEL: define void @not_hoistable_may_alias
42; CHECK-SAME: (ptr addrspace(8) [[P:%.*]], ptr addrspace(8) [[Q:%.*]], i32 [[BOUND:%.*]]) {
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    br label [[LOOP:%.*]]
45; CHECK:       loop:
46; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
47; CHECK-NEXT:    [[NOT_HOISTABLE:%.*]] = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) [[Q]], i32 0, i32 0, i32 0, i32 0)
48; CHECK-NEXT:    [[ORIG:%.*]] = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0)
49; CHECK-NEXT:    [[INC:%.*]] = add i32 [[NOT_HOISTABLE]], [[ORIG]]
50; CHECK-NEXT:    call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 [[INC]], ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0)
51; CHECK-NEXT:    [[NEXT]] = add i32 [[I]], 1
52; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[NEXT]], [[BOUND]]
53; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[TAIL:%.*]]
54; CHECK:       tail:
55; CHECK-NEXT:    ret void
56;
57entry:
58  br label %loop
59loop:
60  %i = phi i32 [0, %entry], [%next, %loop]
61
62  %not.hoistable = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) %q, i32 0, i32 0, i32 0, i32 0)
63  %orig = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) %p, i32 %i, i32 0, i32 0)
64  %inc = add i32 %not.hoistable, %orig
65  call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 %inc, ptr addrspace(8) %p, i32 %i, i32 0, i32 0)
66
67  %next = add i32 %i, 1
68  %cond = icmp ult i32 %next, %bound
69  br i1 %cond, label %loop, label %tail
70tail:
71  ret void
72}
73
74define void @hoistable_alias_scope(ptr addrspace(8) %p, ptr addrspace(8) %q, i32 %bound) {
75; CHECK-LABEL: define void @hoistable_alias_scope
76; CHECK-SAME: (ptr addrspace(8) [[P:%.*]], ptr addrspace(8) [[Q:%.*]], i32 [[BOUND:%.*]]) {
77; CHECK-NEXT:  entry:
78; CHECK-NEXT:    [[HOISTABLE:%.*]] = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) [[Q]], i32 0, i32 0, i32 0, i32 0), !alias.scope !0, !noalias !3
79; CHECK-NEXT:    br label [[LOOP:%.*]]
80; CHECK:       loop:
81; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
82; CHECK-NEXT:    [[ORIG:%.*]] = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0), !alias.scope !3, !noalias !0
83; CHECK-NEXT:    [[INC:%.*]] = add i32 [[HOISTABLE]], [[ORIG]]
84; CHECK-NEXT:    call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 [[INC]], ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0), !alias.scope !3, !noalias !0
85; CHECK-NEXT:    [[NEXT]] = add i32 [[I]], 1
86; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[NEXT]], [[BOUND]]
87; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[TAIL:%.*]]
88; CHECK:       tail:
89; CHECK-NEXT:    ret void
90;
91entry:
92  br label %loop
93loop:
94  %i = phi i32 [0, %entry], [%next, %loop]
95
96  %hoistable = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) %q, i32 0, i32 0, i32 0, i32 0), !alias.scope !4, !noalias !3
97  %orig = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) %p, i32 %i, i32 0, i32 0), !alias.scope !3, !noalias !4
98  %inc = add i32 %hoistable, %orig
99  call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 %inc, ptr addrspace(8) %p, i32 %i, i32 0, i32 0), !alias.scope !3, !noalias !4
100
101  %next = add i32 %i, 1
102  %cond = icmp ult i32 %next, %bound
103  br i1 %cond, label %loop, label %tail
104tail:
105  ret void
106}
107!0 = !{!0, !"hoisting"}
108!1 = !{!1, !0, !"p"}
109!2 = !{!2, !0, !"q"}
110
111!3 = !{!1}
112!4 = !{!2}
113
114define void @not_hoistable_buffer_construction(ptr addrspace(1) noalias %p.global, ptr addrspace(1) noalias %q.global, i32 %bound) {
115; CHECK-LABEL: define void @not_hoistable_buffer_construction
116; CHECK-SAME: (ptr addrspace(1) noalias [[P_GLOBAL:%.*]], ptr addrspace(1) noalias [[Q_GLOBAL:%.*]], i32 [[BOUND:%.*]]) {
117; CHECK-NEXT:  entry:
118; CHECK-NEXT:    [[P_GLOBAL_INT:%.*]] = ptrtoint ptr addrspace(1) [[P_GLOBAL]] to i64
119; CHECK-NEXT:    [[Q_GLOBAL_INT:%.*]] = ptrtoint ptr addrspace(1) [[Q_GLOBAL]] to i64
120; CHECK-NEXT:    [[P_TRUNC:%.*]] = trunc i64 [[P_GLOBAL_INT]] to i48
121; CHECK-NEXT:    [[Q_TRUNC:%.*]] = trunc i64 [[Q_GLOBAL_INT]] to i48
122; CHECK-NEXT:    [[P_EXT:%.*]] = zext i48 [[P_TRUNC]] to i128
123; CHECK-NEXT:    [[Q_EXT:%.*]] = zext i48 [[Q_TRUNC]] to i128
124; CHECK-NEXT:    [[P:%.*]] = inttoptr i128 [[P_EXT]] to ptr addrspace(8)
125; CHECK-NEXT:    [[Q:%.*]] = inttoptr i128 [[Q_EXT]] to ptr addrspace(8)
126; CHECK-NEXT:    br label [[LOOP:%.*]]
127; CHECK:       loop:
128; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
129; CHECK-NEXT:    [[NOT_HOISTABLE:%.*]] = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) [[Q]], i32 0, i32 0, i32 0, i32 0)
130; CHECK-NEXT:    [[ORIG:%.*]] = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0)
131; CHECK-NEXT:    [[INC:%.*]] = add i32 [[NOT_HOISTABLE]], [[ORIG]]
132; CHECK-NEXT:    call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 [[INC]], ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0)
133; CHECK-NEXT:    [[NEXT]] = add i32 [[I]], 1
134; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[NEXT]], [[BOUND]]
135; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[TAIL:%.*]]
136; CHECK:       tail:
137; CHECK-NEXT:    ret void
138;
139entry:
140  %p.global.int = ptrtoint ptr addrspace(1) %p.global to i64
141  %q.global.int = ptrtoint ptr addrspace(1) %q.global to i64
142  %p.trunc = trunc i64 %p.global.int to i48
143  %q.trunc = trunc i64 %q.global.int to i48
144  %p.ext = zext i48 %p.trunc to i128
145  %q.ext = zext i48 %q.trunc to i128
146  %p = inttoptr i128 %p.ext to ptr addrspace(8)
147  %q = inttoptr i128 %q.ext to ptr addrspace(8)
148  br label %loop
149loop:
150  %i = phi i32 [0, %entry], [%next, %loop]
151
152  %not.hoistable = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) %q, i32 0, i32 0, i32 0, i32 0)
153  %orig = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) %p, i32 %i, i32 0, i32 0)
154  %inc = add i32 %not.hoistable, %orig
155  call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 %inc, ptr addrspace(8) %p, i32 %i, i32 0, i32 0)
156
157  %next = add i32 %i, 1
158  %cond = icmp ult i32 %next, %bound
159  br i1 %cond, label %loop, label %tail
160tail:
161  ret void
162}
163
164define void @hoistable_buffer_construction_intrinsic(ptr addrspace(1) noalias %p.global, ptr addrspace(1) noalias %q.global, i32 %bound) {
165; CHECK-LABEL: define void @hoistable_buffer_construction_intrinsic
166; CHECK-SAME: (ptr addrspace(1) noalias [[P_GLOBAL:%.*]], ptr addrspace(1) noalias [[Q_GLOBAL:%.*]], i32 [[BOUND:%.*]]) {
167; CHECK-NEXT:  entry:
168; CHECK-NEXT:    [[P:%.*]] = call ptr addrspace(8) @llvm.amdgcn.make.buffer.rsrc.p1(ptr addrspace(1) [[P_GLOBAL]], i16 0, i32 0, i32 0)
169; CHECK-NEXT:    [[Q:%.*]] = call ptr addrspace(8) @llvm.amdgcn.make.buffer.rsrc.p1(ptr addrspace(1) [[Q_GLOBAL]], i16 0, i32 0, i32 0)
170; CHECK-NEXT:    [[HOISTABLE:%.*]] = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) [[Q]], i32 0, i32 0, i32 0, i32 0)
171; CHECK-NEXT:    br label [[LOOP:%.*]]
172; CHECK:       loop:
173; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
174; CHECK-NEXT:    [[ORIG:%.*]] = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0)
175; CHECK-NEXT:    [[INC:%.*]] = add i32 [[HOISTABLE]], [[ORIG]]
176; CHECK-NEXT:    call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 [[INC]], ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0)
177; CHECK-NEXT:    [[NEXT]] = add i32 [[I]], 1
178; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[NEXT]], [[BOUND]]
179; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[TAIL:%.*]]
180; CHECK:       tail:
181; CHECK-NEXT:    ret void
182;
183entry:
184  %p = call ptr addrspace(8) @llvm.amdgcn.make.buffer.rsrc.p1(ptr addrspace(1) %p.global, i16 0, i32 0, i32 0)
185  %q = call ptr addrspace(8) @llvm.amdgcn.make.buffer.rsrc.p1(ptr addrspace(1) %q.global, i16 0, i32 0, i32 0)
186  br label %loop
187loop:
188  %i = phi i32 [0, %entry], [%next, %loop]
189
190  %hoistable = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) %q, i32 0, i32 0, i32 0, i32 0)
191  %orig = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) %p, i32 %i, i32 0, i32 0)
192  %inc = add i32 %hoistable, %orig
193  call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 %inc, ptr addrspace(8) %p, i32 %i, i32 0, i32 0)
194
195  %next = add i32 %i, 1
196  %cond = icmp ult i32 %next, %bound
197  br i1 %cond, label %loop, label %tail
198tail:
199  ret void
200}
201
202
203define void @hoistable_buffer_construction_alias_scope(ptr addrspace(1) %p.global, ptr addrspace(1) %q.global, i32 %bound) {
204; CHECK-LABEL: define void @hoistable_buffer_construction_alias_scope
205; CHECK-SAME: (ptr addrspace(1) [[P_GLOBAL:%.*]], ptr addrspace(1) [[Q_GLOBAL:%.*]], i32 [[BOUND:%.*]]) {
206; CHECK-NEXT:  entry:
207; CHECK-NEXT:    [[P_GLOBAL_INT:%.*]] = ptrtoint ptr addrspace(1) [[P_GLOBAL]] to i64
208; CHECK-NEXT:    [[Q_GLOBAL_INT:%.*]] = ptrtoint ptr addrspace(1) [[Q_GLOBAL]] to i64
209; CHECK-NEXT:    [[P_TRUNC:%.*]] = trunc i64 [[P_GLOBAL_INT]] to i48
210; CHECK-NEXT:    [[Q_TRUNC:%.*]] = trunc i64 [[Q_GLOBAL_INT]] to i48
211; CHECK-NEXT:    [[P_EXT:%.*]] = zext i48 [[P_TRUNC]] to i128
212; CHECK-NEXT:    [[Q_EXT:%.*]] = zext i48 [[Q_TRUNC]] to i128
213; CHECK-NEXT:    [[P:%.*]] = inttoptr i128 [[P_EXT]] to ptr addrspace(8)
214; CHECK-NEXT:    [[Q:%.*]] = inttoptr i128 [[Q_EXT]] to ptr addrspace(8)
215; CHECK-NEXT:    [[HOISTABLE:%.*]] = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) [[Q]], i32 0, i32 0, i32 0, i32 0), !alias.scope !0, !noalias !3
216; CHECK-NEXT:    br label [[LOOP:%.*]]
217; CHECK:       loop:
218; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
219; CHECK-NEXT:    [[ORIG:%.*]] = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0), !alias.scope !3, !noalias !0
220; CHECK-NEXT:    [[INC:%.*]] = add i32 [[HOISTABLE]], [[ORIG]]
221; CHECK-NEXT:    call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 [[INC]], ptr addrspace(8) [[P]], i32 [[I]], i32 0, i32 0), !alias.scope !3, !noalias !0
222; CHECK-NEXT:    [[NEXT]] = add i32 [[I]], 1
223; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[NEXT]], [[BOUND]]
224; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[TAIL:%.*]]
225; CHECK:       tail:
226; CHECK-NEXT:    ret void
227;
228entry:
229  %p.global.int = ptrtoint ptr addrspace(1) %p.global to i64
230  %q.global.int = ptrtoint ptr addrspace(1) %q.global to i64
231  %p.trunc = trunc i64 %p.global.int to i48
232  %q.trunc = trunc i64 %q.global.int to i48
233  %p.ext = zext i48 %p.trunc to i128
234  %q.ext = zext i48 %q.trunc to i128
235  %p = inttoptr i128 %p.ext to ptr addrspace(8)
236  %q = inttoptr i128 %q.ext to ptr addrspace(8)
237  br label %loop
238loop:
239  %i = phi i32 [0, %entry], [%next, %loop]
240
241  %hoistable = call i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) %q, i32 0, i32 0, i32 0, i32 0), !alias.scope !4, !noalias !3
242  %orig = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) %p, i32 %i, i32 0, i32 0), !alias.scope !3, !noalias !4
243  %inc = add i32 %hoistable, %orig
244  call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 %inc, ptr addrspace(8) %p, i32 %i, i32 0, i32 0), !alias.scope !3, !noalias !4
245
246  %next = add i32 %i, 1
247  %cond = icmp ult i32 %next, %bound
248  br i1 %cond, label %loop, label %tail
249tail:
250  ret void
251}
252
253; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: read)
254declare i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) nocapture readonly, i32, i32, i32 immarg) #0
255; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: read)
256declare i32 @llvm.amdgcn.struct.ptr.buffer.load.i32(ptr addrspace(8) nocapture readonly, i32, i32, i32, i32 immarg) #0
257; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: write)
258declare void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32, ptr addrspace(8) nocapture writeonly, i32, i32, i32 immarg) #1
259; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)declare ptr addrspace(8) @llvm.amdgcn.make.buffer.rsrc.p1(ptr addrspace(1) nocapture readnone, i16, i32, i32) #2
260declare ptr addrspace(8) @llvm.amdgcn.make.buffer.rsrc.p1(ptr addrspace(1) readnone nocapture, i16, i32, i32)
261attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
262attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: write) }
263attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
264