[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