From: Duncan Sands Date: Tue, 30 Oct 2012 16:03:32 +0000 (+0000) Subject: Fix isEliminableCastPair to work correctly in the presence of pointers X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=446cf94cdbbc1f8e22452fc46664ac73d810c6a2;p=oota-llvm.git Fix isEliminableCastPair to work correctly in the presence of pointers with different sizes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167018 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h index b661372f53b..74e51ffa0fb 100644 --- a/include/llvm/InstrTypes.h +++ b/include/llvm/InstrTypes.h @@ -594,7 +594,9 @@ public: Type *SrcTy, ///< SrcTy of 1st cast Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast Type *DstTy, ///< DstTy of 2nd cast - Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + Type *SrcIntPtrTy, ///< Integer type corresponding to Ptr SrcTy, or null + Type *MidIntPtrTy, ///< Integer type corresponding to Ptr MidTy, or null + Type *DstIntPtrTy ///< Integer type corresponding to Ptr DstTy, or null ); /// @brief Return the opcode of this CastInst diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index 119d2f5c99d..1807bea2352 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -238,16 +238,20 @@ isEliminableCastPair( // Get the opcodes of the two Cast instructions Instruction::CastOps firstOp = Instruction::CastOps(CI->getOpcode()); Instruction::CastOps secondOp = Instruction::CastOps(opcode); + Type *SrcIntPtrTy = TD && SrcTy->isPtrOrPtrVectorTy() ? + TD->getIntPtrType(SrcTy) : 0; + Type *MidIntPtrTy = TD && MidTy->isPtrOrPtrVectorTy() ? + TD->getIntPtrType(MidTy) : 0; + Type *DstIntPtrTy = TD && DstTy->isPtrOrPtrVectorTy() ? + TD->getIntPtrType(DstTy) : 0; unsigned Res = CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, - DstTy, - TD ? TD->getIntPtrType(DstTy) : 0); + DstTy, SrcIntPtrTy, MidIntPtrTy, + DstIntPtrTy); // 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 && - (!TD || SrcTy != TD->getIntPtrType(DstTy))) || - (Res == Instruction::PtrToInt && - (!TD || DstTy != TD->getIntPtrType(SrcTy)))) + if ((Res == Instruction::IntToPtr && SrcTy != DstIntPtrTy) || + (Res == Instruction::PtrToInt && DstTy != SrcIntPtrTy)) Res = 0; return Instruction::CastOps(Res); diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 60cd3fbe22d..fe3edac42e7 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -87,9 +87,13 @@ foldConstantCastPair( Instruction::CastOps firstOp = Instruction::CastOps(Op->getOpcode()); Instruction::CastOps secondOp = Instruction::CastOps(opc); + // Assume that pointers are never more than 64 bits wide. + IntegerType *FakeIntPtrTy = Type::getInt64Ty(DstTy->getContext()); + // Let CastInst::isEliminableCastPair do the heavy lifting. return CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, DstTy, - Type::getInt64Ty(DstTy->getContext())); + FakeIntPtrTy, FakeIntPtrTy, + FakeIntPtrTy); } static Constant *FoldBitCast(Constant *V, Type *DestTy) { diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index e9b96d6cd22..39ba4df15b4 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -2141,7 +2141,8 @@ bool CastInst::isNoopCast(const DataLayout &DL) const { /// If no such cast is permited, the function returns 0. unsigned CastInst::isEliminableCastPair( Instruction::CastOps firstOp, Instruction::CastOps secondOp, - Type *SrcTy, Type *MidTy, Type *DstTy, Type *IntPtrTy) { + Type *SrcTy, Type *MidTy, Type *DstTy, Type *SrcIntPtrTy, Type *MidIntPtrTy, + Type *DstIntPtrTy) { // Define the 144 possibilities for these two cast instructions. The values // in this matrix determine what to do in a given situation and select the // case in the switch below. The rows correspond to firstOp, the columns @@ -2244,9 +2245,9 @@ unsigned CastInst::isEliminableCastPair( return 0; case 7: { // ptrtoint, inttoptr -> bitcast (ptr -> ptr) if int size is >= ptr size - if (!IntPtrTy) + if (!SrcIntPtrTy || DstIntPtrTy != SrcIntPtrTy) return 0; - unsigned PtrSize = IntPtrTy->getScalarSizeInBits(); + unsigned PtrSize = SrcIntPtrTy->getScalarSizeInBits(); unsigned MidSize = MidTy->getScalarSizeInBits(); if (MidSize >= PtrSize) return Instruction::BitCast; @@ -2285,9 +2286,9 @@ unsigned CastInst::isEliminableCastPair( return 0; case 13: { // inttoptr, ptrtoint -> bitcast if SrcSize<=PtrSize and SrcSize==DstSize - if (!IntPtrTy) + if (!MidIntPtrTy) return 0; - unsigned PtrSize = IntPtrTy->getScalarSizeInBits(); + unsigned PtrSize = MidIntPtrTy->getScalarSizeInBits(); unsigned SrcSize = SrcTy->getScalarSizeInBits(); unsigned DstSize = DstTy->getScalarSizeInBits(); if (SrcSize <= PtrSize && SrcSize == DstSize) diff --git a/unittests/VMCore/InstructionsTest.cpp b/unittests/VMCore/InstructionsTest.cpp index 4cadc36f8f0..a3b13ce92d1 100644 --- a/unittests/VMCore/InstructionsTest.cpp +++ b/unittests/VMCore/InstructionsTest.cpp @@ -243,5 +243,42 @@ TEST(InstructionsTest, FPMathOperator) { delete I; } + +TEST(InstructionsTest, isEliminableCastPair) { + LLVMContext &C(getGlobalContext()); + + Type* Int32Ty = Type::getInt32Ty(C); + Type* Int64Ty = Type::getInt64Ty(C); + Type* Int64PtrTy = Type::getInt64PtrTy(C); + + // Source and destination pointers have same size -> bitcast. + EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt, + CastInst::IntToPtr, + Int64PtrTy, Int64Ty, Int64PtrTy, + Int32Ty, 0, Int32Ty), + CastInst::BitCast); + + // Source and destination pointers have different sizes -> fail. + EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt, + CastInst::IntToPtr, + Int64PtrTy, Int64Ty, Int64PtrTy, + Int32Ty, 0, Int64Ty), + 0U); + + // Middle pointer big enough -> bitcast. + EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, + CastInst::PtrToInt, + Int64Ty, Int64PtrTy, Int64Ty, + 0, Int64Ty, 0), + CastInst::BitCast); + + // Middle pointer too small -> fail. + EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, + CastInst::PtrToInt, + Int64Ty, Int64PtrTy, Int64Ty, + 0, Int32Ty, 0), + 0U); +} + } // end anonymous namespace } // end namespace llvm