// $Id$
//***************************************************************************
// File:
//	SparcInstrSelection.cpp
// 
// Purpose:
//      BURS instruction selection for SPARC V9 architecture.      
//	
// History:
//	7/02/01	 -  Vikram Adve  -  Created
//**************************************************************************/

#include "SparcInternals.h"
#include "SparcInstrSelectionSupport.h"
#include "SparcRegClassInfo.h"
#include "llvm/CodeGen/InstrSelectionSupport.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrAnnot.h"
#include "llvm/CodeGen/InstrForest.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/DerivedTypes.h"
#include "llvm/iTerminators.h"
#include "llvm/iMemory.h"
#include "llvm/iOther.h"
#include "llvm/BasicBlock.h"
#include "llvm/Function.h"
#include "llvm/Constants.h"
#include "Support/MathExtras.h"
#include <math.h>
using std::vector;

//************************* Forward Declarations ***************************/


static void SetMemOperands_Internal     (vector<MachineInstr*>& mvec,
                                         vector<MachineInstr*>::iterator mvecI,
                                         const InstructionNode* vmInstrNode,
                                         Value* ptrVal,
                                         std::vector<Value*>& idxVec,
                                         bool allConstantIndices,
                                         const TargetMachine& target);


//************************ Internal Functions ******************************/


static inline MachineOpCode 
ChooseBprInstruction(const InstructionNode* instrNode)
{
  MachineOpCode opCode;
  
  Instruction* setCCInstr =
    ((InstructionNode*) instrNode->leftChild())->getInstruction();
  
  switch(setCCInstr->getOpcode())
    {
    case Instruction::SetEQ: opCode = BRZ;   break;
    case Instruction::SetNE: opCode = BRNZ;  break;
    case Instruction::SetLE: opCode = BRLEZ; break;
    case Instruction::SetGE: opCode = BRGEZ; break;
    case Instruction::SetLT: opCode = BRLZ;  break;
    case Instruction::SetGT: opCode = BRGZ;  break;
    default:
      assert(0 && "Unrecognized VM instruction!");
      opCode = INVALID_OPCODE;
      break; 
    }
  
  return opCode;
}


static inline MachineOpCode 
ChooseBpccInstruction(const InstructionNode* instrNode,
                      const BinaryOperator* setCCInstr)
{
  MachineOpCode opCode = INVALID_OPCODE;
  
  bool isSigned = setCCInstr->getOperand(0)->getType()->isSigned();
  
  if (isSigned)
    {
      switch(setCCInstr->getOpcode())
        {
        case Instruction::SetEQ: opCode = BE;  break;
        case Instruction::SetNE: opCode = BNE; break;
        case Instruction::SetLE: opCode = BLE; break;
        case Instruction::SetGE: opCode = BGE; break;
        case Instruction::SetLT: opCode = BL;  break;
        case Instruction::SetGT: opCode = BG;  break;
        default:
          assert(0 && "Unrecognized VM instruction!");
          break; 
        }
    }
  else
    {
      switch(setCCInstr->getOpcode())
        {
        case Instruction::SetEQ: opCode = BE;   break;
        case Instruction::SetNE: opCode = BNE;  break;
        case Instruction::SetLE: opCode = BLEU; break;
        case Instruction::SetGE: opCode = BCC;  break;
        case Instruction::SetLT: opCode = BCS;  break;
        case Instruction::SetGT: opCode = BGU;  break;
        default:
          assert(0 && "Unrecognized VM instruction!");
          break; 
        }
    }
  
  return opCode;
}

static inline MachineOpCode 
ChooseBFpccInstruction(const InstructionNode* instrNode,
                       const BinaryOperator* setCCInstr)
{
  MachineOpCode opCode = INVALID_OPCODE;
  
  switch(setCCInstr->getOpcode())
    {
    case Instruction::SetEQ: opCode = FBE;  break;
    case Instruction::SetNE: opCode = FBNE; break;
    case Instruction::SetLE: opCode = FBLE; break;
    case Instruction::SetGE: opCode = FBGE; break;
    case Instruction::SetLT: opCode = FBL;  break;
    case Instruction::SetGT: opCode = FBG;  break;
    default:
      assert(0 && "Unrecognized VM instruction!");
      break; 
    }
  
  return opCode;
}


// Create a unique TmpInstruction for a boolean value,
// representing the CC register used by a branch on that value.
// For now, hack this using a little static cache of TmpInstructions.
// Eventually the entire BURG instruction selection should be put
// into a separate class that can hold such information.
// The static cache is not too bad because the memory for these
// TmpInstructions will be freed along with the rest of the Function anyway.
// 
static TmpInstruction*
GetTmpForCC(Value* boolVal, const Function *F, const Type* ccType)
{
  typedef hash_map<const Value*, TmpInstruction*> BoolTmpCache;
  static BoolTmpCache boolToTmpCache;     // Map boolVal -> TmpInstruction*
  static const Function *lastFunction = 0;// Use to flush cache between funcs
  
  assert(boolVal->getType() == Type::BoolTy && "Weird but ok! Delete assert");
  
  if (lastFunction != F)
    {
      lastFunction = F;
      boolToTmpCache.clear();
    }
  
  // Look for tmpI and create a new one otherwise.  The new value is
  // directly written to map using the ref returned by operator[].
  TmpInstruction*& tmpI = boolToTmpCache[boolVal];
  if (tmpI == NULL)
    tmpI = new TmpInstruction(ccType, boolVal);
  
  return tmpI;
}


static inline MachineOpCode 
ChooseBccInstruction(const InstructionNode* instrNode,
                     bool& isFPBranch)
{
  InstructionNode* setCCNode = (InstructionNode*) instrNode->leftChild();
  BinaryOperator* setCCInstr = (BinaryOperator*) setCCNode->getInstruction();
  const Type* setCCType = setCCInstr->getOperand(0)->getType();
  
  isFPBranch = setCCType->isFloatingPoint(); // Return value: don't delete!
  
  if (isFPBranch)
    return ChooseBFpccInstruction(instrNode, setCCInstr);
  else
    return ChooseBpccInstruction(instrNode, setCCInstr);
}


static inline MachineOpCode 
ChooseMovFpccInstruction(const InstructionNode* instrNode)
{
  MachineOpCode opCode = INVALID_OPCODE;
  
  switch(instrNode->getInstruction()->getOpcode())
    {
    case Instruction::SetEQ: opCode = MOVFE;  break;
    case Instruction::SetNE: opCode = MOVFNE; break;
    case Instruction::SetLE: opCode = MOVFLE; break;
    case Instruction::SetGE: opCode = MOVFGE; break;
    case Instruction::SetLT: opCode = MOVFL;  break;
    case Instruction::SetGT: opCode = MOVFG;  break;
    default:
      assert(0 && "Unrecognized VM instruction!");
      break; 
    }
  
  return opCode;
}


// Assumes that SUBcc v1, v2 -> v3 has been executed.
// In most cases, we want to clear v3 and then follow it by instruction
// MOVcc 1 -> v3.
// Set mustClearReg=false if v3 need not be cleared before conditional move.
// Set valueToMove=0 if we want to conditionally move 0 instead of 1
//                      (i.e., we want to test inverse of a condition)
// (The latter two cases do not seem to arise because SetNE needs nothing.)
// 
static MachineOpCode
ChooseMovpccAfterSub(const InstructionNode* instrNode,
                     bool& mustClearReg,
                     int& valueToMove)
{
  MachineOpCode opCode = INVALID_OPCODE;
  mustClearReg = true;
  valueToMove = 1;
  
  switch(instrNode->getInstruction()->getOpcode())
    {
    case Instruction::SetEQ: opCode = MOVE;  break;
    case Instruction::SetLE: opCode = MOVLE; break;
    case Instruction::SetGE: opCode = MOVGE; break;
    case Instruction::SetLT: opCode = MOVL;  break;
    case Instruction::SetGT: opCode = MOVG;  break;
    case Instruction::SetNE: assert(0 && "No move required!"); break;
    default:		     assert(0 && "Unrecognized VM instr!"); break; 
    }
  
  return opCode;
}

static inline MachineOpCode
ChooseConvertToFloatInstr(OpLabel vopCode, const Type* opType)
{
  MachineOpCode opCode = INVALID_OPCODE;
  
  switch(vopCode)
    {
    case ToFloatTy: 
      if (opType == Type::SByteTy || opType == Type::ShortTy || opType == Type::IntTy)
        opCode = FITOS;
      else if (opType == Type::LongTy)
        opCode = FXTOS;
      else if (opType == Type::DoubleTy)
        opCode = FDTOS;
      else if (opType == Type::FloatTy)
        ;
      else
        assert(0 && "Cannot convert this type to FLOAT on SPARC");
      break;
      
    case ToDoubleTy: 
      // This is usually used in conjunction with CreateCodeToCopyIntToFloat().
      // Both functions should treat the integer as a 32-bit value for types
      // of 4 bytes or less, and as a 64-bit value otherwise.
      if (opType == Type::SByteTy || opType == Type::UByteTy ||
          opType == Type::ShortTy || opType == Type::UShortTy ||
          opType == Type::IntTy   || opType == Type::UIntTy)
        opCode = FITOD;
      else if (opType == Type::LongTy || opType == Type::ULongTy)
        opCode = FXTOD;
      else if (opType == Type::FloatTy)
        opCode = FSTOD;
      else if (opType == Type::DoubleTy)
        ;
      else
        assert(0 && "Cannot convert this type to DOUBLE on SPARC");
      break;
      
    default:
      break;
    }
  
  return opCode;
}

