Added LLVM project notice to the top of every C++ source file.
[oota-llvm.git] / lib / Target / SparcV9 / InstrSelection / InstrSelection.cpp
index b27f9022bba8d01c42d91ce1d7de57372dacc72f..32dc65e6e1e9196e0b558d4984784c789b463bba 100644 (file)
-// $Id$ -*-c++-*-
-//***************************************************************************
-// File:
-//     InstrSelection.cpp
+//===- InstrSelection.cpp - Machine Independent Inst Selection Driver -----===//
 // 
-// Purpose:
-//     Machine-independent driver file for instruction selection.
-//     This file constructs a forest of BURG instruction trees and then
-//      uses the BURG-generated tree grammar (BURM) to find the optimal
-//      instruction sequences for a given machine.
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// Machine-independent driver file for instruction selection.  This file
+// constructs a forest of BURG instruction trees and then uses the
+// BURG-generated tree grammar (BURM) to find the optimal instruction sequences
+// for a given machine.
 //     
-// History:
-//     7/02/01  -  Vikram Adve  -  Created
-//**************************************************************************/
-
+//===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/InstrSelection.h"
 #include "llvm/CodeGen/InstrSelectionSupport.h"
 #include "llvm/CodeGen/InstrForest.h"
 #include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineCodeForMethod.h"
-#include "llvm/Target/MachineRegInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/Target/TargetRegInfo.h"
 #include "llvm/Target/TargetMachine.h"
-#include "llvm/BasicBlock.h"
 #include "llvm/Function.h"
 #include "llvm/iPHINode.h"
+#include "llvm/Pass.h"
 #include "Support/CommandLine.h"
-#include <iostream>
-using std::cerr;
-
-//******************** Internal Data Declarations ************************/
-
-
-enum SelectDebugLevel_t {
-  Select_NoDebugInfo,
-  Select_PrintMachineCode, 
-  Select_DebugInstTrees, 
-  Select_DebugBurgTrees,
-};
-
-// Enable Debug Options to be specified on the command line
-cl::Enum<enum SelectDebugLevel_t> SelectDebugLevel("dselect", cl::Hidden,
-   "enable instruction selection debugging information",
-   clEnumValN(Select_NoDebugInfo,      "n", "disable debug output"),
-   clEnumValN(Select_PrintMachineCode, "y", "print generated machine code"),
-   clEnumValN(Select_DebugInstTrees,   "i", "print debugging info for instruction selection "),
-   clEnumValN(Select_DebugBurgTrees,   "b", "print burg trees"), 0);
+#include "Support/LeakDetector.h"
+using std::vector;
 
+std::vector<MachineInstr*>
+FixConstantOperandsForInstr(Instruction* vmInstr, MachineInstr* minstr,
+                            TargetMachine& target);
 
-//******************** Forward Function Declarations ***********************/
-
-
-static bool SelectInstructionsForTree   (InstrTreeNode* treeRoot,
-                                         int goalnt,
-                                         TargetMachine &target);
-
-static void PostprocessMachineCodeForTree(InstructionNode* instrNode,
-                                          int ruleForNode,
-                                          short* nts,
-                                          TargetMachine &target);
+namespace {
+  //===--------------------------------------------------------------------===//
+  // SelectDebugLevel - Allow command line control over debugging.
+  //
+  enum SelectDebugLevel_t {
+    Select_NoDebugInfo,
+    Select_PrintMachineCode, 
+    Select_DebugInstTrees, 
+    Select_DebugBurgTrees,
+  };
+  
+  // Enable Debug Options to be specified on the command line
+  cl::opt<SelectDebugLevel_t>
+  SelectDebugLevel("dselect", cl::Hidden,
+                   cl::desc("enable instruction selection debug information"),
+                   cl::values(
+     clEnumValN(Select_NoDebugInfo,      "n", "disable debug output"),
+     clEnumValN(Select_PrintMachineCode, "y", "print generated machine code"),
+     clEnumValN(Select_DebugInstTrees,   "i",
+                "print debugging info for instruction selection"),
+     clEnumValN(Select_DebugBurgTrees,   "b", "print burg trees"),
+                              0));
+
+
+  //===--------------------------------------------------------------------===//
+  //  InstructionSelection Pass
+  //
+  // This is the actual pass object that drives the instruction selection
+  // process.
+  //
+  class InstructionSelection : public FunctionPass {
+    TargetMachine &Target;
+    void InsertCodeForPhis(Function &F);
+    void InsertPhiElimInstructions(BasicBlock *BB,
+                                   const vector<MachineInstr*>& CpVec);
+    void SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt);
+    void PostprocessMachineCodeForTree(InstructionNode* instrNode,
+                                       int ruleForNode, short* nts);
+  public:
+    InstructionSelection(TargetMachine &T) : Target(T) {}
+
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.setPreservesCFG();
+    }
+    
+    bool runOnFunction(Function &F);
+    virtual const char *getPassName() const { return "Instruction Selection"; }
+  };
+}
 
