xref: /llvm-project/llvm/test/Transforms/InstCombine/ptrmask.ll (revision 462cb3cd6cecd0511ecaf0e3ebcaba455ece587d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4target datalayout = "p1:64:64:64:32"
5
6declare ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1), i32)
7declare ptr @llvm.ptrmask.p0.i64(ptr, i64)
8declare <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) >, <2 x i32>)
9declare <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr>, <2 x i64>)
10
11define ptr @ptrmask_combine_consecutive_preserve_attrs(ptr %p0, i64 %m1) {
12; CHECK-LABEL: define ptr @ptrmask_combine_consecutive_preserve_attrs
13; CHECK-SAME: (ptr [[P0:%.*]], i64 [[M1:%.*]]) {
14; CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[M1]], 224
15; CHECK-NEXT:    [[R:%.*]] = call noalias align 32 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[TMP1]])
16; CHECK-NEXT:    ret ptr [[R]]
17;
18  %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 224)
19  %r = call noalias ptr @llvm.ptrmask.p0.i64(ptr %pm0, i64 %m1)
20  ret ptr %r
21}
22
23define <2 x ptr> @ptrmask_combine_consecutive_preserve_attrs_vecs(<2 x ptr> %p0, <2 x i64> %m1) {
24; CHECK-LABEL: define <2 x ptr> @ptrmask_combine_consecutive_preserve_attrs_vecs
25; CHECK-SAME: (<2 x ptr> [[P0:%.*]], <2 x i64> [[M1:%.*]]) {
26; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i64> [[M1]], splat (i64 12345)
27; CHECK-NEXT:    [[R:%.*]] = call align 128 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[P0]], <2 x i64> [[TMP1]])
28; CHECK-NEXT:    ret <2 x ptr> [[R]]
29;
30  %pm0 = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p0, <2 x i64> <i64 12345, i64 12345>)
31  %r = call align 128 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %pm0, <2 x i64> %m1)
32  ret <2 x ptr> %r
33}
34
35define ptr @ptrmask_combine_consecutive_preserve_attrs_fail(ptr %p0, i64 %m0) {
36; CHECK-LABEL: define ptr @ptrmask_combine_consecutive_preserve_attrs_fail
37; CHECK-SAME: (ptr [[P0:%.*]], i64 [[M0:%.*]]) {
38; CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[M0]], 193
39; CHECK-NEXT:    [[R:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[TMP1]])
40; CHECK-NEXT:    ret ptr [[R]]
41;
42  %pm0 = call noalias ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0)
43  %r = call ptr @llvm.ptrmask.p0.i64(ptr %pm0, i64 193)
44  ret ptr %r
45}
46
47define ptr @ptrmask_combine_consecutive_preserve_attrs_todo0(ptr %p0) {
48; CHECK-LABEL: define ptr @ptrmask_combine_consecutive_preserve_attrs_todo0
49; CHECK-SAME: (ptr [[P0:%.*]]) {
50; CHECK-NEXT:    [[PM0:%.*]] = call noalias align 32 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 224)
51; CHECK-NEXT:    ret ptr [[PM0]]
52;
53  %pm0 = call noalias ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 224)
54  %r = call ptr @llvm.ptrmask.p0.i64(ptr %pm0, i64 224)
55  ret ptr %r
56}
57
58define ptr @ptrmask_combine_consecutive_preserve_attrs_todo1(ptr %p0) {
59; CHECK-LABEL: define ptr @ptrmask_combine_consecutive_preserve_attrs_todo1
60; CHECK-SAME: (ptr [[P0:%.*]]) {
61; CHECK-NEXT:    [[PM0:%.*]] = call align 32 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 224)
62; CHECK-NEXT:    ret ptr [[PM0]]
63;
64  %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 224)
65  %r = call noalias ptr @llvm.ptrmask.p0.i64(ptr %pm0, i64 224)
66  ret ptr %r
67}
68
69define ptr addrspace(1) @ptrmask_combine_consecutive_preserve_attrs_todo2(ptr addrspace(1) %p0) {
70; CHECK-LABEL: define ptr addrspace(1) @ptrmask_combine_consecutive_preserve_attrs_todo2
71; CHECK-SAME: (ptr addrspace(1) [[P0:%.*]]) {
72; CHECK-NEXT:    [[PM0:%.*]] = call noalias align 32 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P0]], i32 224)
73; CHECK-NEXT:    ret ptr addrspace(1) [[PM0]]
74;
75  %pm0 = call noalias ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p0, i32 224)
76  %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %pm0, i32 224)
77  ret ptr addrspace(1) %r
78}
79
80define ptr @ptrmask_combine_add_nonnull(ptr %p) {
81; CHECK-LABEL: define ptr @ptrmask_combine_add_nonnull
82; CHECK-SAME: (ptr [[P:%.*]]) {
83; CHECK-NEXT:    [[PM0:%.*]] = call align 4 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -60)
84; CHECK-NEXT:    [[PGEP1:%.*]] = getelementptr i8, ptr [[PM0]], i64 32
85; CHECK-NEXT:    [[R:%.*]] = call nonnull align 32 ptr @llvm.ptrmask.p0.i64(ptr [[PGEP1]], i64 -32)
86; CHECK-NEXT:    ret ptr [[R]]
87;
88  %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -60)
89  %pgep = getelementptr i8, ptr %pm0, i64 33
90  %r = call ptr @llvm.ptrmask.p0.i64(ptr %pgep, i64 -16)
91  ret ptr %r
92}
93
94define ptr @ptrmask_combine_add_alignment(ptr %p) {
95; CHECK-LABEL: define ptr @ptrmask_combine_add_alignment
96; CHECK-SAME: (ptr [[P:%.*]]) {
97; CHECK-NEXT:    [[R:%.*]] = call align 64 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -64)
98; CHECK-NEXT:    ret ptr [[R]]
99;
100  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -64)
101  ret ptr %r
102}
103
104define ptr addrspace(1) @ptrmask_combine_add_alignment2(ptr addrspace(1) align 32 %p) {
105; CHECK-LABEL: define ptr addrspace(1) @ptrmask_combine_add_alignment2
106; CHECK-SAME: (ptr addrspace(1) align 32 [[P:%.*]]) {
107; CHECK-NEXT:    [[R:%.*]] = call align 64 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 -64)
108; CHECK-NEXT:    ret ptr addrspace(1) [[R]]
109;
110  %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 -64)
111  ret ptr addrspace(1) %r
112}
113
114define <2 x ptr> @ptrmask_combine_add_alignment_vec(<2 x ptr> %p) {
115; CHECK-LABEL: define <2 x ptr> @ptrmask_combine_add_alignment_vec
116; CHECK-SAME: (<2 x ptr> [[P:%.*]]) {
117; CHECK-NEXT:    [[R:%.*]] = call align 32 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[P]], <2 x i64> splat (i64 -96))
118; CHECK-NEXT:    ret <2 x ptr> [[R]]
119;
120  %r = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p, <2 x i64> <i64 -96, i64 -96>)
121  ret <2 x ptr> %r
122}
123
124define ptr addrspace(1) @ptrmask_combine_improve_alignment(ptr addrspace(1) %p) {
125; CHECK-LABEL: define ptr addrspace(1) @ptrmask_combine_improve_alignment
126; CHECK-SAME: (ptr addrspace(1) [[P:%.*]]) {
127; CHECK-NEXT:    [[R:%.*]] = call align 64 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 -64)
128; CHECK-NEXT:    ret ptr addrspace(1) [[R]]
129;
130  %r = call align 32 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 -64)
131  ret ptr addrspace(1) %r
132}
133
134define <2 x ptr addrspace(1) > @ptrmask_combine_improve_alignment_vec(<2 x ptr addrspace(1) > %p) {
135; CHECK-LABEL: define <2 x ptr addrspace(1)> @ptrmask_combine_improve_alignment_vec
136; CHECK-SAME: (<2 x ptr addrspace(1)> [[P:%.*]]) {
137; CHECK-NEXT:    [[R:%.*]] = call align 64 <2 x ptr addrspace(1)> @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1)> [[P]], <2 x i32> <i32 -64, i32 -128>)
138; CHECK-NEXT:    ret <2 x ptr addrspace(1)> [[R]]
139;
140  %r = call align 32 <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) > %p, <2 x i32> <i32 -64, i32 -128>)
141  ret <2 x ptr addrspace(1) > %r
142}
143
144define ptr addrspace(1) @ptrmask_combine_improve_alignment_fail(ptr addrspace(1) %p) {
145; CHECK-LABEL: define ptr addrspace(1) @ptrmask_combine_improve_alignment_fail
146; CHECK-SAME: (ptr addrspace(1) [[P:%.*]]) {
147; CHECK-NEXT:    [[R:%.*]] = call align 128 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 -64)
148; CHECK-NEXT:    ret ptr addrspace(1) [[R]]
149;
150  %r = call align 128 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 -64)
151  ret ptr addrspace(1) %r
152}
153
154define i64 @ptrtoint_of_ptrmask(ptr %p, i64 %m) {
155; CHECK-LABEL: define i64 @ptrtoint_of_ptrmask
156; CHECK-SAME: (ptr [[P:%.*]], i64 [[M:%.*]]) {
157; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64
158; CHECK-NEXT:    [[R:%.*]] = and i64 [[M]], [[TMP1]]
159; CHECK-NEXT:    ret i64 [[R]]
160;
161  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m)
162  %r = ptrtoint ptr %pm to i64
163  ret i64 %r
164}
165
166; This succeeds because (ptrtoint i32) gets folded to (trunc i32 (ptrtoint i64))
167define i32 @ptrtoint_of_ptrmask2(ptr %p, i64 %m) {
168; CHECK-LABEL: define i32 @ptrtoint_of_ptrmask2
169; CHECK-SAME: (ptr [[P:%.*]], i64 [[M:%.*]]) {
170; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64
171; CHECK-NEXT:    [[TMP2:%.*]] = and i64 [[M]], [[TMP1]]
172; CHECK-NEXT:    [[R:%.*]] = trunc i64 [[TMP2]] to i32
173; CHECK-NEXT:    ret i32 [[R]]
174;
175  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m)
176  %r = ptrtoint ptr %pm to i32
177  ret i32 %r
178}
179
180define <2 x i64> @ptrtoint_of_ptrmask_vec(<2 x ptr> %p, <2 x i64> %m) {
181; CHECK-LABEL: define <2 x i64> @ptrtoint_of_ptrmask_vec
182; CHECK-SAME: (<2 x ptr> [[P:%.*]], <2 x i64> [[M:%.*]]) {
183; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint <2 x ptr> [[P]] to <2 x i64>
184; CHECK-NEXT:    [[R:%.*]] = and <2 x i64> [[M]], [[TMP1]]
185; CHECK-NEXT:    ret <2 x i64> [[R]]
186;
187  %pm = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p, <2 x i64> %m)
188  %r = ptrtoint <2 x ptr> %pm to <2 x i64>
189  ret <2 x i64> %r
190}
191
192define <2 x i32> @ptrtoint_of_ptrmask_vec2(<2 x ptr> %p, <2 x i64> %m) {
193; CHECK-LABEL: define <2 x i32> @ptrtoint_of_ptrmask_vec2
194; CHECK-SAME: (<2 x ptr> [[P:%.*]], <2 x i64> [[M:%.*]]) {
195; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint <2 x ptr> [[P]] to <2 x i64>
196; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i64> [[M]], [[TMP1]]
197; CHECK-NEXT:    [[R:%.*]] = trunc <2 x i64> [[TMP2]] to <2 x i32>
198; CHECK-NEXT:    ret <2 x i32> [[R]]
199;
200  %pm = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p, <2 x i64> %m)
201  %r = ptrtoint <2 x ptr> %pm to <2 x i32>
202  ret <2 x i32> %r
203}
204
205define i64 @ptrtoint_of_ptrmask_fail(ptr addrspace(1) %p, i32 %m) {
206; CHECK-LABEL: define i64 @ptrtoint_of_ptrmask_fail
207; CHECK-SAME: (ptr addrspace(1) [[P:%.*]], i32 [[M:%.*]]) {
208; CHECK-NEXT:    [[PM:%.*]] = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 [[M]])
209; CHECK-NEXT:    [[R:%.*]] = ptrtoint ptr addrspace(1) [[PM]] to i64
210; CHECK-NEXT:    ret i64 [[R]]
211;
212  %pm = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 %m)
213  %r = ptrtoint ptr addrspace(1) %pm to i64
214  ret i64 %r
215}
216
217define <2 x i32> @ptrtoint_of_ptrmask_vec_fail(<2 x ptr addrspace(1) > %p, <2 x i32> %m) {
218; CHECK-LABEL: define <2 x i32> @ptrtoint_of_ptrmask_vec_fail
219; CHECK-SAME: (<2 x ptr addrspace(1)> [[P:%.*]], <2 x i32> [[M:%.*]]) {
220; CHECK-NEXT:    [[PM:%.*]] = call <2 x ptr addrspace(1)> @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1)> [[P]], <2 x i32> [[M]])
221; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint <2 x ptr addrspace(1)> [[PM]] to <2 x i64>
222; CHECK-NEXT:    [[R:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
223; CHECK-NEXT:    ret <2 x i32> [[R]]
224;
225  %pm = call <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) > %p, <2 x i32> %m)
226  %r = ptrtoint <2 x ptr addrspace(1) > %pm to <2 x i32>
227  ret <2 x i32> %r
228}
229
230define ptr addrspace(1) @ptrmask_is_null(ptr addrspace(1) align 32 %p) {
231; CHECK-LABEL: define ptr addrspace(1) @ptrmask_is_null
232; CHECK-SAME: (ptr addrspace(1) align 32 [[P:%.*]]) {
233; CHECK-NEXT:    [[R:%.*]] = call align 4294967296 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 0)
234; CHECK-NEXT:    ret ptr addrspace(1) [[R]]
235;
236  %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 31)
237  ret ptr addrspace(1) %r
238}
239
240define <2 x ptr addrspace(1) > @ptrmask_is_null_vec(<2 x ptr addrspace(1) > align 64 %p) {
241; CHECK-LABEL: define <2 x ptr addrspace(1)> @ptrmask_is_null_vec
242; CHECK-SAME: (<2 x ptr addrspace(1)> align 64 [[P:%.*]]) {
243; CHECK-NEXT:    [[R:%.*]] = call <2 x ptr addrspace(1)> @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1)> [[P]], <2 x i32> <i32 31, i32 63>)
244; CHECK-NEXT:    ret <2 x ptr addrspace(1)> [[R]]
245;
246  %r = call <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) > %p, <2 x i32> <i32 31, i32 63>)
247  ret <2 x ptr addrspace(1) > %r
248}
249
250define ptr addrspace(1) @ptrmask_is_null_fail(ptr addrspace(1) align 16 %p) {
251; CHECK-LABEL: define ptr addrspace(1) @ptrmask_is_null_fail
252; CHECK-SAME: (ptr addrspace(1) align 16 [[P:%.*]]) {
253; CHECK-NEXT:    [[R:%.*]] = call align 16 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 16)
254; CHECK-NEXT:    ret ptr addrspace(1) [[R]]
255;
256  %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 31)
257  ret ptr addrspace(1) %r
258}
259
260define <2 x ptr addrspace(1) > @ptrmask_is_null_vec_fail(<2 x ptr addrspace(1) > align 32 %p) {
261; CHECK-LABEL: define <2 x ptr addrspace(1)> @ptrmask_is_null_vec_fail
262; CHECK-SAME: (<2 x ptr addrspace(1)> align 32 [[P:%.*]]) {
263; CHECK-NEXT:    [[R:%.*]] = call <2 x ptr addrspace(1)> @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1)> [[P]], <2 x i32> <i32 31, i32 63>)
264; CHECK-NEXT:    ret <2 x ptr addrspace(1)> [[R]]
265;
266  %r = call <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) > %p, <2 x i32> <i32 31, i32 63>)
267  ret <2 x ptr addrspace(1) > %r
268}
269
270define ptr @ptrmask_maintain_provenance_i64(ptr %p0) {
271; CHECK-LABEL: define ptr @ptrmask_maintain_provenance_i64
272; CHECK-SAME: (ptr [[P0:%.*]]) {
273; CHECK-NEXT:    [[R:%.*]] = call align 4294967296 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 0)
274; CHECK-NEXT:    ret ptr [[R]]
275;
276  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 0)
277  ret ptr %r
278}
279
280define ptr addrspace(1) @ptrmask_maintain_provenance_i32(ptr addrspace(1) %p0) {
281; CHECK-LABEL: define ptr addrspace(1) @ptrmask_maintain_provenance_i32
282; CHECK-SAME: (ptr addrspace(1) [[P0:%.*]]) {
283; CHECK-NEXT:    [[R:%.*]] = call align 4294967296 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P0]], i32 0)
284; CHECK-NEXT:    ret ptr addrspace(1) [[R]]
285;
286  %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p0, i32 0)
287  ret ptr addrspace(1) %r
288}
289
290define ptr @ptrmask_is_nop0(ptr align 8 %p) {
291; CHECK-LABEL: define ptr @ptrmask_is_nop0
292; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
293; CHECK-NEXT:    ret ptr [[P]]
294;
295  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -8)
296  ret ptr %pm
297}
298
299define ptr @ptrmask_is_nop1(ptr align 8 %p) {
300; CHECK-LABEL: define ptr @ptrmask_is_nop1
301; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
302; CHECK-NEXT:    ret ptr [[P]]
303;
304  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -4)
305  ret ptr %pm
306}
307
308define ptr @ptrmask_to_modified_gep0(ptr align 8 %p) {
309; CHECK-LABEL: define ptr @ptrmask_to_modified_gep0
310; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
311; CHECK-NEXT:    [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -16)
312; CHECK-NEXT:    ret ptr [[PM]]
313;
314  %gep = getelementptr i8, ptr %p, i32 5
315  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16)
316  ret ptr %pm
317}
318
319define ptr @ptrmask_to_modified_gep1(ptr align 8 %p) {
320; CHECK-LABEL: define ptr @ptrmask_to_modified_gep1
321; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
322; CHECK-NEXT:    ret ptr [[P]]
323;
324  %gep = getelementptr i8, ptr %p, i32 6
325  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -8)
326  ret ptr %pm
327}
328
329define ptr @ptrmask_to_modified_gep2(ptr align 16 %p) {
330; CHECK-LABEL: define ptr @ptrmask_to_modified_gep2
331; CHECK-SAME: (ptr align 16 [[P:%.*]]) {
332; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 12
333; CHECK-NEXT:    ret ptr [[GEP1]]
334;
335  %gep = getelementptr i8, ptr %p, i32 15
336  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4)
337  ret ptr %pm
338}
339
340define ptr @ptrmask_to_modified_gep4(ptr align 8 %p) {
341; CHECK-LABEL: define ptr @ptrmask_to_modified_gep4
342; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
343; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 24
344; CHECK-NEXT:    [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[GEP1]], i64 -16)
345; CHECK-NEXT:    ret ptr [[PM]]
346;
347  %gep = getelementptr i8, ptr %p, i32 29
348  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16)
349  ret ptr %pm
350}
351
352define ptr @ptrmask_to_modified_gep5(ptr align 8 %p) {
353; CHECK-LABEL: define ptr @ptrmask_to_modified_gep5
354; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
355; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 24
356; CHECK-NEXT:    ret ptr [[GEP1]]
357;
358  %gep = getelementptr i8, ptr %p, i32 30
359  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -8)
360  ret ptr %pm
361}
362
363define ptr @ptrmask_to_modified_gep6(ptr align 16 %p) {
364; CHECK-LABEL: define ptr @ptrmask_to_modified_gep6
365; CHECK-SAME: (ptr align 16 [[P:%.*]]) {
366; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 28
367; CHECK-NEXT:    ret ptr [[GEP1]]
368;
369  %gep = getelementptr i8, ptr %p, i32 31
370  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4)
371  ret ptr %pm
372}
373
374define ptr @ptrmask_to_modified_gep_indirect0(ptr align 16 %p) {
375; CHECK-LABEL: define ptr @ptrmask_to_modified_gep_indirect0
376; CHECK-SAME: (ptr align 16 [[P:%.*]]) {
377; CHECK-NEXT:    [[GEP11:%.*]] = getelementptr i8, ptr [[P]], i64 44
378; CHECK-NEXT:    ret ptr [[GEP11]]
379;
380; 44 from 4*sizeof(i32) + (31 & -4)
381  %gep0 = getelementptr i32, ptr %p, i32 4
382  %gep1 = getelementptr i8, ptr %gep0, i32 31
383  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep1, i64 -4)
384  ret ptr %pm
385}
386
387define ptr @ptrmask_to_modified_gep_indirect1(ptr %p) {
388; CHECK-LABEL: define ptr @ptrmask_to_modified_gep_indirect1
389; CHECK-SAME: (ptr [[P:%.*]]) {
390; CHECK-NEXT:    [[PM0:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -16)
391; CHECK-NEXT:    [[PGEP1:%.*]] = getelementptr i8, ptr [[PM0]], i64 32
392; CHECK-NEXT:    ret ptr [[PGEP1]]
393;
394
395  %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -16)
396  %pgep = getelementptr i8, ptr %pm0, i64 33
397  %r = call ptr @llvm.ptrmask.p0.i64(ptr %pgep, i64 -16)
398  ret ptr %r
399}
400
401define ptr @ptrmask_to_modified_gep_zero_argument() {
402; CHECK-LABEL: define ptr @ptrmask_to_modified_gep_zero_argument() {
403; CHECK-NEXT:    [[P:%.*]] = call nonnull align 4 ptr @llvm.ptrmask.p0.i64(ptr nonnull inttoptr (i64 31 to ptr), i64 28)
404; CHECK-NEXT:    ret ptr [[P]]
405;
406  %gep = getelementptr inbounds i8, ptr null, i32 31
407  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4)
408  ret ptr %pm
409}
410
411define ptr @ptrmask_to_preserves_inbounds(ptr align 16 %p) {
412; CHECK-LABEL: define ptr @ptrmask_to_preserves_inbounds
413; CHECK-SAME: (ptr align 16 [[P:%.*]]) {
414; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 28
415; CHECK-NEXT:    ret ptr [[GEP1]]
416;
417  %gep = getelementptr inbounds i8, ptr %p, i32 31
418  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4)
419  ret ptr %pm
420}
421
422define ptr @ptrmask_of_gep_requires_i8(ptr align 8 %p) {
423; CHECK-LABEL: define ptr @ptrmask_of_gep_requires_i8
424; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
425; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 8
426; CHECK-NEXT:    [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[GEP1]], i64 -16)
427; CHECK-NEXT:    ret ptr [[PM]]
428;
429  %gep = getelementptr i16, ptr %p, i32 5
430  %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16)
431  ret ptr %pm
432}
433
434define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented(<2 x ptr> align 8 %p) {
435; CHECK-LABEL: define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented
436; CHECK-SAME: (<2 x ptr> align 8 [[P:%.*]]) {
437; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, <2 x ptr> [[P]], i64 17
438; CHECK-NEXT:    [[PM:%.*]] = call align 32 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[GEP]], <2 x i64> splat (i64 -96))
439; CHECK-NEXT:    ret <2 x ptr> [[PM]]
440;
441  %gep = getelementptr i8, <2 x ptr> %p, i32 17
442  %pm = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %gep, <2 x i64> <i64 -96, i64 -96>)
443  ret <2 x ptr> %pm
444}
445
446define ptr @ptrmask_is_useless0(i64 %i, i64 %m) {
447; CHECK-LABEL: define ptr @ptrmask_is_useless0
448; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {
449; CHECK-NEXT:    [[I0:%.*]] = and i64 [[I]], -4
450; CHECK-NEXT:    [[P0:%.*]] = inttoptr i64 [[I0]] to ptr
451; CHECK-NEXT:    [[R:%.*]] = call align 4 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M]])
452; CHECK-NEXT:    ret ptr [[R]]
453;
454  %m0 = and i64 %m, -4
455  %i0 = and i64 %i, -4
456  %p0 = inttoptr i64 %i0 to ptr
457  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0)
458  ret ptr %r
459}
460
461define ptr @ptrmask_is_useless1(i64 %i, i64 %m) {
462; CHECK-LABEL: define ptr @ptrmask_is_useless1
463; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {
464; CHECK-NEXT:    [[I0:%.*]] = and i64 [[I]], -8
465; CHECK-NEXT:    [[P0:%.*]] = inttoptr i64 [[I0]] to ptr
466; CHECK-NEXT:    [[R:%.*]] = call align 8 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M]])
467; CHECK-NEXT:    ret ptr [[R]]
468;
469  %m0 = and i64 %m, -4
470  %i0 = and i64 %i, -8
471  %p0 = inttoptr i64 %i0 to ptr
472  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0)
473  ret ptr %r
474}
475
476define ptr @ptrmask_is_useless2(i64 %i, i64 %m) {
477; CHECK-LABEL: define ptr @ptrmask_is_useless2
478; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {
479; CHECK-NEXT:    [[I0:%.*]] = and i64 [[I]], 31
480; CHECK-NEXT:    [[P0:%.*]] = inttoptr i64 [[I0]] to ptr
481; CHECK-NEXT:    [[R:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M]])
482; CHECK-NEXT:    ret ptr [[R]]
483;
484  %m0 = and i64 %m, 127
485  %i0 = and i64 %i, 31
486  %p0 = inttoptr i64 %i0 to ptr
487  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0)
488  ret ptr %r
489}
490
491define ptr @ptrmask_is_useless3(i64 %i, i64 %m) {
492; CHECK-LABEL: define ptr @ptrmask_is_useless3
493; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {
494; CHECK-NEXT:    [[I0:%.*]] = and i64 [[I]], 127
495; CHECK-NEXT:    [[P0:%.*]] = inttoptr i64 [[I0]] to ptr
496; CHECK-NEXT:    [[R:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M]])
497; CHECK-NEXT:    ret ptr [[R]]
498;
499  %m0 = and i64 %m, 127
500  %i0 = and i64 %i, 127
501  %p0 = inttoptr i64 %i0 to ptr
502  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0)
503  ret ptr %r
504}
505
506define ptr @ptrmask_is_useless4(i64 %i, i64 %m) {
507; CHECK-LABEL: define ptr @ptrmask_is_useless4
508; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {
509; CHECK-NEXT:    [[I0:%.*]] = and i64 [[I]], -4
510; CHECK-NEXT:    [[P0:%.*]] = inttoptr i64 [[I0]] to ptr
511; CHECK-NEXT:    ret ptr [[P0]]
512;
513  %m0 = or i64 %m, -4
514  %i0 = and i64 %i, -4
515  %p0 = inttoptr i64 %i0 to ptr
516  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0)
517  ret ptr %r
518}
519
520define <2 x ptr> @ptrmask_is_useless_vec(<2 x i64> %i, <2 x i64> %m) {
521; CHECK-LABEL: define <2 x ptr> @ptrmask_is_useless_vec
522; CHECK-SAME: (<2 x i64> [[I:%.*]], <2 x i64> [[M:%.*]]) {
523; CHECK-NEXT:    [[I0:%.*]] = and <2 x i64> [[I]], splat (i64 31)
524; CHECK-NEXT:    [[P0:%.*]] = inttoptr <2 x i64> [[I0]] to <2 x ptr>
525; CHECK-NEXT:    [[R:%.*]] = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[P0]], <2 x i64> [[M]])
526; CHECK-NEXT:    ret <2 x ptr> [[R]]
527;
528  %m0 = and <2 x i64> %m, <i64 127, i64 127>
529  %i0 = and <2 x i64> %i, <i64 31, i64 31>
530  %p0 = inttoptr <2 x i64> %i0 to <2 x ptr>
531  %r = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p0, <2 x i64> %m0)
532  ret <2 x ptr> %r
533}
534
535define <2 x ptr> @ptrmask_is_useless_vec_todo(<2 x i64> %i, <2 x i64> %m) {
536; CHECK-LABEL: define <2 x ptr> @ptrmask_is_useless_vec_todo
537; CHECK-SAME: (<2 x i64> [[I:%.*]], <2 x i64> [[M:%.*]]) {
538; CHECK-NEXT:    [[I0:%.*]] = and <2 x i64> [[I]], <i64 31, i64 127>
539; CHECK-NEXT:    [[P0:%.*]] = inttoptr <2 x i64> [[I0]] to <2 x ptr>
540; CHECK-NEXT:    [[R:%.*]] = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[P0]], <2 x i64> [[M]])
541; CHECK-NEXT:    ret <2 x ptr> [[R]]
542;
543  %m0 = and <2 x i64> %m, <i64 127, i64 127>
544  %i0 = and <2 x i64> %i, <i64 31, i64 127>
545  %p0 = inttoptr <2 x i64> %i0 to <2 x ptr>
546  %r = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p0, <2 x i64> %m0)
547  ret <2 x ptr> %r
548}
549
550define ptr @ptrmask_is_useless_fail0(i64 %i, i64 %m) {
551; CHECK-LABEL: define ptr @ptrmask_is_useless_fail0
552; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {
553; CHECK-NEXT:    [[M0:%.*]] = and i64 [[M]], -4
554; CHECK-NEXT:    [[I0:%.*]] = or i64 [[I]], -4
555; CHECK-NEXT:    [[P0:%.*]] = inttoptr i64 [[I0]] to ptr
556; CHECK-NEXT:    [[R:%.*]] = call align 4 ptr @llvm.ptrmask.p0.i64(ptr nonnull [[P0]], i64 [[M0]])
557; CHECK-NEXT:    ret ptr [[R]]
558;
559  %m0 = and i64 %m, -4
560  %i0 = or i64 %i, -4
561  %p0 = inttoptr i64 %i0 to ptr
562  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0)
563  ret ptr %r
564}
565
566define ptr @ptrmask_is_useless_fail1(i64 %i, i64 %m) {
567; CHECK-LABEL: define ptr @ptrmask_is_useless_fail1
568; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {
569; CHECK-NEXT:    [[M0:%.*]] = and i64 [[M]], 127
570; CHECK-NEXT:    [[I0:%.*]] = and i64 [[I]], 511
571; CHECK-NEXT:    [[P0:%.*]] = inttoptr i64 [[I0]] to ptr
572; CHECK-NEXT:    [[R:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M0]])
573; CHECK-NEXT:    ret ptr [[R]]
574;
575  %m0 = and i64 %m, 127
576  %i0 = and i64 %i, 511
577  %p0 = inttoptr i64 %i0 to ptr
578  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0)
579  ret ptr %r
580}
581
582@GC_arrays = external global { i8, i8, i64 }
583
584define ptr @ptrmask_demandedbits_constantexpr() {
585; CHECK-LABEL: define ptr @ptrmask_demandedbits_constantexpr() {
586; CHECK-NEXT:  entry:
587; CHECK-NEXT:    [[ALIGNED_RESULT:%.*]] = call align 8 ptr @llvm.ptrmask.p0.i64(ptr nonnull @GC_arrays, i64 -8)
588; CHECK-NEXT:    ret ptr [[ALIGNED_RESULT]]
589;
590entry:
591  %aligned_result = call ptr @llvm.ptrmask.p0.i64(ptr getelementptr inbounds (i8, ptr @GC_arrays, i64 1), i64 -8)
592  ret ptr %aligned_result
593}
594