static inline MachineOpCode 
ChooseConvertToIntInstr(Type::PrimitiveID tid, const Type* opType)
{
  MachineOpCode opCode = INVALID_OPCODE;;
  
  if (tid==Type::SByteTyID || tid==Type::ShortTyID  || tid==Type::IntTyID ||
      tid==Type::UByteTyID || tid==Type::UShortTyID || tid==Type::UIntTyID)
    {
      switch (opType->getPrimitiveID())
        {
        case Type::FloatTyID:   opCode = FSTOI; break;
        case Type::DoubleTyID:  opCode = FDTOI; break;
        default:
          assert(0 && "Non-numeric non-bool type cannot be converted to Int");
          break;
        }
    }
  else if (tid==Type::LongTyID || tid==Type::ULongTyID)
    {
      switch (opType->getPrimitiveID())
        {
        case Type::FloatTyID:   opCode = FSTOX; break;
        case Type::DoubleTyID:  opCode = FDTOX; break;
        default:
          assert(0 && "Non-numeric non-bool type cannot be converted to Long");
          break;
        }
    }
  else
      assert(0 && "Should not get here, Mo!");
  
  return opCode;
}

MachineInstr*
CreateConvertToIntInstr(Type::PrimitiveID destTID, Value* srcVal,Value* destVal)
{
  MachineOpCode opCode = ChooseConvertToIntInstr(destTID, srcVal->getType());
  assert(opCode != INVALID_OPCODE && "Expected to need conversion!");
  
  MachineInstr* M = new MachineInstr(opCode);
  M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, srcVal);
  M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, destVal);
  return M;
}

// CreateCodeToConvertIntToFloat: Convert FP value to signed or unsigned integer
// The FP value must be converted to the dest type in an FP register,
// and the result is then copied from FP to int register via memory.
static void
CreateCodeToConvertIntToFloat (const TargetMachine& target,
                               Value* opVal,
                               Instruction* destI,
                               std::vector<MachineInstr*>& mvec,
                               MachineCodeForInstruction& mcfi)
{
  // Create a temporary to represent the FP register into which the
  // int value will placed after conversion.  The type of this temporary
  // depends on the type of FP register to use: single-prec for a 32-bit
  // int or smaller; double-prec for a 64-bit int.
  // 
  const Type* destTypeToUse = (destI->getType() == Type::LongTy)? Type::DoubleTy
                                                                : Type::FloatTy;
  Value* destForCast = new TmpInstruction(destTypeToUse, opVal);
  mcfi.addTemp(destForCast);

  // Create the fp-to-int conversion code
  MachineInstr* M = CreateConvertToIntInstr(destI->getType()->getPrimitiveID(),
                                            opVal, destForCast);
  mvec.push_back(M);

  // Create the fpreg-to-intreg copy code
  target.getInstrInfo().
    CreateCodeToCopyFloatToInt(target, destI->getParent()->getParent(),
                               (TmpInstruction*)destForCast, destI, mvec, mcfi);
}


static inline MachineOpCode 
ChooseAddInstruction(const InstructionNode* instrNode)
{
  return ChooseAddInstructionByType(instrNode->getInstruction()->getType());
}


static inline MachineInstr* 
CreateMovFloatInstruction(const InstructionNode* instrNode,
                          const Type* resultType)
{
  MachineInstr* minstr = new MachineInstr((resultType == Type::FloatTy)
                                          ? FMOVS : FMOVD);
  minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
                               instrNode->leftChild()->getValue());
  minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
                               instrNode->getValue());
  return minstr;
}

static inline MachineInstr* 
CreateAddConstInstruction(const InstructionNode* instrNode)
{
  MachineInstr* minstr = NULL;
  
  Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
  assert(isa<Constant>(constOp));
  
  // Cases worth optimizing are:
  // (1) Add with 0 for float or double: use an FMOV of appropriate type,
  //	 instead of an FADD (1 vs 3 cycles).  There is no integer MOV.
  // 
  if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
      double dval = FPC->getValue();
      if (dval == 0.0)
        minstr = CreateMovFloatInstruction(instrNode,
                                   instrNode->getInstruction()->getType());
    }
  
  return minstr;
}


static inline MachineOpCode 
ChooseSubInstructionByType(const Type* resultType)
{
  MachineOpCode opCode = INVALID_OPCODE;
  
  if (resultType->isIntegral() || isa<PointerType>(resultType))
    {
      opCode = SUB;
    }
  else
    switch(resultType->getPrimitiveID())
      {
      case Type::FloatTyID:  opCode = FSUBS; break;
      case Type::DoubleTyID: opCode = FSUBD; break;
      default: assert(0 && "Invalid type for SUB instruction"); break; 
      }
  
  return opCode;
}


static inline MachineInstr* 
CreateSubConstInstruction(const InstructionNode* instrNode)
{
  MachineInstr* minstr = NULL;
  
  Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
  assert(isa<Constant>(constOp));
  
  // Cases worth optimizing are:
  // (1) Sub with 0 for float or double: use an FMOV of appropriate type,
  //	 instead of an FSUB (1 vs 3 cycles).  There is no integer MOV.
  // 
  if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
    double dval = FPC->getValue();
    if (dval == 0.0)
      minstr = CreateMovFloatInstruction(instrNode,
                                        instrNode->getInstruction()->getType());
  }
  
  return minstr;
}


static inline MachineOpCode 
ChooseFcmpInstruction(const InstructionNode* instrNode)
{
  MachineOpCode opCode = INVALID_OPCODE;
  
  Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
  switch(operand->getType()->getPrimitiveID()) {
  case Type::FloatTyID:  opCode = FCMPS; break;
  case Type::DoubleTyID: opCode = FCMPD; break;
  default: assert(0 && "Invalid type for FCMP instruction"); break; 
  }
  
  return opCode;
}


// Assumes that leftArg and rightArg are both cast instructions.
//
static inline bool
BothFloatToDouble(const InstructionNode* instrNode)
{
  InstrTreeNode* leftArg = instrNode->leftChild();
  InstrTreeNode* rightArg = instrNode->rightChild();
  InstrTreeNode* leftArgArg = leftArg->leftChild();
  InstrTreeNode* rightArgArg = rightArg->leftChild();
  assert(leftArg->getValue()->getType() == rightArg->getValue()->getType());
  
  // Check if both arguments are floats cast to double
  return (leftArg->getValue()->getType() == Type::DoubleTy &&
          leftArgArg->getValue()->getType() == Type::FloatTy &&
          rightArgArg->getValue()->getType() == Type::FloatTy);
}


static inline MachineOpCode 
ChooseMulInstructionByType(const Type* resultType)
{
  MachineOpCode opCode = INVALID_OPCODE;
  
  if (resultType->isIntegral())
    opCode = MULX;
  else
    switch(resultType->getPrimitiveID())
      {
      case Type::FloatTyID:  opCode = FMULS; break;
      case Type::DoubleTyID: opCode = FMULD; break;
      default: assert(0 && "Invalid type for MUL instruction"); break; 
      }
  
  return opCode;
}



static inline MachineInstr*
CreateIntNegInstruction(const TargetMachine& target,
                        Value* vreg)
{
  MachineInstr* minstr = new MachineInstr(SUB);
  minstr->SetMachineOperandReg(0, target.getRegInfo().getZeroRegNum());
  minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, vreg);
  minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, vreg);
  return minstr;
}


// Create instruction sequence for any shift operation.
// SLL or SLLX on an operand smaller than the integer reg. size (64bits)
// requires a second instruction for explicit sign-extension.
// Note that we only have to worry about a sign-bit appearing in the
// most significant bit of the operand after shifting (e.g., bit 32 of
// Int or bit 16 of Short), so we do not have to worry about results
// that are as large as a normal integer register.
// 
static inline void
CreateShiftInstructions(const TargetMachine& target,
                        Function* F,
                        MachineOpCode shiftOpCode,
                        Value* argVal1,
                        Value* optArgVal2, /* Use optArgVal2 if not NULL */
                        unsigned int optShiftNum, /* else use optShiftNum */
                        Instruction* destVal,
                        vector<MachineInstr*>& mvec,
                        MachineCodeForInstruction& mcfi)
{
  assert((optArgVal2 != NULL || optShiftNum <= 64) &&
         "Large shift sizes unexpected, but can be handled below: "
         "You need to check whether or not it fits in immed field below");
  
  // If this is a logical left shift of a type smaller than the standard
  // integer reg. size, we have to extend the sign-bit into upper bits
  // of dest, so we need to put the result of the SLL into a temporary.
  // 
  Value* shiftDest = destVal;
  const Type* opType = argVal1->getType();
  unsigned opSize = target.DataLayout.getTypeSize(argVal1->getType());
  if ((shiftOpCode == SLL || shiftOpCode == SLLX)
      && opSize < target.DataLayout.getIntegerRegize())
    { // put SLL result into a temporary
      shiftDest = new TmpInstruction(argVal1, optArgVal2, "sllTmp");
      mcfi.addTemp(shiftDest);
    }
  
  MachineInstr* M = (optArgVal2 != NULL)
    ? Create3OperandInstr(shiftOpCode, argVal1, optArgVal2, shiftDest)
    : Create3OperandInstr_UImmed(shiftOpCode, argVal1, optShiftNum, shiftDest);
  mvec.push_back(M);
  
  if (shiftDest != destVal)
    { // extend the sign-bit of the result into all upper bits of dest
      assert(8*opSize <= 32 && "Unexpected type size > 4 and < IntRegSize?");
      target.getInstrInfo().
        CreateSignExtensionInstructions(target, F, shiftDest, 8*opSize,
                                        destVal, mvec, mcfi);
    }
}


