DenseMap<Constant*, Constant*> &MutatedMemory,
std::vector<GlobalVariable*> &AllocaTmps,
SmallPtrSet<Constant*, 8> &SimpleConstants,
+ SmallPtrSet<GlobalVariable*, 8> &Invariants,
const TargetData *TD,
const TargetLibraryInfo *TLI);
DenseMap<Constant*, Constant*> &MutatedMemory,
std::vector<GlobalVariable*> &AllocaTmps,
SmallPtrSet<Constant*, 8> &SimpleConstants,
+ SmallPtrSet<GlobalVariable*, 8> &Invariants,
const TargetData *TD,
const TargetLibraryInfo *TLI) {
// This is the main evaluation loop.
// Cannot handle inline asm.
if (isa<InlineAsm>(CS.getCalledValue())) return false;
- if (MemSetInst *MSI = dyn_cast<MemSetInst>(CS.getInstruction())) {
- if (MSI->isVolatile()) return false;
- Constant *Ptr = getVal(Values, MSI->getDest());
- Constant *Val = getVal(Values, MSI->getValue());
- Constant *DestVal = ComputeLoadResult(getVal(Values, Ptr),
- MutatedMemory);
- if (Val->isNullValue() && DestVal && DestVal->isNullValue()) {
- // This memset is a no-op.
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) {
+ if (MemSetInst *MSI = dyn_cast<MemSetInst>(II)) {
+ if (MSI->isVolatile()) return false;
+ Constant *Ptr = getVal(Values, MSI->getDest());
+ Constant *Val = getVal(Values, MSI->getValue());
+ Constant *DestVal = ComputeLoadResult(getVal(Values, Ptr),
+ MutatedMemory);
+ if (Val->isNullValue() && DestVal && DestVal->isNullValue()) {
+ // This memset is a no-op.
+ ++CurInst;
+ continue;
+ }
+ }
+
+ if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
+ II->getIntrinsicID() == Intrinsic::lifetime_end) {
+ ++CurInst;
+ continue;
+ }
+
+ if (II->getIntrinsicID() == Intrinsic::invariant_start) {
+ // We don't insert an entry into Values, as it doesn't have a
+ // meaningful return value.
+ if (!II->use_empty())
+ return false;
+ ConstantInt *Size = cast<ConstantInt>(II->getArgOperand(0));
+ if (Size->isAllOnesValue()) {
+ Value *PtrArg = getVal(Values, II->getArgOperand(1));
+ Value *Ptr = PtrArg->stripPointerCasts();
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr))
+ Invariants.insert(GV);
+ }
+ // Continue even if we do nothing.
++CurInst;
continue;
}
Constant *RetVal;
// Execute the call, if successful, use the return value.
if (!EvaluateFunction(Callee, RetVal, Formals, CallStack,
- MutatedMemory, AllocaTmps, SimpleConstants, TD,
- TLI))
+ MutatedMemory, AllocaTmps, SimpleConstants,
+ Invariants, TD, TLI))
return false;
InstResult = RetVal;
DenseMap<Constant*, Constant*> &MutatedMemory,
std::vector<GlobalVariable*> &AllocaTmps,
SmallPtrSet<Constant*, 8> &SimpleConstants,
+ SmallPtrSet<GlobalVariable*, 8> &Invariants,
const TargetData *TD,
const TargetLibraryInfo *TLI) {
// Check to see if this function is already executing (recursion). If so,
while (1) {
BasicBlock *NextBB;
if (!EvaluateBlock(CurInst, NextBB, CallStack, Values, MutatedMemory,
- AllocaTmps, SimpleConstants, TD, TLI))
+ AllocaTmps, SimpleConstants, Invariants, TD, TLI))
return false;
if (NextBB == 0) {
// simple enough to live in a static initializer of a global.
SmallPtrSet<Constant*, 8> SimpleConstants;
+ // Invariants - These global variables have been marked invariant by the
+ // static constructor.
+ SmallPtrSet<GlobalVariable*, 8> Invariants;
+
// Call the function.
Constant *RetValDummy;
bool EvalSuccess = EvaluateFunction(F, RetValDummy,
SmallVector<Constant*, 0>(), CallStack,
MutatedMemory, AllocaTmps,
- SimpleConstants, TD, TLI);
+ SimpleConstants, Invariants, TD, TLI);
if (EvalSuccess) {
// We succeeded at evaluation: commit the result.
for (DenseMap<Constant*, Constant*>::iterator I = MutatedMemory.begin(),
E = MutatedMemory.end(); I != E; ++I)
CommitValueTo(I->second, I->first);
+ for (SmallPtrSet<GlobalVariable*, 8>::iterator I = Invariants.begin(),
+ E = Invariants.end(); I != E; ++I)
+ (*I)->setConstant(true);
}
// At this point, we are done interpreting. If we created any 'alloca'
--- /dev/null
+; RUN: opt -globalopt -S -o - < %s | FileCheck %s
+
+declare {}* @llvm.invariant.start(i64 %size, i8* nocapture %ptr)
+
+define void @test1(i8* %ptr) {
+ call {}* @llvm.invariant.start(i64 -1, i8* %ptr)
+ ret void
+}
+
+@object1 = global i32 0
+; CHECK: @object1 = constant i32 -1
+define void @ctor1() {
+ store i32 -1, i32* @object1
+ %A = bitcast i32* @object1 to i8*
+ call void @test1(i8* %A)
+ ret void
+}
+
+
+@object2 = global i32 0
+; CHECK: @object2 = global i32 0
+define void @ctor2() {
+ store i32 -1, i32* @object2
+ %A = bitcast i32* @object2 to i8*
+ %B = call {}* @llvm.invariant.start(i64 -1, i8* %A)
+ ; Why in the world does this pass the verifier?
+ %C = bitcast {}* %B to i8*
+ ret void
+}
+
+@llvm.global_ctors = appending constant
+ [2 x { i32, void ()* }]
+ [ { i32, void ()* } { i32 65535, void ()* @ctor1 },
+ { i32, void ()* } { i32 65535, void ()* @ctor2 } ]