Skip to content

Commit 56a3ced

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

File tree

2 files changed

+122
-4
lines changed

2 files changed

+122
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,6 +2040,40 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
20402040
Changed = true;
20412041
}
20422042

2043+
// Combine:
2044+
// (ptrmask (getelementptr i8, ptr p, imm i), imm mask)
2045+
// -> (ptrmask (getelementptr i8, ptr p, imm (i & mask)), imm mask)
2046+
// where only the low bits known to be zero in the pointer are changed
2047+
uint64_t GEPIndex;
2048+
uint64_t PtrMaskImmediate;
2049+
if (match(&CI, m_Intrinsic<Intrinsic::ptrmask>(
2050+
m_GEP(m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
2051+
m_ConstantInt(PtrMaskImmediate)))) {
2052+
auto *GEP = cast<GetElementPtrInst>(II->getArgOperand(0));
2053+
2054+
if (GEP->getSourceElementType() == Type::getInt8Ty(CI.getContext())) {
2055+
unsigned Log2Align = llvm::Log2(InnerPtr->getPointerAlignment(DL));
2056+
uint64_t PointerAlignBits = (uint64_t(1) << Log2Align) - 1;
2057+
2058+
uint64_t HighBitsGEPIndex = GEPIndex & ~PointerAlignBits;
2059+
uint64_t MaskedLowBitsGEPIndex =
2060+
GEPIndex & PointerAlignBits & PtrMaskImmediate;
2061+
2062+
uint64_t MaskedGEPIndex = HighBitsGEPIndex | MaskedLowBitsGEPIndex;
2063+
2064+
if (MaskedGEPIndex != GEPIndex) {
2065+
Type *I64 = Type::getInt64Ty(CI.getContext());
2066+
auto MaskedGEP =
2067+
Builder.CreateGEP(GEP->getSourceElementType(), InnerPtr,
2068+
ConstantInt::get(I64, MaskedGEPIndex),
2069+
GEP->getName(), GEP->isInBounds());
2070+
2071+
replaceOperand(CI, 0, MaskedGEP);
2072+
Changed = true;
2073+
}
2074+
}
2075+
}
2076+
20432077
// See if we can deduce non-null.
20442078
if (!CI.hasRetAttr(Attribute::NonNull) &&
20452079
(Known.isNonZero() ||

llvm/test/Transforms/InstCombine/ptrmask.ll

Lines changed: 88 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,90 @@ 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+
290374
define ptr @ptrmask_is_useless0(i64 %i, i64 %m) {
291375
; CHECK-LABEL: define ptr @ptrmask_is_useless0
292376
; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {

0 commit comments

Comments
 (0)