// Does not create any instructions if we cannot exploit constant to
// create a cheaper instruction.
// This returns the approximate cost of the instructions generated,
// which is used to pick the cheapest when both operands are constant.
static inline unsigned int
CreateMulConstInstruction(const TargetMachine &target, Function* F,
                          Value* lval, Value* rval, Instruction* destVal,
                          vector<MachineInstr*>& mvec,
                          MachineCodeForInstruction& mcfi)
{
  /* Use max. multiply cost, viz., cost of MULX */
  unsigned int cost = target.getInstrInfo().minLatency(MULX);
  unsigned int firstNewInstr = mvec.size();
  
  Value* constOp = rval;
  if (! isa<Constant>(constOp))
    return cost;
  
  // Cases worth optimizing are:
  // (1) Multiply by 0 or 1 for any type: replace with copy (ADD or FMOV)
  // (2) Multiply by 2^x for integer types: replace with Shift
  // 
  const Type* resultType = destVal->getType();
  
  if (resultType->isIntegral() || isa<PointerType>(resultType))
    {
      bool isValidConst;
      int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst);
      if (isValidConst)
        {
          unsigned pow;
          bool needNeg = false;
          if (C < 0)
            {
              needNeg = true;
              C = -C;
            }
          
          if (C == 0 || C == 1)
            {
              cost = target.getInstrInfo().minLatency(ADD);
              MachineInstr* M = (C == 0)
                ? Create3OperandInstr_Reg(ADD,
                                          target.getRegInfo().getZeroRegNum(),
                                          target.getRegInfo().getZeroRegNum(),
                                          destVal)
                : Create3OperandInstr_Reg(ADD, lval,
                                          target.getRegInfo().getZeroRegNum(),
                                          destVal);
              mvec.push_back(M);
            }
          else if (isPowerOf2(C, pow))
            {
              unsigned int opSize = target.DataLayout.getTypeSize(resultType);
              MachineOpCode opCode = (opSize <= 32)? SLL : SLLX;
              CreateShiftInstructions(target, F, opCode, lval, NULL, pow,
                                      destVal, mvec, mcfi); 
            }
          
          if (mvec.size() > 0 && needNeg)
            { // insert <reg = SUB 0, reg> after the instr to flip the sign
              MachineInstr* M = CreateIntNegInstruction(target, destVal);
              mvec.push_back(M);
            }
        }
    }
  else
    {
      if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp))
        {
          double dval = FPC->getValue();
          if (fabs(dval) == 1)
            {
              MachineOpCode opCode =  (dval < 0)
                ? (resultType == Type::FloatTy? FNEGS : FNEGD)
                : (resultType == Type::FloatTy? FMOVS : FMOVD);
              MachineInstr* M = Create2OperandInstr(opCode, lval, destVal);
              mvec.push_back(M);
            } 
        }
    }
  
  if (firstNewInstr < mvec.size())
    {
      cost = 0;
      for (unsigned int i=firstNewInstr; i < mvec.size(); ++i)
        cost += target.getInstrInfo().minLatency(mvec[i]->getOpCode());
    }
  
  return cost;
}


// Does not create any instructions if we cannot exploit constant to
// create a cheaper instruction.
// 
static inline void
CreateCheapestMulConstInstruction(const TargetMachine &target,
                                  Function* F,
                                  Value* lval, Value* rval,
                                  Instruction* destVal,
                                  vector<MachineInstr*>& mvec,
                                  MachineCodeForInstruction& mcfi)
{
  Value* constOp;
  if (isa<Constant>(lval) && isa<Constant>(rval))
    { // both operands are constant: try both orders!
      vector<MachineInstr*> mvec1, mvec2;
      unsigned int lcost = CreateMulConstInstruction(target, F, lval, rval,
                                                     destVal, mvec1, mcfi);
      unsigned int rcost = CreateMulConstInstruction(target, F, rval, lval,
                                                     destVal, mvec2, mcfi);
      vector<MachineInstr*>& mincostMvec =  (lcost <= rcost)? mvec1 : mvec2;
      vector<MachineInstr*>& maxcostMvec =  (lcost <= rcost)? mvec2 : mvec1;
      mvec.insert(mvec.end(), mincostMvec.begin(), mincostMvec.end()); 

      for (unsigned int i=0; i < maxcostMvec.size(); ++i)
        delete maxcostMvec[i];
    }
  else if (isa<Constant>(rval))         // rval is constant, but not lval
    CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
  else if (isa<Constant>(lval))         // lval is constant, but not rval
    CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
  
  // else neither is constant
  return;
}

// Return NULL if we cannot exploit constant to create a cheaper instruction
static inline void
CreateMulInstruction(const TargetMachine &target, Function* F,
                     Value* lval, Value* rval, Instruction* destVal,
                     vector<MachineInstr*>& mvec,
                     MachineCodeForInstruction& mcfi,
                     MachineOpCode forceMulOp = INVALID_MACHINE_OPCODE)
{
  unsigned int L = mvec.size();
  CreateCheapestMulConstInstruction(target,F, lval, rval, destVal, mvec, mcfi);
  if (mvec.size() == L)
    { // no instructions were added so create MUL reg, reg, reg.
      // Use FSMULD if both operands are actually floats cast to doubles.
      // Otherwise, use the default opcode for the appropriate type.
      MachineOpCode mulOp = ((forceMulOp != INVALID_MACHINE_OPCODE)
                             ? forceMulOp 
                             : ChooseMulInstructionByType(destVal->getType()));
      MachineInstr* M = new MachineInstr(mulOp);
      M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, lval);
      M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, rval);
      M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, destVal);
      mvec.push_back(M);
    }
}


// Generate a divide instruction for Div or Rem.
// For Rem, this assumes that the operand type will be signed if the result
// type is signed.  This is correct because they must have the same sign.
// 
static inline MachineOpCode 
ChooseDivInstruction(TargetMachine &target,
                     const InstructionNode* instrNode)
{
  MachineOpCode opCode = INVALID_OPCODE;
  
  const Type* resultType = instrNode->getInstruction()->getType();
  
  if (resultType->isIntegral())
    opCode = resultType->isSigned()? SDIVX : UDIVX;
  else
    switch(resultType->getPrimitiveID())
      {
      case Type::FloatTyID:  opCode = FDIVS; break;
      case Type::DoubleTyID: opCode = FDIVD; break;
      default: assert(0 && "Invalid type for DIV instruction"); break; 
      }
  
  return opCode;
}


// Return NULL if we cannot exploit constant to create a cheaper instruction
static inline void
CreateDivConstInstruction(TargetMachine &target,
                          const InstructionNode* instrNode,
                          vector<MachineInstr*>& mvec)
{
  MachineInstr* minstr1 = NULL;
  MachineInstr* minstr2 = NULL;
  
  Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
  if (! isa<Constant>(constOp))
    return;
  
  // Cases worth optimizing are:
  // (1) Divide by 1 for any type: replace with copy (ADD or FMOV)
  // (2) Divide by 2^x for integer types: replace with SR[L or A]{X}
  // 
  const Type* resultType = instrNode->getInstruction()->getType();
  
  if (resultType->isIntegral())
    {
      unsigned pow;
      bool isValidConst;
      int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst);
      if (isValidConst)
        {
          bool needNeg = false;
          if (C < 0)
            {
              needNeg = true;
              C = -C;
            }
          
          if (C == 1)
            {
              minstr1 = new MachineInstr(ADD);
              minstr1->SetMachineOperandVal(0,
                                           MachineOperand::MO_VirtualRegister,
                                           instrNode->leftChild()->getValue());
              minstr1->SetMachineOperandReg(1,
                                        target.getRegInfo().getZeroRegNum());
            }
          else if (isPowerOf2(C, pow))
            {
              MachineOpCode opCode= ((resultType->isSigned())
                                     ? (resultType==Type::LongTy)? SRAX : SRA
                                     : (resultType==Type::LongTy)? SRLX : SRL);
              minstr1 = new MachineInstr(opCode);
              minstr1->SetMachineOperandVal(0,
                                           MachineOperand::MO_VirtualRegister,
                                           instrNode->leftChild()->getValue());
              minstr1->SetMachineOperandConst(1,
                                          MachineOperand::MO_UnextendedImmed,
                                          pow);
            }
          
          if (minstr1 && needNeg)
            { // insert <reg = SUB 0, reg> after the instr to flip the sign
              minstr2 = CreateIntNegInstruction(target,
                                                   instrNode->getValue());
            }
        }
    }
  else
    {
      if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp))
        {
          double dval = FPC->getValue();
          if (fabs(dval) == 1)
            {
              bool needNeg = (dval < 0);
              
              MachineOpCode opCode = needNeg
                ? (resultType == Type::FloatTy? FNEGS : FNEGD)
                : (resultType == Type::FloatTy? FMOVS : FMOVD);
              
              minstr1 = new MachineInstr(opCode);
              minstr1->SetMachineOperandVal(0,
                                           MachineOperand::MO_VirtualRegister,
                                           instrNode->leftChild()->getValue());
            } 
        }
    }
  
  if (minstr1 != NULL)
    minstr1->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
                                 instrNode->getValue());   
  
  if (minstr1)
    mvec.push_back(minstr1);
  if (minstr2)
    mvec.push_back(minstr2);
}


