[llvm-commits] CVS: llvm/lib/Transforms/IPO/ArgumentPromotion.cpp

Chris Lattner lattner at cs.uiuc.edu
Sun Jun 20 19:16:00 PDT 2004


Changes in directory llvm/lib/Transforms/IPO:

ArgumentPromotion.cpp updated: 1.6 -> 1.7

---
Log message:

Make order of argument addition deterministic.  In particular, the layout
of ConstantInt objects in memory used to determine which order arguments
were added in in some cases. 


---
Diffs of the changes:  (+35 -10)

Index: llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
diff -u llvm/lib/Transforms/IPO/ArgumentPromotion.cpp:1.6 llvm/lib/Transforms/IPO/ArgumentPromotion.cpp:1.7
--- llvm/lib/Transforms/IPO/ArgumentPromotion.cpp:1.6	Sun May 23 16:21:17 2004
+++ llvm/lib/Transforms/IPO/ArgumentPromotion.cpp	Sun Jun 20 19:07:58 2004
@@ -185,7 +185,7 @@
   // We can only promote this argument if all of the uses are loads, or are GEP
   // instructions (with constant indices) that are subsequently loaded.
   std::vector<LoadInst*> Loads;
-  std::vector<std::vector<Constant*> > GEPIndices;
+  std::vector<std::vector<ConstantInt*> > GEPIndices;
   for (Value::use_iterator UI = Arg->use_begin(), E = Arg->use_end();
        UI != E; ++UI)
     if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) {
@@ -200,9 +200,9 @@
         return isSafeToPromoteArgument(Arg);
       }
       // Ensure that all of the indices are constants.
-      std::vector<Constant*> Operands;
+      std::vector<ConstantInt*> Operands;
       for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i)
-        if (Constant *C = dyn_cast<Constant>(GEP->getOperand(i)))
+        if (ConstantInt *C = dyn_cast<ConstantInt>(GEP->getOperand(i)))
           Operands.push_back(C);
         else
           return false;  // Not a constant operand GEP!
@@ -279,6 +279,29 @@
   return true;
 }
 
+namespace {
+  /// GEPIdxComparator - Provide a strong ordering for GEP indices.  All Value*
+  /// elements are instances of ConstantInt.
+  ///
+  struct GEPIdxComparator {
+    bool operator()(const std::vector<Value*> &LHS,
+                    const std::vector<Value*> &RHS) const {
+      unsigned idx = 0;
+      for (; idx < LHS.size() && idx < RHS.size(); ++idx) {
+        if (LHS[idx] != RHS[idx]) {
+          return cast<ConstantInt>(LHS[idx])->getRawValue() < 
+                 cast<ConstantInt>(RHS[idx])->getRawValue();
+        }
+      }
+
+      // Return less than if we ran out of stuff in LHS and we didn't run out of
+      // stuff in RHS.
+      return idx == LHS.size() && idx != RHS.size();
+    }
+  };
+}
+
+
 /// DoPromotion - This method actually performs the promotion of the specified
 /// arguments.  At this point, we know that it's safe to do so.
 void ArgPromotion::DoPromotion(Function *F, std::vector<Argument*> &Args2Prom) {
@@ -289,6 +312,8 @@
   const FunctionType *FTy = F->getFunctionType();
   std::vector<const Type*> Params;
 
+  typedef std::set<std::vector<Value*>, GEPIdxComparator> ScalarizeTable;
+
   // ScalarizedElements - If we are promoting a pointer that has elements
   // accessed out of it, keep track of which elements are accessed so that we
   // can add one argument for each.
@@ -296,7 +321,7 @@
   // Arguments that are directly loaded will have a zero element value here, to
   // handle cases where there are both a direct load and GEP accesses.
   //
-  std::map<Argument*, std::set<std::vector<Value*> > > ScalarizedElements;
+  std::map<Argument*, ScalarizeTable> ScalarizedElements;
 
   // OriginalLoads - Keep track of a representative load instruction from the
   // original function so that we can tell the alias analysis implementation
@@ -311,7 +336,7 @@
     } else {
       // Okay, this is being promoted.  Check to see if there are any GEP uses
       // of the argument.
-      std::set<std::vector<Value*> > &ArgIndices = ScalarizedElements[I];
+      ScalarizeTable &ArgIndices = ScalarizedElements[I];
       for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
            ++UI) {
         Instruction *User = cast<Instruction>(*UI);
@@ -327,7 +352,7 @@
       }
 
       // Add a parameter to the function for each element passed in.
-      for (std::set<std::vector<Value*> >::iterator SI = ArgIndices.begin(),
+      for (ScalarizeTable::iterator SI = ArgIndices.begin(),
              E = ArgIndices.end(); SI != E; ++SI)
         Params.push_back(GetElementPtrInst::getIndexedType(I->getType(), *SI));
 
@@ -377,8 +402,8 @@
         Args.push_back(*AI);          // Unmodified argument
       else if (!I->use_empty()) {
         // Non-dead argument: insert GEPs and loads as appropriate.
-        std::set<std::vector<Value*> > &ArgIndices = ScalarizedElements[I];
-        for (std::set<std::vector<Value*> >::iterator SI = ArgIndices.begin(),
+        ScalarizeTable &ArgIndices = ScalarizedElements[I];
+        for (ScalarizeTable::iterator SI = ArgIndices.begin(),
                E = ArgIndices.end(); SI != E; ++SI) {
           Value *V = *AI;
           LoadInst *OrigLoad = OriginalLoads[*SI];
@@ -446,7 +471,7 @@
       // Otherwise, if we promoted this argument, then all users are load
       // instructions, and all loads should be using the new argument that we
       // added.
-      std::set<std::vector<Value*> > &ArgIndices = ScalarizedElements[I];
+      ScalarizeTable &ArgIndices = ScalarizedElements[I];
 
       while (!I->use_empty()) {
         if (LoadInst *LI = dyn_cast<LoadInst>(I->use_back())) {
@@ -464,7 +489,7 @@
 
           unsigned ArgNo = 0;
           Function::aiterator TheArg = I2;
-          for (std::set<std::vector<Value*> >::iterator It = ArgIndices.begin();
+          for (ScalarizeTable::iterator It = ArgIndices.begin();
                *It != Operands; ++It, ++TheArg) {
             assert(It != ArgIndices.end() && "GEP not handled??");
           }





More information about the llvm-commits mailing list