-static void InsertCode4AllPhisInMeth(Function *F, TargetMachine &target);
+TmpInstruction::TmpInstruction(MachineCodeForInstruction& mcfi,
+                               Value *s1, Value *s2, const std::string &name)
+  : Instruction(s1->getType(), Instruction::UserOp1, name)
+{
+  mcfi.addTemp(this);
 
+  Operands.push_back(Use(s1, this));  // s1 must be non-null
+  if (s2) {
+    Operands.push_back(Use(s2, this));
+  }
 
+  // TmpInstructions should not be garbage checked.
+  LeakDetector::removeGarbageObject(this);
+}
+  
+// Constructor that requires the type of the temporary to be specified.
+// Both S1 and S2 may be NULL.(
+TmpInstruction::TmpInstruction(MachineCodeForInstruction& mcfi,
+                               const Type *Ty, Value *s1, Value* s2,
+                               const std::string &name)
+  : Instruction(Ty, Instruction::UserOp1, name)
+{
+  mcfi.addTemp(this);
 
-//******************* Externally Visible Functions *************************/
+  if (s1) { Operands.push_back(Use(s1, this)); }
+  if (s2) { Operands.push_back(Use(s2, this)); }
 
+  // TmpInstructions should not be garbage checked.
+  LeakDetector::removeGarbageObject(this);
+}
 
-//---------------------------------------------------------------------------
-// Entry point for instruction selection using BURG.
-// Returns true if instruction selection failed, false otherwise.
-//---------------------------------------------------------------------------
 
-bool
-SelectInstructionsForMethod(Function *F, TargetMachine &target)
+bool InstructionSelection::runOnFunction(Function &F)
 {
-  bool failed = false;
-  
   //
   // Build the instruction trees to be given as inputs to BURG.
   // 
-  InstrForest instrForest(F);
+  InstrForest instrForest(&F);
   
   if (SelectDebugLevel >= Select_DebugInstTrees)
     {
-      cerr << "\n\n*** Input to instruction selection for function "
-          << F->getName() << "\n\n";
-      F->dump();
-      
-      cerr << "\n\n*** Instruction trees for function "
-          << F->getName() << "\n\n";
+      std::cerr << "\n\n*** Input to instruction selection for function "
+               << F.getName() << "\n\n" << F
+                << "\n\n*** Instruction trees for function "
+                << F.getName() << "\n\n";
       instrForest.dump();
     }
   
@@ -107,74 +145,40 @@ SelectInstructionsForMethod(Function *F, TargetMachine &target)
       if (SelectDebugLevel >= Select_DebugBurgTrees)
        {
          printcover(basicNode, 1, 0);
-         cerr << "\nCover cost == " << treecost(basicNode, 1, 0) << "\n\n";
+         std::cerr << "\nCover cost == " << treecost(basicNode, 1, 0) <<"\n\n";
          printMatches(basicNode);
        }
       
       // Then recursively walk the tree to select instructions
-      if (SelectInstructionsForTree(basicNode, /*goalnt*/1, target))
-       {
-         failed = true;
-         break;
-       }
+      SelectInstructionsForTree(basicNode, /*goalnt*/1);
     }
   
   //
-  // Record instructions in the vector for each basic block
+  // Create the MachineBasicBlock records and add all of the MachineInstrs
+  // defined in the MachineCodeForInstruction objects to also live in the
+  // MachineBasicBlock objects.
   // 