static void
CreateCodeForVariableSizeAlloca(const TargetMachine& target,
                                Instruction* result,
                                unsigned int tsize,
                                Value* numElementsVal,
                                vector<MachineInstr*>& getMvec)
{
  MachineInstr* M;
  
  // Create a Value to hold the (constant) element size
  Value* tsizeVal = ConstantSInt::get(Type::IntTy, tsize);

  // Get the constant offset from SP for dynamically allocated storage
  // and create a temporary Value to hold it.
  assert(result && result->getParent() && "Result value is not part of a fn?");
  Function *F = result->getParent()->getParent();
  MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(F);
  bool growUp;
  ConstantSInt* dynamicAreaOffset =
    ConstantSInt::get(Type::IntTy,
                      target.getFrameInfo().getDynamicAreaOffset(mcInfo,growUp));
  assert(! growUp && "Has SPARC v9 stack frame convention changed?");

  // Create a temporary value to hold the result of MUL
  TmpInstruction* tmpProd = new TmpInstruction(numElementsVal, tsizeVal);
  MachineCodeForInstruction::get(result).addTemp(tmpProd);
  
  // Instruction 1: mul numElements, typeSize -> tmpProd
  M = new MachineInstr(MULX);
  M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, numElementsVal);
  M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tsizeVal);
  M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, tmpProd);
  getMvec.push_back(M);
        
  // Instruction 2: sub %sp, tmpProd -> %sp
  M = new MachineInstr(SUB);
  M->SetMachineOperandReg(0, target.getRegInfo().getStackPointer());
  M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpProd);
  M->SetMachineOperandReg(2, target.getRegInfo().getStackPointer());
  getMvec.push_back(M);
  
  // Instruction 3: add %sp, frameSizeBelowDynamicArea -> result
  M = new MachineInstr(ADD);
  M->SetMachineOperandReg(0, target.getRegInfo().getStackPointer());
  M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, dynamicAreaOffset);
  M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, result);
  getMvec.push_back(M);
}        


static void
CreateCodeForFixedSizeAlloca(const TargetMachine& target,
                             Instruction* result,
                             unsigned int tsize,
                             unsigned int numElements,
                             vector<MachineInstr*>& getMvec)
{
  assert(result && result->getParent() &&
         "Result value is not part of a function?");
  Function *F = result->getParent()->getParent();
  MachineCodeForMethod &mcInfo = MachineCodeForMethod::get(F);

  // Check if the offset would small enough to use as an immediate in
  // load/stores (check LDX because all load/stores have the same-size immediate
  // field).  If not, put the variable in the dynamically sized area of the
  // frame.
  unsigned int paddedSizeIgnored;
  int offsetFromFP = mcInfo.computeOffsetforLocalVar(target, result,
                                                     paddedSizeIgnored,
                                                     tsize * numElements);
  if (! target.getInstrInfo().constantFitsInImmedField(LDX, offsetFromFP))
    {
      CreateCodeForVariableSizeAlloca(target, result, tsize, 
                                      ConstantSInt::get(Type::IntTy,numElements),
                                      getMvec);
      return;
    }
  
  // else offset fits in immediate field so go ahead and allocate it.
  offsetFromFP = mcInfo.allocateLocalVar(target, result, tsize * numElements);
  
  // Create a temporary Value to hold the constant offset.
  // This is needed because it may not fit in the immediate field.
  ConstantSInt* offsetVal = ConstantSInt::get(Type::IntTy, offsetFromFP);
  
  // Instruction 1: add %fp, offsetFromFP -> result
  MachineInstr* M = new MachineInstr(ADD);
  M->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
  M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, offsetVal); 
  M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, result);
  
  getMvec.push_back(M);
}



// Check for a constant (uint) 0.
inline bool
IsZero(Value* idx)
{
  return (isa<ConstantInt>(idx) && cast<ConstantInt>(idx)->isNullValue());
}


//------------------------------------------------------------------------ 
// Function SetOperandsForMemInstr
//
// Choose addressing mode for the given load or store instruction.
// Use [reg+reg] if it is an indexed reference, and the index offset is
//		 not a constant or if it cannot fit in the offset field.
// Use [reg+offset] in all other cases.
// 
// This assumes that all array refs are "lowered" to one of these forms:
//	%x = load (subarray*) ptr, constant	; single constant offset
//	%x = load (subarray*) ptr, offsetVal	; single non-constant offset
// Generally, this should happen via strength reduction + LICM.
// Also, strength reduction should take care of using the same register for
// the loop index variable and an array index, when that is profitable.
//------------------------------------------------------------------------ 

static void
SetOperandsForMemInstr(vector<MachineInstr*>& mvec,
                       vector<MachineInstr*>::iterator mvecI,
                       const InstructionNode* vmInstrNode,
                       const TargetMachine& target)
{
  MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
  
  // Variables to hold the index vector and ptr value.
  // The major work here is to extract these for all 3 instruction types
  // and to try to fold chains of constant indices into a single offset.
  // After that, we call SetMemOperands_Internal(), which creates the
  // appropriate operands for the machine instruction.
  vector<Value*> idxVec;
  bool allConstantIndices = true;
  Value* ptrVal = memInst->getPointerOperand();

  // If there is a GetElemPtr instruction to fold in to this instr,
  // it must be in the left child for Load and GetElemPtr, and in the
  // right child for Store instructions.
  InstrTreeNode* ptrChild = (vmInstrNode->getOpLabel() == Instruction::Store
                             ? vmInstrNode->rightChild()
                             : vmInstrNode->leftChild()); 

  // Check if all indices are constant for this instruction
  for (MemAccessInst::op_iterator OI=memInst->idx_begin(),OE=memInst->idx_end();
       allConstantIndices && OI != OE; ++OI)
    if (! isa<Constant>(*OI))
      allConstantIndices = false; 

  // If we have only constant indices, fold chains of constant indices
  // in this and any preceding GetElemPtr instructions.
  if (allConstantIndices &&
      (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
       ptrChild->getOpLabel() == GetElemPtrIdx))
    if (Value* newPtr = FoldGetElemChain((InstructionNode*) ptrChild, idxVec))
      ptrVal = newPtr;

  // Append the index vector of the current instruction, if any.
  // Discard any leading [0] index.
  if (memInst->getNumIndices() > 0)
    idxVec.insert(idxVec.end(),
                  memInst->idx_begin() + IsZero(*memInst->idx_begin()),
                  memInst->idx_end());

  // Now create the appropriate operands for the machine instruction
  SetMemOperands_Internal(mvec, mvecI, vmInstrNode,
                          ptrVal, idxVec, allConstantIndices, target);
}


// Generate the correct operands (and additional instructions if needed)
// for the given pointer and given index vector.
//
static void
SetMemOperands_Internal(vector<MachineInstr*>& mvec,
                        vector<MachineInstr*>::iterator mvecI,
                        const InstructionNode* vmInstrNode,
                        Value* ptrVal,
                        vector<Value*>& idxVec,
                        bool allConstantIndices,
                        const TargetMachine& target)
{
  MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
  
  // Initialize so we default to storing the offset in a register.
  int64_t smallConstOffset = 0;
  Value* valueForRegOffset = NULL;
  MachineOperand::MachineOperandType offsetOpType =
    MachineOperand::MO_VirtualRegister;

  // Check if there is an index vector and if so, compute the
  // right offset for structures and for arrays 
  // 
  if (idxVec.size() > 0)
    {
      const PointerType* ptrType = cast<PointerType>(ptrVal->getType());
      
      // If all indices are constant, compute the combined offset directly.
      if (allConstantIndices)
        {
          // Compute the offset value using the index vector. Create a
          // virtual reg. for it since it may not fit in the immed field.
          uint64_t offset = target.DataLayout.getIndexedOffset(ptrType,idxVec);
          valueForRegOffset = ConstantSInt::get(Type::LongTy, offset);
        }
      else
        {
          // There is at least one non-constant offset.  Therefore, this must
          // be an array ref, and must have been lowered to a single non-zero
          // offset.  (An extra leading zero offset, if any, can be ignored.)
          // Generate code sequence to compute address from index.
          // 
          assert(idxVec.size() == 1U + IsZero(idxVec[0])
                 && "Array refs must be lowered before Instruction Selection");

          Value* idxVal = idxVec[IsZero(idxVec[0])];

          vector<MachineInstr*> mulVec;
          Instruction* addr = new TmpInstruction(Type::UIntTy, memInst);
          MachineCodeForInstruction::get(memInst).addTemp(addr);

          // The call to getTypeSize() will fail if size is not constant.
          unsigned int eltSize =
            target.DataLayout.getTypeSize(ptrType->getElementType());
          assert(eltSize > 0 && "Invalid or non-const array element size");
          ConstantUInt* eltVal = ConstantUInt::get(Type::UIntTy, eltSize);

          // CreateMulInstruction() folds constants intelligently enough.
          CreateMulInstruction(target,
                               memInst->getParent()->getParent(),
                               idxVal,         /* lval, not likely const */
                               eltVal,         /* rval, likely constant */
                               addr,           /* result*/
                               mulVec,
                               MachineCodeForInstruction::get(memInst),
                               INVALID_MACHINE_OPCODE);

          // Insert mulVec[] before *mvecI in mvec[] and update mvecI
          // to point to the same instruction it pointed to before.
          assert(mulVec.size() > 0 && "No multiply code created?");
          vector<MachineInstr*>::iterator oldMvecI = mvecI;
          for (unsigned i=0, N=mulVec.size(); i < N; ++i)
            mvecI = mvec.insert(mvecI, mulVec[i]) + 1;  // pts to mem instr

          valueForRegOffset = addr;
        }
    }
  else
    {
      offsetOpType = MachineOperand::MO_SignExtendedImmed;
      smallConstOffset = 0;
    }

  // For STORE:
  //   Operand 0 is value, operand 1 is ptr, operand 2 is offset
  // For LOAD or GET_ELEMENT_PTR,
  //   Operand 0 is ptr, operand 1 is offset, operand 2 is result.
  // 
  unsigned offsetOpNum, ptrOpNum;
  if (memInst->getOpcode() == Instruction::Store)
    {
      (*mvecI)->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
                                     vmInstrNode->leftChild()->getValue());
      ptrOpNum = 1;
      offsetOpNum = 2;
    }
  else
    {
      ptrOpNum = 0;
      offsetOpNum = 1;
      (*mvecI)->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
                                     memInst);
    }
  
  (*mvecI)->SetMachineOperandVal(ptrOpNum, MachineOperand::MO_VirtualRegister,
                                 ptrVal);
  
  if (offsetOpType == MachineOperand::MO_VirtualRegister)
    {
      assert(valueForRegOffset != NULL);
      (*mvecI)->SetMachineOperandVal(offsetOpNum, offsetOpType,
                                     valueForRegOffset); 
    }
  else
    (*mvecI)->SetMachineOperandConst(offsetOpNum, offsetOpType,
                                     smallConstOffset);
}


