1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces -instsimplify %s | FileCheck %s
3
4define i8 @ptrmask_cast_local_to_flat(i8 addrspace(3)* %src.ptr, i64 %mask) {
5; CHECK-LABEL: @ptrmask_cast_local_to_flat(
6; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(3)* [[SRC_PTR:%.*]] to i8*
7; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
8; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
9; CHECK-NEXT:    ret i8 [[LOAD]]
10;
11  %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
12  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
13  %load = load i8, i8* %masked
14  ret i8 %load
15}
16
17define i8 @ptrmask_cast_private_to_flat(i8 addrspace(5)* %src.ptr, i64 %mask) {
18; CHECK-LABEL: @ptrmask_cast_private_to_flat(
19; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(5)* [[SRC_PTR:%.*]] to i8*
20; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
21; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
22; CHECK-NEXT:    ret i8 [[LOAD]]
23;
24  %cast = addrspacecast i8 addrspace(5)* %src.ptr to i8*
25  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
26  %load = load i8, i8* %masked
27  ret i8 %load
28}
29
30define i8 @ptrmask_cast_region_to_flat(i8 addrspace(2)* %src.ptr, i64 %mask) {
31; CHECK-LABEL: @ptrmask_cast_region_to_flat(
32; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(2)* [[SRC_PTR:%.*]] to i8*
33; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
34; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
35; CHECK-NEXT:    ret i8 [[LOAD]]
36;
37  %cast = addrspacecast i8 addrspace(2)* %src.ptr to i8*
38  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
39  %load = load i8, i8* %masked
40  ret i8 %load
41}
42
43define i8 @ptrmask_cast_global_to_flat(i8 addrspace(1)* %src.ptr, i64 %mask) {
44; CHECK-LABEL: @ptrmask_cast_global_to_flat(
45; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(1)* [[SRC_PTR:%.*]] to i8*
46; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
47; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
48; CHECK-NEXT:    ret i8 [[LOAD]]
49;
50  %cast = addrspacecast i8 addrspace(1)* %src.ptr to i8*
51  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
52  %load = load i8, i8* %masked
53  ret i8 %load
54}
55
56define i8 @ptrmask_cast_999_to_flat(i8 addrspace(999)* %src.ptr, i64 %mask) {
57; CHECK-LABEL: @ptrmask_cast_999_to_flat(
58; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(999)* [[SRC_PTR:%.*]] to i8*
59; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
60; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
61; CHECK-NEXT:    ret i8 [[LOAD]]
62;
63  %cast = addrspacecast i8 addrspace(999)* %src.ptr to i8*
64  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
65  %load = load i8, i8* %masked
66  ret i8 %load
67}
68
69define i8 @ptrmask_cast_flat_to_local(i8* %ptr, i64 %mask) {
70; CHECK-LABEL: @ptrmask_cast_flat_to_local(
71; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[PTR:%.*]], i64 [[MASK:%.*]])
72; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8* [[MASKED]] to i8 addrspace(3)*
73; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[CAST]], align 1
74; CHECK-NEXT:    ret i8 [[LOAD]]
75;
76  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %ptr, i64 %mask)
77  %cast = addrspacecast i8* %masked to i8 addrspace(3)*
78  %load = load i8, i8 addrspace(3)* %cast
79  ret i8 %load
80}
81
82define i8 @ptrmask_cast_flat_to_private(i8* %ptr, i64 %mask) {
83; CHECK-LABEL: @ptrmask_cast_flat_to_private(
84; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[PTR:%.*]], i64 [[MASK:%.*]])
85; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8* [[MASKED]] to i8 addrspace(5)*
86; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(5)* [[CAST]], align 1
87; CHECK-NEXT:    ret i8 [[LOAD]]
88;
89  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %ptr, i64 %mask)
90  %cast = addrspacecast i8* %masked to i8 addrspace(5)*
91  %load = load i8, i8 addrspace(5)* %cast
92  ret i8 %load
93}
94
95define i8 @ptrmask_cast_flat_to_global(i8* %ptr, i64 %mask) {
96; CHECK-LABEL: @ptrmask_cast_flat_to_global(
97; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[PTR:%.*]], i64 [[MASK:%.*]])
98; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8* [[MASKED]] to i8 addrspace(1)*
99; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(1)* [[CAST]], align 1
100; CHECK-NEXT:    ret i8 [[LOAD]]
101;
102  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %ptr, i64 %mask)
103  %cast = addrspacecast i8* %masked to i8 addrspace(1)*
104  %load = load i8, i8 addrspace(1)* %cast
105  ret i8 %load
106}
107
108@lds0 = internal addrspace(3) global i8 123, align 4
109@gv = internal addrspace(1) global i8 123, align 4
110
111define i8 @ptrmask_cast_local_to_flat_global(i64 %mask) {
112; CHECK-LABEL: @ptrmask_cast_local_to_flat_global(
113; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(3)* @lds0 to i8*), i64 [[MASK:%.*]])
114; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
115; CHECK-NEXT:    ret i8 [[LOAD]]
116;
117  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(3)* @lds0 to i8*), i64 %mask)
118  %load = load i8, i8* %masked, align 1
119  ret i8 %load
120}
121
122define i8 @ptrmask_cast_global_to_flat_global(i64 %mask) {
123; CHECK-LABEL: @ptrmask_cast_global_to_flat_global(
124; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(1)* @gv to i8*), i64 [[MASK:%.*]])
125; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
126; CHECK-NEXT:    ret i8 [[LOAD]]
127;
128  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(1)* @gv to i8*), i64 %mask)
129  %load = load i8, i8* %masked, align 1
130  ret i8 %load
131}
132
133define i8 @multi_ptrmask_cast_global_to_flat(i8 addrspace(1)* %src.ptr, i64 %mask) {
134; CHECK-LABEL: @multi_ptrmask_cast_global_to_flat(
135; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(1)* [[SRC_PTR:%.*]] to i8*
136; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8 addrspace(1)* [[SRC_PTR]], align 1
137; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
138; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8* [[MASKED]], align 1
139; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[LOAD1]]
140; CHECK-NEXT:    ret i8 [[ADD]]
141;
142  %cast = addrspacecast i8 addrspace(1)* %src.ptr to i8*
143  %load0 = load i8, i8* %cast
144  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
145  %load1 = load i8, i8* %masked
146  %add = add i8 %load0, %load1
147  ret i8 %add
148}
149
150; Can't rewrite the ptrmask, but can rewrite other use instructions
151define i8 @multi_ptrmask_cast_local_to_flat(i8 addrspace(3)* %src.ptr, i64 %mask) {
152; CHECK-LABEL: @multi_ptrmask_cast_local_to_flat(
153; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(3)* [[SRC_PTR:%.*]] to i8*
154; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8 addrspace(3)* [[SRC_PTR]], align 1
155; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
156; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8* [[MASKED]], align 1
157; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[LOAD1]]
158; CHECK-NEXT:    ret i8 [[ADD]]
159;
160  %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
161  %load0 = load i8, i8* %cast
162  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
163  %load1 = load i8, i8* %masked
164  %add = add i8 %load0, %load1
165  ret i8 %add
166}
167
168define i8 @multi_ptrmask_cast_region_to_flat(i8 addrspace(2)* %src.ptr, i64 %mask) {
169; CHECK-LABEL: @multi_ptrmask_cast_region_to_flat(
170; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(2)* [[SRC_PTR:%.*]] to i8*
171; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8 addrspace(2)* [[SRC_PTR]], align 1
172; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
173; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8* [[MASKED]], align 1
174; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[LOAD1]]
175; CHECK-NEXT:    ret i8 [[ADD]]
176;
177  %cast = addrspacecast i8 addrspace(2)* %src.ptr to i8*
178  %load0 = load i8, i8* %cast
179  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
180  %load1 = load i8, i8* %masked
181  %add = add i8 %load0, %load1
182  ret i8 %add
183}
184
185declare i8* @llvm.ptrmask.p0i8.i64(i8*, i64) #0
186declare i8 addrspace(5)* @llvm.ptrmask.p5i8.i32(i8 addrspace(5)*, i32) #0
187declare i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)*, i32) #0
188declare i8 addrspace(1)* @llvm.ptrmask.p1i8.i64(i8 addrspace(1)*, i64) #0
189
190attributes #0 = { nounwind readnone speculatable willreturn }
191