ScalarRepl does not modify the CFG. Say so!
[oota-llvm.git] / lib / Transforms / Scalar / ScalarReplAggregates.cpp
index c540bba2703679b461dcb0f9c2744ad9ed0404c1..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,7 +23,17 @@ 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 isSafeElementUse(Value *Ptr);
+    bool isSafeUseOfAllocation(Instruction *User);
+    bool isSafeStructAllocaToPromote(AllocationInst *AI);
+    bool isSafeArrayAllocaToPromote(AllocationInst *AI);
     AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocationInst *Base);
   };
 
@@ -59,48 +70,13 @@ bool SROA::runOnFunction(Function &F) {
         (!isa<StructType>(AI->getAllocatedType()) &&
          !isa<ArrayType>(AI->getAllocatedType()))) continue;
 
-    const ArrayType *AT = dyn_cast<ArrayType>(AI->getAllocatedType());
-
-    // Loop over the use list of the alloca.  We can only transform it if there
-    // are only getelementptr instructions (with a zero first index) and free
-    // instructions.
-    //
-    bool CannotTransform = false;
-    for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
-         I != E; ++I) {
-      Instruction *User = cast<Instruction>(*I);
-      if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
-        // The GEP is safe to transform if it is of the form GEP <ptr>, 0, <cst>
-        if (GEPI->getNumOperands() <= 2 ||
-            GEPI->getOperand(1) != Constant::getNullValue(Type::LongTy) ||
-            !isa<Constant>(GEPI->getOperand(2)) ||
-            isa<ConstantExpr>(GEPI->getOperand(2))) {
-          DEBUG(std::cerr << "Cannot transform: " << *AI << "  due to user: "
-                          << User);
-          CannotTransform = true;
-          break;
-        }
-
-        // If this is an array access, check to make sure that index falls
-        // within the array.  If not, something funny is going on, so we won't
-        // do the optimization.
-        if (AT && cast<ConstantSInt>(GEPI->getOperand(2))->getValue() >=
-            AT->getNumElements()) {
-          DEBUG(std::cerr << "Cannot transform: " << *AI << "  due to user: "
-                          << User);
-          CannotTransform = true;
-          break;
-        }
-
-      } else {
-        DEBUG(std::cerr << "Cannot transform: " << *AI << "  due to user: "
-                        << User);
-        CannotTransform = true;
-        break;
-      }
-    }
-
-    if (CannotTransform) continue;
+    // Check that all of the users of the allocation are capable of being
+    // transformed.
+    if (isa<StructType>(AI->getAllocatedType())) {
+      if (!isSafeStructAllocaToPromote(AI))
+        continue;
+    } else if (!isSafeArrayAllocaToPromote(AI))
+      continue;
 
     DEBUG(std::cerr << "Found inst to xform: " << *AI);
     Changed = true;
@@ -115,6 +91,7 @@ bool SROA::runOnFunction(Function &F) {
         WorkList.push_back(NA);  // Add to worklist for recursive processing
       }
     } else {
+      const ArrayType *AT = cast<ArrayType>(AI->getAllocatedType());
       ElementAllocas.reserve(AT->getNumElements());
       const Type *ElTy = AT->getElementType();
       for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) {
@@ -133,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];
@@ -153,12 +126,12 @@ bool SROA::runOnFunction(Function &F) {
           // expanded itself once the worklist is rerun.
           //
           std::string OldName = GEPI->getName();  // Steal the old name...
+          std::vector<Value*> NewArgs;
+          NewArgs.push_back(Constant::getNullValue(Type::LongTy));
+          NewArgs.insert(NewArgs.end(), GEPI->op_begin()+3, GEPI->op_end());
           GEPI->setName("");
           RepValue =
-            new GetElementPtrInst(AllocaToUse, 
-                                  std::vector<Value*>(GEPI->op_begin()+3, 
-                                                      GEPI->op_end()),
-                                  OldName, GEPI);
+            new GetElementPtrInst(AllocaToUse, NewArgs, OldName, GEPI);
         }
 
         // Move all of the users over to the new GEP.