// 
// Substitute operand `operandNum' of the instruction in node `treeNode'
// in place of the use(s) of that instruction in node `parent'.
// Check both explicit and implicit operands!
// Also make sure to skip over a parent who:
// (1) is a list node in the Burg tree, or
// (2) itself had its results forwarded to its parent
// 
static void
ForwardOperand(InstructionNode* treeNode,
               InstrTreeNode*   parent,
               int operandNum)
{
  assert(treeNode && parent && "Invalid invocation of ForwardOperand");
  
  Instruction* unusedOp = treeNode->getInstruction();
  Value* fwdOp = unusedOp->getOperand(operandNum);

  // The parent itself may be a list node, so find the real parent instruction
  while (parent->getNodeType() != InstrTreeNode::NTInstructionNode)
    {
      parent = parent->parent();
      assert(parent && "ERROR: Non-instruction node has no parent in tree.");
    }
  InstructionNode* parentInstrNode = (InstructionNode*) parent;
  
  Instruction* userInstr = parentInstrNode->getInstruction();
  MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(userInstr);

  // The parent's mvec would be empty if it was itself forwarded.
  // Recursively call ForwardOperand in that case...
  //
  if (mvec.size() == 0)
    {
      assert(parent->parent() != NULL &&
             "Parent could not have been forwarded, yet has no instructions?");
      ForwardOperand(treeNode, parent->parent(), operandNum);
    }
  else
    {
      for (unsigned i=0, N=mvec.size(); i < N; i++)
        {
          MachineInstr* minstr = mvec[i];
          for (unsigned i=0, numOps=minstr->getNumOperands(); i < numOps; ++i)
            {
              const MachineOperand& mop = minstr->getOperand(i);
              if (mop.getOperandType() == MachineOperand::MO_VirtualRegister &&
                  mop.getVRegValue() == unusedOp)
                minstr->SetMachineOperandVal(i,
                                MachineOperand::MO_VirtualRegister, fwdOp);
            }
          
          for (unsigned i=0,numOps=minstr->getNumImplicitRefs(); i<numOps; ++i)
            if (minstr->getImplicitRef(i) == unusedOp)
              minstr->setImplicitRef(i, fwdOp,
                                     minstr->implicitRefIsDefined(i),
                                     minstr->implicitRefIsDefinedAndUsed(i));
        }
    }
}


inline bool
AllUsesAreBranches(const Instruction* setccI)
{
  for (Value::use_const_iterator UI=setccI->use_begin(), UE=setccI->use_end();
       UI != UE; ++UI)
    if (! isa<TmpInstruction>(*UI)     // ignore tmp instructions here
        && cast<Instruction>(*UI)->getOpcode() != Instruction::Br)
      return false;
  return true;
}

//******************* Externally Visible Functions *************************/

//------------------------------------------------------------------------ 
// External Function: ThisIsAChainRule
//
// Purpose:
//   Check if a given BURG rule is a chain rule.
//------------------------------------------------------------------------ 

extern bool
ThisIsAChainRule(int eruleno)
{
  switch(eruleno)
    {
    case 111:	// stmt:  reg
    case 113:	// stmt:  bool
    case 123:
    case 124:
    case 125:
    case 126:
    case 127:
    case 128:
    case 129:
    case 130:
    case 131:
    case 132:
    case 133:
    case 155:
    case 221:
    case 222:
    case 241:
    case 242:
    case 243:
    case 244:
    case 321:
      return true; break;
      
    default:
      return false; break;
    }
}


//------------------------------------------------------------------------ 
// External Function: GetInstructionsByRule
//
// Purpose:
//   Choose machine instructions for the SPARC according to the
//   patterns chosen by the BURG-generated parser.
//------------------------------------------------------------------------ 

