[llvm-commits] [llvm] r48210 - in /llvm/trunk: lib/Transforms/Scalar/SCCP.cpp test/Transforms/SCCP/2008-03-10-sret.ll

Devang Patel dpatel at apple.com
Mon Mar 10 22:46:42 PDT 2008


Author: dpatel
Date: Tue Mar 11 00:46:42 2008
New Revision: 48210

URL: http://llvm.org/viewvc/llvm-project?rev=48210&view=rev
Log:
Initial multiple return values support.

Added:
    llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/SCCP.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=48210&r1=48209&r2=48210&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Tue Mar 11 00:46:42 2008
@@ -129,6 +129,21 @@
   }
 };
 
+/// LatticeValIndex - LatticeVal and associated Index. This is used
+/// to track individual operand Lattice values for multi value ret instructions.
+class VISIBILITY_HIDDEN LatticeValIndexed {
+ public:
+  LatticeValIndexed(unsigned I = 0) { Index = I; }
+  LatticeVal &getLatticeVal() { return LV; }
+  unsigned getIndex() const { return Index; }
+
+  void setLatticeVal(LatticeVal &L) { LV = L; }
+  void setIndex(unsigned I) { Index = I; }
+
+ private:
+  LatticeVal LV;
+  unsigned Index;
+};
 //===----------------------------------------------------------------------===//
 //
 /// SCCPSolver - This class is a general purpose solver for Sparse Conditional
@@ -144,10 +159,14 @@
   /// overdefined, it's entry is simply removed from this map.
   DenseMap<GlobalVariable*, LatticeVal> TrackedGlobals;
 
-  /// TrackedFunctionRetVals - If we are tracking arguments into and the return
+  /// TrackedRetVals - If we are tracking arguments into and the return
   /// value out of a function, it will have an entry in this map, indicating
   /// what the known return value for the function is.
-  DenseMap<Function*, LatticeVal> TrackedFunctionRetVals;
+  DenseMap<Function*, LatticeVal> TrackedRetVals;
+
+  /// TrackedMultipleRetVals - Same as TrackedRetVals, but used for functions
+  /// that return multiple values.
+  std::multimap<Function*, LatticeValIndexed> TrackedMultipleRetVals;
 
   // The reason for two worklists is that overdefined is the lowest state
   // on the lattice, and moving things to overdefined as fast as possible
@@ -198,7 +217,13 @@
   void AddTrackedFunction(Function *F) {
     assert(F->hasInternalLinkage() && "Can only track internal functions!");
     // Add an entry, F -> undef.
-    TrackedFunctionRetVals[F];
+    if (const StructType *STy = dyn_cast<StructType>(F->getReturnType())) {
+      for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
+        TrackedMultipleRetVals.insert(std::pair<Function *, LatticeValIndexed>
+                                      (F, LatticeValIndexed(i)));
+    }
+    else
+      TrackedRetVals[F];
   }
 
   /// Solve - Solve for constants and executable blocks.
@@ -224,10 +249,10 @@
     return ValueState;
   }
 
-  /// getTrackedFunctionRetVals - Get the inferred return value map.
+  /// getTrackedRetVals - Get the inferred return value map.
   ///
