Instruction selection via pattern matching on instruction trees using BURG.
authorVikram S. Adve <vadve@cs.uiuc.edu>
Sat, 21 Jul 2001 12:41:50 +0000 (12:41 +0000)
committerVikram S. Adve <vadve@cs.uiuc.edu>
Sat, 21 Jul 2001 12:41:50 +0000 (12:41 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/InstrSelection/InstrForest.cpp [new file with mode: 0644]
lib/CodeGen/InstrSelection/InstrSelection.cpp [new file with mode: 0644]
lib/CodeGen/InstrSelection/Makefile [new file with mode: 0644]
lib/CodeGen/MachineInstr.cpp [new file with mode: 0644]
lib/Target/SparcV9/InstrSelection/InstrForest.cpp [new file with mode: 0644]
lib/Target/SparcV9/InstrSelection/InstrSelection.cpp [new file with mode: 0644]
lib/Target/SparcV9/InstrSelection/Makefile [new file with mode: 0644]

diff --git a/lib/CodeGen/InstrSelection/InstrForest.cpp b/lib/CodeGen/InstrSelection/InstrForest.cpp
new file mode 100644 (file)
index 0000000..8ea2931
--- /dev/null
@@ -0,0 +1,461 @@
+// $Id$
+//---------------------------------------------------------------------------
+// File:
+//     InstrForest.cpp
+// 
+// Purpose:
+//     Convert SSA graph to instruction trees for instruction selection.
+// 
+// Strategy:
+//  The key goal is to group instructions into a single
+//  tree if one or more of them might be potentially combined into a single
+//  complex instruction in the target machine.
+//  Since this grouping is completely machine-independent, we do it as
+//  aggressive as possible to exploit any possible taret instructions.
+//  In particular, we group two instructions O and I if:
+//      (1) Instruction O computes an operand used by instruction I,
+//  and (2) O and I are part of the same basic block,
+//  and (3) O has only a single use, viz., I.
+// 
+// History:
+//     6/28/01  -  Vikram Adve  -  Created
+// 
+//---------------------------------------------------------------------------
+
+
+//************************** System Include Files **************************/
+
+#include <assert.h>
+#include <iostream.h>
+#include <bool.h>
+#include <string>
+
+//*************************** User Include Files ***************************/
+
+#include "llvm/Type.h"
+#include "llvm/Module.h"
+#include "llvm/Method.h"
+#include "llvm/Instruction.h"
+#include "llvm/iTerminators.h"
+#include "llvm/iMemory.h"
+#include "llvm/ConstPoolVals.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Bytecode/Reader.h"
+#include "llvm/Bytecode/Writer.h"
+#include "llvm/Tools/CommandLine.h"
+#include "llvm/LLC/CompileContext.h"
+#include "llvm/Codegen/MachineInstr.h"
+#include "llvm/Codegen/InstrForest.h"
+
+//************************ Class Implementations **************************/
+
+
+//------------------------------------------------------------------------ 
+// class InstrTreeNode
+//------------------------------------------------------------------------ 
+
+
+InstrTreeNode::InstrTreeNode(InstrTreeNodeType nodeType,
+                            Value* _val)
+  : treeNodeType(nodeType),
+    val(_val)
+{
+  basicNode.leftChild = NULL;
+  basicNode.rightChild = NULL;
+  basicNode.parent = NULL;
+  basicNode.opLabel = InvalidOp;
+  basicNode.treeNodePtr = this;
+}
+
+InstrTreeNode::~InstrTreeNode()
+{}
+
+
+void
+InstrTreeNode::dump(int dumpChildren,
+                   int indent) const
+{
+  this->dumpNode(indent);
+  
+  if (dumpChildren)
+    {
+      if (leftChild())
+       leftChild()->dump(dumpChildren, indent+1);
+      if (rightChild())
+       rightChild()->dump(dumpChildren, indent+1);
+    }
+}
+
+
+InstructionNode::InstructionNode(Instruction* _instr)
+  : InstrTreeNode(NTInstructionNode, _instr)
+{
+  OpLabel opLabel = _instr->getOpcode();
+
+  // Distinguish special cases of some instructions such as Ret and Br
+  // 
+  if (opLabel == Instruction::Ret && ((ReturnInst*) _instr)->getReturnValue())
+    {
+      opLabel = RetValueOp;             // ret(value) operation
+    }
+  else if (opLabel == Instruction::Br && ! ((BranchInst*) _instr)->isUnconditional())
+    {
+      opLabel = BrCondOp;              // br(cond) operation
+    }
+  else if (opLabel >= Instruction::SetEQ && opLabel <= Instruction::SetGT)
+    {
+      opLabel = SetCCOp;               // common label for all SetCC ops
+    }
+  else if (opLabel == Instruction::Alloca && _instr->getNumOperands() > 0)
+    {
+      opLabel = AllocaN;                // Alloca(ptr, N) operation
+    }
+  else if ((opLabel == Instruction::Load ||
+           opLabel == Instruction::GetElementPtr)
+          && ((MemAccessInst*)_instr)->getFirstOffsetIdx() > 0)
+    {
+      opLabel = opLabel + 100;          // load/getElem with index vector
+    }
+  else if (opLabel == Instruction::Cast)
+    {
+      const Type* instrValueType = _instr->getType();
+      switch(instrValueType->getPrimitiveID())
+       {
+       case Type::BoolTyID:    opLabel = ToBoolTy;  break;
+       case Type::UByteTyID:   opLabel = ToUByteTy; break;
+       case Type::SByteTyID:   opLabel = ToSByteTy; break;
+       case Type::UShortTyID:  opLabel = ToUShortTy; break;
+       case Type::ShortTyID:   opLabel = ToShortTy; break;
+       case Type::UIntTyID:    opLabel = ToUIntTy; break;
+       case Type::IntTyID:     opLabel = ToIntTy; break;
+       case Type::ULongTyID:   opLabel = ToULongTy; break;
+       case Type::LongTyID:    opLabel = ToLongTy; break;
+       case Type::FloatTyID:   opLabel = ToFloatTy; break;
+       case Type::DoubleTyID:  opLabel = ToDoubleTy; break;
+       default:
+         if (instrValueType->isArrayType())
+           opLabel = ToArrayTy;
+         else if (instrValueType->isPointerType())
+           opLabel = ToPointerTy;
+         else
+           ; // Just use `Cast' opcode otherwise. It's probably ignored.
+         break;
+       }
+    }
+  
+  basicNode.opLabel = opLabel;
+}
+
+void
+InstructionNode::reverseBinaryArgumentOrder()
+{
+  assert(getInstruction()->isBinaryOp());
+  
+  // switch arguments for the instruction
+  ((BinaryOperator*) getInstruction())->swapOperands();
+  
+  // switch arguments for this tree node itself
+  BasicTreeNode* leftCopy = basicNode.leftChild;
+  basicNode.leftChild = basicNode.rightChild;
+  basicNode.rightChild = leftCopy;
+}
+
+void
+InstructionNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << getInstruction()->getOpcodeName();
+  
+  const vector<MachineInstr*>& mvec = getInstruction()->getMachineInstrVec();
+  if (mvec.size() > 0)
+    cout << "\tMachine Instructions:  ";
+  for (unsigned int i=0; i < mvec.size(); i++)
+    {
+      mvec[i]->dump(0);
+      if (i < mvec.size() - 1)
+       cout << ";  ";
+    }
+  
+  cout << endl;
+}
+
+
+VRegListNode::VRegListNode()
+  : InstrTreeNode(NTVRegListNode, NULL)
+{
+  basicNode.opLabel = VRegListOp;
+}
+
+void
+VRegListNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << "List" << endl;
+}
+
+
+VRegNode::VRegNode(Value* _val)
+  : InstrTreeNode(NTVRegNode, _val)
+{
+  basicNode.opLabel = VRegNodeOp;
+}
+
+void
+VRegNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << "VReg " << getValue() << "\t(type "
+       << (int) getValue()->getValueType() << ")" << endl;
+}
+
+
+ConstantNode::ConstantNode(ConstPoolVal* constVal)
+  : InstrTreeNode(NTConstNode, constVal)
+{
+  basicNode.opLabel = ConstantNodeOp;
+}
+
+void
+ConstantNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << "Constant " << getValue() << "\t(type "
+       << (int) getValue()->getValueType() << ")" << endl;
+}
+
+
+LabelNode::LabelNode(BasicBlock* _bblock)
+  : InstrTreeNode(NTLabelNode, _bblock)
+{
+  basicNode.opLabel = LabelNodeOp;
+}
+
+void
+LabelNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << "Label " << getValue() << endl;
+}
+
+//------------------------------------------------------------------------
+// class InstrForest
+// 
+// A forest of instruction trees, usually for a single method.
+//------------------------------------------------------------------------ 
+
+void
+InstrForest::buildTreesForMethod(Method *method)
+{
+  for (Method::inst_iterator instrIter = method->inst_begin();
+       instrIter != method->inst_end();
+       ++instrIter)
+    {
+      Instruction *instr = *instrIter;
+      if (! instr->isPHINode())
+       (void) this->buildTreeForInstruction(instr);
+    } 
+}
+
+
+void
+InstrForest::dump() const
+{
+  for (hash_set<InstructionNode*, ptrHashFunc >::const_iterator
+        treeRootIter = treeRoots.begin();
+       treeRootIter != treeRoots.end();
+       ++treeRootIter)
+    {
+      (*treeRootIter)->dump(/*dumpChildren*/ 1, /*indent*/ 0);
+    }
+}
+
+inline void
+InstrForest::noteTreeNodeForInstr(Instruction* instr,
+                                 InstructionNode* treeNode)
+{
+  assert(treeNode->getNodeType() == InstrTreeNode::NTInstructionNode);
+  (*this)[instr] = treeNode;
+  treeRoots.insert(treeNode);          // mark node as root of a new tree
+}
+
+
+inline void
+InstrForest::setLeftChild(InstrTreeNode* parent, InstrTreeNode* child)
+{
+  parent->basicNode.leftChild = & child->basicNode;
+  child->basicNode.parent = & parent->basicNode;
+  if (child->getNodeType() == InstrTreeNode::NTInstructionNode)
+    treeRoots.erase((InstructionNode*) child); // no longer a tree root
+}
+
+
+inline void
+InstrForest::setRightChild(InstrTreeNode* parent, InstrTreeNode* child)
+{
+  parent->basicNode.rightChild = & child->basicNode;
+  child->basicNode.parent = & parent->basicNode;
+  if (child->getNodeType() == InstrTreeNode::NTInstructionNode)
+    treeRoots.erase((InstructionNode*) child); // no longer a tree root
+}
+
+
+InstructionNode*
+InstrForest::buildTreeForInstruction(Instruction* instr)
+{
+  InstructionNode* treeNode = this->getTreeNodeForInstr(instr);
+  if (treeNode != NULL)
+    {// treeNode has already been constructed for this instruction
+      assert(treeNode->getInstruction() == instr);
+      return treeNode;
+    }
+  
+  // Otherwise, create a new tree node for this instruction.
+  // 
+  treeNode = new InstructionNode(instr);
+  this->noteTreeNodeForInstr(instr, treeNode);
+  
+  // If the instruction has more than 2 instruction operands,
+  // then we will not add any children.  This assumes that instructions
+  // like 'call' that have more than 2 instruction operands do not
+  // ever get combined with the instructions that compute the operands. 
+  // Note that we only count operands of type instruction and not other
+  // values such as branch labels for a branch or switch instruction.
+  //
+  // To do this efficiently, we'll walk all operands, build treeNodes
+  // for all instruction operands and save them in an array, and then
+  // insert children at the end if there are not more than 2.
+  // As a performance optimization, allocate a child array only
+  // if a fixed array is too small.
+  // 
+  int numChildren = 0;
+  const unsigned int MAX_CHILD = 8;
+  static InstrTreeNode* fixedChildArray[MAX_CHILD];
+  InstrTreeNode** childArray =
+    (instr->getNumOperands() > MAX_CHILD)
+    ? new (InstrTreeNode*)[instr->getNumOperands()]
+    : fixedChildArray;
+  
+  //
+  // Walk the operands of the instruction
+  // 
+  for (Instruction::op_iterator opIter = instr->op_begin();
+       opIter != instr->op_end();
+       ++opIter)
+    {
+      Value* operand = *opIter;
+      
+      // Check if the operand is a data value, not an branch label, type,
+      // method or module.  If the operand is an address type (i.e., label
+      // or method) that is used in an non-branching operation, e.g., `add'.
+      // that should be considered a data value.
+      
+      // Check latter condition here just to simplify the next IF.
+      bool includeAddressOperand =
+       ((operand->getValueType() == Value::BasicBlockVal
+         || operand->getValueType() == Value::MethodVal)
+        && ! instr->isTerminator());
+        
+      if (/* (*opIter) != NULL
+            &&*/ includeAddressOperand
+                 || operand->getValueType() == Value::InstructionVal
+                 ||  operand->getValueType() == Value::ConstantVal
+                 ||  operand->getValueType() == Value::MethodArgumentVal)
+       {// This operand is a data value
+         
+         // An instruction that computes the incoming value is added as a
+         // child of the current instruction if:
+         //   the value has only a single use
+         //   AND both instructions are in the same basic block
+         //   AND the instruction is not a PHI
+         // 
+         // (Note that if the value has only a single use (viz., `instr'),
+         //  the def of the value can be safely moved just before instr
+         //  and therefore it is safe to combine these two instructions.)
+         // 
+         // In all other cases, the virtual register holding the value
+         // is used directly, i.e., made a child of the instruction node.
+         // 
+         InstrTreeNode* opTreeNode;
+         if (operand->getValueType() == Value::InstructionVal
+             && operand->use_size() == 1
+             && ((Instruction*)operand)->getParent() == instr->getParent()
+             && ! ((Instruction*)operand)->isPHINode())
+           {
+             // Recursively create a treeNode for it.
+             opTreeNode =this->buildTreeForInstruction((Instruction*)operand);
+           }
+         else if (operand->getValueType() == Value::ConstantVal)
+           {
+             // Create a leaf node for a constant
+             opTreeNode = new ConstantNode((ConstPoolVal*) operand);
+           }
+         else
+           {
+             // Create a leaf node for the virtual register
+             opTreeNode = new VRegNode(operand);
+           }
+         
+         childArray[numChildren] = opTreeNode;
+         numChildren++;
+       }
+    }
+  
+  //-------------------------------------------------------------------- 
+  // Add any selected operands as children in the tree.
+  // Certain instructions can have more than 2 in some instances (viz.,
+  // a CALL or a memory access -- LOAD, STORE, and GetElemPtr -- to an
+  // array or struct). Make the operands of every such instruction into
+  // a right-leaning binary tree with the operand nodes at the leaves
+  // and VRegList nodes as internal nodes.
+  //-------------------------------------------------------------------- 
+  
+  InstrTreeNode* parent = treeNode;            // new VRegListNode();
+  int n;
+  
+  if (numChildren > 2)
+    {
+      unsigned instrOpcode = treeNode->getInstruction()->getOpcode();
+      assert(instrOpcode == Instruction::Call ||
+            instrOpcode == Instruction::Load ||
+            instrOpcode == Instruction::Store ||
+            instrOpcode == Instruction::GetElementPtr);
+    }
+  
+  // Insert the first child as a direct child
+  if (numChildren >= 1)
+    this->setLeftChild(parent, childArray[0]);
+  
+  // Create a list node for children 2 .. N-1, if any
+  for (n = numChildren-1; n >= 2; n--)
+    { // We have more than two children
+      InstrTreeNode* listNode = new VRegListNode();
+      this->setRightChild(parent, listNode);
+      this->setLeftChild(listNode, childArray[numChildren - n]);
+      parent = listNode;
+    }
+  
+  // Now insert the last remaining child (if any).
+  if (numChildren >= 2)
+    {
+      assert(n == 1);
+      this->setRightChild(parent, childArray[numChildren - 1]);
+    }
+  
+  if (childArray != fixedChildArray)
+    {
+      delete[] childArray; 
+    }
+  
+  return treeNode;
+}
+
diff --git a/lib/CodeGen/InstrSelection/InstrSelection.cpp b/lib/CodeGen/InstrSelection/InstrSelection.cpp
new file mode 100644 (file)
index 0000000..0d7dc7e
--- /dev/null
@@ -0,0 +1,279 @@
+// $Id$ -*-c++-*-
+//***************************************************************************
+// File:
+//     InstrSelection.h
+// 
+// Purpose:
+//     
+// History:
+//     7/02/01  -  Vikram Adve  -  Created
+//***************************************************************************
+
+
+//************************** System Include Files **************************/
+
+#include <assert.h>
+#include <stdio.h>
+#include <iostream.h>
+#include <bool.h>
+#include <string>
+
+//*************************** User Include Files ***************************/
+
+#include "llvm/Method.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Type.h"
+#include "llvm/iMemory.h"
+#include "llvm/Instruction.h"
+#include "llvm/LLC/CompileContext.h"
+#include "llvm/Codegen/InstrForest.h"
+#include "llvm/Codegen/MachineInstr.h"
+#include "llvm/Codegen/InstrSelection.h"
+
+
+//************************* Forward Declarations ***************************/
+
+static bool SelectInstructionsForTree  (BasicTreeNode* treeRoot,
+                                        int goalnt,
+                                        CompileContext& ccontext);
+
+
+//******************* Externally Visible Functions *************************/
+
+
+//---------------------------------------------------------------------------
+// Entry point for instruction selection using BURG.
+// Returns true if instruction selection failed, false otherwise.
+//---------------------------------------------------------------------------
+
+bool
+SelectInstructionsForMethod(Method* method,
+                           CompileContext& ccontext)
+{
+  bool failed = false;
+  
+  InstrForest instrForest;
+  instrForest.buildTreesForMethod(method);
+      
+  const hash_set<InstructionNode*, ptrHashFunc>&
+    treeRoots = instrForest.getRootSet();
+  
+  //
+  // Invoke BURG instruction selection for each tree
+  // 
+  for (hash_set<InstructionNode*, ptrHashFunc >::const_iterator
+        treeRootIter = treeRoots.begin();
+       treeRootIter != treeRoots.end();
+       ++treeRootIter)
+    {
+      BasicTreeNode* basicNode = (*treeRootIter)->getBasicNode();
+      
+      // Invoke BURM to label each tree node with a state
+      (void) burm_label(basicNode);
+      
+      if (ccontext.getOptions().IntOptionValue(DEBUG_INSTR_SELECT_OPT)
+         >= DEBUG_BURG_TREES)
+       {
+         printcover(basicNode, 1, 0);
+         printf("\nCover cost == %d\n\n", treecost(basicNode, 1, 0));
+         printMatches(basicNode);
+       }
+      
+      // Then recursively walk the tree to select instructions
+      if (SelectInstructionsForTree(basicNode, /*goalnt*/1, ccontext))
+       {
+         failed = true;
+         break;
+       }
+    }
+  
+  if (!failed)
+    {
+      if ( ccontext.getOptions().IntOptionValue(DEBUG_INSTR_SELECT_OPT)
+          >= DEBUG_INSTR_TREES)
+       {
+         cout << "\n\n*** Instruction trees for method "
+              << (method->hasName()? method->getName() : "")
+              << endl << endl;
+         instrForest.dump();
+       }
+      
+      if (ccontext.getOptions().IntOptionValue(DEBUG_INSTR_SELECT_OPT) > 0)
+       PrintMachineInstructions(method, ccontext);     
+    }
+  
+  return false;
+}
+
+
+//---------------------------------------------------------------------------
+// Function: FoldGetElemChain
+// 
+// Purpose:
+//   Fold a chain of GetElementPtr instructions into an equivalent
+//   (Pointer, IndexVector) pair.  Returns the pointer Value, and
+//   stores the resulting IndexVector in argument chainIdxVec.
+//---------------------------------------------------------------------------
+
+Value*
+FoldGetElemChain(const InstructionNode* getElemInstrNode,
+                vector<ConstPoolVal*>& chainIdxVec)
+{
+  MemAccessInst* getElemInst = (MemAccessInst*)
+    getElemInstrNode->getInstruction();
+  
+  // Initialize return values from the incoming instruction
+  Value* ptrVal = getElemInst->getPtrOperand();
+  chainIdxVec = getElemInst->getIndexVec(); // copies index vector values
+  
+  // Now chase the chain of getElementInstr instructions, if any
+  InstrTreeNode* ptrChild = getElemInstrNode->leftChild();
+  while (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
+        ptrChild->getOpLabel() == GetElemPtrIdx)
+    {
+      // Child is a GetElemPtr instruction
+      getElemInst = (MemAccessInst*)
+       ((InstructionNode*) ptrChild)->getInstruction();
+      const vector<ConstPoolVal*>& idxVec = getElemInst->getIndexVec();
+      
+      // Get the pointer value out of ptrChild and *prepend* its index vector
+      ptrVal = getElemInst->getPtrOperand();
+      chainIdxVec.insert(chainIdxVec.begin(), idxVec.begin(), idxVec.end());
+      
+      ptrChild = ptrChild->leftChild();
+    }
+  
+  return ptrVal;
+}
+
+
+void
+PrintMachineInstructions(Method* method,
+                        CompileContext& ccontext)
+{
+  cout << "\n" << method->getReturnType()
+       << " \"" << method->getName() << "\"" << endl;
+  
+  for (Method::const_iterator bbIter = method->begin();
+       bbIter != method->end();
+       ++bbIter)
+    {
+      BasicBlock* bb = *bbIter;
+      cout << "\n"
+          << (bb->hasName()? bb->getName() : "Label")
+          << " (" << bb << ")" << ":"
+          << endl;
+      
+      for (BasicBlock::const_iterator instrIter = bb->begin();
+          instrIter != bb->end();
+          ++instrIter)
+       {
+         Instruction *instr = *instrIter;
+         const MachineCodeForVMInstr& minstrVec = instr->getMachineInstrVec();
+         for (unsigned i=0, N=minstrVec.size(); i < N; i++)
+           cout << "\t" << *minstrVec[i] << endl;
+       }
+    } 
+}
+
+//*********************** Private Functions *****************************/
+
+
+//---------------------------------------------------------------------------
+// Function SelectInstructionsForTree 
+// 
+// Recursively walk the tree to select instructions.
+// Do this top-down so that child instructions can exploit decisions
+// made at the child instructions.
+// 
+// E.g., if br(setle(reg,const)) decides the constant is 0 and uses
+// a branch-on-integer-register instruction, then the setle node
+// can use that information to avoid generating the SUBcc instruction.
+//
+// Note that this cannot be done bottom-up because setle must do this
+// only if it is a child of the branch (otherwise, the result of setle
+// may be used by multiple instructions).
+//---------------------------------------------------------------------------
+
+bool
+SelectInstructionsForTree(BasicTreeNode* treeRoot,
+                         int goalnt,
+                         CompileContext& ccontext)
+{
+  // Use a static vector to avoid allocating a new one per VM instruction
+  static MachineInstr* minstrVec[MAX_INSTR_PER_VMINSTR];
+  
+  // 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" << endl;
+      return true;
+    }
+  
+  // Get this rule's non-terminals and the corresponding child nodes (if any)
+  // 
+  short *nts = burm_nts[ruleForNode];
+  
+  
+  // First, select instructions for the current node and rule.
+  // (If this is a list node, not an instruction, then skip this step).
+  // This function is specific to the target architecture.
+  // 
+  if (treeRoot->opLabel != VRegListOp)
+    {
+      InstructionNode* instrNode = (InstructionNode*) MainTreeNode(treeRoot);
+      assert(instrNode->getNodeType() == InstrTreeNode::NTInstructionNode);
+      
+      unsigned N = GetInstructionsByRule(instrNode, ruleForNode, nts, ccontext,
+                                        minstrVec);
+      assert(N <= MAX_INSTR_PER_VMINSTR);
+      for (unsigned i=0; i < N; i++)
+       {
+         assert(minstrVec[i] != NULL);
+         instrNode->getInstruction()->addMachineInstruction(minstrVec[i]);
+       }
+    }
+  
+  // Then, recursively compile the child nodes, if any.
+  // 
+  if (nts[0])
+    { // i.e., there is at least one kid
+
+      BasicTreeNode* kids[2];
+      int currentRule = ruleForNode;
+      burm_kids(treeRoot, currentRule, kids);
+      
+      // First skip over any chain rules so that we don't visit
+      // the current node again.
+      // 
+      while (ThisIsAChainRule(currentRule))
+       {
+         currentRule = burm_rule(treeRoot->state, nts[0]);
+         nts = burm_nts[currentRule];
+         burm_kids(treeRoot, currentRule, kids);
+       }
+      
+      // 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++)
+       {
+         assert(i < 2);
+         InstrTreeNode::InstrTreeNodeType
+           nodeType = MainTreeNode(kids[i])->getNodeType();
+         if (nodeType == InstrTreeNode::NTVRegListNode ||
+             nodeType == InstrTreeNode::NTInstructionNode)
+           {
+             bool failed= SelectInstructionsForTree(kids[i], nts[i],ccontext);
+             if (failed)
+               return true;                    // failure
+           }
+       }
+    }
+  
+  return false;                                // success
+}
+
diff --git a/lib/CodeGen/InstrSelection/Makefile b/lib/CodeGen/InstrSelection/Makefile
new file mode 100644 (file)
index 0000000..985ddaf
--- /dev/null
@@ -0,0 +1,13 @@
+LEVEL = ../../..
+
+DIRS  = 
+
+LIBRARYNAME = select
+
+## List source files in link order
+Source  = \
+         InstrSelection.o \
+         MachineInstr.o \
+         InstrForest.o
+
+include $(LEVEL)/Makefile.common
diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp
new file mode 100644 (file)
index 0000000..1b6f25a
--- /dev/null
@@ -0,0 +1,344 @@
+// $Id$
+//***************************************************************************
+// File:
+//     MachineInstr.cpp
+// 
+// Purpose:
+//     
+// 
+// Strategy:
+// 
+// History:
+//     7/2/01   -  Vikram Adve  -  Created
+//**************************************************************************/
+
+
+//************************** System Include Files **************************/
+
+#include <strstream.h>
+#include <string>
+#include <vector>
+
+//*************************** User Include Files ***************************/
+
+#include "llvm/Type.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/ConstPoolVals.h"
+#include "llvm/Value.h"
+#include "llvm/Instruction.h"
+#include "llvm/Codegen/InstrForest.h"
+#include "llvm/Codegen/MachineInstr.h"
+
+//************************ Class Implementations **************************/
+
+
+bool
+MachineInstrInfo::constantFitsInImmedField(int64_t intValue) const
+{
+  // First, check if opCode has an immed field.
+  bool isSignExtended;
+  uint64_t maxImmedValue = this->maxImmedConstant(isSignExtended);
+  if (maxImmedValue != 0)
+    {
+      // Now check if the constant fits
+      if (intValue <= (int64_t) maxImmedValue &&
+         intValue >= -((int64_t) maxImmedValue+1))
+       return true;
+    }
+  
+  return false;
+}
+
+MachineInstr::MachineInstr(MachineOpCode _opCode,
+                          OpCodeMask    _opCodeMask)
+  : opCode(_opCode),
+    opCodeMask(_opCodeMask),
+    operands(TargetMachineInstrInfo[_opCode].numOperands)
+{
+}
+
+MachineInstr::~MachineInstr()
+{
+}
+
+void
+MachineInstr::SetMachineOperand(unsigned int i,
+                               MachineOperand::MachineOperandType operandType,
+                               Value* _val)
+{
+  assert(i < TargetMachineInstrInfo[opCode].numOperands);
+  operands[i].Initialize(operandType, _val);
+}
+
+void
+MachineInstr::SetMachineOperand(unsigned int i,
+                               MachineOperand::MachineOperandType operandType,
+                               int64_t intValue)
+{
+  assert(i < TargetMachineInstrInfo[opCode].numOperands);
+  operands[i].InitializeConst(operandType, intValue);
+}
+
+void
+MachineInstr::SetMachineOperand(unsigned int i,
+                               unsigned int regNum)
+{
+  assert(i < TargetMachineInstrInfo[opCode].numOperands);
+  operands[i].InitializeReg(regNum);
+}
+
+void
+MachineInstr::dump(unsigned int indent)
+{
+  for (unsigned i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << *this;
+}
+
+ostream&
+operator<< (ostream& os, const MachineInstr& minstr)
+{
+  os << TargetMachineInstrInfo[minstr.opCode].opCodeString;
+  
+  for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++)
+    os << "\t" << minstr.getOperand(i);
+  
+  return os;
+}
+
+ostream&
+operator<< (ostream& os, const MachineOperand& mop)
+{
+  strstream regInfo;
+  if (mop.machineOperandType == MachineOperand::MO_Register)
+    {
+      if (mop.vregType == MachineOperand::MO_VirtualReg)
+       regInfo << "(val " << mop.value << ")" << ends;
+      else
+       regInfo << "("       << mop.regNum << ")" << ends;
+    }
+  else if (mop.machineOperandType == MachineOperand::MO_CCRegister)
+    regInfo << "(val " << mop.value << ")" << ends;
+  
+  switch(mop.machineOperandType)
+    {
+    case MachineOperand::MO_Register:
+      os << "%reg" << regInfo.str();
+      free(regInfo.str());
+      break;
+      
+    case MachineOperand::MO_CCRegister:
+      os << "%ccreg" << regInfo.str();
+      free(regInfo.str());
+      break;
+
+    case MachineOperand::MO_SignExtendedImmed:
+      os << mop.immedVal;
+      break;
+
+    case MachineOperand::MO_UnextendedImmed:
+      os << mop.immedVal;
+      break;
+
+    case MachineOperand::MO_PCRelativeDisp:
+      os << "%disp(label " << mop.value << ")";
+      break;
+
+    default:
+      assert(0 && "Unrecognized operand type");
+      break;
+    }
+
+  return os;
+}
+
+
+//---------------------------------------------------------------------------
+// Target-independent utility routines for creating machine instructions
+//---------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------ 
+// Function Set2OperandsFromInstr
+// Function Set3OperandsFromInstr
+// 
+// For the common case of 2- and 3-operand arithmetic/logical instructions,
+// set the m/c instr. operands directly from the VM instruction's operands.
+// Check whether the first or second operand is 0 and can use a dedicated "0" register.
+// Check whether the second operand should use an immediate field or register.
+// (First and third operands are never immediates for such instructions.)
+// 
+// Arguments:
+// canDiscardResult: Specifies that the result operand can be discarded
+//                  by using the dedicated "0"
+// 
+// op1position, op2position and resultPosition: Specify in which position
+//                  in the machine instruction the 3 operands (arg1, arg2
+//                  and result) should go.
+// 
+// RETURN VALUE: unsigned int flags, where
+//     flags & 0x01    => operand 1 is constant and needs a register
+//     flags & 0x02    => operand 2 is constant and needs a register
+//------------------------------------------------------------------------ 
+
+void
+Set2OperandsFromInstr(MachineInstr* minstr,
+                     InstructionNode* vmInstrNode,
+                     const TargetMachine& targetMachine,
+                     bool canDiscardResult,
+                     int op1Position,
+                     int resultPosition)
+{
+  Set3OperandsFromInstr(minstr, vmInstrNode, targetMachine,
+                       canDiscardResult, op1Position,
+                       /*op2Position*/ -1, resultPosition);
+}
+
+
+unsigned
+Set3OperandsFromInstrJUNK(MachineInstr* minstr,
+                     InstructionNode* vmInstrNode,
+                     const TargetMachine& targetMachine,
+                     bool canDiscardResult,
+                     int op1Position,
+                     int op2Position,
+                     int resultPosition)
+{
+  assert(op1Position >= 0);
+  assert(resultPosition >= 0);
+  
+  unsigned returnFlags = 0x0;
+  
+  // Check if operand 1 is 0 and if so, try to use the register that gives 0, if any.
+  Value* op1Value = vmInstrNode->leftChild()->getValue();
+  bool isValidConstant;
+  int64_t intValue = GetConstantValueAsSignedInt(op1Value, isValidConstant);
+  if (isValidConstant && intValue == 0 && targetMachine.zeroRegNum >= 0)
+    minstr->SetMachineOperand(op1Position, /*regNum*/ targetMachine.zeroRegNum);
+  else
+    {
+      if (op1Value->getValueType() == Value::ConstantVal)
+       {// value is constant and must be loaded from constant pool
+         returnFlags = returnFlags | (1 << op1Position);
+       }
+      minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register,
+                                            op1Value);
+    }
+  
+  // Check if operand 2 (if any) fits in the immediate field of the instruction,
+  // of if it is 0 and can use a dedicated machine register
+  if (op2Position >= 0)
+    {
+      Value* op2Value = vmInstrNode->rightChild()->getValue();
+      int64_t immedValue;
+      MachineOperand::VirtualRegisterType vregType;
+      unsigned int machineRegNum;
+      
+      MachineOperand::MachineOperandType
+       op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(),targetMachine,
+                                  /*canUseImmed*/ true,
+                                  vregType, machineRegNum, immedValue);
+      
+      if (op2type == MachineOperand::MO_Register)
+       {
+         if (vregType == MachineOperand::MO_MachineReg)
+           minstr->SetMachineOperand(op2Position, machineRegNum);
+         else
+           {
+             if (op2Value->getValueType() == Value::ConstantVal)
+               {// value is constant and must be loaded from constant pool
+                 returnFlags = returnFlags | (1 << op2Position);
+               }
+             minstr->SetMachineOperand(op2Position, op2type, op2Value);
+           }
+       }
+      else
+       minstr->SetMachineOperand(op2Position, op2type, immedValue);
+    }
+  
+  // If operand 3 (result) can be discarded, use a dead register if one exists
+  if (canDiscardResult && targetMachine.zeroRegNum >= 0)
+    minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum);
+  else
+    minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register,
+                                             vmInstrNode->getValue());
+
+  return returnFlags;
+}
+
+
+void
+Set3OperandsFromInstr(MachineInstr* minstr,
+                     InstructionNode* vmInstrNode,
+                     const TargetMachine& targetMachine,
+                     bool canDiscardResult,
+                     int op1Position,
+                     int op2Position,
+                     int resultPosition)
+{
+  assert(op1Position >= 0);
+  assert(resultPosition >= 0);
+  
+  // operand 1
+  minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register,
+                           vmInstrNode->leftChild()->getValue());   
+  
+  // operand 2 (if any)
+  if (op2Position >= 0)
+    minstr->SetMachineOperand(op2Position, MachineOperand::MO_Register,
+                             vmInstrNode->rightChild()->getValue());   
+  
+  // result operand: if it can be discarded, use a dead register if one exists
+  if (canDiscardResult && targetMachine.zeroRegNum >= 0)
+    minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum);
+  else
+    minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register,
+                                             vmInstrNode->getValue());
+}
+
+
+MachineOperand::MachineOperandType
+ChooseRegOrImmed(Value* val,
+                MachineOpCode opCode,
+                const TargetMachine& targetMachine,
+                bool canUseImmed,
+                MachineOperand::VirtualRegisterType& getVRegType,
+                unsigned int& getMachineRegNum,
+                int64_t& getImmedValue)
+{
+  MachineOperand::MachineOperandType opType = MachineOperand::MO_Register;
+  getVRegType = MachineOperand::MO_VirtualReg;
+  getMachineRegNum = 0;
+  getImmedValue = 0;
+  
+  // Check for the common case first: argument is not constant
+  // 
+  if (val->getValueType() != Value::ConstantVal)
+    return opType;
+  
+  // Now get the constant value and check if it fits in the IMMED field.
+  // Take advantage of the fact that the max unsigned value will rarely
+  // fit into any IMMED field and ignore that case (i.e., cast smaller
+  // unsigned constants to signed).
+  // 
+  bool isValidConstant;
+  int64_t intValue = GetConstantValueAsSignedInt(val, isValidConstant);
+  
+  if (isValidConstant)
+    {
+      if (intValue == 0 && targetMachine.zeroRegNum >= 0)
+       {
+         getVRegType = MachineOperand::MO_MachineReg;
+         getMachineRegNum = targetMachine.zeroRegNum;
+       }
+      else if (canUseImmed &&
+              targetMachine.machineInstrInfo[opCode].constantFitsInImmedField(intValue))
+       {
+         opType = MachineOperand::MO_SignExtendedImmed;
+         getImmedValue = intValue;
+       }
+    }
+  
+  return opType;
+}
diff --git a/lib/Target/SparcV9/InstrSelection/InstrForest.cpp b/lib/Target/SparcV9/InstrSelection/InstrForest.cpp
new file mode 100644 (file)
index 0000000..8ea2931
--- /dev/null
@@ -0,0 +1,461 @@
+// $Id$
+//---------------------------------------------------------------------------
+// File:
+//     InstrForest.cpp
+// 
+// Purpose:
+//     Convert SSA graph to instruction trees for instruction selection.
+// 
+// Strategy:
+//  The key goal is to group instructions into a single
+//  tree if one or more of them might be potentially combined into a single
+//  complex instruction in the target machine.
+//  Since this grouping is completely machine-independent, we do it as
+//  aggressive as possible to exploit any possible taret instructions.
+//  In particular, we group two instructions O and I if:
+//      (1) Instruction O computes an operand used by instruction I,
+//  and (2) O and I are part of the same basic block,
+//  and (3) O has only a single use, viz., I.
+// 
+// History:
+//     6/28/01  -  Vikram Adve  -  Created
+// 
+//---------------------------------------------------------------------------
+
+
+//************************** System Include Files **************************/
+
+#include <assert.h>
+#include <iostream.h>
+#include <bool.h>
+#include <string>
+
+//*************************** User Include Files ***************************/
+
+#include "llvm/Type.h"
+#include "llvm/Module.h"
+#include "llvm/Method.h"
+#include "llvm/Instruction.h"
+#include "llvm/iTerminators.h"
+#include "llvm/iMemory.h"
+#include "llvm/ConstPoolVals.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Bytecode/Reader.h"
+#include "llvm/Bytecode/Writer.h"
+#include "llvm/Tools/CommandLine.h"
+#include "llvm/LLC/CompileContext.h"
+#include "llvm/Codegen/MachineInstr.h"
+#include "llvm/Codegen/InstrForest.h"
+
+//************************ Class Implementations **************************/
+
+
+//------------------------------------------------------------------------ 
+// class InstrTreeNode
+//------------------------------------------------------------------------ 
+
+
+InstrTreeNode::InstrTreeNode(InstrTreeNodeType nodeType,
+                            Value* _val)
+  : treeNodeType(nodeType),
+    val(_val)
+{
+  basicNode.leftChild = NULL;
+  basicNode.rightChild = NULL;
+  basicNode.parent = NULL;
+  basicNode.opLabel = InvalidOp;
+  basicNode.treeNodePtr = this;
+}
+
+InstrTreeNode::~InstrTreeNode()
+{}
+
+
+void
+InstrTreeNode::dump(int dumpChildren,
+                   int indent) const
+{
+  this->dumpNode(indent);
+  
+  if (dumpChildren)
+    {
+      if (leftChild())
+       leftChild()->dump(dumpChildren, indent+1);
+      if (rightChild())
+       rightChild()->dump(dumpChildren, indent+1);
+    }
+}
+
+
+InstructionNode::InstructionNode(Instruction* _instr)
+  : InstrTreeNode(NTInstructionNode, _instr)
+{
+  OpLabel opLabel = _instr->getOpcode();
+
+  // Distinguish special cases of some instructions such as Ret and Br
+  // 
+  if (opLabel == Instruction::Ret && ((ReturnInst*) _instr)->getReturnValue())
+    {
+      opLabel = RetValueOp;             // ret(value) operation
+    }
+  else if (opLabel == Instruction::Br && ! ((BranchInst*) _instr)->isUnconditional())
+    {
+      opLabel = BrCondOp;              // br(cond) operation
+    }
+  else if (opLabel >= Instruction::SetEQ && opLabel <= Instruction::SetGT)
+    {
+      opLabel = SetCCOp;               // common label for all SetCC ops
+    }
+  else if (opLabel == Instruction::Alloca && _instr->getNumOperands() > 0)
+    {
+      opLabel = AllocaN;                // Alloca(ptr, N) operation
+    }
+  else if ((opLabel == Instruction::Load ||
+           opLabel == Instruction::GetElementPtr)
+          && ((MemAccessInst*)_instr)->getFirstOffsetIdx() > 0)
+    {
+      opLabel = opLabel + 100;          // load/getElem with index vector
+    }
+  else if (opLabel == Instruction::Cast)
+    {
+      const Type* instrValueType = _instr->getType();
+      switch(instrValueType->getPrimitiveID())
+       {
+       case Type::BoolTyID:    opLabel = ToBoolTy;  break;
+       case Type::UByteTyID:   opLabel = ToUByteTy; break;
+       case Type::SByteTyID:   opLabel = ToSByteTy; break;
+       case Type::UShortTyID:  opLabel = ToUShortTy; break;
+       case Type::ShortTyID:   opLabel = ToShortTy; break;
+       case Type::UIntTyID:    opLabel = ToUIntTy; break;
+       case Type::IntTyID:     opLabel = ToIntTy; break;
+       case Type::ULongTyID:   opLabel = ToULongTy; break;
+       case Type::LongTyID:    opLabel = ToLongTy; break;
+       case Type::FloatTyID:   opLabel = ToFloatTy; break;
+       case Type::DoubleTyID:  opLabel = ToDoubleTy; break;
+       default:
+         if (instrValueType->isArrayType())
+           opLabel = ToArrayTy;
+         else if (instrValueType->isPointerType())
+           opLabel = ToPointerTy;
+         else
+           ; // Just use `Cast' opcode otherwise. It's probably ignored.
+         break;
+       }
+    }
+  
+  basicNode.opLabel = opLabel;
+}
+
+void
+InstructionNode::reverseBinaryArgumentOrder()
+{
+  assert(getInstruction()->isBinaryOp());
+  
+  // switch arguments for the instruction
+  ((BinaryOperator*) getInstruction())->swapOperands();
+  
+  // switch arguments for this tree node itself
+  BasicTreeNode* leftCopy = basicNode.leftChild;
+  basicNode.leftChild = basicNode.rightChild;
+  basicNode.rightChild = leftCopy;
+}
+
+void
+InstructionNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << getInstruction()->getOpcodeName();
+  
+  const vector<MachineInstr*>& mvec = getInstruction()->getMachineInstrVec();
+  if (mvec.size() > 0)
+    cout << "\tMachine Instructions:  ";
+  for (unsigned int i=0; i < mvec.size(); i++)
+    {
+      mvec[i]->dump(0);
+      if (i < mvec.size() - 1)
+       cout << ";  ";
+    }
+  
+  cout << endl;
+}
+
+
+VRegListNode::VRegListNode()
+  : InstrTreeNode(NTVRegListNode, NULL)
+{
+  basicNode.opLabel = VRegListOp;
+}
+
+void
+VRegListNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << "List" << endl;
+}
+
+
+VRegNode::VRegNode(Value* _val)
+  : InstrTreeNode(NTVRegNode, _val)
+{
+  basicNode.opLabel = VRegNodeOp;
+}
+
+void
+VRegNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << "VReg " << getValue() << "\t(type "
+       << (int) getValue()->getValueType() << ")" << endl;
+}
+
+
+ConstantNode::ConstantNode(ConstPoolVal* constVal)
+  : InstrTreeNode(NTConstNode, constVal)
+{
+  basicNode.opLabel = ConstantNodeOp;
+}
+
+void
+ConstantNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << "Constant " << getValue() << "\t(type "
+       << (int) getValue()->getValueType() << ")" << endl;
+}
+
+
+LabelNode::LabelNode(BasicBlock* _bblock)
+  : InstrTreeNode(NTLabelNode, _bblock)
+{
+  basicNode.opLabel = LabelNodeOp;
+}
+
+void
+LabelNode::dumpNode(int indent) const
+{
+  for (int i=0; i < indent; i++)
+    cout << "    ";
+  
+  cout << "Label " << getValue() << endl;
+}
+
+//------------------------------------------------------------------------
+// class InstrForest
+// 
+// A forest of instruction trees, usually for a single method.
+//------------------------------------------------------------------------ 
+
+void
+InstrForest::buildTreesForMethod(Method *method)
+{
+  for (Method::inst_iterator instrIter = method->inst_begin();
+       instrIter != method->inst_end();
+       ++instrIter)
+    {
+      Instruction *instr = *instrIter;
+      if (! instr->isPHINode())
+       (void) this->buildTreeForInstruction(instr);
+    } 
+}
+
+
+void
+InstrForest::dump() const
+{
+  for (hash_set<InstructionNode*, ptrHashFunc >::const_iterator
+        treeRootIter = treeRoots.begin();
+       treeRootIter != treeRoots.end();
+       ++treeRootIter)
+    {
+      (*treeRootIter)->dump(/*dumpChildren*/ 1, /*indent*/ 0);
+    }
+}
+
+inline void
+InstrForest::noteTreeNodeForInstr(Instruction* instr,
+                                 InstructionNode* treeNode)
+{
+  assert(treeNode->getNodeType() == InstrTreeNode::NTInstructionNode);
+  (*this)[instr] = treeNode;
+  treeRoots.insert(treeNode);          // mark node as root of a new tree
+}
+
+
+inline void
+InstrForest::setLeftChild(InstrTreeNode* parent, InstrTreeNode* child)
+{
+  parent->basicNode.leftChild = & child->basicNode;
+  child->basicNode.parent = & parent->basicNode;
+  if (child->getNodeType() == InstrTreeNode::NTInstructionNode)
+    treeRoots.erase((InstructionNode*) child); // no longer a tree root
+}
+
+
+inline void
+InstrForest::setRightChild(InstrTreeNode* parent, InstrTreeNode* child)
+{
+  parent->basicNode.rightChild = & child->basicNode;
+  child->basicNode.parent = & parent->basicNode;
+  if (child->getNodeType() == InstrTreeNode::NTInstructionNode)
+    treeRoots.erase((InstructionNode*) child); // no longer a tree root
+}
+
+
+InstructionNode*
+InstrForest::buildTreeForInstruction(Instruction* instr)
+{
+  InstructionNode* treeNode = this->getTreeNodeForInstr(instr);
+  if (treeNode != NULL)
+    {// treeNode has already been constructed for this instruction
+      assert(treeNode->getInstruction() == instr);
+      return treeNode;
+    }
+  
+  // Otherwise, create a new tree node for this instruction.
+  // 
+  treeNode = new InstructionNode(instr);
+  this->noteTreeNodeForInstr(instr, treeNode);
+  
+  // If the instruction has more than 2 instruction operands,
+  // then we will not add any children.  This assumes that instructions
+  // like 'call' that have more than 2 instruction operands do not
+  // ever get combined with the instructions that compute the operands. 
+  // Note that we only count operands of type instruction and not other
+  // values such as branch labels for a branch or switch instruction.
+  //
+  // To do this efficiently, we'll walk all operands, build treeNodes
+  // for all instruction operands and save them in an array, and then
+  // insert children at the end if there are not more than 2.
+  // As a performance optimization, allocate a child array only
+  // if a fixed array is too small.
+  // 
+  int numChildren = 0;
+  const unsigned int MAX_CHILD = 8;
+  static InstrTreeNode* fixedChildArray[MAX_CHILD];
+  InstrTreeNode** childArray =
+    (instr->getNumOperands() > MAX_CHILD)
+    ? new (InstrTreeNode*)[instr->getNumOperands()]
+    : fixedChildArray;
+  
+  //
+  // Walk the operands of the instruction
+  // 
+  for (Instruction::op_iterator opIter = instr->op_begin();
+       opIter != instr->op_end();
+       ++opIter)
+    {
+      Value* operand = *opIter;
+      
+      // Check if the operand is a data value, not an branch label, type,
+      // method or module.  If the operand is an address type (i.e., label
+      // or method) that is used in an non-branching operation, e.g., `add'.
+      // that should be considered a data value.
+      
+      // Check latter condition here just to simplify the next IF.
+      bool includeAddressOperand =
+       ((operand->getValueType() == Value::BasicBlockVal
+         || operand->getValueType() == Value::MethodVal)
+        && ! instr->isTerminator());
+        
+      if (/* (*opIter) != NULL
+            &&*/ includeAddressOperand
+                 || operand->getValueType() == Value::InstructionVal
+                 ||  operand->getValueType() == Value::ConstantVal
+                 ||  operand->getValueType() == Value::MethodArgumentVal)
+       {// This operand is a data value
+         
+         // An instruction that computes the incoming value is added as a
+         // child of the current instruction if:
+         //   the value has only a single use
+         //   AND both instructions are in the same basic block
+         //   AND the instruction is not a PHI
+         // 
+         // (Note that if the value has only a single use (viz., `instr'),
+         //  the def of the value can be safely moved just before instr
+         //  and therefore it is safe to combine these two instructions.)
+         // 
+         // In all other cases, the virtual register holding the value
+         // is used directly, i.e., made a child of the instruction node.
+         // 
+         InstrTreeNode* opTreeNode;
+         if (operand->getValueType() == Value::InstructionVal
+             && operand->use_size() == 1
+             && ((Instruction*)operand)->getParent() == instr->getParent()
+             && ! ((Instruction*)operand)->isPHINode())
+           {
+             // Recursively create a treeNode for it.
+             opTreeNode =this->buildTreeForInstruction((Instruction*)operand);
+           }
+         else if (operand->getValueType() == Value::ConstantVal)
+           {
+             // Create a leaf node for a constant
+             opTreeNode = new ConstantNode((ConstPoolVal*) operand);
+           }
+         else
+           {
+             // Create a leaf node for the virtual register
+             opTreeNode = new VRegNode(operand);
+           }
+         
+         childArray[numChildren] = opTreeNode;
+         numChildren++;
+       }
+    }
+  
+  //-------------------------------------------------------------------- 
+  // Add any selected operands as children in the tree.
+  // Certain instructions can have more than 2 in some instances (viz.,
+  // a CALL or a memory access -- LOAD, STORE, and GetElemPtr -- to an
+  // array or struct). Make the operands of every such instruction into
+  // a right-leaning binary tree with the operand nodes at the leaves
+  // and VRegList nodes as internal nodes.
+  //-------------------------------------------------------------------- 
+  
+  InstrTreeNode* parent = treeNode;            // new VRegListNode();
+  int n;
+  
+  if (numChildren > 2)
+    {
+      unsigned instrOpcode = treeNode->getInstruction()->getOpcode();
+      assert(instrOpcode == Instruction::Call ||
+            instrOpcode == Instruction::Load ||
+            instrOpcode == Instruction::Store ||
+            instrOpcode == Instruction::GetElementPtr);
+    }
+  
+  // Insert the first child as a direct child
+  if (numChildren >= 1)
+    this->setLeftChild(parent, childArray[0]);
+  
+  // Create a list node for children 2 .. N-1, if any
+  for (n = numChildren-1; n >= 2; n--)
+    { // We have more than two children
+      InstrTreeNode* listNode = new VRegListNode();
+      this->setRightChild(parent, listNode);
+      this->setLeftChild(listNode, childArray[numChildren - n]);
+      parent = listNode;
+    }
+  
+  // Now insert the last remaining child (if any).
+  if (numChildren >= 2)
+    {
+      assert(n == 1);
+      this->setRightChild(parent, childArray[numChildren - 1]);
+    }
+  
+  if (childArray != fixedChildArray)
+    {
+      delete[] childArray; 
+    }
+  
+  return treeNode;
+}
+
diff --git a/lib/Target/SparcV9/InstrSelection/InstrSelection.cpp b/lib/Target/SparcV9/InstrSelection/InstrSelection.cpp
new file mode 100644 (file)
index 0000000..0d7dc7e
--- /dev/null
@@ -0,0 +1,279 @@
+// $Id$ -*-c++-*-
+//***************************************************************************
+// File:
+//     InstrSelection.h
+// 
+// Purpose:
+//     
+// History:
+//     7/02/01  -  Vikram Adve  -  Created
+//***************************************************************************
+
+
+//************************** System Include Files **************************/
+
+#include <assert.h>
+#include <stdio.h>
+#include <iostream.h>
+#include <bool.h>
+#include <string>
+
+//*************************** User Include Files ***************************/
+
+#include "llvm/Method.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Type.h"
+#include "llvm/iMemory.h"
+#include "llvm/Instruction.h"
+#include "llvm/LLC/CompileContext.h"
+#include "llvm/Codegen/InstrForest.h"
+#include "llvm/Codegen/MachineInstr.h"
+#include "llvm/Codegen/InstrSelection.h"
+
+
+//************************* Forward Declarations ***************************/
+
+static bool SelectInstructionsForTree  (BasicTreeNode* treeRoot,
+                                        int goalnt,
+                                        CompileContext& ccontext);
+
+
+//******************* Externally Visible Functions *************************/
+
+
+//---------------------------------------------------------------------------
+// Entry point for instruction selection using BURG.
+// Returns true if instruction selection failed, false otherwise.
+//---------------------------------------------------------------------------
+
+bool
+SelectInstructionsForMethod(Method* method,
+                           CompileContext& ccontext)
+{
+  bool failed = false;
+  
+  InstrForest instrForest;
+  instrForest.buildTreesForMethod(method);
+      
+  const hash_set<InstructionNode*, ptrHashFunc>&
+    treeRoots = instrForest.getRootSet();
+  
+  //
+  // Invoke BURG instruction selection for each tree
+  // 
+  for (hash_set<InstructionNode*, ptrHashFunc >::const_iterator
+        treeRootIter = treeRoots.begin();
+       treeRootIter != treeRoots.end();
+       ++treeRootIter)
+    {
+      BasicTreeNode* basicNode = (*treeRootIter)->getBasicNode();
+      
+      // Invoke BURM to label each tree node with a state
+      (void) burm_label(basicNode);
+      
+      if (ccontext.getOptions().IntOptionValue(DEBUG_INSTR_SELECT_OPT)
+         >= DEBUG_BURG_TREES)
+       {
+         printcover(basicNode, 1, 0);
+         printf("\nCover cost == %d\n\n", treecost(basicNode, 1, 0));
+         printMatches(basicNode);
+       }
+      
+      // Then recursively walk the tree to select instructions
+      if (SelectInstructionsForTree(basicNode, /*goalnt*/1, ccontext))
+       {
+         failed = true;
+         break;
+       }
+    }
+  
+  if (!failed)
+    {
+      if ( ccontext.getOptions().IntOptionValue(DEBUG_INSTR_SELECT_OPT)
+          >= DEBUG_INSTR_TREES)
+       {
+         cout << "\n\n*** Instruction trees for method "
+              << (method->hasName()? method->getName() : "")
+              << endl << endl;
+         instrForest.dump();
+       }
+      
+      if (ccontext.getOptions().IntOptionValue(DEBUG_INSTR_SELECT_OPT) > 0)
+       PrintMachineInstructions(method, ccontext);     
+    }
+  
+  return false;
+}
+
+
+//---------------------------------------------------------------------------
+// Function: FoldGetElemChain
+// 
+// Purpose:
+//   Fold a chain of GetElementPtr instructions into an equivalent
+//   (Pointer, IndexVector) pair.  Returns the pointer Value, and
+//   stores the resulting IndexVector in argument chainIdxVec.
+//---------------------------------------------------------------------------
+
+Value*
+FoldGetElemChain(const InstructionNode* getElemInstrNode,
+                vector<ConstPoolVal*>& chainIdxVec)
+{
+  MemAccessInst* getElemInst = (MemAccessInst*)
+    getElemInstrNode->getInstruction();
+  
+  // Initialize return values from the incoming instruction
+  Value* ptrVal = getElemInst->getPtrOperand();
+  chainIdxVec = getElemInst->getIndexVec(); // copies index vector values
+  
+  // Now chase the chain of getElementInstr instructions, if any
+  InstrTreeNode* ptrChild = getElemInstrNode->leftChild();
+  while (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
+        ptrChild->getOpLabel() == GetElemPtrIdx)
+    {
+      // Child is a GetElemPtr instruction
+      getElemInst = (MemAccessInst*)
+       ((InstructionNode*) ptrChild)->getInstruction();
+      const vector<ConstPoolVal*>& idxVec = getElemInst->getIndexVec();
+      
+      // Get the pointer value out of ptrChild and *prepend* its index vector
+      ptrVal = getElemInst->getPtrOperand();
+      chainIdxVec.insert(chainIdxVec.begin(), idxVec.begin(), idxVec.end());
+      
+      ptrChild = ptrChild->leftChild();
+    }
+  
+  return ptrVal;
+}
+
+
+void
+PrintMachineInstructions(Method* method,
+                        CompileContext& ccontext)
+{
+  cout << "\n" << method->getReturnType()
+       << " \"" << method->getName() << "\"" << endl;
+  
+  for (Method::const_iterator bbIter = method->begin();
+       bbIter != method->end();
+       ++bbIter)
+    {
+      BasicBlock* bb = *bbIter;
+      cout << "\n"
+          << (bb->hasName()? bb->getName() : "Label")
+          << " (" << bb << ")" << ":"
+          << endl;
+      
+      for (BasicBlock::const_iterator instrIter = bb->begin();
+          instrIter != bb->end();
+          ++instrIter)
+       {
+         Instruction *instr = *instrIter;
+         const MachineCodeForVMInstr& minstrVec = instr->getMachineInstrVec();
+         for (unsigned i=0, N=minstrVec.size(); i < N; i++)
+           cout << "\t" << *minstrVec[i] << endl;
+       }
+    } 
+}
+
+//*********************** Private Functions *****************************/
+
+
+//---------------------------------------------------------------------------
+// Function SelectInstructionsForTree 
+// 
+// Recursively walk the tree to select instructions.
+// Do this top-down so that child instructions can exploit decisions
+// made at the child instructions.
+// 
+// E.g., if br(setle(reg,const)) decides the constant is 0 and uses
+// a branch-on-integer-register instruction, then the setle node
+// can use that information to avoid generating the SUBcc instruction.
+//
+// Note that this cannot be done bottom-up because setle must do this
+// only if it is a child of the branch (otherwise, the result of setle
+// may be used by multiple instructions).
+//---------------------------------------------------------------------------
+
+bool
+SelectInstructionsForTree(BasicTreeNode* treeRoot,
+                         int goalnt,
+                         CompileContext& ccontext)
+{
+  // Use a static vector to avoid allocating a new one per VM instruction
+  static MachineInstr* minstrVec[MAX_INSTR_PER_VMINSTR];
+  
+  // 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" << endl;
+      return true;
+    }
+  
+  // Get this rule's non-terminals and the corresponding child nodes (if any)
+  // 
+  short *nts = burm_nts[ruleForNode];
+  
+  
+  // First, select instructions for the current node and rule.
+  // (If this is a list node, not an instruction, then skip this step).
+  // This function is specific to the target architecture.
+  // 
+  if (treeRoot->opLabel != VRegListOp)
+    {
+      InstructionNode* instrNode = (InstructionNode*) MainTreeNode(treeRoot);
+      assert(instrNode->getNodeType() == InstrTreeNode::NTInstructionNode);
+      
+      unsigned N = GetInstructionsByRule(instrNode, ruleForNode, nts, ccontext,
+                                        minstrVec);
+      assert(N <= MAX_INSTR_PER_VMINSTR);
+      for (unsigned i=0; i < N; i++)
+       {
+         assert(minstrVec[i] != NULL);
+         instrNode->getInstruction()->addMachineInstruction(minstrVec[i]);
+       }
+    }
+  
+  // Then, recursively compile the child nodes, if any.
+  // 
+  if (nts[0])
+    { // i.e., there is at least one kid
+
+      BasicTreeNode* kids[2];
+      int currentRule = ruleForNode;
+      burm_kids(treeRoot, currentRule, kids);
+      
+      // First skip over any chain rules so that we don't visit
+      // the current node again.
+      // 
+      while (ThisIsAChainRule(currentRule))
+       {
+         currentRule = burm_rule(treeRoot->state, nts[0]);
+         nts = burm_nts[currentRule];
+         burm_kids(treeRoot, currentRule, kids);
+       }
+      
+      // 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++)
+       {
+         assert(i < 2);
+         InstrTreeNode::InstrTreeNodeType
+           nodeType = MainTreeNode(kids[i])->getNodeType();
+         if (nodeType == InstrTreeNode::NTVRegListNode ||
+             nodeType == InstrTreeNode::NTInstructionNode)
+           {
+             bool failed= SelectInstructionsForTree(kids[i], nts[i],ccontext);
+             if (failed)
+               return true;                    // failure
+           }
+       }
+    }
+  
+  return false;                                // success
+}
+
diff --git a/lib/Target/SparcV9/InstrSelection/Makefile b/lib/Target/SparcV9/InstrSelection/Makefile
new file mode 100644 (file)
index 0000000..985ddaf
--- /dev/null
@@ -0,0 +1,13 @@
+LEVEL = ../../..
+
+DIRS  = 
+
+LIBRARYNAME = select
+
+## List source files in link order
+Source  = \
+         InstrSelection.o \
+         MachineInstr.o \
+         InstrForest.o
+
+include $(LEVEL)/Makefile.common