void
GetInstructionsByRule(InstructionNode* subtreeRoot,
                      int ruleForNode,
                      short* nts,
                      TargetMachine &target,
                      vector<MachineInstr*>& mvec)
{
  bool checkCast = false;		// initialize here to use fall-through
  int nextRule;
  int forwardOperandNum = -1;
  unsigned int allocaSize = 0;
  MachineInstr* M, *M2;
  unsigned int L;

  mvec.clear(); 
  
  // If the code for this instruction was folded into the parent (user),
  // then do nothing!
  if (subtreeRoot->isFoldedIntoParent())
    return;
  
  // 
  // Let's check for chain rules outside the switch so that we don't have
  // to duplicate the list of chain rule production numbers here again
  // 
  if (ThisIsAChainRule(ruleForNode))
    {
      // Chain rules have a single nonterminal on the RHS.
      // Get the rule that matches the RHS non-terminal and use that instead.
      // 
      assert(nts[0] && ! nts[1]
             && "A chain rule should have only one RHS non-terminal!");
      nextRule = burm_rule(subtreeRoot->state, nts[0]);
      nts = burm_nts[nextRule];
      GetInstructionsByRule(subtreeRoot, nextRule, nts, target, mvec);
    }
  else
    {
      switch(ruleForNode) {
      case 1:	// stmt:   Ret
      case 2:	// stmt:   RetValue(reg)
      {         // NOTE: Prepass of register allocation is responsible
                //	 for moving return value to appropriate register.
                // Mark the return-address register as a hidden virtual reg.
                // Mark the return value   register as an implicit ref of
                // the machine instruction.
         	// Finally put a NOP in the delay slot.
        ReturnInst *returnInstr =
          cast<ReturnInst>(subtreeRoot->getInstruction());
        assert(returnInstr->getOpcode() == Instruction::Ret);
        
        Instruction* returnReg = new TmpInstruction(returnInstr);
        MachineCodeForInstruction::get(returnInstr).addTemp(returnReg);
        
        M = new MachineInstr(JMPLRET);
        M->SetMachineOperandReg(0, MachineOperand::MO_VirtualRegister,
                                      returnReg);
        M->SetMachineOperandConst(1,MachineOperand::MO_SignExtendedImmed,
                                   (int64_t)8);
        M->SetMachineOperandReg(2, target.getRegInfo().getZeroRegNum());
        
        if (returnInstr->getReturnValue() != NULL)
          M->addImplicitRef(returnInstr->getReturnValue());
        
        mvec.push_back(M);
        mvec.push_back(new MachineInstr(NOP));
        
        break;
      }  
        
      case 3:	// stmt:   Store(reg,reg)
      case 4:	// stmt:   Store(reg,ptrreg)
        mvec.push_back(new MachineInstr(
                         ChooseStoreInstruction(
                            subtreeRoot->leftChild()->getValue()->getType())));
        SetOperandsForMemInstr(mvec, mvec.end()-1, subtreeRoot, target);
        break;

      case 5:	// stmt:   BrUncond
        M = new MachineInstr(BA);
        M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp,
             cast<BranchInst>(subtreeRoot->getInstruction())->getSuccessor(0));
        mvec.push_back(M);
        
        // delay slot
        mvec.push_back(new MachineInstr(NOP));
        break;

      case 206:	// stmt:   BrCond(setCCconst)
      { // setCCconst => boolean was computed with `%b = setCC type reg1 const'
        // If the constant is ZERO, we can use the branch-on-integer-register
        // instructions and avoid the SUBcc instruction entirely.
        // Otherwise this is just the same as case 5, so just fall through.
        // 
        InstrTreeNode* constNode = subtreeRoot->leftChild()->rightChild();
        assert(constNode &&
               constNode->getNodeType() ==InstrTreeNode::NTConstNode);
        Constant *constVal = cast<Constant>(constNode->getValue());
        bool isValidConst;
        
        if ((constVal->getType()->isIntegral()
             || isa<PointerType>(constVal->getType()))
            && GetConstantValueAsSignedInt(constVal, isValidConst) == 0
            && isValidConst)
          {
            // That constant is a zero after all...
            // Use the left child of setCC as the first argument!
            // Mark the setCC node so that no code is generated for it.
            InstructionNode* setCCNode = (InstructionNode*)
                                         subtreeRoot->leftChild();
            assert(setCCNode->getOpLabel() == SetCCOp);
            setCCNode->markFoldedIntoParent();
            
            BranchInst* brInst=cast<BranchInst>(subtreeRoot->getInstruction());
            
            M = new MachineInstr(ChooseBprInstruction(subtreeRoot));
            M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
                                    setCCNode->leftChild()->getValue());
            M->SetMachineOperandVal(1, MachineOperand::MO_PCRelativeDisp,
                                    brInst->getSuccessor(0));
            mvec.push_back(M);
            
            // delay slot
            mvec.push_back(new MachineInstr(NOP));

            // false branch
            M = new MachineInstr(BA);
            M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp,
                                    brInst->getSuccessor(1));
            mvec.push_back(M);
            
            // delay slot
            mvec.push_back(new MachineInstr(NOP));
            
            break;
          }
        // ELSE FALL THROUGH
      }

      case 6:	// stmt:   BrCond(bool)
      { // bool => boolean was computed with some boolean operator
        // (SetCC, Not, ...).  We need to check whether the type was a FP,
        // signed int or unsigned int, and check the branching condition in
        // order to choose the branch to use.
        // If it is an integer CC, we also need to find the unique
        // TmpInstruction representing that CC.
        // 
        BranchInst* brInst = cast<BranchInst>(subtreeRoot->getInstruction());
        bool isFPBranch;
        M = new MachineInstr(ChooseBccInstruction(subtreeRoot, isFPBranch));
        
        Value* ccValue = GetTmpForCC(subtreeRoot->leftChild()->getValue(),
                                     brInst->getParent()->getParent(),
                                     isFPBranch? Type::FloatTy : Type::IntTy);
        
        M->SetMachineOperandVal(0, MachineOperand::MO_CCRegister, ccValue);
        M->SetMachineOperandVal(1, MachineOperand::MO_PCRelativeDisp,
                                   brInst->getSuccessor(0));
        mvec.push_back(M);
        
        // delay slot
        mvec.push_back(new MachineInstr(NOP));
        
        // false branch
        M = new MachineInstr(BA);
        M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp,
                                   brInst->getSuccessor(1));
        mvec.push_back(M);
        
        // delay slot
        mvec.push_back(new MachineInstr(NOP));
        break;
      }
        
      case 208:	// stmt:   BrCond(boolconst)
      {
        // boolconst => boolean is a constant; use BA to first or second label
        Constant* constVal = 
          cast<Constant>(subtreeRoot->leftChild()->getValue());
        unsigned dest = cast<ConstantBool>(constVal)->getValue()? 0 : 1;
        
        M = new MachineInstr(BA);
        M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp,
          cast<BranchInst>(subtreeRoot->getInstruction())->getSuccessor(dest));
        mvec.push_back(M);
        
        // delay slot
        mvec.push_back(new MachineInstr(NOP));
        break;
      }
        
      case   8:	// stmt:   BrCond(boolreg)
      { // boolreg   => boolean is stored in an existing register.
        // Just use the branch-on-integer-register instruction!
        // 
        M = new MachineInstr(BRNZ);
        M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
                                      subtreeRoot->leftChild()->getValue());
        M->SetMachineOperandVal(1, MachineOperand::MO_PCRelativeDisp,
              cast<BranchInst>(subtreeRoot->getInstruction())->getSuccessor(0));
        mvec.push_back(M);

        // delay slot
        mvec.push_back(new MachineInstr(NOP));

        // false branch
        M = new MachineInstr(BA);
        M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp,
              cast<BranchInst>(subtreeRoot->getInstruction())->getSuccessor(1));
        mvec.push_back(M);
        
        // delay slot
        mvec.push_back(new MachineInstr(NOP));
        break;
      }  
      
      case 9:	// stmt:   Switch(reg)
        assert(0 && "*** SWITCH instruction is not implemented yet.");
        break;

      case 10:	// reg:   VRegList(reg, reg)
        assert(0 && "VRegList should never be the topmost non-chain rule");
        break;

      case 21:	// bool:  Not(bool):	Both these are implemented as:
      case 421:	// reg:   BNot(reg) :	     reg = reg XOR-NOT 0
        M = new MachineInstr(XNOR);
        M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
                                subtreeRoot->leftChild()->getValue());
        M->SetMachineOperandReg(1, target.getRegInfo().getZeroRegNum());
        M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
                                subtreeRoot->getValue());
        mvec.push_back(M);
        break;

      case 322:	// reg:   ToBoolTy(bool):
      case 22:	// reg:   ToBoolTy(reg):
      {
        const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
        assert(opType->isIntegral() || isa<PointerType>(opType)
               || opType == Type::BoolTy);
        forwardOperandNum = 0;          // forward first operand to user
        break;
      }
      
      case 23:	// reg:   ToUByteTy(reg)
      case 25:	// reg:   ToUShortTy(reg)
      case 27:	// reg:   ToUIntTy(reg)
      case 29:	// reg:   ToULongTy(reg)
      {
        Instruction* destI =  subtreeRoot->getInstruction();
        Value* opVal = subtreeRoot->leftChild()->getValue();
        const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
        if (opType->isIntegral()
            || isa<PointerType>(opType)
            || opType == Type::BoolTy)
          {
            unsigned opSize = target.DataLayout.getTypeSize(opType);
            unsigned destSize = target.DataLayout.getTypeSize(destI->getType());
            if (opSize > destSize ||
                (opType->isSigned()
                 && destSize < target.DataLayout.getIntegerRegize()))
              { // operand is larger than dest,
                //    OR both are equal but smaller than the full register size
                //       AND operand is signed, so it may have extra sign bits:
                // mask high bits using AND
                M = Create3OperandInstr(AND, opVal,
                                        ConstantUInt::get(Type::ULongTy,
                                              ((uint64_t) 1 << 8*destSize) - 1),
                                        destI);
                mvec.push_back(M);
              }
            else
              forwardOperandNum = 0;          // forward first operand to user
          }
        else if (opType->isFloatingPoint())
          CreateCodeToConvertIntToFloat(target, opVal, destI, mvec,
                                        MachineCodeForInstruction::get(destI));
        else
          assert(0 && "Unrecognized operand type for convert-to-unsigned");

        break;
      }
      
      case 24:	// reg:   ToSByteTy(reg)
      case 26:	// reg:   ToShortTy(reg)
      case 28:	// reg:   ToIntTy(reg)
      case 30:	// reg:   ToLongTy(reg)
      {
        Instruction* destI =  subtreeRoot->getInstruction();
        Value* opVal = subtreeRoot->leftChild()->getValue();
        MachineCodeForInstruction& mcfi =MachineCodeForInstruction::get(destI);

        const Type* opType = opVal->getType();
        if (opType->isIntegral()
            || isa<PointerType>(opType)
            || opType == Type::BoolTy)
          {
            // These operand types have the same format as the destination,
            // but may have different size: add sign bits or mask as needed.
            // 
            const Type* destType = destI->getType();
            unsigned opSize = target.DataLayout.getTypeSize(opType);
            unsigned destSize = target.DataLayout.getTypeSize(destType);
            if (opSize < destSize && !opType->isSigned())
              { // operand is unsigned and smaller than dest: sign-extend
                target.getInstrInfo().CreateSignExtensionInstructions(target, destI->getParent()->getParent(), opVal, 8*opSize, destI, mvec, mcfi);
              }
            else if (opSize > destSize)
              { // operand is larger than dest: mask high bits using AND
                // and then sign-extend using SRA by 0!
                // 
                TmpInstruction *tmpI = new TmpInstruction(destType, opVal,
                                                          destI, "maskHi");
                mcfi.addTemp(tmpI);
                M = Create3OperandInstr(AND, opVal,
                                        ConstantUInt::get(Type::UIntTy,
                                              ((uint64_t) 1 << 8*destSize)-1),
                                        tmpI);
                mvec.push_back(M);
                
                target.getInstrInfo().CreateSignExtensionInstructions(target, destI->getParent()->getParent(), tmpI, 8*destSize, destI, mvec, mcfi);
              }
            else
              forwardOperandNum = 0;          // forward first operand to user
          }
        else if (opType->isFloatingPoint())
          CreateCodeToConvertIntToFloat(target, opVal, destI, mvec, mcfi);
        else
          assert(0 && "Unrecognized operand type for convert-to-signed");

        break;
      }  
      
      case  31:	// reg:   ToFloatTy(reg):
      case  32:	// reg:   ToDoubleTy(reg):
      case 232:	// reg:   ToDoubleTy(Constant):
        
        // If this instruction has a parent (a user) in the tree 
        // and the user is translated as an FsMULd instruction,
        // then the cast is unnecessary.  So check that first.
        // In the future, we'll want to do the same for the FdMULq instruction,
        // so do the check here instead of only for ToFloatTy(reg).
        // 
        if (subtreeRoot->parent() != NULL &&
            MachineCodeForInstruction::get(((InstructionNode*)subtreeRoot->parent())->getInstruction())[0]->getOpCode() == FSMULD)
          {
            forwardOperandNum = 0;          // forward first operand to user
          }
        else
          {
            Value* leftVal = subtreeRoot->leftChild()->getValue();
            const Type* opType = leftVal->getType();
            MachineOpCode opCode=ChooseConvertToFloatInstr(
                                       subtreeRoot->getOpLabel(), opType);
            if (opCode == INVALID_OPCODE)	// no conversion needed
              {
                forwardOperandNum = 0;      // forward first operand to user
              }
            else
              {
                // If the source operand is a non-FP type it must be
                // first copied from int to float register via memory!
                Instruction *dest = subtreeRoot->getInstruction();
                Value* srcForCast;
                int n = 0;
                if (! opType->isFloatingPoint())
                  {
                    // Create a temporary to represent the FP register
                    // into which the integer will be copied via memory.
                    // The type of this temporary will determine the FP
                    // register used: single-prec for a 32-bit int or smaller,
                    // double-prec for a 64-bit int.
                    // 
                    const Type* srcTypeToUse =
                      (leftVal->getType() == Type::LongTy)? Type::DoubleTy
                                                          : Type::FloatTy;
                    
                    srcForCast = new TmpInstruction(srcTypeToUse, dest);
                    MachineCodeForInstruction &destMCFI = 
                      MachineCodeForInstruction::get(dest);
                    destMCFI.addTemp(srcForCast);
                    
                    target.getInstrInfo().CreateCodeToCopyIntToFloat(target,
                         dest->getParent()->getParent(),
                         leftVal, (TmpInstruction*) srcForCast,
                         mvec, destMCFI);
                  }
                else
                  srcForCast = leftVal;
                
                M = new MachineInstr(opCode);
                M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
                                           srcForCast);
                M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
                                           dest);
                mvec.push_back(M);
              }
          }
        break;

      case 19:	// reg:   ToArrayTy(reg):
      case 20:	// reg:   ToPointerTy(reg):
        forwardOperandNum = 0;          // forward first operand to user
        break;

      case 233:	// reg:   Add(reg, Constant)
        M = CreateAddConstInstruction(subtreeRoot);
        if (M != NULL)
          {
            mvec.push_back(M);
            break;
          }
        // ELSE FALL THROUGH
        
      case 33:	// reg:   Add(reg, reg)
        mvec.push_back(new MachineInstr(ChooseAddInstruction(subtreeRoot)));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;

      case 234:	// reg:   Sub(reg, Constant)
        M = CreateSubConstInstruction(subtreeRoot);
        if (M != NULL)
          {
            mvec.push_back(M);
            break;
          }
        // ELSE FALL THROUGH
        
      case 34:	// reg:   Sub(reg, reg)
        mvec.push_back(new MachineInstr(ChooseSubInstructionByType(
                                   subtreeRoot->getInstruction()->getType())));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;

      case 135:	// reg:   Mul(todouble, todouble)
        checkCast = true;
        // FALL THROUGH 

      case 35:	// reg:   Mul(reg, reg)
      {
        MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
                                 ? FSMULD
                                 : INVALID_MACHINE_OPCODE);
        Instruction* mulInstr = subtreeRoot->getInstruction();
        CreateMulInstruction(target, mulInstr->getParent()->getParent(),
                             subtreeRoot->leftChild()->getValue(),
                             subtreeRoot->rightChild()->getValue(),
                             mulInstr, mvec,
                             MachineCodeForInstruction::get(mulInstr),forceOp);
        break;
      }
      case 335:	// reg:   Mul(todouble, todoubleConst)
        checkCast = true;
        // FALL THROUGH 

      case 235:	// reg:   Mul(reg, Constant)
      {
        MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
                                 ? FSMULD
                                 : INVALID_MACHINE_OPCODE);
        Instruction* mulInstr = subtreeRoot->getInstruction();
        CreateMulInstruction(target, mulInstr->getParent()->getParent(),
                             subtreeRoot->leftChild()->getValue(),
                             subtreeRoot->rightChild()->getValue(),
                             mulInstr, mvec,
                             MachineCodeForInstruction::get(mulInstr),
                             forceOp);
        break;
      }
      case 236:	// reg:   Div(reg, Constant)
        L = mvec.size();
        CreateDivConstInstruction(target, subtreeRoot, mvec);
        if (mvec.size() > L)
          break;
        // ELSE FALL THROUGH
      
      case 36:	// reg:   Div(reg, reg)
        mvec.push_back(new MachineInstr(ChooseDivInstruction(target, subtreeRoot)));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;

      case  37:	// reg:   Rem(reg, reg)
      case 237:	// reg:   Rem(reg, Constant)
      {
        Instruction* remInstr = subtreeRoot->getInstruction();
        
        TmpInstruction* quot = new TmpInstruction(
                                        subtreeRoot->leftChild()->getValue(),
                                        subtreeRoot->rightChild()->getValue());
        TmpInstruction* prod = new TmpInstruction(
                                        quot,
                                        subtreeRoot->rightChild()->getValue());
        MachineCodeForInstruction::get(remInstr).addTemp(quot).addTemp(prod); 
        
        M = new MachineInstr(ChooseDivInstruction(target, subtreeRoot));
        Set3OperandsFromInstr(M, subtreeRoot, target);
        M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,quot);
        mvec.push_back(M);
        
        M = new MachineInstr(ChooseMulInstructionByType(
                                   subtreeRoot->getInstruction()->getType()));
        M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,quot);
        M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
                                      subtreeRoot->rightChild()->getValue());
        M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,prod);
        mvec.push_back(M);
        
        M = new MachineInstr(ChooseSubInstructionByType(
                                   subtreeRoot->getInstruction()->getType()));
        Set3OperandsFromInstr(M, subtreeRoot, target);
        M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,prod);
        mvec.push_back(M);
        
        break;
      }
      
      case  38:	// bool:   And(bool, bool)
      case 238:	// bool:   And(bool, boolconst)
      case 338:	// reg :   BAnd(reg, reg)
      case 538:	// reg :   BAnd(reg, Constant)
        mvec.push_back(new MachineInstr(AND));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;

      case 138:	// bool:   And(bool, not)
      case 438:	// bool:   BAnd(bool, not)
        mvec.push_back(new MachineInstr(ANDN));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;

      case  39:	// bool:   Or(bool, bool)
      case 239:	// bool:   Or(bool, boolconst)
      case 339:	// reg :   BOr(reg, reg)
      case 539:	// reg :   BOr(reg, Constant)
        mvec.push_back(new MachineInstr(OR));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;

      case 139:	// bool:   Or(bool, not)
      case 439:	// bool:   BOr(bool, not)
        mvec.push_back(new MachineInstr(ORN));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;

      case  40:	// bool:   Xor(bool, bool)
      case 240:	// bool:   Xor(bool, boolconst)
      case 340:	// reg :   BXor(reg, reg)
      case 540:	// reg :   BXor(reg, Constant)
        mvec.push_back(new MachineInstr(XOR));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;

      case 140:	// bool:   Xor(bool, not)
      case 440:	// bool:   BXor(bool, not)
        mvec.push_back(new MachineInstr(XNOR));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;

      case 41:	// boolconst:   SetCC(reg, Constant)
        // 
        // If the SetCC was folded into the user (parent), it will be
        // caught above.  All other cases are the same as case 42,
        // so just fall through.
        // 
      case 42:	// bool:   SetCC(reg, reg):
      {
        // This generates a SUBCC instruction, putting the difference in
        // a result register, and setting a condition code.
        // 
        // If the boolean result of the SetCC is used by anything other
        // than a branch instruction, or if it is used outside the current
        // basic block, the boolean must be
        // computed and stored in the result register.  Otherwise, discard
        // the difference (by using %g0) and keep only the condition code.
        // 
        // To compute the boolean result in a register we use a conditional
        // move, unless the result of the SUBCC instruction can be used as
        // the bool!  This assumes that zero is FALSE and any non-zero
        // integer is TRUE.
        // 
        InstructionNode* parentNode = (InstructionNode*) subtreeRoot->parent();
        Instruction* setCCInstr = subtreeRoot->getInstruction();
        
        bool keepBoolVal = parentNode == NULL ||
                           ! AllUsesAreBranches(setCCInstr);
        bool subValIsBoolVal = setCCInstr->getOpcode() == Instruction::SetNE;
        bool keepSubVal = keepBoolVal && subValIsBoolVal;
        bool computeBoolVal = keepBoolVal && ! subValIsBoolVal;
        
        bool mustClearReg;
        int valueToMove;
        MachineOpCode movOpCode = 0;
        
        // Mark the 4th operand as being a CC register, and as a def
        // A TmpInstruction is created to represent the CC "result".
        // Unlike other instances of TmpInstruction, this one is used
        // by machine code of multiple LLVM instructions, viz.,
        // the SetCC and the branch.  Make sure to get the same one!
        // Note that we do this even for FP CC registers even though they
        // are explicit operands, because the type of the operand
        // needs to be a floating point condition code, not an integer
        // condition code.  Think of this as casting the bool result to
        // a FP condition code register.
        // 
        Value* leftVal = subtreeRoot->leftChild()->getValue();
        bool isFPCompare = leftVal->getType()->isFloatingPoint();
        
        TmpInstruction* tmpForCC = GetTmpForCC(setCCInstr,
                                     setCCInstr->getParent()->getParent(),
                                     isFPCompare ? Type::FloatTy : Type::IntTy);
        MachineCodeForInstruction::get(setCCInstr).addTemp(tmpForCC);
        
        if (! isFPCompare)
          {
            // Integer condition: dest. should be %g0 or an integer register.
            // If result must be saved but condition is not SetEQ then we need
            // a separate instruction to compute the bool result, so discard
            // result of SUBcc instruction anyway.
            // 
            M = new MachineInstr(SUBcc);
            Set3OperandsFromInstr(M, subtreeRoot, target, ! keepSubVal);
            M->SetMachineOperandVal(3, MachineOperand::MO_CCRegister,
                                    tmpForCC, /*def*/true);
            mvec.push_back(M);
            
            if (computeBoolVal)
              { // recompute bool using the integer condition codes
                movOpCode =
                  ChooseMovpccAfterSub(subtreeRoot,mustClearReg,valueToMove);
              }
          }
        else
          {
            // FP condition: dest of FCMP should be some FCCn register
            M = new MachineInstr(ChooseFcmpInstruction(subtreeRoot));
            M->SetMachineOperandVal(0, MachineOperand::MO_CCRegister,
                                          tmpForCC);
            M->SetMachineOperandVal(1,MachineOperand::MO_VirtualRegister,
                                         subtreeRoot->leftChild()->getValue());
            M->SetMachineOperandVal(2,MachineOperand::MO_VirtualRegister,
                                        subtreeRoot->rightChild()->getValue());
            mvec.push_back(M);
            
            if (computeBoolVal)
              {// recompute bool using the FP condition codes
                mustClearReg = true;
                valueToMove = 1;
                movOpCode = ChooseMovFpccInstruction(subtreeRoot);
              }
          }
        
        if (computeBoolVal)
          {
            if (mustClearReg)
              {// Unconditionally set register to 0
                M = new MachineInstr(SETHI);
                M->SetMachineOperandConst(0,MachineOperand::MO_UnextendedImmed,
                                          (int64_t)0);
                M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
                                        setCCInstr);
                mvec.push_back(M);
              }
            
            // Now conditionally move `valueToMove' (0 or 1) into the register
            // Mark the register as a use (as well as a def) because the old
            // value should be retained if the condition is false.
            M = new MachineInstr(movOpCode);
            M->SetMachineOperandVal(0, MachineOperand::MO_CCRegister,
                                    tmpForCC);
            M->SetMachineOperandConst(1, MachineOperand::MO_UnextendedImmed,
                                      valueToMove);
            M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
                                    setCCInstr, /*isDef*/ true,
                                    /*isDefAndUse*/ true);
            mvec.push_back(M);
          }
        break;
      }    

      case 43:	// boolreg: VReg
      case 44:	// boolreg: Constant
        break;

      case 51:	// reg:   Load(reg)
      case 52:	// reg:   Load(ptrreg)
      case 53:	// reg:   LoadIdx(reg,reg)
      case 54:	// reg:   LoadIdx(ptrreg,reg)
        mvec.push_back(new MachineInstr(ChooseLoadInstruction(
                                     subtreeRoot->getValue()->getType())));
        SetOperandsForMemInstr(mvec, mvec.end()-1, subtreeRoot, target);
        break;

      case 55:	// reg:   GetElemPtr(reg)
      case 56:	// reg:   GetElemPtrIdx(reg,reg)
        // If the GetElemPtr was folded into the user (parent), it will be
        // caught above.  For other cases, we have to compute the address.
        mvec.push_back(new MachineInstr(ADD));
        SetOperandsForMemInstr(mvec, mvec.end()-1, subtreeRoot, target);
        break;
        
      case 57:	// reg:  Alloca: Implement as 1 instruction:
      {         //	    add %fp, offsetFromFP -> result
        AllocationInst* instr =
          cast<AllocationInst>(subtreeRoot->getInstruction());
        unsigned int tsize =
          target.findOptimalStorageSize(instr->getAllocatedType());
        assert(tsize != 0);
        CreateCodeForFixedSizeAlloca(target, instr, tsize, 1, mvec);
        break;
      }
      
      case 58:	// reg:   Alloca(reg): Implement as 3 instructions:
                //	mul num, typeSz -> tmp
                //	sub %sp, tmp    -> %sp
      {         //	add %sp, frameSizeBelowDynamicArea -> result
        AllocationInst* instr =
          cast<AllocationInst>(subtreeRoot->getInstruction());
        const Type* eltType = instr->getAllocatedType();
        
        // If #elements is constant, use simpler code for fixed-size allocas
        int tsize = (int) target.findOptimalStorageSize(eltType);
        Value* numElementsVal = NULL;
        bool isArray = instr->isArrayAllocation();
        
        if (!isArray ||
            isa<Constant>(numElementsVal = instr->getArraySize()))
          { // total size is constant: generate code for fixed-size alloca
            unsigned int numElements = isArray? 
              cast<ConstantUInt>(numElementsVal)->getValue() : 1;
            CreateCodeForFixedSizeAlloca(target, instr, tsize,
                                         numElements, mvec);
          }
        else // total size is not constant.
          CreateCodeForVariableSizeAlloca(target, instr, tsize,
                                          numElementsVal, mvec);
        break;
      }
      
      case 61:	// reg:   Call
      {         // Generate a direct (CALL) or indirect (JMPL). depending
                // Mark the return-address register and the indirection
                // register (if any) as hidden virtual registers.
                // Also, mark the operands of the Call and return value (if
                // any) as implicit operands of the CALL machine instruction.
                // 
                // If this is a varargs function, floating point arguments
                // have to passed in integer registers so insert
                // copy-float-to-int instructions for each float operand.
                // 
        CallInst *callInstr = cast<CallInst>(subtreeRoot->getInstruction());
        Value *callee = callInstr->getCalledValue();
        
        // Create hidden virtual register for return address, with type void*. 
        TmpInstruction* retAddrReg =
          new TmpInstruction(PointerType::get(Type::VoidTy), callInstr);
        MachineCodeForInstruction::get(callInstr).addTemp(retAddrReg);
        
        // Generate the machine instruction and its operands.
        // Use CALL for direct function calls; this optimistically assumes
        // the PC-relative address fits in the CALL address field (22 bits).
        // Use JMPL for indirect calls.
        // 
        if (isa<Function>(callee))
          { // direct function call
            M = new MachineInstr(CALL);
            M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp,
                                    callee);
          } 
        else
          { // indirect function call
            M = new MachineInstr(JMPLCALL);
            M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
                                    callee);
            M->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,
                                      (int64_t) 0);
            M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
                                    retAddrReg);
          }
        
        mvec.push_back(M);

        const FunctionType* funcType =
          cast<FunctionType>(cast<PointerType>(callee->getType())
                             ->getElementType());
        bool isVarArgs = funcType->isVarArg();
        bool noPrototype = isVarArgs && funcType->getNumParams() == 0;
        
        // Use an annotation to pass information about call arguments
        // to the register allocator.
        CallArgsDescriptor* argDesc = new CallArgsDescriptor(callInstr,
                                         retAddrReg, isVarArgs, noPrototype);
        M->addAnnotation(argDesc);
        
        assert(callInstr->getOperand(0) == callee
               && "This is assumed in the loop below!");
        
        for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i)
          {
            Value* argVal = callInstr->getOperand(i);
            Instruction* intArgReg = NULL;
            
            // Check for FP arguments to varargs functions.
            // Any such argument in the first $K$ args must be passed in an
            // integer register, where K = #integer argument registers.
            if (isVarArgs && argVal->getType()->isFloatingPoint())
              {
                // If it is a function with no prototype, pass value
                // as an FP value as well as a varargs value
                if (noPrototype)
                  argDesc->getArgInfo(i-1).setUseFPArgReg();
                
                // If this arg. is in the first $K$ regs, add a copy
                // float-to-int instruction to pass the value as an integer.
                if (i < target.getRegInfo().GetNumOfIntArgRegs())
                  {
                    MachineCodeForInstruction &destMCFI = 
                      MachineCodeForInstruction::get(callInstr);   
                    intArgReg = new TmpInstruction(Type::IntTy, argVal);
                    destMCFI.addTemp(intArgReg);
                    
                    vector<MachineInstr*> copyMvec;
                    target.getInstrInfo().CreateCodeToCopyFloatToInt(target,
                                           callInstr->getParent()->getParent(),
                                           argVal, (TmpInstruction*) intArgReg,
                                           copyMvec, destMCFI);
                    mvec.insert(mvec.begin(),copyMvec.begin(),copyMvec.end());
                    
                    argDesc->getArgInfo(i-1).setUseIntArgReg();
                    argDesc->getArgInfo(i-1).setArgCopy(intArgReg);
                  }
                else
                  // Cannot fit in first $K$ regs so pass the arg on the stack
                  argDesc->getArgInfo(i-1).setUseStackSlot();
              }
            
            if (intArgReg)
              mvec.back()->addImplicitRef(intArgReg);
            
            mvec.back()->addImplicitRef(argVal);
          }
        
        // Add the return value as an implicit ref.  The call operands
        // were added above.
        if (callInstr->getType() != Type::VoidTy)
          mvec.back()->addImplicitRef(callInstr, /*isDef*/ true);
        
        // For the CALL instruction, the ret. addr. reg. is also implicit
        if (isa<Function>(callee))
          mvec.back()->addImplicitRef(retAddrReg, /*isDef*/ true);
        
        // delay slot
        mvec.push_back(new MachineInstr(NOP));
        break;
      }
      
      case 62:	// reg:   Shl(reg, reg)
      {
        Value* argVal1 = subtreeRoot->leftChild()->getValue();
        Value* argVal2 = subtreeRoot->rightChild()->getValue();
        Instruction* shlInstr = subtreeRoot->getInstruction();
        
        const Type* opType = argVal1->getType();
        assert(opType->isIntegral()
               || opType == Type::BoolTy
               || isa<PointerType>(opType)&&"Shl unsupported for other types");
        
        CreateShiftInstructions(target, shlInstr->getParent()->getParent(),
                                (opType == Type::LongTy)? SLLX : SLL,
                                argVal1, argVal2, 0, shlInstr, mvec,
                                MachineCodeForInstruction::get(shlInstr));
        break;
      }
      
      case 63:	// reg:   Shr(reg, reg)
      { const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
        assert(opType->isIntegral()
               || isa<PointerType>(opType)&&"Shr unsupported for other types");
        mvec.push_back(new MachineInstr((opType->isSigned()
                                   ? ((opType == Type::LongTy)? SRAX : SRA)
                                   : ((opType == Type::LongTy)? SRLX : SRL))));
        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
        break;
      }
      
      case 64:	// reg:   Phi(reg,reg)
        break;                          // don't forward the value

