[llvm-commits] [gcc-plugin] r81216 - in /gcc-plugin/trunk: llvm-convert.cpp llvm-internal.h

Duncan Sands baldrick at free.fr
Tue Sep 8 07:14:24 PDT 2009


Author: baldrick
Date: Tue Sep  8 09:14:24 2009
New Revision: 81216

URL: http://llvm.org/viewvc/llvm-project?rev=81216&view=rev
Log:
Emit phi nodes in two stages: first define the phi and associate it with
the corresponding ssa name without populating the phi node with operands.
This is because ssa names occurring as operands may not have been defined
yet (phi nodes are special this way).  After all basic blocks have been
output, revist the phi nodes and populate them with operands.  The plugin
can now compile loops thanks to this fix.

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

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

==============================================================================
--- gcc-plugin/trunk/llvm-convert.cpp (original)
+++ gcc-plugin/trunk/llvm-convert.cpp Tue Sep  8 09:14:24 2009
@@ -637,6 +637,40 @@
 }
 
 Function *TreeToLLVM::FinishFunctionBody() {
+  // 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));
+    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;
+      DenseMap<basic_block, BasicBlock*>::iterator BI = BasicBlocks.find(bb);
+      // If it does not exist then it was unreachable - skip this phi argument.
+      if (BI == BasicBlocks.end())
+        continue;
+
+      // Obtain the incoming value.  It is important not to add new instructions
+      // to the function, which is why this is done by hand.
+      tree def = gimple_phi_arg(P.gcc_phi, i)->def;
+      Value *Val;
+
+      // The incoming value is either an ssa name or a constant.
+      // FIXME: Not clear what is allowed here exactly.
+      if (TREE_CODE(def) == SSA_NAME) {
+        DenseMap<tree, Value*>::iterator NI = SSANames.find(def);
+        assert(NI != SSANames.end() && "PHI operand never defined!");
+        Val = NI->second;
+      } else {
+        Val = TreeConstantToLLVM::Convert(def);
+      }
+
+      P.PHI->addIncoming(Val, BI->second);
+    }
+  }
+  PendingPhis.clear();
+
   // Insert the return block at the end of the function.
   EmitBlock(ReturnBB);
 
@@ -753,14 +787,29 @@
   if (bb != ENTRY_BLOCK_PTR)
     EmitBlock(getBasicBlock(bb));
 
-  // Render phi nodes.
+  // Create an LLVM phi node for each GCC phi and define the associated ssa name
+  // using it.  Do not populate with operands at this point since some ssa names
+  // the phi uses may not have been defined yet - phis are special this way.
   for (gimple_stmt_iterator gsi = gsi_start_phis(bb); !gsi_end_p(gsi);
        gsi_next(&gsi)) {
-      gimple phi = gsi_stmt(gsi);
-      // Skip virtual operands.
-      if (!is_gimple_reg(gimple_phi_result(phi)))
-        continue;
-      RenderGIMPLE_PHI(phi);
+    gimple gcc_phi = gsi_stmt(gsi);
+    // Skip virtual operands.
+    if (!is_gimple_reg(gimple_phi_result(gcc_phi)))
+      continue;
+
+    // Create the LLVM phi node.
+    const Type *Ty = ConvertType(TREE_TYPE(gimple_phi_result(gcc_phi)));
+    PHINode *PHI = Builder.CreatePHI(Ty);
+
+    // The phi defines the associated ssa name.
+    tree name = gimple_phi_result(gcc_phi);
+    assert(TREE_CODE(name) == SSA_NAME && "PHI result not an SSA name!");
+    assert(SSANames.find(name) == SSANames.end() && "Multiply defined SSA name!");
+    SSANames[name] = PHI;
+
+    // The phi operands will be populated later - remember the phi node.
+    PhiRecord P = { gcc_phi, PHI };
+    PendingPhis.push_back(P);
   }
 
   // Render statements.
@@ -8038,26 +8087,6 @@
 //                      ... Convert GIMPLE to LLVM ...
 //===----------------------------------------------------------------------===//
 
-void TreeToLLVM::RenderGIMPLE_PHI(gimple stmt) {
-  // Create the corresponding LLVM phi node.
-  const Type *Ty = ConvertType(TREE_TYPE(gimple_phi_result(stmt)));
-  PHINode *Phi = Builder.CreatePHI(Ty);
-
-  // Populate the phi operands.
-  Phi->reserveOperandSpace(gimple_phi_num_args(stmt));
-  for (size_t i = 0; i < gimple_phi_num_args(stmt); ++i) {
-    BasicBlock *BB = getBasicBlock(gimple_phi_arg_edge(stmt, i)->src);
-    Value *Val = Emit(gimple_phi_arg(stmt, i)->def, 0);
-    Phi->addIncoming(Val, BB);
-  }
-
-  // The phi defines the associated ssa name.
-  tree name = gimple_phi_result(stmt);
-  assert(TREE_CODE(name) == SSA_NAME && "PHI result not an SSA name!");
-  assert(SSANames.find(name) == SSANames.end() && "Multiply defined SSA name!");
-  SSANames[name] = Phi;
-}
-
 void TreeToLLVM::RenderGIMPLE_COND(gimple stmt) {
   // Compute the LLVM opcodes corresponding to the GCC comparison.
   unsigned UIPred = 0, SIPred = 0, FPPred = 0;

Modified: gcc-plugin/trunk/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/gcc-plugin/trunk/llvm-internal.h?rev=81216&r1=81215&r2=81216&view=diff

==============================================================================
--- gcc-plugin/trunk/llvm-internal.h (original)
+++ gcc-plugin/trunk/llvm-internal.h Tue Sep  8 09:14:24 2009
@@ -302,6 +302,12 @@
   bool isBitfield() const { return BitStart != 255; }
 };
 
+/// PhiRecord - This struct holds the LLVM PHI node associated with a GCC phi.
+struct PhiRecord {
+  gimple gcc_phi;
+  PHINode *PHI;
+};
+
 /// TreeToLLVM - An instance of this class is created and used to convert the
 /// body of each function to LLVM.
 ///
@@ -320,9 +326,6 @@
   /// same as &Fn->back().
   LLVMBuilder Builder;
 
-  /// BasicBlocks - Map from GCC to LLVM basic blocks.
-  DenseMap<basic_block, BasicBlock*> BasicBlocks;
-
   // AllocaInsertionPoint - Place to insert alloca instructions.  Lazily created
   // and managed by CreateTemporary.
   Instruction *AllocaInsertionPoint;
@@ -331,6 +334,12 @@
   // definitions.
   Instruction *SSAInsertionPoint;
 
+  /// BasicBlocks - Map from GCC to LLVM basic blocks.
+  DenseMap<basic_block, BasicBlock*> BasicBlocks;
+
+  /// PendingPhis - Phi nodes which have not yet been populated with operands.
+  SmallVector<PhiRecord, 16> PendingPhis;
+
   // SSANames - Map from GCC ssa names to the defining LLVM value.
   DenseMap<tree, Value*> SSANames;
 
@@ -507,7 +516,6 @@
 
   // Render* - Convert GIMPLE to LLVM.
 
-  void RenderGIMPLE_PHI(gimple_statement_d *);
   void RenderGIMPLE_COND(gimple_statement_d *);
 
 private:





More information about the llvm-commits mailing list