[llvm] [InstCombine] Fold pointer adding in integer to arithmetic add (PR #91596)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 16 06:12:48 PDT 2024
https://github.com/YanWQ-monad updated https://github.com/llvm/llvm-project/pull/91596
>From c33503abc9c7b08f64878ec3c4dcdb1d7b4bc3fb Mon Sep 17 00:00:00 2001
From: YanWQ-monad <YanWQmonad at gmail.com>
Date: Thu, 9 May 2024 20:15:28 +0800
Subject: [PATCH 1/4] [InstCombine] Pre-commit: add tests
---
llvm/test/Transforms/InstCombine/cast_ptr.ll | 58 ++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/cast_ptr.ll b/llvm/test/Transforms/InstCombine/cast_ptr.ll
index 5c6c012064e05..185c02fbdafca 100644
--- a/llvm/test/Transforms/InstCombine/cast_ptr.ll
+++ b/llvm/test/Transforms/InstCombine/cast_ptr.ll
@@ -244,3 +244,61 @@ define <2 x i32> @insertelt_extra_use2(<2 x i32> %x, ptr %p) {
%r = ptrtoint <2 x ptr> %i to <2 x i32>
ret <2 x i32> %r
}
+
+define i32 @ptr_add_in_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @ptr_add_in_int(
+; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr
+; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i32 [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %ptr = inttoptr i32 %x to ptr
+ %p2 = getelementptr inbounds i8, ptr %ptr, i32 %y
+ %r = ptrtoint ptr %p2 to i32
+ ret i32 %r
+}
+
+define i32 @ptr_add_in_int_const(i32 %x) {
+; CHECK-LABEL: @ptr_add_in_int_const(
+; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr
+; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i32 4096
+; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %ptr = inttoptr i32 %x to ptr
+ %p2 = getelementptr inbounds i8, ptr %ptr, i32 4096
+ %r = ptrtoint ptr %p2 to i32
+ ret i32 %r
+}
+
+declare void @use_ptr(ptr)
+
+define i32 @ptr_add_in_int_extra_use1(i32 %x) {
+; CHECK-LABEL: @ptr_add_in_int_extra_use1(
+; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr
+; CHECK-NEXT: call void @use_ptr(ptr [[PTR]])
+; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i32 4096
+; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %ptr = inttoptr i32 %x to ptr
+ call void @use_ptr(ptr %ptr)
+ %p2 = getelementptr inbounds i8, ptr %ptr, i32 4096
+ %r = ptrtoint ptr %p2 to i32
+ ret i32 %r
+}
+
+define i32 @ptr_add_in_int_extra_use2(i32 %x) {
+; CHECK-LABEL: @ptr_add_in_int_extra_use2(
+; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr
+; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i32 4096
+; CHECK-NEXT: call void @use_ptr(ptr nonnull [[P2]])
+; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %ptr = inttoptr i32 %x to ptr
+ %p2 = getelementptr inbounds i8, ptr %ptr, i32 4096
+ call void @use_ptr(ptr %p2)
+ %r = ptrtoint ptr %p2 to i32
+ ret i32 %r
+}
>From 2ead05c200c649938587ba539eab8c3239b8f740 Mon Sep 17 00:00:00 2001
From: YanWQ-monad <YanWQmonad at gmail.com>
Date: Thu, 9 May 2024 21:19:52 +0800
Subject: [PATCH 2/4] [InstCombine] Fold pointer adding in integer to
arithmetic add
---
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 10 ++++++++++
llvm/test/Transforms/InstCombine/cast_ptr.ll | 8 ++------
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 11e31877de38c..18ad8706f8843 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -2073,6 +2073,16 @@ Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) {
return InsertElementInst::Create(Vec, NewCast, Index);
}
+ // (ptrtoint (gep (inttoptr Base), Offset)) -> Base + Offset
+ Value *Base, *Offset;
+ if (match(SrcOp, m_OneUse(m_PtrAdd(m_OneUse(m_IntToPtr(m_Value(Base))),
+ m_Value(Offset)))) &&
+ Base->getType() == Ty && Offset->getType() == Ty) {
+ auto *NewOp = BinaryOperator::CreateAdd(Base, Offset);
+ NewOp->setHasNoUnsignedWrap(true);
+ return NewOp;
+ }
+
return commonCastTransforms(CI);
}
diff --git a/llvm/test/Transforms/InstCombine/cast_ptr.ll b/llvm/test/Transforms/InstCombine/cast_ptr.ll
index 185c02fbdafca..0e191748226df 100644
--- a/llvm/test/Transforms/InstCombine/cast_ptr.ll
+++ b/llvm/test/Transforms/InstCombine/cast_ptr.ll
@@ -247,9 +247,7 @@ define <2 x i32> @insertelt_extra_use2(<2 x i32> %x, ptr %p) {
define i32 @ptr_add_in_int(i32 %x, i32 %y) {
; CHECK-LABEL: @ptr_add_in_int(
-; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr
-; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i32 [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32
+; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i32 [[R]]
;
%ptr = inttoptr i32 %x to ptr
@@ -260,9 +258,7 @@ define i32 @ptr_add_in_int(i32 %x, i32 %y) {
define i32 @ptr_add_in_int_const(i32 %x) {
; CHECK-LABEL: @ptr_add_in_int_const(
-; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr
-; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i32 4096
-; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32
+; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], 4096
; CHECK-NEXT: ret i32 [[R]]
;
%ptr = inttoptr i32 %x to ptr
>From fb5bd152f6e8bc52b3c0e3c45ae2759998f39e72 Mon Sep 17 00:00:00 2001
From: YanWQ-monad <YanWQmonad at gmail.com>
Date: Thu, 9 May 2024 22:19:33 +0800
Subject: [PATCH 3/4] [InstCombine] Check before add nuw flag
---
.../InstCombine/InstCombineCasts.cpp | 12 ++++--
llvm/test/Transforms/InstCombine/cast_ptr.ll | 39 ++++++++++++++++++-
2 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 18ad8706f8843..1801fda1e80c2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -2074,12 +2074,16 @@ Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) {
}
// (ptrtoint (gep (inttoptr Base), Offset)) -> Base + Offset
- Value *Base, *Offset;
- if (match(SrcOp, m_OneUse(m_PtrAdd(m_OneUse(m_IntToPtr(m_Value(Base))),
- m_Value(Offset)))) &&
+ Value *Base, *Offset, *GEP;
+ if (match(SrcOp, m_OneUse(m_Value(GEP))) &&
+ match(GEP,
+ m_PtrAdd(m_OneUse(m_IntToPtr(m_Value(Base))), m_Value(Offset))) &&
Base->getType() == Ty && Offset->getType() == Ty) {
+ auto *GEPInst = cast<GetElementPtrInst>(GEP);
+
auto *NewOp = BinaryOperator::CreateAdd(Base, Offset);
- NewOp->setHasNoUnsignedWrap(true);
+ if (GEPInst->isInBounds() && isKnownNonNegative(Offset, SQ))
+ NewOp->setHasNoUnsignedWrap(true);
return NewOp;
}
diff --git a/llvm/test/Transforms/InstCombine/cast_ptr.ll b/llvm/test/Transforms/InstCombine/cast_ptr.ll
index 0e191748226df..278e9d8452337 100644
--- a/llvm/test/Transforms/InstCombine/cast_ptr.ll
+++ b/llvm/test/Transforms/InstCombine/cast_ptr.ll
@@ -247,7 +247,7 @@ define <2 x i32> @insertelt_extra_use2(<2 x i32> %x, ptr %p) {
define i32 @ptr_add_in_int(i32 %x, i32 %y) {
; CHECK-LABEL: @ptr_add_in_int(
-; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i32 [[R]]
;
%ptr = inttoptr i32 %x to ptr
@@ -256,6 +256,32 @@ define i32 @ptr_add_in_int(i32 %x, i32 %y) {
ret i32 %r
}
+define i32 @ptr_add_in_int_nneg(i32 %x, i32 %y) {
+; CHECK-LABEL: @ptr_add_in_int_nneg(
+; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)
+; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[Z]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %z = call i32 @llvm.abs.i32(i32 %y, i1 true)
+ %ptr = inttoptr i32 %x to ptr
+ %p2 = getelementptr inbounds i8, ptr %ptr, i32 %z
+ %r = ptrtoint ptr %p2 to i32
+ ret i32 %r
+}
+
+define i32 @ptr_add_in_int_not_inbounds(i32 %x, i32 %y) {
+; CHECK-LABEL: @ptr_add_in_int_not_inbounds(
+; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)
+; CHECK-NEXT: [[R:%.*]] = add i32 [[Z]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %z = call i32 @llvm.abs.i32(i32 %y, i1 true)
+ %ptr = inttoptr i32 %x to ptr
+ %p2 = getelementptr i8, ptr %ptr, i32 %z
+ %r = ptrtoint ptr %p2 to i32
+ ret i32 %r
+}
+
define i32 @ptr_add_in_int_const(i32 %x) {
; CHECK-LABEL: @ptr_add_in_int_const(
; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], 4096
@@ -267,6 +293,17 @@ define i32 @ptr_add_in_int_const(i32 %x) {
ret i32 %r
}
+define i32 @ptr_add_in_int_const_negative(i32 %x) {
+; CHECK-LABEL: @ptr_add_in_int_const_negative(
+; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], -4096
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %ptr = inttoptr i32 %x to ptr
+ %p2 = getelementptr inbounds i8, ptr %ptr, i32 -4096
+ %r = ptrtoint ptr %p2 to i32
+ ret i32 %r
+}
+
declare void @use_ptr(ptr)
define i32 @ptr_add_in_int_extra_use1(i32 %x) {
>From 58f22f90b417628902e79d7276e7fbe207f60d22 Mon Sep 17 00:00:00 2001
From: YanWQ-monad <YanWQmonad at gmail.com>
Date: Thu, 16 May 2024 21:11:49 +0800
Subject: [PATCH 4/4] [InstCombine] Support for arbitrary GEPs
---
.../InstCombine/InstCombineCasts.cpp | 34 +++++++++----------
llvm/test/Transforms/InstCombine/cast_ptr.ll | 12 +++++++
2 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 1801fda1e80c2..1b4c319032cab 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -2049,16 +2049,28 @@ Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) {
Mask->getType() == Ty)
return BinaryOperator::CreateAnd(Builder.CreatePtrToInt(Ptr, Ty), Mask);
- if (auto *GEP = dyn_cast<GetElementPtrInst>(SrcOp)) {
+ if (auto *GEP = dyn_cast<GEPOperator>(SrcOp)) {
// Fold ptrtoint(gep null, x) to multiply + constant if the GEP has one use.
// While this can increase the number of instructions it doesn't actually
// increase the overall complexity since the arithmetic is just part of
// the GEP otherwise.
if (GEP->hasOneUse() &&
isa<ConstantPointerNull>(GEP->getPointerOperand())) {
- return replaceInstUsesWith(
- CI, Builder.CreateIntCast(EmitGEPOffset(cast<GEPOperator>(GEP)), Ty,
- /*isSigned=*/false));
+ return replaceInstUsesWith(CI,
+ Builder.CreateIntCast(EmitGEPOffset(GEP), Ty,
+ /*isSigned=*/false));
+ }
+
+ // (ptrtoint (gep (inttoptr Base), ...)) -> Base + Offset
+ Value *Base;
+ if (GEP->hasOneUse() &&
+ match(GEP->getPointerOperand(), m_OneUse(m_IntToPtr(m_Value(Base)))) &&
+ Base->getType() == Ty) {
+ Value *Offset = EmitGEPOffset(GEP);
+ auto *NewOp = BinaryOperator::CreateAdd(Base, Offset);
+ if (GEP->isInBounds() && isKnownNonNegative(Offset, SQ))
+ NewOp->setHasNoUnsignedWrap(true);
+ return NewOp;
}
}
@@ -2073,20 +2085,6 @@ Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) {
return InsertElementInst::Create(Vec, NewCast, Index);
}
- // (ptrtoint (gep (inttoptr Base), Offset)) -> Base + Offset
- Value *Base, *Offset, *GEP;
- if (match(SrcOp, m_OneUse(m_Value(GEP))) &&
- match(GEP,
- m_PtrAdd(m_OneUse(m_IntToPtr(m_Value(Base))), m_Value(Offset))) &&
- Base->getType() == Ty && Offset->getType() == Ty) {
- auto *GEPInst = cast<GetElementPtrInst>(GEP);
-
- auto *NewOp = BinaryOperator::CreateAdd(Base, Offset);
- if (GEPInst->isInBounds() && isKnownNonNegative(Offset, SQ))
- NewOp->setHasNoUnsignedWrap(true);
- return NewOp;
- }
-
return commonCastTransforms(CI);
}
diff --git a/llvm/test/Transforms/InstCombine/cast_ptr.ll b/llvm/test/Transforms/InstCombine/cast_ptr.ll
index 278e9d8452337..130a9f6b8833c 100644
--- a/llvm/test/Transforms/InstCombine/cast_ptr.ll
+++ b/llvm/test/Transforms/InstCombine/cast_ptr.ll
@@ -256,6 +256,18 @@ define i32 @ptr_add_in_int(i32 %x, i32 %y) {
ret i32 %r
}
+define i32 @ptr_add_in_int_2(i32 %x, i32 %y) {
+; CHECK-LABEL: @ptr_add_in_int_2(
+; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i32 [[Y:%.*]], 2
+; CHECK-NEXT: [[R:%.*]] = add i32 [[P2_IDX]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %ptr = inttoptr i32 %x to ptr
+ %p2 = getelementptr inbounds i32, ptr %ptr, i32 %y
+ %r = ptrtoint ptr %p2 to i32
+ ret i32 %r
+}
+
define i32 @ptr_add_in_int_nneg(i32 %x, i32 %y) {
; CHECK-LABEL: @ptr_add_in_int_nneg(
; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)
More information about the llvm-commits
mailing list