[llvm-commits] [gcc-plugin] r81348 - /gcc-plugin/trunk/llvm-convert.cpp

Duncan Sands baldrick at free.fr
Wed Sep 9 09:38:21 PDT 2009


Author: baldrick
Date: Wed Sep  9 11:38:21 2009
New Revision: 81348

URL: http://llvm.org/viewvc/llvm-project?rev=81348&view=rev
Log:
Handle phi nodes where predecessors occur multiple times,
for example because several switch cases branch to it.  In
GCC there is only one predecessor in this case, so with the
previous logic the phi node would end up with less operands
than there are basic block predecessors.

Modified:
    gcc-plugin/trunk/llvm-convert.cpp

Modified: gcc-plugin/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/gcc-plugin/trunk/llvm-convert.cpp?rev=81348&r1=81347&r2=81348&view=diff

==============================================================================
--- gcc-plugin/trunk/llvm-convert.cpp (original)
+++ gcc-plugin/trunk/llvm-convert.cpp Wed Sep  9 11:38:21 2009
@@ -34,6 +34,7 @@
 #include "llvm/Module.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/System/Host.h"
+#include "llvm/Support/CFG.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MathExtras.h"
@@ -640,12 +641,14 @@
 }
 
 Function *TreeToLLVM::FinishFunctionBody() {
+  DenseMap<BasicBlock*, Value*> IncomingValues;
+
   // Populate phi nodes with their operands now that all ssa names have been
   // defined.
   for (unsigned i = 0, e = PendingPhis.size(); i < e; ++i) {
     PhiRecord &P = PendingPhis[i];
 
-    P.PHI->reserveOperandSpace(gimple_phi_num_args(P.gcc_phi));
+    // Extract the incoming value for each predecessor from the GCC phi node.
     for (size_t i = 0; i < gimple_phi_num_args(P.gcc_phi); ++i) {
       // Find the incoming basic block.
       basic_block bb = gimple_phi_arg_edge(P.gcc_phi, i)->src;
@@ -667,8 +670,26 @@
       else
         Val = TreeConstantToLLVM::Convert(def);
 
-      P.PHI->addIncoming(Val, BI->second);
+      // Predecessors can occur more times in LLVM than in GCC, where they only
+      // occur once, so it is not enough to push one phi operand per GCC edge.
+      // Instead, remember the incoming value for each predecessor in a map.
+      assert(IncomingValues.find(BI->second) == IncomingValues.end() &&
+             "Multiple edges between basic blocks!");
+      IncomingValues[BI->second] = Val;
+    }
+
+    // Now iterate over all LLVM predecessors, adding phi operands as we go.
+    BasicBlock *CurBB = P.PHI->getParent();
+    P.PHI->reserveOperandSpace(gimple_phi_num_args(P.gcc_phi));
+    for (pred_iterator PI = pred_begin(CurBB), PE = pred_end(CurBB); PI != PE;
+         ++PI) {
+      BasicBlock *IncomingBB = *PI;
+      assert(IncomingValues.find(IncomingBB) != IncomingValues.end() &&
+             "No incoming value for predecessor!");
+      P.PHI->addIncoming(IncomingValues[IncomingBB], IncomingBB);
     }
+
+    IncomingValues.clear();
   }
   PendingPhis.clear();
 





More information about the llvm-commits mailing list