ScalarRepl does not modify the CFG. Say so!
[oota-llvm.git] / lib / Transforms / Scalar / ScalarReplAggregates.cpp
index 2ac6ce643c0e771b00228619d583925ee8d5d978..864f8764aa528bf700b7c9c4f6a06fc9846ed148 100644 (file)
@@ -13,8 +13,9 @@
 #include "llvm/iMemory.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Constants.h"
-#include "Support/StringExtras.h"
+#include "Support/Debug.h"
 #include "Support/Statistic.h"
+#include "Support/StringExtras.h"
 
 namespace {
   Statistic<> NumReplaced("scalarrepl", "Number of alloca's broken up");
@@ -22,8 +23,14 @@ namespace {
   struct SROA : public FunctionPass {
     bool runOnFunction(Function &F);
 
+    // getAnalysisUsage - This pass does not require any passes, but we know it
+    // will not alter the CFG, so say so.
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.setPreservesCFG();
+    }
+
   private:
-    bool isSafeArrayElementUse(Value *Ptr);
+    bool isSafeElementUse(Value *Ptr);
     bool isSafeUseOfAllocation(Instruction *User);
     bool isSafeStructAllocaToPromote(AllocationInst *AI);
     bool isSafeArrayAllocaToPromote(AllocationInst *AI);
@@ -103,11 +110,7 @@ bool SROA::runOnFunction(Function &F) {
       Instruction *User = cast<Instruction>(*I);
       if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
         // We now know that the GEP is of the form: GEP <ptr>, 0, <cst>
-        uint64_t Idx;
-        if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(GEPI->getOperand(2)))
-          Idx = CSI->getValue();
-        else
-          Idx = cast<ConstantUInt>(GEPI->getOperand(2))->getValue();
+        uint64_t Idx = cast<ConstantInt>(GEPI->getOperand(2))->getRawValue();
         
         assert(Idx < ElementAllocas.size() && "Index out of range?");
         AllocaInst *AllocaToUse = ElementAllocas[Idx];
@@ -166,11 +169,10 @@ bool SROA::isSafeUseOfAllocation(Instruction *User) {
   return true;
 }
 
-
-/// isSafeArrayElementUse - Check to see if this use is an allowed use for a
+/// isSafeElementUse - Check to see if this use is an allowed use for a
 /// getelementptr instruction of an array aggregate allocation.
 ///
-bool SROA::isSafeArrayElementUse(Value *Ptr) {
+bool SROA::isSafeElementUse(Value *Ptr) {
   for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end();
        I != E; ++I) {
     Instruction *User = cast<Instruction>(*I);
@@ -183,15 +185,8 @@ bool SROA::isSafeArrayElementUse(Value *Ptr) {
         if (!isa<Constant>(GEP->getOperand(1)) ||
             !cast<Constant>(GEP->getOperand(1))->isNullValue())
           return false;  // Using pointer arithmetic to navigate the array...
-        
-        // Check to see if there are any structure indexes involved in this GEP.
-        // If so, then we can safely break the array up until at least the
-        // structure.
-        for (unsigned i = 2, e = GEP->getNumOperands(); i != e; ++i)
-          if (GEP->getOperand(i)->getType()->isUnsigned())
-            break;
       }
-      return isSafeArrayElementUse(GEP);
+      return isSafeElementUse(GEP);
     }
     default:
       DEBUG(std::cerr << "  Transformation preventing inst: " << *User);
@@ -210,12 +205,18 @@ bool SROA::isSafeStructAllocaToPromote(AllocationInst *AI) {
   // the users are safe to transform.
   //
   for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
-       I != E; ++I)
+       I != E; ++I) {
     if (!isSafeUseOfAllocation(cast<Instruction>(*I))) {
       DEBUG(std::cerr << "Cannot transform: " << *AI << "  due to user: "
                       << *I);
       return false;
     }
+
+    // Pedantic check to avoid breaking broken programs...
+    if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*I))
+      if (GEPI->getNumOperands() == 3 && !isSafeElementUse(GEPI))
+        return false;
+  }
   return true;
 }
 
@@ -253,7 +254,7 @@ bool SROA::isSafeArrayAllocaToPromote(AllocationInst *AI) {
       //   P = &A[0];  P = P + 1
       // is legal, and should prevent promotion.
       //
-      if (!isSafeArrayElementUse(GEPI)) {
+      if (!isSafeElementUse(GEPI)) {
         DEBUG(std::cerr << "Cannot transform: " << *AI
                         << "  due to uses of user: " << *GEPI);
         return false;