-  for (Function::iterator BI = F->begin(), BE = F->end(); BI != BE; ++BI)
+  MachineFunction &MF = MachineFunction::get(&F);
+  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) {
+    MachineBasicBlock *MCBB = new MachineBasicBlock(BI);
+    MF.getBasicBlockList().push_back(MCBB);
+
     for (BasicBlock::iterator II = BI->begin(); II != BI->end(); ++II) {
-      MachineCodeForInstruction &mvec =MachineCodeForInstruction::get(II);
-      for (unsigned i=0; i < mvec.size(); i++)
-        BI->getMachineInstrVec().push_back(mvec[i]);
+      MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(II);
+      MCBB->insert(MCBB->end(), mvec.begin(), mvec.end());
     }
+  }
 
-  // Insert phi elimination code -- added by Ruchira
-  InsertCode4AllPhisInMeth(F, target);
-
+  // Insert phi elimination code
+  InsertCodeForPhis(F);
   
   if (SelectDebugLevel >= Select_PrintMachineCode)
     {
-      cerr << "\n*** Machine instructions after INSTRUCTION SELECTION\n";
-      MachineCodeForMethod::get(F).dump();
+      std::cerr << "\n*** Machine instructions after INSTRUCTION SELECTION\n";
+      MachineFunction::get(&F).dump();
     }
   
-  return false;
-}
-
-
-//*********************** Private Functions *****************************/
-
-
-//-------------------------------------------------------------------------
-// Thid method inserts a copy instruction to a predecessor BB as a result
-// of phi elimination.
-//-------------------------------------------------------------------------
-
-void
-InsertPhiElimInstructions(BasicBlock *BB, const vector<MachineInstr*>& CpVec)
-{ 
-  Instruction *TermInst = (Instruction*)BB->getTerminator();
-  MachineCodeForInstruction &MC4Term =MachineCodeForInstruction::get(TermInst);
-  MachineInstr *FirstMIOfTerm = *( MC4Term.begin() );
-  
-  assert( FirstMIOfTerm && "No Machine Instrs for terminator" );
-  
-  // get an iterator to machine instructions in the BB
-  MachineCodeForBasicBlock& bbMvec = BB->getMachineInstrVec();
-  MachineCodeForBasicBlock::iterator MCIt =  bbMvec.begin();
-  
-  // find the position of first machine instruction generated by the
-  // terminator of this BB
-  for( ; (MCIt != bbMvec.end()) && (*MCIt != FirstMIOfTerm) ; ++MCIt )
-    ;
-  assert( MCIt != bbMvec.end() && "Start inst of terminator not found");
-  
-  // insert the copy instructions just before the first machine instruction
-  // generated for the terminator
-  bbMvec.insert(MCIt, CpVec.begin(), CpVec.end());
-  
-  //cerr << "\nPhiElimination copy inst: " <<   *CopyInstVec[0];
+  return true;
 }
 
 
@@ -183,28 +187,33 @@ InsertPhiElimInstructions(BasicBlock *BB, const vector<MachineInstr*>& CpVec)
 //-------------------------------------------------------------------------
 
 void
