Improve the safety of my globalopt enhancement by ensuring that the bitcast
of the stored value to the new store type is always. Also, add a testcase.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123563 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp
index 8519fce..bf04594 100644
--- a/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/lib/Transforms/IPO/GlobalOpt.cpp
@@ -2358,21 +2358,31 @@
const Type *NewTy=cast<PointerType>(Ptr->getType())->getElementType();
- // A bitcast'd pointer implicitly points to the first field of a
- // struct. Insert implicity "gep @x, 0, 0, ..." until we get down
- // to the first concrete member.
- // FIXME: This could be extended to work for arrays as well.
- while (const StructType *STy = dyn_cast<StructType>(NewTy)) {
- NewTy = STy->getTypeAtIndex(0U);
+ // In order to push the bitcast onto the stored value, a bitcast
+ // from NewTy to Val's type must be legal. If it's not, we can try
+ // introspecting NewTy to find a legal conversion.
+ while (!Val->getType()->canLosslesslyBitCastTo(NewTy)) {
+ // If NewTy is a struct, we can convert the pointer to the struct
+ // into a pointer to its first member.
+ // FIXME: This could be extended to support arrays as well.
+ if (const StructType *STy = dyn_cast<StructType>(NewTy)) {
+ NewTy = STy->getTypeAtIndex(0U);
+
+ const IntegerType *IdxTy =IntegerType::get(NewTy->getContext(), 32);
+ Constant *IdxZero = ConstantInt::get(IdxTy, 0, false);
+ Constant * const IdxList[] = {IdxZero, IdxZero};
+
+ Ptr = ConstantExpr::getGetElementPtr(Ptr, IdxList, 2);
- const IntegerType *IdxTy =IntegerType::get(NewTy->getContext(), 32);
- Constant *IdxZero = ConstantInt::get(IdxTy, 0, false);
- Constant * const IdxList[] = {IdxZero, IdxZero};
-
- Ptr = ConstantExpr::getGetElementPtr(Ptr, IdxList, 2);
+ // If we can't improve the situation by introspecting NewTy,
+ // we have to give up.
+ } else {
+ return 0;
+ }
}
- if (!isa<PointerType>(NewTy)) return false;
+ // If we found compatible types, go ahead and push the bitcast
+ // onto the stored value.
Val = ConstantExpr::getBitCast(Val, NewTy);
}