Respect address space sizes in isEliminableCastPair.
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Tue, 30 Jul 2013 22:27:10 +0000 (22:27 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Tue, 30 Jul 2013 22:27:10 +0000 (22:27 +0000)
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
lib/IR/Instructions.cpp
unittests/IR/InstructionsTest.cpp

index da9762fa627d9d648ae4822aee8534408e73bff8..8c5a9837016d18f455c8e213817fc342a75959fc 100644 (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) {
index 665fe66ccc39fbc8b49855350e07012777a4a2a1..49a9e8c18d2be2c10bd469b083bb45ca82a57e13 100644 (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)
index 34d662dcb343d8321128f068746e4cdc838ead52..c2fdceb7eb52458dda78f90260e2a4e2147cbba8 100644 (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
+
+