Temporarily revert r54792. It's causing an ICE during bootstrapping.
[oota-llvm.git] / lib / Transforms / Scalar / SCCP.cpp
index da715acd29b5f77ff08fae341a9b1263a2886ae6..8c64d8ff7c98f7ad887a9e9a62b92b62bbe8d778 100644 (file)
@@ -29,6 +29,7 @@
 #include "llvm/Instructions.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ConstantFolding.h"
+#include "llvm/Analysis/ValueTracking.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/Support/CallSite.h"
 #include "llvm/Support/Compiler.h"
@@ -383,13 +384,14 @@ private:
   void visitTerminatorInst(TerminatorInst &TI);
 
   void visitCastInst(CastInst &I);
-  void visitGetResultInst(GetResultInst &GRI);
   void visitSelectInst(SelectInst &I);
   void visitBinaryOperator(Instruction &I);
   void visitCmpInst(CmpInst &I);
   void visitExtractElementInst(ExtractElementInst &I);
   void visitInsertElementInst(InsertElementInst &I);
   void visitShuffleVectorInst(ShuffleVectorInst &I);
+  void visitExtractValueInst(ExtractValueInst &EVI);
+  void visitInsertValueInst(InsertValueInst &IVI);
 
   // Instructions that cannot be folded away...
   void visitStoreInst     (Instruction &I);
@@ -630,6 +632,17 @@ void SCCPSolver::visitReturnInst(ReturnInst &I) {
       if (It == TrackedMultipleRetVals.end()) break;
       mergeInValue(It->second, F, getValueState(I.getOperand(i)));
     }
+  } else if (!TrackedMultipleRetVals.empty() &&
+             I.getNumOperands() == 1 &&
+             isa<StructType>(I.getOperand(0)->getType())) {
+    for (unsigned i = 0, e = I.getOperand(0)->getType()->getNumContainedTypes();
+         i != e; ++i) {
+      std::map<std::pair<Function*, unsigned>, LatticeVal>::iterator
+        It = TrackedMultipleRetVals.find(std::make_pair(F, i));
+      if (It == TrackedMultipleRetVals.end()) break;
+      Value *Val = FindInsertedValue(I.getOperand(0), i);
+      mergeInValue(It->second, F, getValueState(Val));
+    }
   }
 }
 
@@ -655,34 +668,40 @@ void SCCPSolver::visitCastInst(CastInst &I) {
                                            VState.getConstant(), I.getType()));
 }
 
-void SCCPSolver::visitGetResultInst(GetResultInst &GRI) {
-  Value *Aggr = GRI.getOperand(0);
+void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) {
+  Value *Aggr = EVI.getAggregateOperand();
 
-  // If the operand to the getresult is an undef, the result is undef.
+  // If the operand to the extractvalue is an undef, the result is undef.
   if (isa<UndefValue>(Aggr))
     return;
+
+  // Currently only handle single-index extractvalues.
+  if (EVI.getNumIndices() != 1) {
+    markOverdefined(&EVI);
+    return;
+  }
   
-  Function *F;
+  Function *F = 0;
   if (CallInst *CI = dyn_cast<CallInst>(Aggr))
     F = CI->getCalledFunction();
-  else
-    F = cast<InvokeInst>(Aggr)->getCalledFunction();
+  else if (InvokeInst *II = dyn_cast<InvokeInst>(Aggr))
+    F = II->getCalledFunction();
 
   // TODO: If IPSCCP resolves the callee of this function, we could propagate a
   // result back!
   if (F == 0 || TrackedMultipleRetVals.empty()) {
-    markOverdefined(&GRI);
+    markOverdefined(&EVI);
     return;
   }
   
   // See if we are tracking the result of the callee.
   std::map<std::pair<Function*, unsigned>, LatticeVal>::iterator
-    It = TrackedMultipleRetVals.find(std::make_pair(F, GRI.getIndex()));
+    It = TrackedMultipleRetVals.find(std::make_pair(F, *EVI.idx_begin()));
 
   // If not tracking this function (for example, it is a declaration) just move
   // to overdefined.
   if (It == TrackedMultipleRetVals.end()) {
-    markOverdefined(&GRI);
+    markOverdefined(&EVI);
     return;
   }
   
@@ -690,6 +709,51 @@ void SCCPSolver::visitGetResultInst(GetResultInst &GRI) {
   // handling.
 }
 
+void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) {
+  Value *Aggr = IVI.getAggregateOperand();
+  Value *Val = IVI.getInsertedValueOperand();
+
+  // If the operands to the insertvalue are undef, the result is undef.
+  if (isa<UndefValue>(Aggr) && isa<UndefValue>(Val))
+    return;
+
+  // Currently only handle single-index insertvalues.
+  if (IVI.getNumIndices() != 1) {
+    markOverdefined(&IVI);
+    return;
+  }
+
+  // Currently only handle insertvalue instructions that are in a single-use
+  // chain that builds up a return value.
+  for (const InsertValueInst *TmpIVI = &IVI; ; ) {
+    if (!TmpIVI->hasOneUse()) {
+      markOverdefined(&IVI);
+      return;
+    }
+    const Value *V = *TmpIVI->use_begin();
+    if (isa<ReturnInst>(V))
+      break;
+    TmpIVI = dyn_cast<InsertValueInst>(V);
+    if (!TmpIVI) {
+      markOverdefined(&IVI);
+      return;
+    }
+  }
+  
+  // See if we are tracking the result of the callee.
+  Function *F = IVI.getParent()->getParent();
+  std::map<std::pair<Function*, unsigned>, LatticeVal>::iterator
+    It = TrackedMultipleRetVals.find(std::make_pair(F, *IVI.idx_begin()));
+
+  // Merge in the inserted member value.
+  if (It != TrackedMultipleRetVals.end())
+    mergeInValue(It->second, F, getValueState(Val));
+
+  // Mark the aggregate result of the IVI overdefined; any tracking that we do
+  // will be done on the individual member values.
+  markOverdefined(&IVI);
+}
+
 void SCCPSolver::visitSelectInst(SelectInst &I) {
   LatticeVal &CondValue = getValueState(I.getCondition());
   if (CondValue.isUndefined())
@@ -1149,17 +1213,11 @@ CallOverdefined:
   }
 
   // If this is a single/zero retval case, see if we're tracking the function.
