[llvm-commits] [llvm] r123477 - /llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
Owen Anderson
resistor at mac.com
Fri Jan 14 14:19:20 PST 2011
Author: resistor
Date: Fri Jan 14 16:19:20 2011
New Revision: 123477
URL: http://llvm.org/viewvc/llvm-project?rev=123477&view=rev
Log:
Enhance GlobalOpt to be able evaluate initializers that involve stores through
bitcasts, at least in simple cases. This fixes clang's CodeGenCXX/virtual-base-dtor.cpp
Modified:
llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=123477&r1=123476&r2=123477&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Fri Jan 14 16:19:20 2011
@@ -2128,8 +2128,9 @@
/// isSimpleEnoughPointerToCommit - Return true if this constant is simple
-/// enough for us to understand. In particular, if it is a cast of something,
-/// we punt. We basically just support direct accesses to globals and GEP's of
+/// enough for us to understand. In particular, if it is a cast to anything
+/// other than from one pointer type to another pointer type, we punt.
+/// We basically just support direct accesses to globals and GEP's of
/// globals. This should be kept up to date with CommitValueTo.
static bool isSimpleEnoughPointerToCommit(Constant *C) {
// Conservatively, avoid aggregate types. This is because we don't
@@ -2163,6 +2164,20 @@
return false;
return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE);
+
+ // A constantexpr bitcast from a pointer to another pointer is a no-op,
+ // and we know how to evaluate it by moving the bitcast from the pointer
+ // operand to the value operand.
+ } else if (CE->getOpcode() == Instruction::BitCast &&
+ CE->getType()->isPointerTy() &&
+ CE->getOperand(0)->getType()->isPointerTy()) {
+ GlobalVariable *GV = cast<GlobalVariable>(CE->getOperand(0));
+ // Do not allow weak/*_odr/linkonce/dllimport/dllexport linkage or
+ // external globals.
+ if (!GV->hasUniqueInitializer())
+ return false;
+
+ return true;
}
return false;
}
@@ -2336,6 +2351,38 @@
// of one global variable divided by another) then we can't commit it.
if (!isSimpleEnoughValueToCommit(Val, SimpleConstants))
return false;
+
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
+ if (CE->getOpcode() == Instruction::BitCast) {
+ // If we're evaluating a store through a bitcast, then we need
+ // to pull the bitcast off the pointer type and push it onto the
+ // stored value.
+ Ptr = dyn_cast<Constant>(Ptr->getOperand(0));
+ if (!Ptr) return false;
+
+ const PointerType *Ty = dyn_cast<PointerType>(Ptr->getType());
+ if (!Ty) return false;
+ const Type *NewTy = Ty->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);
+
+ 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 (!isa<PointerType>(NewTy)) return false;
+ Val = ConstantExpr::getBitCast(Val, NewTy);
+ }
+
MutatedMemory[Ptr] = Val;
} else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CurInst)) {
InstResult = ConstantExpr::get(BO->getOpcode(),
More information about the llvm-commits
mailing list