[llvm-commits] [llvm] r48020 - in /llvm/trunk: lib/Transforms/Utils/InlineFunction.cpp test/Transforms/SRETPromotion/2008-03-07-Inline-2.ll test/Transforms/SRETPromotion/2008-03-07-Inline.ll

Devang Patel dpatel at apple.com
Fri Mar 7 12:06:16 PST 2008


Author: dpatel
Date: Fri Mar  7 14:06:16 2008
New Revision: 48020

URL: http://llvm.org/viewvc/llvm-project?rev=48020&view=rev
Log:
Update inliner to handle functions that return multiple values.

Added:
    llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline-2.ll
    llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline.ll
Modified:
    llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp

Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=48020&r1=48019&r2=48020&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Fri Mar  7 14:06:16 2008
@@ -503,65 +503,74 @@
   // Now that the function is correct, make it a little bit nicer.  In
   // particular, move the basic blocks inserted from the end of the function
   // into the space made by splitting the source basic block.
-  //
   Caller->getBasicBlockList().splice(AfterCallBB, Caller->getBasicBlockList(),
                                      FirstNewBlock, Caller->end());
 
   // Handle all of the return instructions that we just cloned in, and eliminate
   // any users of the original call/invoke instruction.
-  if (Returns.size() > 1) {
+  if (!Returns.empty()) {
     // The PHI node should go at the front of the new basic block to merge all
     // possible incoming values.
-    //
-    PHINode *PHI = 0;
+    SmallVector<PHINode *, 4> PHIs;
     if (!TheCall->use_empty()) {
-      PHI = new PHINode(CalledFunc->getReturnType(),
-                        TheCall->getName(), AfterCallBB->begin());
-
-      // Anything that used the result of the function call should now use the
-      // PHI node as their operand.
-      //
-      TheCall->replaceAllUsesWith(PHI);
+      const Type *RTy = CalledFunc->getReturnType();
+      if (const StructType *STy = dyn_cast<StructType>(RTy)) {
+        unsigned NumRetVals = STy->getNumElements();
+        // Create new phi nodes such that phi node number in the PHIs vector
+        // match corresponding return value operand number.
+        for (unsigned i = 0; i < NumRetVals; ++i) {
+          PHINode *PHI = new PHINode(STy->getElementType(i),
+                                     TheCall->getName(), AfterCallBB->begin());
+          PHIs.push_back(PHI);
+        }
+        // TheCall results are used by GetResult instructions. 
+        while (!TheCall->use_empty()) {
+          GetResultInst *GR = cast<GetResultInst>(TheCall->use_back());
+          GR->replaceAllUsesWith(PHIs[GR->getIndex()]);
+          GR->eraseFromParent();
+        }
+      } else {
+        PHINode *PHI = new PHINode(RTy, TheCall->getName(), AfterCallBB->begin());
+        PHIs.push_back(PHI);
+        // Anything that used the result of the function call should now use the
+        // PHI node as their operand.
+        TheCall->replaceAllUsesWith(PHI); 
+      } 
     }
 
-    // Loop over all of the return instructions, turning them into unconditional
-    // branches to the merge point now, and adding entries to the PHI node as
+    // Loop over all of the return instructions adding entries to the PHI node as
     // appropriate.
-    for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
-      ReturnInst *RI = Returns[i];
-
-      if (PHI) {
-        assert(RI->getReturnValue() && "Ret should have value!");
-        assert(RI->getReturnValue()->getType() == PHI->getType() &&
-               "Ret value not consistent in function!");
-        PHI->addIncoming(RI->getReturnValue(), RI->getParent());
+    if (!PHIs.empty()) {
+      const Type *RTy = CalledFunc->getReturnType();
+      if (const StructType *STy = dyn_cast<StructType>(RTy)) {
+        unsigned NumRetVals = STy->getNumElements();
+        for (unsigned j = 0; j < NumRetVals; ++j) {
+          PHINode *PHI = PHIs[j];
+          // Each PHI node will receive one value from each return instruction.
+          for(unsigned i = 0, e = Returns.size(); i != e; ++i) {
+            ReturnInst *RI = Returns[i];
+            PHI->addIncoming(RI->getReturnValue(j /*PHI number matches operand number*/), 
+                             RI->getParent());
+          }
+        }
+      } else {
+        for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
+          ReturnInst *RI = Returns[i];
+          assert(PHIs.size() == 1 && "Invalid number of PHI nodes");
+          assert(RI->getReturnValue() && "Ret should have value!");
+          assert(RI->getReturnValue()->getType() == PHIs[0]->getType() &&
+                 "Ret value not consistent in function!");
+          PHIs[0]->addIncoming(RI->getReturnValue(), RI->getParent());
+        }
       }
+    }
 
-      // Add a branch to the merge point where the PHI node lives if it exists.
+    // Add a branch to the merge points and remove retrun instructions.
+    for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
+      ReturnInst *RI = Returns[i];
       new BranchInst(AfterCallBB, RI);
-
-      // Delete the return instruction now
       RI->getParent()->getInstList().erase(RI);
     }
-
-  } else if (!Returns.empty()) {
-    // Otherwise, if there is exactly one return value, just replace anything
-    // using the return value of the call with the computed value.
-    if (!TheCall->use_empty())
-      TheCall->replaceAllUsesWith(Returns[0]->getReturnValue());
-
-    // Splice the code from the return block into the block that it will return
-    // to, which contains the code that was after the call.
-    BasicBlock *ReturnBB = Returns[0]->getParent();
-    AfterCallBB->getInstList().splice(AfterCallBB->begin(),
-                                      ReturnBB->getInstList());
-
-    // Update PHI nodes that use the ReturnBB to use the AfterCallBB.
-    ReturnBB->replaceAllUsesWith(AfterCallBB);
-
-    // Delete the return instruction now and empty ReturnBB now.
-    Returns[0]->eraseFromParent();
-    ReturnBB->eraseFromParent();
   } else if (!TheCall->use_empty()) {
     // No returns, but something is using the return value of the call.  Just
     // nuke the result.

Added: llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline-2.ll?rev=48020&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline-2.ll (added)
+++ llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline-2.ll Fri Mar  7 14:06:16 2008
@@ -0,0 +1,46 @@
+; RUN: llvm-as < %s | opt -inline -sretpromotion -disable-output
+	%struct.Demand = type { double, double }
+	%struct.branch = type { %struct.Demand, double, double, double, double, %struct.branch*, [12 x %struct.leaf*] }
+	%struct.leaf = type { %struct.Demand, double, double }
+ at P = external global double		; <double*> [#uses=1]
+
+define %struct.leaf* @build_leaf() nounwind  {
+entry:
+	unreachable
+}
+
+define void @Compute_Branch(%struct.Demand* sret  %agg.result, %struct.branch* %br, double %theta_R, double %theta_I, double %pi_R, double %pi_I) nounwind  {
+entry:
+	%a2 = alloca %struct.Demand		; <%struct.Demand*> [#uses=2]
+	br i1 false, label %bb46, label %bb
+
+bb:		; preds = %entry
+	ret void
+
+bb46:		; preds = %entry
+	br label %bb72
+
+bb49:		; preds = %bb72
+	call void @Compute_Leaf( %struct.Demand* sret  %a2, %struct.leaf* null, double 0.000000e+00, double 0.000000e+00 ) nounwind 
+	%tmp66 = getelementptr %struct.Demand* %a2, i32 0, i32 1		; <double*> [#uses=0]
+	br label %bb72
+
+bb72:		; preds = %bb49, %bb46
+	br i1 false, label %bb49, label %bb77
+
+bb77:		; preds = %bb72
+	ret void
+}
+
+define void @Compute_Leaf(%struct.Demand* sret  %agg.result, %struct.leaf* %l, double %pi_R, double %pi_I) nounwind  {
+entry:
+	%tmp10 = load double* @P, align 8		; <double> [#uses=1]
+	%tmp11 = fcmp olt double %tmp10, 0.000000e+00		; <i1> [#uses=1]
+	br i1 %tmp11, label %bb, label %bb13
+
+bb:		; preds = %entry
+	br label %bb13
+
+bb13:		; preds = %bb, %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline.ll?rev=48020&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline.ll (added)
+++ llvm/trunk/test/Transforms/SRETPromotion/2008-03-07-Inline.ll Fri Mar  7 14:06:16 2008
@@ -0,0 +1,46 @@
+; RUN: llvm-as < %s | opt -inline -sretpromotion -disable-output
+	%struct.Demand = type { double, double }
+	%struct.branch = type { %struct.Demand, double, double, double, double, %struct.branch*, [12 x %struct.leaf*] }
+	%struct.leaf = type { %struct.Demand, double, double }
+ at P = external global double		; <double*> [#uses=1]
+
+define %struct.leaf* @build_leaf() nounwind  {
+entry:
+	unreachable
+}
+
+define void @Compute_Branch(%struct.Demand* sret  %agg.result, %struct.branch* %br, double %theta_R, double %theta_I, double %pi_R, double %pi_I) nounwind  {
+entry:
+	%a2 = alloca %struct.Demand		; <%struct.Demand*> [#uses=2]
+	br i1 false, label %bb46, label %bb
+
+bb:		; preds = %entry
+	ret void
+
+bb46:		; preds = %entry
+	br label %bb72
+
+bb49:		; preds = %bb72
+	call void @Compute_Leaf( %struct.Demand* sret  %a2, %struct.leaf* null, double 0.000000e+00, double 0.000000e+00 ) nounwind 
+	%tmp66 = getelementptr %struct.Demand* %a2, i32 0, i32 1		; <double*> [#uses=0]
+	br label %bb72
+
+bb72:		; preds = %bb49, %bb46
+	br i1 false, label %bb49, label %bb77
+
+bb77:		; preds = %bb72
+	ret void
+}
+
+define void @Compute_Leaf(%struct.Demand* sret  %agg.result, %struct.leaf* %l, double %pi_R, double %pi_I) nounwind  {
+entry:
+	%tmp10 = load double* @P, align 8		; <double> [#uses=1]
+	%tmp11 = fcmp olt double %tmp10, 0.000000e+00		; <i1> [#uses=1]
+	br i1 %tmp11, label %bb, label %bb13
+
+bb:		; preds = %entry
+	ret void
+
+bb13:		; preds = %entry
+	ret void
+}





More information about the llvm-commits mailing list