-InsertCode4AllPhisInMeth(Function *F, TargetMachine &target)
+InstructionSelection::InsertCodeForPhis(Function &F)
 {
   // for all basic blocks in function
   //
-  for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) {
-    BasicBlock::InstListType &InstList = BB->getInstList();
-    for (BasicBlock::iterator IIt = InstList.begin();
-         PHINode *PN = dyn_cast<PHINode>(&*IIt); ++IIt) {
+  MachineFunction &MF = MachineFunction::get(&F);
+  for (MachineFunction::iterator BB = MF.begin(); BB != MF.end(); ++BB) {
+    for (BasicBlock::const_iterator IIt = BB->getBasicBlock()->begin();
+         const PHINode *PN = dyn_cast<PHINode>(IIt); ++IIt) {
       // FIXME: This is probably wrong...
       Value *PhiCpRes = new PHINode(PN->getType(), "PhiCp:");
-        
+
+      // The leak detector shouldn't track these nodes.  They are not garbage,
+      // even though their parent field is never filled in.
+      //
+      LeakDetector::removeGarbageObject(PhiCpRes);
+
       // for each incoming value of the phi, insert phi elimination
       //
       for (unsigned i = 0; i < PN->getNumIncomingValues(); ++i) {
         // insert the copy instruction to the predecessor BB
         vector<MachineInstr*> mvec, CpVec;
-        target.getRegInfo().cpValue2Value(PN->getIncomingValue(i), PhiCpRes,
+        Target.getRegInfo().cpValue2Value(PN->getIncomingValue(i), PhiCpRes,
                                           mvec);
         for (vector<MachineInstr*>::iterator MI=mvec.begin();
              MI != mvec.end(); ++MI) {
           vector<MachineInstr*> CpVec2 =
-            FixConstantOperandsForInstr(PN, *MI, target);
+            FixConstantOperandsForInstr(const_cast<PHINode*>(PN), *MI, Target);
           CpVec2.push_back(*MI);
           CpVec.insert(CpVec.end(), CpVec2.begin(), CpVec2.end());
         }
@@ -213,46 +222,51 @@ InsertCode4AllPhisInMeth(Function *F, TargetMachine &target)
       }
       
       vector<MachineInstr*> mvec;
-      target.getRegInfo().cpValue2Value(PhiCpRes, PN, mvec);
-      
-      // get an iterator to machine instructions in the BB
-      MachineCodeForBasicBlock& bbMvec = BB->getMachineInstrVec();
-      
-      bbMvec.insert(bbMvec.begin(), mvec.begin(), mvec.end());
+      Target.getRegInfo().cpValue2Value(PhiCpRes, const_cast<PHINode*>(PN),
+                                        mvec);
+      BB->insert(BB->begin(), mvec.begin(), mvec.end());
     }  // for each Phi Instr in BB
   } // for all BBs in function
 }
 
+//-------------------------------------------------------------------------
+// Thid method inserts a copy instruction to a predecessor BB as a result
+// of phi elimination.
+//-------------------------------------------------------------------------
 
-//---------------------------------------------------------------------------
-// Function PostprocessMachineCodeForTree
-// 
-// Apply any final cleanups to machine code for the root of a subtree
-// after selection for all its children has been completed.
-//---------------------------------------------------------------------------
-
-static void
-PostprocessMachineCodeForTree(InstructionNode* instrNode,
-                              int ruleForNode,
-                              short* nts,
-                              TargetMachine &target)
-{
-  // Fix up any constant operands in the machine instructions to either
-  // use an immediate field or to load the constant into a register
-  // Walk backwards and use direct indexes to allow insertion before current
-  // 
-  Instruction* vmInstr = instrNode->getInstruction();
-  MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(vmInstr);
-  for (int i = (int) mvec.size()-1; i >= 0; i--)
-    {
-      std::vector<MachineInstr*> loadConstVec =
-        FixConstantOperandsForInstr(vmInstr, mvec[i], target);
-      
-      if (loadConstVec.size() > 0)
-        mvec.insert(mvec.begin()+i, loadConstVec.begin(), loadConstVec.end());
+void
+InstructionSelection::InsertPhiElimInstructions(BasicBlock *BB,
+                                            const vector<MachineInstr*>& CpVec)
+{ 
+  Instruction *TermInst = (Instruction*)BB->getTerminator();
+  MachineCodeForInstruction &MC4Term = MachineCodeForInstruction::get(TermInst);
+  MachineInstr *FirstMIOfTerm = MC4Term.front();
+  assert (FirstMIOfTerm && "No Machine Instrs for terminator");
+
+  MachineFunction &MF = MachineFunction::get(BB->getParent());
+
+  // FIXME: if PHI instructions existed in the machine code, this would be
+  // unnecessary.
+  MachineBasicBlock *MBB = 0;
+  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
+    if (I->getBasicBlock() == BB) {
+      MBB = I;
+      break;
     }
+
+  // find the position of first machine instruction generated by the
+  // terminator of this BB
+  MachineBasicBlock::iterator MCIt =
+    std::find(MBB->begin(), MBB->end(), FirstMIOfTerm);
+
+  assert(MCIt != MBB->end() && "Start inst of terminator not found");
+  
+  // insert the copy instructions just before the first machine instruction
+  // generated for the terminator
+  MBB->insert(MCIt, CpVec.begin(), CpVec.end());
 }
 
+
 //---------------------------------------------------------------------------
 // Function SelectInstructionsForTree 
 // 
@@ -269,20 +283,18 @@ PostprocessMachineCodeForTree(InstructionNode* instrNode,
 // may be used by multiple instructions).
 //---------------------------------------------------------------------------
 
-bool
-SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
-                         TargetMachine &target)
+void 
+InstructionSelection::SelectInstructionsForTree(InstrTreeNode* treeRoot,
+                                                int goalnt)
 {
   // Get the rule that matches this node.
   // 
   int ruleForNode = burm_rule(treeRoot->state, goalnt);
   
-  if (ruleForNode == 0)
-    {
-      cerr << "Could not match instruction tree for instr selection\n";
-      assert(0);
-      return true;
-    }
+  if (ruleForNode == 0) {
+    std::cerr << "Could not match instruction tree for instr selection\n";
+    abort();
+  }
   
   // Get this rule's non-terminals and the corresponding child nodes (if any)
   // 
@@ -299,7 +311,7 @@ SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
       InstructionNode* instrNode = (InstructionNode*)treeRoot;
       assert(instrNode->getNodeType() == InstrTreeNode::NTInstructionNode);
       
-      GetInstructionsByRule(instrNode, ruleForNode, nts, target, minstrVec);
+      GetInstructionsByRule(instrNode, ruleForNode, nts, Target, minstrVec);
       
       MachineCodeForInstruction &mvec = 
         MachineCodeForInstruction::get(instrNode->getInstruction());
@@ -327,28 +339,55 @@ SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
       // Now we have the first non-chain rule so we have found
       // the actual child nodes.  Recursively compile them.
       // 
-      for (int i = 0; nts[i]; i++)
+      for (unsigned i = 0; nts[i]; i++)
        {
          assert(i < 2);
          InstrTreeNode::InstrTreeNodeType nodeType = kids[i]->getNodeType();
          if (nodeType == InstrTreeNode::NTVRegListNode ||
              nodeType == InstrTreeNode::NTInstructionNode)
-           {
-             if (SelectInstructionsForTree(kids[i], nts[i], target))
-               return true;                    // failure
-           }
+            SelectInstructionsForTree(kids[i], nts[i]);
        }
     }
   
-  // Finally, do any postprocessing on this node after its children
+  // Finally, do any post-processing on this node after its children
   // have been translated
   // 
   if (treeRoot->opLabel != VRegListOp)
+    PostprocessMachineCodeForTree((InstructionNode*)treeRoot, ruleForNode, nts);
+}
+
+//---------------------------------------------------------------------------
+// Function PostprocessMachineCodeForTree
+// 
+// Apply any final cleanups to machine code for the root of a subtree
+// after selection for all its children has been completed.
+//
+void
+InstructionSelection::PostprocessMachineCodeForTree(InstructionNode* instrNode,
+                                                    int ruleForNode,
+                                                    short* nts) 
+{
+  // Fix up any constant operands in the machine instructions to either
+  // use an immediate field or to load the constant into a register
+  // Walk backwards and use direct indexes to allow insertion before current
+  // 
+  Instruction* vmInstr = instrNode->getInstruction();
+  MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(vmInstr);
+  for (unsigned i = mvec.size(); i != 0; --i)
     {
-      InstructionNode* instrNode = (InstructionNode*)treeRoot;
-      PostprocessMachineCodeForTree(instrNode, ruleForNode, nts, target);
+      vector<MachineInstr*> loadConstVec =
+        FixConstantOperandsForInstr(vmInstr, mvec[i-1], Target);
+      
+      mvec.insert(mvec.begin()+i-1, loadConstVec.begin(), loadConstVec.end());
     }
-  
-  return false;                                // success
 }
 
+
+
+//===----------------------------------------------------------------------===//
+// createInstructionSelectionPass - Public entrypoint for instruction selection
+// and this file as a whole...
+//
+FunctionPass *createInstructionSelectionPass(TargetMachine &T) {
+  return new InstructionSelection(T);
+}