Skip to content

Commit 3fc2507

Browse files
[InstCombine] ptrmask of gep for dynamic pointer aligment
1 parent 3ab5dbb commit 3fc2507

File tree

2 files changed

+192
-4
lines changed

2 files changed

+192
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,48 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
966966
I, 1, (DemandedMask & ~LHSKnown.Zero).zextOrTrunc(MaskWidth)))
967967
return I;
968968

969+
// Combine:
970+
// (ptrmask (getelementptr i8, ptr p, imm i), imm mask)
971+
// -> (ptrmask (getelementptr i8, ptr p, imm (i & mask)), imm mask)
972+
// where only the low bits known to be zero in the pointer are changed
973+
Value *InnerPtr;
974+
uint64_t GEPIndex;
975+
uint64_t PtrMaskImmediate;
976+
if (match(I, m_Intrinsic<Intrinsic::ptrmask>(
977+
m_GEP(m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
978+
m_ConstantInt(PtrMaskImmediate)))) {
979+
980+
auto *GEP = cast<GetElementPtrInst>(II->getArgOperand(0));
981+
982+
const unsigned trailingZeros =
983+
computeKnownBits(GEP->getOperand(0), Depth + 1, GEP)
984+
.countMinTrailingZeros();
985+
const bool charIndexed =
986+
GEP->getSourceElementType() == Type::getInt8Ty(I->getContext());
987+
988+
if (charIndexed && (trailingZeros < 64)) {
989+
uint64_t PointerAlignBits = (uint64_t(1) << trailingZeros) - 1;
990+
991+
uint64_t HighBitsGEPIndex = GEPIndex & ~PointerAlignBits;
992+
uint64_t MaskedLowBitsGEPIndex =
993+
GEPIndex & PointerAlignBits & PtrMaskImmediate;
994+
995+
uint64_t MaskedGEPIndex = HighBitsGEPIndex | MaskedLowBitsGEPIndex;
996+
997+
if (MaskedGEPIndex != GEPIndex) {
998+
Type *I64 = Type::getInt64Ty(I->getContext());
999+
Builder.SetInsertPoint(I);
1000+
Vakue *MaskedGEP =
1001+
Builder.CreateGEP(GEP->getSourceElementType(), InnerPtr,
1002+
ConstantInt::get(I64, MaskedGEPIndex),
1003+
GEP->getName(), GEP->isInBounds());
1004+
1005+
replaceOperand(*I, 0, MaskedGEP);
1006+
return I;
1007+
}
1008+
}
1009+
}
1010+
9691011
break;
9701012
}
9711013

llvm/test/Transforms/InstCombine/ptrmask.ll

Lines changed: 150 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ define ptr addrspace(1) @ptrmask_combine_consecutive_preserve_attrs_todo2(ptr ad
8080
define ptr @ptrmask_combine_add_nonnull(ptr %p) {
8181
; CHECK-LABEL: define ptr @ptrmask_combine_add_nonnull
8282
; CHECK-SAME: (ptr [[P:%.*]]) {
83-
; CHECK-NEXT: [[PM0:%.*]] = call align 64 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -64)
84-
; CHECK-NEXT: [[PGEP:%.*]] = getelementptr i8, ptr [[PM0]], i64 33
85-
; CHECK-NEXT: [[R:%.*]] = call nonnull align 32 ptr @llvm.ptrmask.p0.i64(ptr [[PGEP]], i64 -32)
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)
8686
; CHECK-NEXT: ret ptr [[R]]
8787
;
88-
%pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -64)
88+
%pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -60)
8989
%pgep = getelementptr i8, ptr %pm0, i64 33
9090
%r = call ptr @llvm.ptrmask.p0.i64(ptr %pgep, i64 -16)
9191
ret ptr %r
@@ -287,6 +287,152 @@ define ptr addrspace(1) @ptrmask_maintain_provenance_i32(ptr addrspace(1) %p0) {
287287
ret ptr addrspace(1) %r
288288
}
289289

290+
define 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+
299+
define 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+
308+
define 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+
319+
define 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+
329+
define 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+
340+
define 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+
352+
define 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+
363+
define 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+
374+
define 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+
; 44 from 4*sizeof(i32) + (31 & -4)
378+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 44
379+
; CHECK-NEXT: ret ptr [[GEP1]]
380+
;
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+
387+
define ptr @ptrmask_to_modified_gep_indirect1(ptr %p) {
388+
; CHECK-LABEL: define ptr @ptrmask_to_modified_gep_indirect1
389+
; CHECK-SAME: (ptr [[P:%.*]]) {
390+
391+
; CHECK-NEXT: [[R:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -16)
392+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[R]], i64 32
393+
; CHECK-NEXT: ret ptr [[GEP]]
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+
401+
define ptr @ptrmask_to_preserves_inbounds(ptr align 16 %p) {
402+
; CHECK-LABEL: define ptr @ptrmask_to_preserves_inbounds
403+
; CHECK-SAME: (ptr align 16 [[P:%.*]]) {
404+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 28
405+
; CHECK-NEXT: ret ptr [[GEP1]]
406+
;
407+
%gep = getelementptr inbounds i8, ptr %p, i32 31
408+
%pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4)
409+
ret ptr %pm
410+
}
411+
412+
define ptr @ptrmask_of_gep_requires_i8(ptr align 8 %p) {
413+
; CHECK-LABEL: define ptr @ptrmask_of_gep_requires_i8
414+
; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
415+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 8
416+
; CHECK-NEXT: [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[GEP1]], i64 -16)
417+
; CHECK-NEXT: ret ptr [[PM]]
418+
;
419+
%gep = getelementptr i16, ptr %p, i32 5
420+
%pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16)
421+
ret ptr %pm
422+
}
423+
424+
define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented(<2 x ptr> align 8 %p) {
425+
; CHECK-LABEL: define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented
426+
; CHECK-SAME: (<2 x ptr> align 8 [[P:%.*]]) {
427+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, <2 x ptr> [[P]], i64 17
428+
; CHECK-NEXT: [[PM:%.*]] = call align 32 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[GEP]], <2 x i64> <i64 -96, i64 -96>)
429+
; CHECK-NEXT: ret <2 x ptr> [[PM]]
430+
;
431+
%gep = getelementptr i8, <2 x ptr> %p, i32 17
432+
%pm = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %gep, <2 x i64> <i64 -96, i64 -96>)
433+
ret <2 x ptr> %pm
434+
}
435+
290436
define ptr @ptrmask_is_useless0(i64 %i, i64 %m) {
291437
; CHECK-LABEL: define ptr @ptrmask_is_useless0
292438
; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {

0 commit comments

Comments
 (0)