Skip to content

Commit de8a821

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

File tree

2 files changed

+147
-4
lines changed

2 files changed

+147
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,41 @@ 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+
auto *GEP = cast<GetElementPtrInst>(II->getArgOperand(0));
980+
981+
if (GEP->getSourceElementType() == Type::getInt8Ty(I->getContext())) {
982+
unsigned Log2Align = llvm::Log2(InnerPtr->getPointerAlignment(DL));
983+
uint64_t PointerAlignBits = (uint64_t(1) << Log2Align) - 1;
984+
985+
uint64_t HighBitsGEPIndex = GEPIndex & ~PointerAlignBits;
986+
uint64_t MaskedLowBitsGEPIndex =
987+
GEPIndex & PointerAlignBits & PtrMaskImmediate;
988+
989+
uint64_t MaskedGEPIndex = HighBitsGEPIndex | MaskedLowBitsGEPIndex;
990+
991+
if (MaskedGEPIndex != GEPIndex) {
992+
Type *I64 = Type::getInt64Ty(I->getContext());
993+
auto MaskedGEP =
994+
Builder.CreateGEP(GEP->getSourceElementType(), InnerPtr,
995+
ConstantInt::get(I64, MaskedGEPIndex),
996+
GEP->getName(), GEP->isInBounds());
997+
998+
replaceOperand(*I, 0, MaskedGEP);
999+
return I;
1000+
}
1001+
}
1002+
}
1003+
9691004
break;
9701005
}
9711006

llvm/test/Transforms/InstCombine/ptrmask.ll

Lines changed: 112 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,114 @@ 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_of_gep_requires_i8(ptr align 8 %p) {
375+
; CHECK-LABEL: define ptr @ptrmask_of_gep_requires_i8
376+
; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
377+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 8
378+
; CHECK-NEXT: [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[GEP1]], i64 -16)
379+
; CHECK-NEXT: ret ptr [[PM]]
380+
;
381+
%gep = getelementptr i16, ptr %p, i32 5
382+
%pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16)
383+
ret ptr %pm
384+
}
385+
386+
define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented(<2 x ptr> align 8 %p) {
387+
; CHECK-LABEL: define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented
388+
; CHECK-SAME: (<2 x ptr> align 8 [[P:%.*]]) {
389+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, <2 x ptr> [[P]], i64 17
390+
; CHECK-NEXT: [[PM:%.*]] = call align 32 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[GEP]], <2 x i64> <i64 -96, i64 -96>)
391+
; CHECK-NEXT: ret <2 x ptr> [[PM]]
392+
;
393+
%gep = getelementptr i8, <2 x ptr> %p, i32 17
394+
%pm = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %gep, <2 x i64> <i64 -96, i64 -96>)
395+
ret <2 x ptr> %pm
396+
}
397+
290398
define ptr @ptrmask_is_useless0(i64 %i, i64 %m) {
291399
; CHECK-LABEL: define ptr @ptrmask_is_useless0
292400
; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {

0 commit comments

Comments
 (0)