#undef NEED_PHI_MACHINE_INSTRS
#ifdef NEED_PHI_MACHINE_INSTRS
      {		// This instruction has variable #operands, so resultPos is 0.
        Instruction* phi = subtreeRoot->getInstruction();
        M = new MachineInstr(PHI, 1 + phi->getNumOperands());
        M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
                                      subtreeRoot->getValue());
        for (unsigned i=0, N=phi->getNumOperands(); i < N; i++)
          M->SetMachineOperandVal(i+1, MachineOperand::MO_VirtualRegister,
                                  phi->getOperand(i));
        mvec.push_back(M);
        break;
      }  
#endif // NEED_PHI_MACHINE_INSTRS
      
      
      case 71:	// reg:     VReg
      case 72:	// reg:     Constant
        break;                          // don't forward the value

      default:
        assert(0 && "Unrecognized BURG rule");
        break;
      }
    }
  
  if (forwardOperandNum >= 0)
    { // We did not generate a machine instruction but need to use operand.
      // If user is in the same tree, replace Value in its machine operand.
      // If not, insert a copy instruction which should get coalesced away
      // by register allocation.
      if (subtreeRoot->parent() != NULL)
        ForwardOperand(subtreeRoot, subtreeRoot->parent(), forwardOperandNum);
      else
        {
          vector<MachineInstr*> minstrVec;
          Instruction* instr = subtreeRoot->getInstruction();
          target.getInstrInfo().
            CreateCopyInstructionsByType(target,
                                         instr->getParent()->getParent(),
                                         instr->getOperand(forwardOperandNum),
                                         instr, minstrVec,
                                        MachineCodeForInstruction::get(instr));
          assert(minstrVec.size() > 0);
          mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
        }
    }
}