-  const StructType *RetSTy = dyn_cast<StructType>(I->getType());
-  if (RetSTy == 0) {
-    // Check to see if we're tracking this callee, if not, handle it in the
-    // common path above.
-    DenseMap<Function*, LatticeVal>::iterator TFRVI = TrackedRetVals.find(F);
-    if (TFRVI == TrackedRetVals.end())
-      goto CallOverdefined;
-    
+  DenseMap<Function*, LatticeVal>::iterator TFRVI = TrackedRetVals.find(F);
+  if (TFRVI != TrackedRetVals.end()) {
     // If so, propagate the return value of the callee into this call result.
     mergeInValue(I, TFRVI->second);
-  } else {
+  } else if (isa<StructType>(I->getType())) {
     // Check to see if we're tracking this callee, if not, handle it in the
     // common path above.
     std::map<std::pair<Function*, unsigned>, LatticeVal>::iterator
@@ -1168,13 +1226,25 @@ CallOverdefined:
       goto CallOverdefined;
     
     // If we are tracking this callee, propagate the return values of the call
-    // into this call site.  We do this by walking all the getresult uses.
+    // into this call site.  We do this by walking all the uses. Single-index
+    // ExtractValueInst uses can be tracked; anything more complicated is
+    // currently handled conservatively.
     for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
          UI != E; ++UI) {
-      GetResultInst *GRI = cast<GetResultInst>(*UI);
-      mergeInValue(GRI, 
-                   TrackedMultipleRetVals[std::make_pair(F, GRI->getIndex())]);
+      if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(*UI)) {
+        if (EVI->getNumIndices() == 1) {
+          mergeInValue(EVI, 
+                  TrackedMultipleRetVals[std::make_pair(F, *EVI->idx_begin())]);
+          continue;
+        }
+      }
+      // The aggregate value is used in a way not handled here. Assume nothing.
+      markOverdefined(*UI);
     }
+  } else {
+    // Otherwise we're not tracking this callee, so handle it in the
+    // common path above.
+    goto CallOverdefined;
   }
    
   // Finally, if this is the first call to the function hit, mark its entry
@@ -1513,7 +1583,6 @@ bool SCCP::runOnFunction(Function &F) {
       for (BasicBlock::iterator BI = BB->begin(), E = BB->end(); BI != E; ) {
         Instruction *Inst = BI++;
         if (Inst->getType() == Type::VoidTy ||
-            isa<StructType>(Inst->getType()) ||
             isa<TerminatorInst>(Inst))
           continue;
         
@@ -1690,7 +1759,6 @@ bool IPSCCP::runOnModule(Module &M) {
         for (BasicBlock::iterator BI = BB->begin(), E = BB->end(); BI != E; ) {
           Instruction *Inst = BI++;
           if (Inst->getType() == Type::VoidTy ||
-              isa<StructType>(Inst->getType()) ||
               isa<TerminatorInst>(Inst))
             continue;