-  const DenseMap<Function*, LatticeVal> &getTrackedFunctionRetVals() {
-    return TrackedFunctionRetVals;
+  const DenseMap<Function*, LatticeVal> &getTrackedRetVals() {
+    return TrackedRetVals;
   }
 
   /// getTrackedGlobals - Get and return the set of inferred initializers for
@@ -374,6 +399,7 @@
   void visitTerminatorInst(TerminatorInst &TI);
 
   void visitCastInst(CastInst &I);
+  void visitGetResultInst(GetResultInst &GRI);
   void visitSelectInst(SelectInst &I);
   void visitBinaryOperator(Instruction &I);
   void visitCmpInst(CmpInst &I);
@@ -608,20 +634,35 @@
 void SCCPSolver::visitReturnInst(ReturnInst &I) {
   if (I.getNumOperands() == 0) return;  // Ret void
 
-  // If we are tracking the return value of this function, merge it in.
   Function *F = I.getParent()->getParent();
-  if (F->hasInternalLinkage() && !TrackedFunctionRetVals.empty()) {
+  // If we are tracking the return value of this function, merge it in.
+  if (!F->hasInternalLinkage())
+    return;
+
+  if (!TrackedRetVals.empty()) {
     DenseMap<Function*, LatticeVal>::iterator TFRVI =
-      TrackedFunctionRetVals.find(F);
-    if (TFRVI != TrackedFunctionRetVals.end() &&
+      TrackedRetVals.find(F);
+    if (TFRVI != TrackedRetVals.end() &&
         !TFRVI->second.isOverdefined()) {
       LatticeVal &IV = getValueState(I.getOperand(0));
       mergeInValue(TFRVI->second, F, IV);
+      return;
+    }
+  }
+  
+  // Handle function that returns multiple values.
+  std::multimap<Function*, LatticeValIndexed>::iterator It, E;
+  tie(It, E) = TrackedMultipleRetVals.equal_range(F);
+  if (It != E) {
+    for (; It != E; ++It) {
+      LatticeValIndexed &LV = It->second;
+      unsigned Idx = LV.getIndex();
+      Value *V = I.getOperand(Idx);
+      mergeInValue(LV.getLatticeVal(), V, getValueState(V));
     }
   }
 }
 
-
 void SCCPSolver::visitTerminatorInst(TerminatorInst &TI) {
   SmallVector<bool, 16> SuccFeasible;
   getFeasibleSuccessors(TI, SuccFeasible);
@@ -644,6 +685,30 @@
                                            VState.getConstant(), I.getType()));
 }
 
+void SCCPSolver::visitGetResultInst(GetResultInst &GRI) {
+  unsigned Idx = GRI.getIndex();
+  Value *Aggr = GRI.getOperand(0);
+  Function *F = NULL;
+  if (CallInst *CI = dyn_cast<CallInst>(Aggr)) 
+    F = CI->getCalledFunction();
+  else if (InvokeInst *II = dyn_cast<InvokeInst>(Aggr))
+    F = II->getCalledFunction();
+
+  assert (F && "Invalid GetResultInst operands!");
+
+  std::multimap<Function*, LatticeValIndexed>::iterator It, E;
+  tie(It, E) = TrackedMultipleRetVals.equal_range(F);
+  if (It == E) 
+    return;
+
+  for (; It != E; ++It) {
+    LatticeValIndexed &LIV = It->second;
+    if (LIV.getIndex() == Idx) {
+      mergeInValue(&GRI, LIV.getLatticeVal());
+    }
+  }
+}
+
 void SCCPSolver::visitSelectInst(SelectInst &I) {
   LatticeVal &CondValue = getValueState(I.getCondition());
   if (CondValue.isUndefined())
@@ -1061,18 +1126,28 @@
 void SCCPSolver::visitCallSite(CallSite CS) {
   Function *F = CS.getCalledFunction();
 
+  DenseMap<Function*, LatticeVal>::iterator TFRVI =TrackedRetVals.end();
   // If we are tracking this function, we must make sure to bind arguments as
   // appropriate.
-  DenseMap<Function*, LatticeVal>::iterator TFRVI =TrackedFunctionRetVals.end();
-  if (F && F->hasInternalLinkage())
-    TFRVI = TrackedFunctionRetVals.find(F);
+  bool FirstCall = false;
+  if (F && F->hasInternalLinkage()) {
+    TFRVI = TrackedRetVals.find(F);
+    if (TFRVI != TrackedRetVals.end()) 
+      FirstCall = true;
+    else {
+      std::multimap<Function*, LatticeValIndexed>::iterator It, E;
+      tie(It, E) = TrackedMultipleRetVals.equal_range(F);
+      if (It != E) 
+        FirstCall = true;
+    }
+  }
 
-  if (TFRVI != TrackedFunctionRetVals.end()) {
+  if (FirstCall) {
     // If this is the first call to the function hit, mark its entry block
     // executable.
     if (!BBExecutable.count(F->begin()))
       MarkBlockExecutable(F->begin());
-
+    
     CallSite::arg_iterator CAI = CS.arg_begin();
     for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end();
          AI != E; ++AI, ++CAI) {
@@ -1091,8 +1166,9 @@
   LatticeVal &IV = ValueState[I];
   if (IV.isOverdefined()) return;
 
-  // Propagate the return value of the function to the value of the instruction.
-  if (TFRVI != TrackedFunctionRetVals.end()) {
+  // Propagate the single return value of the function to the value of the 
+  // instruction.
+  if (TFRVI != TrackedRetVals.end()) {
     mergeInValue(IV, I, TFRVI->second);
     return;
   }
@@ -1684,7 +1760,7 @@
   // all call uses with the inferred value.  This means we don't need to bother
   // actually returning anything from the function.  Replace all return
   // instructions with return undef.
-  const DenseMap<Function*, LatticeVal> &RV =Solver.getTrackedFunctionRetVals();
+  const DenseMap<Function*, LatticeVal> &RV = Solver.getTrackedRetVals();
   for (DenseMap<Function*, LatticeVal>::const_iterator I = RV.begin(),
          E = RV.end(); I != E; ++I)
     if (!I->second.isOverdefined() &&

Added: llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll?rev=48210&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll (added)
+++ llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll Tue Mar 11 00:46:42 2008
@@ -0,0 +1,12 @@
+; RUN: llvm-as < %s  | opt -ipsccp -disable-output
+
+define internal {i32, i32} @bar(i32 %A) {
+	%X = add i32 1, 2
+	ret i32 %A, i32 %A
+}
+
+define i32 @foo() {
+	%X = call {i32, i32} @bar(i32 17)
+        %Y = getresult {i32, i32} %X, 0
+	ret i32 %Y
+}





More information about the llvm-commits mailing list