[llvm] [InstCombine] ptrmask of gep for dynamic pointer aligment (PR #80002)
Jon Chesterfield via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 30 06:57:10 PST 2024
https://github.com/JonChesterfield updated https://github.com/llvm/llvm-project/pull/80002
>From a849004621097807a3794af4b97930be2cfcb8b7 Mon Sep 17 00:00:00 2001
From: Jon Chesterfield <jonathanchesterfield at gmail.com>
Date: Tue, 30 Jan 2024 13:04:26 +0000
Subject: [PATCH] [InstCombine] ptrmask of gep for dynamic pointer aligment
---
.../InstCombine/InstCombineCalls.cpp | 34 +++++
llvm/test/Transforms/InstCombine/ptrmask.ll | 116 +++++++++++++++++-
2 files changed, 146 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index a647be2d26c76..ed2cc14a23c51 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2040,6 +2040,40 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Changed = true;
}
+ // Combine:
+ // (ptrmask (getelementptr i8, ptr p, imm i), imm mask)
+ // -> (ptrmask (getelementptr i8, ptr p, imm (i & mask)), imm mask)
+ // where only the low bits known to be zero in the pointer are changed
+ uint64_t GEPIndex;
+ uint64_t PtrMaskImmediate;
+ if (match(&CI, m_Intrinsic<Intrinsic::ptrmask>(
+ m_GEP(m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
+ m_ConstantInt(PtrMaskImmediate)))) {
+ auto *GEP = cast<GetElementPtrInst>(II->getArgOperand(0));
+
+ if (GEP->getSourceElementType() == Type::getInt8Ty(CI.getContext())) {
+ unsigned Log2Align = llvm::Log2(InnerPtr->getPointerAlignment(DL));
+ uint64_t PointerAlignBits = (uint64_t(1) << Log2Align) - 1;
+
+ uint64_t HighBitsGEPIndex = GEPIndex & ~PointerAlignBits;
+ uint64_t MaskedLowBitsGEPIndex =
+ GEPIndex & PointerAlignBits & PtrMaskImmediate;
+
+ uint64_t MaskedGEPIndex = HighBitsGEPIndex | MaskedLowBitsGEPIndex;
+
+ if (MaskedGEPIndex != GEPIndex) {
+ Type *I64 = Type::getInt64Ty(CI.getContext());
+ auto MaskedGEP =
+ Builder.CreateGEP(GEP->getSourceElementType(), InnerPtr,
+ ConstantInt::get(I64, MaskedGEPIndex),
+ GEP->getName(), GEP->isInBounds());
+
+ replaceOperand(CI, 0, MaskedGEP);
+ Changed = true;
+ }
+ }
+ }
+
// See if we can deduce non-null.
if (!CI.hasRetAttr(Attribute::NonNull) &&
(Known.isNonZero() ||
diff --git a/llvm/test/Transforms/InstCombine/ptrmask.ll b/llvm/test/Transforms/InstCombine/ptrmask.ll
index afeb5d5251d0f..0870e0dbd8a6b 100644
--- a/llvm/test/Transforms/InstCombine/ptrmask.ll
+++ b/llvm/test/Transforms/InstCombine/ptrmask.ll
@@ -80,12 +80,12 @@ define ptr addrspace(1) @ptrmask_combine_consecutive_preserve_attrs_todo2(ptr ad
define ptr @ptrmask_combine_add_nonnull(ptr %p) {
; CHECK-LABEL: define ptr @ptrmask_combine_add_nonnull
; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT: [[PM0:%.*]] = call align 64 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -64)
-; CHECK-NEXT: [[PGEP:%.*]] = getelementptr i8, ptr [[PM0]], i64 33
-; CHECK-NEXT: [[R:%.*]] = call nonnull align 32 ptr @llvm.ptrmask.p0.i64(ptr [[PGEP]], i64 -32)
+; CHECK-NEXT: [[PM0:%.*]] = call align 4 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -60)
+; CHECK-NEXT: [[PGEP1:%.*]] = getelementptr i8, ptr [[PM0]], i64 32
+; CHECK-NEXT: [[R:%.*]] = call nonnull align 32 ptr @llvm.ptrmask.p0.i64(ptr [[PGEP1]], i64 -32)
; CHECK-NEXT: ret ptr [[R]]
;
- %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -64)
+ %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -60)
%pgep = getelementptr i8, ptr %pm0, i64 33
%r = call ptr @llvm.ptrmask.p0.i64(ptr %pgep, i64 -16)
ret ptr %r
@@ -287,6 +287,114 @@ define ptr addrspace(1) @ptrmask_maintain_provenance_i32(ptr addrspace(1) %p0) {
ret ptr addrspace(1) %r
}
+define ptr @ptrmask_is_nop0(ptr align 8 %p) {
+; CHECK-LABEL: define ptr @ptrmask_is_nop0
+; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
+; CHECK-NEXT: ret ptr [[P]]
+;
+ %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -8)
+ ret ptr %pm
+}
+
+define ptr @ptrmask_is_nop1(ptr align 8 %p) {
+; CHECK-LABEL: define ptr @ptrmask_is_nop1
+; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
+; CHECK-NEXT: ret ptr [[P]]
+;
+ %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -4)
+ ret ptr %pm
+}
+
+define ptr @ptrmask_to_modified_gep0(ptr align 8 %p) {
+; CHECK-LABEL: define ptr @ptrmask_to_modified_gep0
+; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
+; CHECK-NEXT: [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -16)
+; CHECK-NEXT: ret ptr [[PM]]
+;
+ %gep = getelementptr i8, ptr %p, i32 5
+ %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16)
+ ret ptr %pm
+}
+
+define ptr @ptrmask_to_modified_gep1(ptr align 8 %p) {
+; CHECK-LABEL: define ptr @ptrmask_to_modified_gep1
+; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
+; CHECK-NEXT: ret ptr [[P]]
+;
+ %gep = getelementptr i8, ptr %p, i32 6
+ %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -8)
+ ret ptr %pm
+}
+
+define ptr @ptrmask_to_modified_gep2(ptr align 16 %p) {
+; CHECK-LABEL: define ptr @ptrmask_to_modified_gep2
+; CHECK-SAME: (ptr align 16 [[P:%.*]]) {
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 12
+; CHECK-NEXT: ret ptr [[GEP1]]
+;
+ %gep = getelementptr i8, ptr %p, i32 15
+ %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4)
+ ret ptr %pm
+}
+
+define ptr @ptrmask_to_modified_gep4(ptr align 8 %p) {
+; CHECK-LABEL: define ptr @ptrmask_to_modified_gep4
+; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 24
+; CHECK-NEXT: [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[GEP1]], i64 -16)
+; CHECK-NEXT: ret ptr [[PM]]
+;
+ %gep = getelementptr i8, ptr %p, i32 29
+ %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16)
+ ret ptr %pm
+}
+
+define ptr @ptrmask_to_modified_gep5(ptr align 8 %p) {
+; CHECK-LABEL: define ptr @ptrmask_to_modified_gep5
+; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 24
+; CHECK-NEXT: ret ptr [[GEP1]]
+;
+ %gep = getelementptr i8, ptr %p, i32 30
+ %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -8)
+ ret ptr %pm
+}
+
+define ptr @ptrmask_to_modified_gep6(ptr align 16 %p) {
+; CHECK-LABEL: define ptr @ptrmask_to_modified_gep6
+; CHECK-SAME: (ptr align 16 [[P:%.*]]) {
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 28
+; CHECK-NEXT: ret ptr [[GEP1]]
+;
+ %gep = getelementptr i8, ptr %p, i32 31
+ %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4)
+ ret ptr %pm
+}
+
+define ptr @ptrmask_of_gep_requires_i8(ptr align 8 %p) {
+; CHECK-LABEL: define ptr @ptrmask_of_gep_requires_i8
+; CHECK-SAME: (ptr align 8 [[P:%.*]]) {
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 8
+; CHECK-NEXT: [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[GEP1]], i64 -16)
+; CHECK-NEXT: ret ptr [[PM]]
+;
+ %gep = getelementptr i16, ptr %p, i32 5
+ %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16)
+ ret ptr %pm
+}
+
+define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented(<2 x ptr> align 8 %p) {
+; CHECK-LABEL: define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented
+; CHECK-SAME: (<2 x ptr> align 8 [[P:%.*]]) {
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, <2 x ptr> [[P]], i64 17
+; CHECK-NEXT: [[PM:%.*]] = call align 32 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[GEP]], <2 x i64> <i64 -96, i64 -96>)
+; CHECK-NEXT: ret <2 x ptr> [[PM]]
+;
+ %gep = getelementptr i8, <2 x ptr> %p, i32 17
+ %pm = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %gep, <2 x i64> <i64 -96, i64 -96>)
+ ret <2 x ptr> %pm
+}
+
define ptr @ptrmask_is_useless0(i64 %i, i64 %m) {
; CHECK-LABEL: define ptr @ptrmask_is_useless0
; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) {
More information about the llvm-commits
mailing list