[llvm-commits] [llvm] r150794 - in /llvm/trunk: lib/Transforms/IPO/GlobalOpt.cpp test/Transforms/GlobalOpt/invariant.ll
Nick Lewycky
nicholas at mxc.ca
Thu Feb 16 22:59:21 PST 2012
Author: nicholas
Date: Fri Feb 17 00:59:21 2012
New Revision: 150794
URL: http://llvm.org/viewvc/llvm-project?rev=150794&view=rev
Log:
Add support for invariant.start inside the static constructor evaluator. This is
useful to represent a variable that is const in the source but can't be constant
in the IR because of a non-trivial constructor. If globalopt evaluates the
constructor, and there was an invariant.start with no matching invariant.end
possible, it will mark the global constant afterwards.
Added:
llvm/trunk/test/Transforms/GlobalOpt/invariant.ll
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=150794&r1=150793&r2=150794&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Fri Feb 17 00:59:21 2012
@@ -2295,6 +2295,7 @@
DenseMap<Constant*, Constant*> &MutatedMemory,
std::vector<GlobalVariable*> &AllocaTmps,
SmallPtrSet<Constant*, 8> &SimpleConstants,
+ SmallPtrSet<GlobalVariable*, 8> &Invariants,
const TargetData *TD,
const TargetLibraryInfo *TLI);
@@ -2307,6 +2308,7 @@
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.
@@ -2415,14 +2417,39 @@
// 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;
}
@@ -2453,8 +2480,8 @@
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;
@@ -2521,6 +2548,7 @@
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,
@@ -2552,7 +2580,7 @@
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) {
@@ -2607,12 +2635,16 @@
// 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.
@@ -2622,6 +2654,9 @@
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'
Added: llvm/trunk/test/Transforms/GlobalOpt/invariant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/invariant.ll?rev=150794&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/invariant.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/invariant.ll Fri Feb 17 00:59:21 2012
@@ -0,0 +1,34 @@
+; 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
+}
+
+ at 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
+}
+
+
+ at 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
+}
+
+ at llvm.global_ctors = appending constant
+ [2 x { i32, void ()* }]
+ [ { i32, void ()* } { i32 65535, void ()* @ctor1 },
+ { i32, void ()* } { i32 65535, void ()* @ctor2 } ]
More information about the llvm-commits
mailing list