[llvm] [InstCombine] Fold pointer adding in integer to arithmetic add (PR #91596)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 9 07:21:34 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/3] [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/3] [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/3] [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) {



More information about the llvm-commits mailing list