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

Marina Taylor via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 6 04:11:20 PDT 2024


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

>From 919852cd07e452db923077297f81ea4fa66a6240 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   | 110 ++++++++++++++++++
 1 file changed, 110 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..21ffca0c85db6b
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll
@@ -0,0 +1,110 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+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 b5db1ab4b68baa492bab99d66b632f25b061f282 Mon Sep 17 00:00:00 2001
From: Marina Taylor <marina_taylor at apple.com>
Date: Fri, 6 Sep 2024 12:02:46 +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   | 25 ++++++------------
 2 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 8e8d472a5df1d3..af60b1886fc72e 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 = ConstantExpr::getPtrToInt(RHSC, SrcTy);
+    }
+
+    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 21ffca0c85db6b..cff5a88553d321 100644
--- a/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+; RUN: opt < %s -passes='instcombine<max-iterations=2>' -S | FileCheck %s
 
 target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 
@@ -7,9 +7,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
@@ -20,8 +18,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
@@ -31,9 +28,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>
@@ -44,8 +39,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>
@@ -56,10 +50,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
@@ -71,8 +63,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>
@@ -97,7 +88,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