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:    [[TMP1:%.*]] = call i8 addrspace(1)* @llvm.ptrmask.p1i8.i64(i8 addrspace(1)* [[SRC_PTR:%.*]], i64 [[MASK:%.*]])
46; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(1)* [[TMP1]], align 1
47; CHECK-NEXT:    ret i8 [[LOAD]]
48;
49  %cast = addrspacecast i8 addrspace(1)* %src.ptr to i8*
50  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
51  %load = load i8, i8* %masked
52  ret i8 %load
53}
54
55define i8 @ptrmask_cast_999_to_flat(i8 addrspace(999)* %src.ptr, i64 %mask) {
56; CHECK-LABEL: @ptrmask_cast_999_to_flat(
57; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(999)* @llvm.ptrmask.p999i8.i64(i8 addrspace(999)* [[SRC_PTR:%.*]], i64 [[MASK:%.*]])
58; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(999)* [[TMP1]], align 1
59; CHECK-NEXT:    ret i8 [[LOAD]]
60;
61  %cast = addrspacecast i8 addrspace(999)* %src.ptr to i8*
62  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
63  %load = load i8, i8* %masked
64  ret i8 %load
65}
66
67define i8 @ptrmask_cast_flat_to_local(i8* %ptr, i64 %mask) {
68; CHECK-LABEL: @ptrmask_cast_flat_to_local(
69; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[PTR:%.*]], i64 [[MASK:%.*]])
70; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8* [[MASKED]] to i8 addrspace(3)*
71; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[CAST]], align 1
72; CHECK-NEXT:    ret i8 [[LOAD]]
73;
74  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %ptr, i64 %mask)
75  %cast = addrspacecast i8* %masked to i8 addrspace(3)*
76  %load = load i8, i8 addrspace(3)* %cast
77  ret i8 %load
78}
79
80define i8 @ptrmask_cast_flat_to_private(i8* %ptr, i64 %mask) {
81; CHECK-LABEL: @ptrmask_cast_flat_to_private(
82; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[PTR:%.*]], i64 [[MASK:%.*]])
83; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8* [[MASKED]] to i8 addrspace(5)*
84; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(5)* [[CAST]], align 1
85; CHECK-NEXT:    ret i8 [[LOAD]]
86;
87  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %ptr, i64 %mask)
88  %cast = addrspacecast i8* %masked to i8 addrspace(5)*
89  %load = load i8, i8 addrspace(5)* %cast
90  ret i8 %load
91}
92
93define i8 @ptrmask_cast_flat_to_global(i8* %ptr, i64 %mask) {
94; CHECK-LABEL: @ptrmask_cast_flat_to_global(
95; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[PTR:%.*]], i64 [[MASK:%.*]])
96; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8* [[MASKED]] to i8 addrspace(1)*
97; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(1)* [[CAST]], align 1
98; CHECK-NEXT:    ret i8 [[LOAD]]
99;
100  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %ptr, i64 %mask)
101  %cast = addrspacecast i8* %masked to i8 addrspace(1)*
102  %load = load i8, i8 addrspace(1)* %cast
103  ret i8 %load
104}
105
106@lds0 = internal addrspace(3) global i8 123, align 4
107@gv = internal addrspace(1) global i8 123, align 4
108
109define i8 @ptrmask_cast_local_to_flat_global(i64 %mask) {
110; CHECK-LABEL: @ptrmask_cast_local_to_flat_global(
111; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(3)* @lds0 to i8*), i64 [[MASK:%.*]])
112; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
113; CHECK-NEXT:    ret i8 [[LOAD]]
114;
115  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(3)* @lds0 to i8*), i64 %mask)
116  %load = load i8, i8* %masked, align 1
117  ret i8 %load
118}
119
120define i8 @ptrmask_cast_global_to_flat_global(i64 %mask) {
121; CHECK-LABEL: @ptrmask_cast_global_to_flat_global(
122; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(1)* @llvm.ptrmask.p1i8.i64(i8 addrspace(1)* @gv, i64 [[MASK:%.*]])
123; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(1)* [[TMP1]], align 1
124; CHECK-NEXT:    ret i8 [[LOAD]]
125;
126  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(1)* @gv to i8*), i64 %mask)
127  %load = load i8, i8* %masked, align 1
128  ret i8 %load
129}
130
131define i8 @multi_ptrmask_cast_global_to_flat(i8 addrspace(1)* %src.ptr, i64 %mask) {
132; CHECK-LABEL: @multi_ptrmask_cast_global_to_flat(
133; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8 addrspace(1)* [[SRC_PTR:%.*]], align 1
134; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(1)* @llvm.ptrmask.p1i8.i64(i8 addrspace(1)* [[SRC_PTR]], i64 [[MASK:%.*]])
135; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8 addrspace(1)* [[TMP1]], align 1
136; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[LOAD1]]
137; CHECK-NEXT:    ret i8 [[ADD]]
138;
139  %cast = addrspacecast i8 addrspace(1)* %src.ptr to i8*
140  %load0 = load i8, i8* %cast
141  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
142  %load1 = load i8, i8* %masked
143  %add = add i8 %load0, %load1
144  ret i8 %add
145}
146
147; Can't rewrite the ptrmask, but can rewrite other use instructions
148define i8 @multi_ptrmask_cast_local_to_flat(i8 addrspace(3)* %src.ptr, i64 %mask) {
149; CHECK-LABEL: @multi_ptrmask_cast_local_to_flat(
150; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(3)* [[SRC_PTR:%.*]] to i8*
151; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8 addrspace(3)* [[SRC_PTR]], align 1
152; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
153; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8* [[MASKED]], align 1
154; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[LOAD1]]
155; CHECK-NEXT:    ret i8 [[ADD]]
156;
157  %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
158  %load0 = load i8, i8* %cast
159  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
160  %load1 = load i8, i8* %masked
161  %add = add i8 %load0, %load1
162  ret i8 %add
163}
164
165define i8 @multi_ptrmask_cast_region_to_flat(i8 addrspace(2)* %src.ptr, i64 %mask) {
166; CHECK-LABEL: @multi_ptrmask_cast_region_to_flat(
167; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(2)* [[SRC_PTR:%.*]] to i8*
168; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8 addrspace(2)* [[SRC_PTR]], align 1
169; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
170; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8* [[MASKED]], align 1
171; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[LOAD1]]
172; CHECK-NEXT:    ret i8 [[ADD]]
173;
174  %cast = addrspacecast i8 addrspace(2)* %src.ptr to i8*
175  %load0 = load i8, i8* %cast
176  %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
177  %load1 = load i8, i8* %masked
178  %add = add i8 %load0, %load1
179  ret i8 %add
180}
181
182declare i8* @llvm.ptrmask.p0i8.i64(i8*, i64) #0
183declare i8 addrspace(5)* @llvm.ptrmask.p5i8.i32(i8 addrspace(5)*, i32) #0
184declare i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)*, i32) #0
185declare i8 addrspace(1)* @llvm.ptrmask.p1i8.i64(i8 addrspace(1)*, i64) #0
186
187attributes #0 = { nounwind readnone speculatable willreturn }
188