From 19be41ccf383b43715b76a275775d24f7fc4a082 Mon Sep 17 00:00:00 2001 From: Marina Taylor 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 | 106 ++++++++++++++++++ 1 file changed, 106 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 0000000000000..e4abfaae97ffb --- /dev/null +++ b/llvm/test/Transforms/InstCombine/icmp-inttoptr.ll @@ -0,0 +1,106 @@ +; 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]], +; 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> to <2 x ptr>) + ret <2 x i1> %cmp +} + +define i1 @inttoptr_size_mismatch(i200 %x, i64 %y) { +; CHECK-LABEL: @inttoptr_size_mismatch( +; CHECK-NEXT: [[TMP1:%.*]] = trunc i200 [[X:%.*]] to i64 +; CHECK-NEXT: [[XPTR:%.*]] = inttoptr i64 [[TMP1]] 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 i200 %x to ptr + %yptr = inttoptr i64 %y to ptr + %cmp = icmp eq ptr %xptr, %yptr + ret i1 %cmp +} + +define <2 x i1> @inttoptr_vector_constant_size_mismatch(<2 x i64> %x) { +; CHECK-LABEL: @inttoptr_vector_constant_size_mismatch( +; CHECK-NEXT: [[XPTR:%.*]] = inttoptr <2 x i64> [[X:%.*]] to <2 x ptr> +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x ptr> [[XPTR]], +; 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 (<2x i9> 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 d2ffe528ec0044998b7389dc6dcfe62c42d6a912 Mon Sep 17 00:00:00 2001 From: Marina Taylor Date: Mon, 23 Sep 2024 23:12:04 +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 80d6ceca094d8..698abbb34c18c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6087,12 +6087,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(SrcTy)) { - SrcTy = cast(SrcTy)->getElementType(); - DestTy = cast(DestTy)->getElementType(); + auto CompatibleSizes = [&](Type *PtrTy, Type *IntTy) { + if (isa(PtrTy)) { + PtrTy = cast(PtrTy)->getElementType(); + IntTy = cast(IntTy)->getElementType(); } - return DL.getPointerTypeSizeInBits(SrcTy) == DestTy->getIntegerBitWidth(); + return DL.getPointerTypeSizeInBits(PtrTy) == IntTy->getIntegerBitWidth(); }; if (CastOp0->getOpcode() == Instruction::PtrToInt && CompatibleSizes(SrcTy, DestTy)) { @@ -6109,6 +6109,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(ICmp.getOperand(1))) { + Value *IntSrc = IntToPtrOp1->getOperand(0); + if (IntSrc->getType() == Op0Src->getType()) + NewOp1 = IntToPtrOp1->getOperand(0); + } else if (auto *RHSC = dyn_cast(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 e4abfaae97ffb..dd731a9c44863 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]], +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i64> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %xptr = inttoptr <2 x i64> %x to <2 x ptr> @@ -54,9 +48,7 @@ define <2 x i1> @inttoptr_vector_constant(<2 x i64> %x) { define i1 @inttoptr_size_mismatch(i200 %x, i64 %y) { ; CHECK-LABEL: @inttoptr_size_mismatch( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i200 [[X:%.*]] to i64 -; CHECK-NEXT: [[XPTR:%.*]] = inttoptr i64 [[TMP1]] to ptr -; CHECK-NEXT: [[YPTR:%.*]] = inttoptr i64 [[Y:%.*]] to ptr -; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[XPTR]], [[YPTR]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[Y:%.*]], [[TMP1]] ; CHECK-NEXT: ret i1 [[CMP]] ; %xptr = inttoptr i200 %x to ptr @@ -67,8 +59,7 @@ define i1 @inttoptr_size_mismatch(i200 %x, i64 %y) { define <2 x i1> @inttoptr_vector_constant_size_mismatch(<2 x i64> %x) { ; CHECK-LABEL: @inttoptr_vector_constant_size_mismatch( -; CHECK-NEXT: [[XPTR:%.*]] = inttoptr <2 x i64> [[X:%.*]] to <2 x ptr> -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x ptr> [[XPTR]], +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i64> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %xptr = inttoptr <2 x i64> %x to <2 x ptr> @@ -93,7 +84,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