From a0e6969bbe1c4de13b0c4635df03c354c3993ef7 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 24 Mar 2009 18:35:40 +0000 Subject: [PATCH] canonicalize inttoptr and ptrtoint instructions which cast pointers to/from integer types that are not intptr_t to convert to intptr_t then do an integer conversion to the dest type. This exposes the cast to the optimizer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67638 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 42 ++++++++++++++++--- test/Transforms/InstCombine/ptr-int-cast.ll | 16 +++++++ 2 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 test/Transforms/InstCombine/ptr-int-cast.ll diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index e4e7971549e..17ac5b7d8d5 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -218,7 +218,7 @@ namespace { Instruction *visitFPToSI(FPToSIInst &FI); Instruction *visitUIToFP(CastInst &CI); Instruction *visitSIToFP(CastInst &CI); - Instruction *visitPtrToInt(CastInst &CI); + Instruction *visitPtrToInt(PtrToIntInst &CI); Instruction *visitIntToPtr(IntToPtrInst &CI); Instruction *visitBitCast(BitCastInst &CI); Instruction *FoldSelectOpOp(SelectInst &SI, Instruction *TI, @@ -474,9 +474,16 @@ isEliminableCastPair( Instruction::CastOps firstOp = Instruction::CastOps(CI->getOpcode()); Instruction::CastOps secondOp = Instruction::CastOps(opcode); - return Instruction::CastOps( - CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, - DstTy, TD->getIntPtrType())); + unsigned Res = CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, + DstTy, TD->getIntPtrType()); + + // We don't want to form an inttoptr or ptrtoint that converts to an integer + // type that differs from the pointer size. + if ((Res == Instruction::IntToPtr && SrcTy != TD->getIntPtrType()) || + (Res == Instruction::PtrToInt && DstTy != TD->getIntPtrType())) + Res = 0; + + return Instruction::CastOps(Res); } /// ValueRequiresCast - Return true if the cast from "V to Ty" actually results @@ -8536,11 +8543,36 @@ Instruction *InstCombiner::visitSIToFP(CastInst &CI) { return commonCastTransforms(CI); } -Instruction *InstCombiner::visitPtrToInt(CastInst &CI) { +Instruction *InstCombiner::visitPtrToInt(PtrToIntInst &CI) { + // If the destination integer type is smaller than the intptr_t type for + // this target, do a ptrtoint to intptr_t then do a trunc. This allows the + // trunc to be exposed to other transforms. Don't do this for extending + // ptrtoint's, because we don't know if the target sign or zero extends its + // pointers. + if (CI.getType()->getPrimitiveSizeInBits() < TD->getPointerSizeInBits()) { + Value *P = InsertNewInstBefore(new PtrToIntInst(CI.getOperand(0), + TD->getIntPtrType(), + "tmp"), CI); + return new TruncInst(P, CI.getType()); + } + return commonPointerCastTransforms(CI); } Instruction *InstCombiner::visitIntToPtr(IntToPtrInst &CI) { + // If the source integer type is larger than the intptr_t type for + // this target, do a trunc to the intptr_t type, then inttoptr of it. This + // allows the trunc to be exposed to other transforms. Don't do this for + // extending inttoptr's, because we don't know if the target sign or zero + // extends to pointers. + if (CI.getOperand(0)->getType()->getPrimitiveSizeInBits() > + TD->getPointerSizeInBits()) { + Value *P = InsertNewInstBefore(new TruncInst(CI.getOperand(0), + TD->getIntPtrType(), + "tmp"), CI); + return new IntToPtrInst(P, CI.getType()); + } + if (Instruction *I = commonCastTransforms(CI)) return I; diff --git a/test/Transforms/InstCombine/ptr-int-cast.ll b/test/Transforms/InstCombine/ptr-int-cast.ll new file mode 100644 index 00000000000..5c154397775 --- /dev/null +++ b/test/Transforms/InstCombine/ptr-int-cast.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis > %t + +define i1 @test1(i32 *%x) nounwind { +entry: +; RUN: grep {ptrtoint i32\\* %x to i64} %t + %tmp = ptrtoint i32* %x to i1 + ret i1 %tmp +} + +define i32* @test2(i128 %x) nounwind { +entry: +; RUN: grep {inttoptr i64 %.mp1 to i32\\*} %t + %tmp = inttoptr i128 %x to i32* + ret i32* %tmp +} + -- 2.34.1