[llvm] [InstCombine] Compare `icmp inttoptr, inttoptr` values directly (PR #107012)

Marina Taylor via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 13 07:00:20 PDT 2024


https://github.com/citymarina updated https://github.com/llvm/llvm-project/pull/107012

>From 33b53c02085edf3bbed3da66e3ad0dd70e95e395 Mon Sep 17 00:00:00 2001
From: Marina Taylor <marina_taylor at apple.com>
Date: Fri, 6 Sep 2024 11:47:32 +0100
Subject: [PATCH 1/2] [InstCombine] Add tests for fold of `icmp inttoptr,
 inttoptr`. NFC

---
 .../Transforms/InstCombine/icmp-inttoptr.ll   | 108 ++++++++++++++++++
 1 file changed, 108 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/icmp-inttoptr.ll

diff --git a/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll b/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll
new file mode 100644
index 00000000000000..692948c6c17899
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll
@@ -0,0 +1,108 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+declare void @use_ptr(ptr)
+
+define i1 @inttoptr(i64 %x, i64 %y) {
+; CHECK-LABEL: @inttoptr(
+; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr i64 [[X:%.*]] to ptr
+; CHECK-NEXT:    [[YPTR:%.*]] = inttoptr i64 [[Y:%.*]] to ptr
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[XPTR]], [[YPTR]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %xptr = inttoptr i64 %x to ptr
+  %yptr = inttoptr i64 %y to ptr
+  %cmp = icmp eq ptr %xptr, %yptr
+  ret i1 %cmp
+}
+
+define i1 @inttoptr_constant(i64 %x) {
+; CHECK-LABEL: @inttoptr_constant(
+; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr i64 [[X:%.*]] to ptr
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[XPTR]], inttoptr (i64 42 to ptr)
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %xptr = inttoptr i64 %x to ptr
+  %cmp = icmp eq ptr %xptr, inttoptr (i64 42 to ptr)
+  ret i1 %cmp
+}
+
+define <2 x i1> @inttoptr_vector(<2 x i64> %x, <2 x i64> %y) {
+; CHECK-LABEL: @inttoptr_vector(
+; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr <2 x i64> [[X:%.*]] to <2 x ptr>
+; CHECK-NEXT:    [[YPTR:%.*]] = inttoptr <2 x i64> [[Y:%.*]] to <2 x ptr>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x ptr> [[XPTR]], [[YPTR]]
+; CHECK-NEXT:    ret <2 x i1> [[CMP]]
+;
+  %xptr = inttoptr <2 x i64> %x to <2 x ptr>
+  %yptr = inttoptr <2 x i64> %y to <2 x ptr>
+  %cmp = icmp eq <2 x ptr> %xptr, %yptr
+  ret <2 x i1> %cmp
+}
+
+define <2 x i1> @inttoptr_vector_constant(<2 x i64> %x) {
+; CHECK-LABEL: @inttoptr_vector_constant(
+; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr <2 x i64> [[X:%.*]] to <2 x ptr>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x ptr> [[XPTR]], <ptr inttoptr (i64 42 to ptr), ptr inttoptr (i64 123 to ptr)>
+; CHECK-NEXT:    ret <2 x i1> [[CMP]]
+;
+  %xptr = inttoptr <2 x i64> %x to <2 x ptr>
+  %cmp = icmp eq <2 x ptr> %xptr, inttoptr (<2 x i64> <i64 42, i64 123> to <2 x ptr>)
+  ret <2 x i1> %cmp
+}
+
+define i1 @inttoptr_size_mismatch(i200 %x, i9 %y) {
+; CHECK-LABEL: @inttoptr_size_mismatch(
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i200 [[X:%.*]] to i64
+; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr i64 [[TMP1]] to ptr
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i9 [[Y:%.*]] to i64
+; CHECK-NEXT:    [[YPTR:%.*]] = inttoptr i64 [[TMP2]] to ptr
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[XPTR]], [[YPTR]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %xptr = inttoptr i200 %x to ptr
+  %yptr = inttoptr i9 %y to ptr
+  %cmp = icmp eq ptr %xptr, %yptr
+  ret i1 %cmp
+}
+
+define <2 x i1> @inttoptr_vector_constant_size_mismatch(<2 x i200> %x) {
+; CHECK-LABEL: @inttoptr_vector_constant_size_mismatch(
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i200> [[X:%.*]] to <2 x i64>
+; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr <2 x i64> [[TMP1]] to <2 x ptr>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x ptr> [[XPTR]], <ptr inttoptr (i9 42 to ptr), ptr inttoptr (i9 123 to ptr)>
+; CHECK-NEXT:    ret <2 x i1> [[CMP]]
+;
+  %xptr = inttoptr <2 x i200> %x to <2 x ptr>
+  %cmp = icmp eq <2 x ptr> %xptr, inttoptr (<2x i9> <i9 42, i9 123> to <2 x ptr>)
+  ret <2 x i1> %cmp
+}
+
+define i1 @inttoptr_oneside(i64 %x, ptr %y) {
+; CHECK-LABEL: @inttoptr_oneside(
+; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr i64 [[X:%.*]] to ptr
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[Y:%.*]], [[XPTR]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %xptr = inttoptr i64 %x to ptr
+  %cmp = icmp eq ptr %xptr, %y
+  ret i1 %cmp
+}
+
+define i1 @inttoptr_used(i64 %x, i64 %y) {
+; CHECK-LABEL: @inttoptr_used(
+; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr i64 [[X:%.*]] to ptr
+; CHECK-NEXT:    [[YPTR:%.*]] = inttoptr i64 [[Y:%.*]] to ptr
+; CHECK-NEXT:    call void @use_ptr(ptr [[XPTR]])
+; CHECK-NEXT:    call void @use_ptr(ptr [[YPTR]])
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt ptr [[XPTR]], [[YPTR]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %xptr = inttoptr i64 %x to ptr
+  %yptr = inttoptr i64 %y to ptr
+  call void @use_ptr(ptr %xptr)
+  call void @use_ptr(ptr %yptr)
+  %cmp = icmp ugt ptr %xptr, %yptr
+  ret i1 %cmp
+}
+

>From 0204fad8c95201acc6e4aac8fd2b0b8d54a54829 Mon Sep 17 00:00:00 2001
From: Marina Taylor <marina_taylor at apple.com>
Date: Fri, 13 Sep 2024 14:54:29 +0100
Subject: [PATCH 2/2] [InstCombine] Compare `icmp inttoptr, inttoptr` values
 directly

InstCombine already has some rules for `icmp ptrtoint, ptrtoint` to
drop the casts and compare the source values. This change adds the
same for the reverse case with `inttoptr`.
---
 .../InstCombine/InstCombineCompares.cpp       | 26 +++++++++++++++----
 .../Transforms/InstCombine/icmp-inttoptr.ll   | 23 +++++-----------
 2 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 8e8d472a5df1d3..b8ab07824b8551 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6081,12 +6081,12 @@ Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {
 
   // Turn icmp (ptrtoint x), (ptrtoint/c) into a compare of the input if the
   // integer type is the same size as the pointer type.
-  auto CompatibleSizes = [&](Type *SrcTy, Type *DestTy) {
-    if (isa<VectorType>(SrcTy)) {
-      SrcTy = cast<VectorType>(SrcTy)->getElementType();
-      DestTy = cast<VectorType>(DestTy)->getElementType();
+  auto CompatibleSizes = [&](Type *PtrTy, Type *IntTy) {
+    if (isa<VectorType>(PtrTy)) {
+      PtrTy = cast<VectorType>(PtrTy)->getElementType();
+      IntTy = cast<VectorType>(IntTy)->getElementType();
     }
-    return DL.getPointerTypeSizeInBits(SrcTy) == DestTy->getIntegerBitWidth();
+    return DL.getPointerTypeSizeInBits(PtrTy) == IntTy->getIntegerBitWidth();
   };
   if (CastOp0->getOpcode() == Instruction::PtrToInt &&
       CompatibleSizes(SrcTy, DestTy)) {
@@ -6103,6 +6103,22 @@ Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {
       return new ICmpInst(ICmp.getPredicate(), Op0Src, NewOp1);
   }
 
+  // Do the same in the other direction for icmp (inttoptr x), (inttoptr/c).
+  if (CastOp0->getOpcode() == Instruction::IntToPtr &&
+      CompatibleSizes(DestTy, SrcTy)) {
+    Value *NewOp1 = nullptr;
+    if (auto *IntToPtrOp1 = dyn_cast<IntToPtrInst>(ICmp.getOperand(1))) {
+      Value *IntSrc = IntToPtrOp1->getOperand(0);
+      if (IntSrc->getType() == Op0Src->getType())
+        NewOp1 = IntToPtrOp1->getOperand(0);
+    } else if (auto *RHSC = dyn_cast<Constant>(ICmp.getOperand(1))) {
+      NewOp1 = ConstantFoldConstant(ConstantExpr::getPtrToInt(RHSC, SrcTy), DL);
+    }
+
+    if (NewOp1)
+      return new ICmpInst(ICmp.getPredicate(), Op0Src, NewOp1);
+  }
+
   if (Instruction *R = foldICmpWithTrunc(ICmp))
     return R;
 
diff --git a/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll b/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll
index 692948c6c17899..5504a1d40e95ea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll
@@ -5,9 +5,7 @@ declare void @use_ptr(ptr)
 
 define i1 @inttoptr(i64 %x, i64 %y) {
 ; CHECK-LABEL: @inttoptr(
-; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr i64 [[X:%.*]] to ptr
-; CHECK-NEXT:    [[YPTR:%.*]] = inttoptr i64 [[Y:%.*]] to ptr
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[XPTR]], [[YPTR]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %xptr = inttoptr i64 %x to ptr
@@ -18,8 +16,7 @@ define i1 @inttoptr(i64 %x, i64 %y) {
 
 define i1 @inttoptr_constant(i64 %x) {
 ; CHECK-LABEL: @inttoptr_constant(
-; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr i64 [[X:%.*]] to ptr
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[XPTR]], inttoptr (i64 42 to ptr)
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[X:%.*]], 42
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %xptr = inttoptr i64 %x to ptr
@@ -29,9 +26,7 @@ define i1 @inttoptr_constant(i64 %x) {
 
 define <2 x i1> @inttoptr_vector(<2 x i64> %x, <2 x i64> %y) {
 ; CHECK-LABEL: @inttoptr_vector(
-; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr <2 x i64> [[X:%.*]] to <2 x ptr>
-; CHECK-NEXT:    [[YPTR:%.*]] = inttoptr <2 x i64> [[Y:%.*]] to <2 x ptr>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x ptr> [[XPTR]], [[YPTR]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i64> [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %xptr = inttoptr <2 x i64> %x to <2 x ptr>
@@ -42,8 +37,7 @@ define <2 x i1> @inttoptr_vector(<2 x i64> %x, <2 x i64> %y) {
 
 define <2 x i1> @inttoptr_vector_constant(<2 x i64> %x) {
 ; CHECK-LABEL: @inttoptr_vector_constant(
-; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr <2 x i64> [[X:%.*]] to <2 x ptr>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x ptr> [[XPTR]], <ptr inttoptr (i64 42 to ptr), ptr inttoptr (i64 123 to ptr)>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i64> [[X:%.*]], <i64 42, i64 123>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %xptr = inttoptr <2 x i64> %x to <2 x ptr>
@@ -54,10 +48,8 @@ define <2 x i1> @inttoptr_vector_constant(<2 x i64> %x) {
 define i1 @inttoptr_size_mismatch(i200 %x, i9 %y) {
 ; CHECK-LABEL: @inttoptr_size_mismatch(
 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i200 [[X:%.*]] to i64
-; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr i64 [[TMP1]] to ptr
 ; CHECK-NEXT:    [[TMP2:%.*]] = zext i9 [[Y:%.*]] to i64
-; CHECK-NEXT:    [[YPTR:%.*]] = inttoptr i64 [[TMP2]] to ptr
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[XPTR]], [[YPTR]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %xptr = inttoptr i200 %x to ptr
@@ -69,8 +61,7 @@ define i1 @inttoptr_size_mismatch(i200 %x, i9 %y) {
 define <2 x i1> @inttoptr_vector_constant_size_mismatch(<2 x i200> %x) {
 ; CHECK-LABEL: @inttoptr_vector_constant_size_mismatch(
 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i200> [[X:%.*]] to <2 x i64>
-; CHECK-NEXT:    [[XPTR:%.*]] = inttoptr <2 x i64> [[TMP1]] to <2 x ptr>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x ptr> [[XPTR]], <ptr inttoptr (i9 42 to ptr), ptr inttoptr (i9 123 to ptr)>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i64> [[TMP1]], <i64 42, i64 123>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %xptr = inttoptr <2 x i200> %x to <2 x ptr>
@@ -95,7 +86,7 @@ define i1 @inttoptr_used(i64 %x, i64 %y) {
 ; CHECK-NEXT:    [[YPTR:%.*]] = inttoptr i64 [[Y:%.*]] to ptr
 ; CHECK-NEXT:    call void @use_ptr(ptr [[XPTR]])
 ; CHECK-NEXT:    call void @use_ptr(ptr [[YPTR]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt ptr [[XPTR]], [[YPTR]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i64 [[X]], [[Y]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %xptr = inttoptr i64 %x to ptr



More information about the llvm-commits mailing list