Respect address space sizes in isEliminableCastPair.

This avoids constant folding bitcast/ptrtoint/inttoptr combinations
that have illegal bitcasts between differently sized address spaces.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187455 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Matt Arsenault 2013-07-30 22:27:10 +00:00
parent 485c7fd76b
commit 3181f5900f
3 changed files with 131 additions and 16 deletions

View File

@ -75,7 +75,7 @@ static unsigned
foldConstantCastPair(
unsigned opc, ///< opcode of the second cast constant expression
ConstantExpr *Op, ///< the first cast constant expression
Type *DstTy ///< desintation type of the first cast
Type *DstTy ///< destination type of the first cast
) {
assert(Op && Op->isCast() && "Can't fold cast of cast without a cast!");
assert(DstTy && DstTy->isFirstClassType() && "Invalid cast destination type");
@ -87,13 +87,14 @@ foldConstantCastPair(
Instruction::CastOps firstOp = Instruction::CastOps(Op->getOpcode());
Instruction::CastOps secondOp = Instruction::CastOps(opc);
// Assume that pointers are never more than 64 bits wide.
// Assume that pointers are never more than 64 bits wide, and only use this
// for the middle type. Otherwise we could end up folding away illegal
// bitcasts between address spaces with different sizes.
IntegerType *FakeIntPtrTy = Type::getInt64Ty(DstTy->getContext());
// Let CastInst::isEliminableCastPair do the heavy lifting.
return CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, DstTy,
FakeIntPtrTy, FakeIntPtrTy,
FakeIntPtrTy);
0, FakeIntPtrTy, 0);
}
static Constant *FoldBitCast(Constant *V, Type *DestTy) {

View File

@ -2224,12 +2224,20 @@ unsigned CastInst::isEliminableCastPair(
if (SrcTy->isFloatingPointTy())
return secondOp;
return 0;
case 7: {
// ptrtoint, inttoptr -> bitcast (ptr -> ptr) if int size is >= ptr size
case 7: {
unsigned MidSize = MidTy->getScalarSizeInBits();
// Check the address spaces first. If we know they are in the same address
// space, the pointer sizes must be the same so we can still fold this
// without knowing the actual sizes as long we know that the intermediate
// pointer is the largest possible pointer size.
if (MidSize == 64 &&
SrcTy->getPointerAddressSpace() == DstTy->getPointerAddressSpace())
return Instruction::BitCast;
// ptrtoint, inttoptr -> bitcast (ptr -> ptr) if int size is >= ptr size.
if (!SrcIntPtrTy || DstIntPtrTy != SrcIntPtrTy)
return 0;
unsigned PtrSize = SrcIntPtrTy->getScalarSizeInBits();
unsigned MidSize = MidTy->getScalarSizeInBits();
if (MidSize >= PtrSize)
return Instruction::BitCast;
return 0;
@ -2254,17 +2262,46 @@ unsigned CastInst::isEliminableCastPair(
if (SrcTy == DstTy)
return Instruction::BitCast;
return 0; // If the types are not the same we can't eliminate it.
case 11:
// bitcast followed by ptrtoint is allowed as long as the bitcast
// is a pointer to pointer cast.
if (SrcTy->isPointerTy() && MidTy->isPointerTy())
case 11: {
// bitcast followed by ptrtoint is allowed as long as the bitcast is a
// pointer to pointer cast, and the pointers are the same size.
PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy);
PointerType *MidPtrTy = dyn_cast<PointerType>(MidTy);
if (!SrcPtrTy || !MidPtrTy)
return 0;
// If the address spaces are the same, we know they are the same size
// without size information
if (SrcPtrTy->getAddressSpace() == MidPtrTy->getAddressSpace())
return secondOp;
if (!SrcIntPtrTy || !MidIntPtrTy)
return 0;
if (SrcIntPtrTy->getScalarSizeInBits() ==
MidIntPtrTy->getScalarSizeInBits())
return secondOp;
return 0;
case 12:
// inttoptr, bitcast -> intptr if bitcast is a ptr to ptr cast
if (MidTy->isPointerTy() && DstTy->isPointerTy())
}
case 12: {
// inttoptr, bitcast -> inttoptr if bitcast is a ptr to ptr cast
// and the ptrs are to address spaces of the same size
PointerType *MidPtrTy = dyn_cast<PointerType>(MidTy);
PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy);
if (!MidPtrTy || !DstPtrTy)
return 0;
if (MidPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace())
return firstOp;
if (MidIntPtrTy &&
DstIntPtrTy &&
MidIntPtrTy->getScalarSizeInBits() ==
DstIntPtrTy->getScalarSizeInBits())
return firstOp;
return 0;
}
case 13: {
// inttoptr, ptrtoint -> bitcast if SrcSize<=PtrSize and SrcSize==DstSize
if (!MidIntPtrTy)

View File

@ -318,6 +318,7 @@ TEST(InstructionsTest, FPMathOperator) {
TEST(InstructionsTest, isEliminableCastPair) {
LLVMContext &C(getGlobalContext());
Type* Int16Ty = Type::getInt16Ty(C);
Type* Int32Ty = Type::getInt32Ty(C);
Type* Int64Ty = Type::getInt64Ty(C);
Type* Int64PtrTy = Type::getInt64PtrTy(C);
@ -329,11 +330,20 @@ TEST(InstructionsTest, isEliminableCastPair) {
Int32Ty, 0, Int32Ty),
CastInst::BitCast);
// Source and destination pointers have different sizes -> fail.
// Source and destination have unknown sizes, but the same address space and
// the intermediate int is the maximum pointer size -> bitcast
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt,
CastInst::IntToPtr,
Int64PtrTy, Int64Ty, Int64PtrTy,
Int32Ty, 0, Int64Ty),
0, 0, 0),
CastInst::BitCast);
// Source and destination have unknown sizes, but the same address space and
// the intermediate int is not the maximum pointer size -> nothing
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt,
CastInst::IntToPtr,
Int64PtrTy, Int32Ty, Int64PtrTy,
0, 0, 0),
0U);
// Middle pointer big enough -> bitcast.
@ -349,7 +359,74 @@ TEST(InstructionsTest, isEliminableCastPair) {
Int64Ty, Int64PtrTy, Int64Ty,
0, Int32Ty, 0),
0U);
// Test that we don't eliminate bitcasts between different address spaces,
// or if we don't have available pointer size information.
DataLayout DL("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16"
"-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64"
"-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128");
Type* Int64PtrTyAS1 = Type::getInt64PtrTy(C, 1);
Type* Int64PtrTyAS2 = Type::getInt64PtrTy(C, 2);
IntegerType *Int16SizePtr = DL.getIntPtrType(C, 1);
IntegerType *Int64SizePtr = DL.getIntPtrType(C, 2);
// Fail since the ptr int types are not provided
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
CastInst::BitCast,
Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2,
0, 0, 0),
0U);
// Fail since the the bitcast is between different sized address spaces
EXPECT_EQ(CastInst::isEliminableCastPair(
CastInst::IntToPtr,
CastInst::BitCast,
Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2,
0, Int16SizePtr, Int64SizePtr),
0U);
// Fail since the the bitcast is between different sized address spaces
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
CastInst::BitCast,
Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2,
0, Int16SizePtr, Int64SizePtr),
0U);
// Pass since the bitcast address spaces are the same
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
CastInst::BitCast,
Int16Ty, Int64PtrTyAS1, Int64PtrTyAS1,
0, 0, 0),
CastInst::IntToPtr);
// Fail without known pointer sizes and different address spaces
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::BitCast,
CastInst::PtrToInt,
Int64PtrTyAS1, Int64PtrTyAS2, Int16Ty,
0, 0, 0),
0U);
// Pass since the address spaces are the same, even though the pointer sizes
// are unknown
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::BitCast,
CastInst::PtrToInt,
Int64PtrTyAS1, Int64PtrTyAS1, Int32Ty,
0, 0, 0),
Instruction::PtrToInt);
// Fail since the bitcast is the wrong size
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::BitCast,
CastInst::PtrToInt,
Int64PtrTyAS1, Int64PtrTyAS2, Int64Ty,
Int16SizePtr, Int64SizePtr, 0),
0U);
}
} // end anonymous namespace
} // end namespace llvm