From 3181f5900ff5d9800c38284c7d3427cb6e306c9a Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 30 Jul 2013 22:27:10 +0000 Subject: [PATCH] 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 --- lib/IR/ConstantFold.cpp | 9 ++-- lib/IR/Instructions.cpp | 57 ++++++++++++++++++---- unittests/IR/InstructionsTest.cpp | 81 ++++++++++++++++++++++++++++++- 3 files changed, 131 insertions(+), 16 deletions(-) diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index da9762fa627..8c5a9837016 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -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) { diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 665fe66ccc3..49a9e8c18d2 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -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(SrcTy); + PointerType *MidPtrTy = dyn_cast(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(MidTy); + PointerType *DstPtrTy = dyn_cast(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) diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp index 34d662dcb34..c2fdceb7eb5 100644 --- a/unittests/IR/InstructionsTest.cpp +++ b/unittests/IR/InstructionsTest.cpp @@ -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 + +