From 2aae304cbcc0ec4d57e9cd002887f26daa7dfd5d Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Fri, 12 Jan 2024 23:03:07 +0800 Subject: [PATCH] [InstCombine] Fold `icmp pred (inttoptr X), (inttoptr Y) -> icmp pred X, Y` (#77832) NOTE: Alive2 proofs are unavailable because `inttoptr` is unsupported. --- .../InstCombine/InstCombineCompares.cpp | 9 ++++ llvm/test/Transforms/InstCombine/cast_ptr.ll | 45 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 7c1aff445524..da94bb1d2a8f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -5703,6 +5703,15 @@ Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) { return new ICmpInst(ICmp.getPredicate(), Op0Src, NewOp1); } + // Turn icmp pred (inttoptr x), (inttoptr y) into icmp pred x, y + if (CastOp0->getOpcode() == Instruction::IntToPtr && + CompatibleSizes(DestTy, SrcTy)) { + Value *Op1Src; + if (match(ICmp.getOperand(1), m_IntToPtr(m_Value(Op1Src))) && + Op1Src->getType() == SrcTy) + return new ICmpInst(ICmp.getPredicate(), Op0Src, Op1Src); + } + if (Instruction *R = foldICmpWithTrunc(ICmp)) return R; diff --git a/llvm/test/Transforms/InstCombine/cast_ptr.ll b/llvm/test/Transforms/InstCombine/cast_ptr.ll index 5c6c012064e0..8865af0a34a4 100644 --- a/llvm/test/Transforms/InstCombine/cast_ptr.ll +++ b/llvm/test/Transforms/InstCombine/cast_ptr.ll @@ -113,6 +113,51 @@ define i1 @test4(i32 %A) { ret i1 %C } +define i1 @test4_icmp_with_var(i32 %A1, i32 %A2) { +; CHECK-LABEL: @test4_icmp_with_var( +; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A1:%.*]], [[A2:%.*]] +; CHECK-NEXT: ret i1 [[C]] +; + %B1 = inttoptr i32 %A1 to ptr + %B2 = inttoptr i32 %A2 to ptr + %C = icmp ugt ptr %B1, %B2 + ret i1 %C +} + +define i1 @test4_cmp_with_nonnull_constant(i32 %A) { +; CHECK-LABEL: @test4_cmp_with_nonnull_constant( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], 1 +; CHECK-NEXT: ret i1 [[C]] +; + %B = inttoptr i32 %A to ptr + %C = icmp eq ptr %B, inttoptr (i32 1 to ptr) + ret i1 %C +} + +define i1 @test4_cmp_eq_0_or_1(i32 %x) { +; CHECK-LABEL: @test4_cmp_eq_0_or_1( +; CHECK-NEXT: [[OR:%.*]] = icmp ult i32 [[X:%.*]], 2 +; CHECK-NEXT: ret i1 [[OR]] +; + %cast = inttoptr i32 %x to ptr + %tobool = icmp eq i32 %x, 0 + %cmp = icmp eq ptr %cast, inttoptr (i32 1 to ptr) + %or = or i1 %tobool, %cmp + ret i1 %or +} + +define i1 @test4_icmp_with_var_mismatched_type(i32 %A1, i64 %A2) { +; CHECK-LABEL: @test4_icmp_with_var_mismatched_type( +; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[A2:%.*]] to i32 +; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[TMP1]], [[A1:%.*]] +; CHECK-NEXT: ret i1 [[C]] +; + %B1 = inttoptr i32 %A1 to ptr + %B2 = inttoptr i64 %A2 to ptr + %C = icmp ugt ptr %B1, %B2 + ret i1 %C +} + define i1 @test4_as2(i16 %A) { ; CHECK-LABEL: @test4_as2( ; CHECK-NEXT: [[C:%.*]] = icmp eq i16 [[A:%.*]], 0