@@ -177,3 +150,117 @@ bool SROA::runOnFunction(Function &F) {
 
   return Changed;
 }
+
+
+/// isSafeUseOfAllocation - Check to see if this user is an allowed use for an
+/// aggregate allocation.
+///
+bool SROA::isSafeUseOfAllocation(Instruction *User) {
+  if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
+    // The GEP is safe to transform if it is of the form GEP <ptr>, 0, <cst>
+    if (GEPI->getNumOperands() <= 2 ||
+        GEPI->getOperand(1) != Constant::getNullValue(Type::LongTy) ||
+        !isa<Constant>(GEPI->getOperand(2)) ||
+        isa<ConstantExpr>(GEPI->getOperand(2)))
+      return false;
+  } else {
+    return false;
+  }
+  return true;
+}
+
+/// isSafeElementUse - Check to see if this use is an allowed use for a
+/// getelementptr instruction of an array aggregate allocation.
+///
+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);
+    switch (User->getOpcode()) {
+    case Instruction::Load:  return true;
+    case Instruction::Store: return User->getOperand(0) != Ptr;
+    case Instruction::GetElementPtr: {
+      GetElementPtrInst *GEP = cast<GetElementPtrInst>(User);
+      if (GEP->getNumOperands() > 1) {
+        if (!isa<Constant>(GEP->getOperand(1)) ||
+            !cast<Constant>(GEP->getOperand(1))->isNullValue())
+          return false;  // Using pointer arithmetic to navigate the array...
+      }
+      return isSafeElementUse(GEP);
+    }
+    default:
+      DEBUG(std::cerr << "  Transformation preventing inst: " << *User);
+      return false;
+    }
+  }
+  return true;  // All users look ok :)
+}
+
+
+/// isSafeStructAllocaToPromote - Check to see if the specified allocation of a
+/// structure can be broken down into elements.
+///
+bool SROA::isSafeStructAllocaToPromote(AllocationInst *AI) {
+  // Loop over the use list of the alloca.  We can only transform it if all of
+  // the users are safe to transform.
+  //
+  for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
+       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;
+}
+
+
+/// isSafeArrayAllocaToPromote - Check to see if the specified allocation of a
+/// structure can be broken down into elements.
+///
+bool SROA::isSafeArrayAllocaToPromote(AllocationInst *AI) {
+  const ArrayType *AT = cast<ArrayType>(AI->getAllocatedType());
+  int64_t NumElements = AT->getNumElements();
+
+  // Loop over the use list of the alloca.  We can only transform it if all of
+  // the users are safe to transform.  Array allocas have extra constraints to
+  // meet though.
+  //
+  for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
+       I != E; ++I) {
+    Instruction *User = cast<Instruction>(*I);
+    if (!isSafeUseOfAllocation(User)) {
+      DEBUG(std::cerr << "Cannot transform: " << *AI << "  due to user: "
+                      << User);
+      return false;
+    }
+
+    // Check to make sure that getelementptr follow the extra rules for arrays:
+    if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
+      // Check to make sure that index falls within the array.  If not,
+      // something funny is going on, so we won't do the optimization.
+      //
+      if (cast<ConstantSInt>(GEPI->getOperand(2))->getValue() >= NumElements)
+        return false;
+
+      // Check to make sure that the only thing that uses the resultant pointer
+      // is safe for an array access.  For example, code that looks like:
+      //   P = &A[0];  P = P + 1
+      // is legal, and should prevent promotion.
+      //
+      if (!isSafeElementUse(GEPI)) {
+        DEBUG(std::cerr << "Cannot transform: " << *AI
+                        << "  due to uses of user: " << *GEPI);
+        return false;
+      }
+    }
+  }
+  return true;
+}
+