with different sizes.
llvm-svn: 167018
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
// 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);
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) {
/// 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
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;
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)
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