1. Add a bottom-up pass on BURG trees that is used to fix constant operands.
authorVikram S. Adve <vadve@cs.uiuc.edu>
Wed, 17 Oct 2001 23:57:50 +0000 (23:57 +0000)
committerVikram S. Adve <vadve@cs.uiuc.edu>
Wed, 17 Oct 2001 23:57:50 +0000 (23:57 +0000)
   Needs to be bottom up because constant values may be forward-substituted
   to their uses (i.e., into the parent in the BURG tree).
2. Move most of the constant-fixup code into machine-indepedent file
   InstrSelectionSupport.cpp.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@859 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/InstrSelection/InstrSelection.cpp
lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp
lib/CodeGen/MachineInstr.cpp
lib/Target/SparcV9/InstrSelection/InstrSelection.cpp
lib/Target/SparcV9/InstrSelection/InstrSelectionSupport.cpp

index d52088c0eb6474c715144e323e16c0fac2c0f83d..df9098f21918322b23974d87a2810b22e12e782f 100644 (file)
@@ -15,6 +15,7 @@
 
 
 #include "llvm/CodeGen/InstrSelection.h"
+#include "llvm/CodeGen/InstrSelectionSupport.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Instruction.h"
@@ -22,7 +23,7 @@
 #include "llvm/Method.h"
 
 static bool SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
-                                     TargetMachine &Target);
+                                     TargetMachine &target);
 
 
 enum SelectDebugLevel_t {
@@ -48,7 +49,7 @@ cl::Enum<enum SelectDebugLevel_t> SelectDebugLevel("dselect", cl::NoFlags,
 //---------------------------------------------------------------------------
 
 bool
-SelectInstructionsForMethod(Method* method, TargetMachine &Target)
+SelectInstructionsForMethod(Method* method, TargetMachine &target)
 {
   bool failed = false;
   
@@ -86,7 +87,7 @@ SelectInstructionsForMethod(Method* method, TargetMachine &Target)
        }
       
       // Then recursively walk the tree to select instructions
-      if (SelectInstructionsForTree(basicNode, /*goalnt*/1, Target))
+      if (SelectInstructionsForTree(basicNode, /*goalnt*/1, target))
        {
          failed = true;
          break;
@@ -120,6 +121,35 @@ SelectInstructionsForMethod(Method* method, TargetMachine &Target)
 //*********************** Private Functions *****************************/
 
 
+//---------------------------------------------------------------------------
+// Function PostprocessMachineCodeForTree
+// 
+// Apply any final cleanups to machine code for the root of a subtree
+// after selection for all its children has been completed.
+//---------------------------------------------------------------------------
+
+void
+PostprocessMachineCodeForTree(InstructionNode* instrNode,
+                              int ruleForNode,
+                              short* nts,
+                              TargetMachine &target)
+{
+  // Fix up any constant operands in the machine instructions to either
+  // use an immediate field or to load the constant into a register
+  // Walk backwards and use direct indexes to allow insertion before current
+  // 
+  Instruction* vmInstr = instrNode->getInstruction();
+  MachineCodeForVMInstr& mvec = vmInstr->getMachineInstrVec();
+  for (int i = (int) mvec.size()-1; i >= 0; i--)
+    {
+      vector<MachineInstr*> loadConstVec =
+        FixConstantOperandsForInstr(vmInstr, mvec[i], target);
+      
+      if (loadConstVec.size() > 0)
+        mvec.insert(mvec.begin()+i, loadConstVec.begin(), loadConstVec.end());
+    }
+}
+
 //---------------------------------------------------------------------------
 // Function SelectInstructionsForTree 
 // 
@@ -138,7 +168,7 @@ SelectInstructionsForMethod(Method* method, TargetMachine &Target)
 
 bool
 SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
-                         TargetMachine &Target)
+                         TargetMachine &target)
 {
   // Use a static vector to avoid allocating a new one per VM instruction
   static MachineInstr* minstrVec[MAX_INSTR_PER_VMINSTR];
@@ -158,7 +188,6 @@ SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
   // 
   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.
@@ -168,7 +197,7 @@ SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
       InstructionNode* instrNode = (InstructionNode*)treeRoot;
       assert(instrNode->getNodeType() == InstrTreeNode::NTInstructionNode);
     
-      unsigned N = GetInstructionsByRule(instrNode, ruleForNode, nts, Target,
+      unsigned N = GetInstructionsByRule(instrNode, ruleForNode, nts, target,
                                         minstrVec);
       assert(N <= MAX_INSTR_PER_VMINSTR);
       for (unsigned i=0; i < N; i++)
@@ -206,12 +235,21 @@ SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
          if (nodeType == InstrTreeNode::NTVRegListNode ||
              nodeType == InstrTreeNode::NTInstructionNode)
            {
-             if (SelectInstructionsForTree(kids[i], nts[i], Target))
+             if (SelectInstructionsForTree(kids[i], nts[i], target))
                return true;                    // failure
            }
        }
     }
   
+  // Finally, do any postprocessing on this node after its children
+  // have been translated
+  // 
+  if (treeRoot->opLabel != VRegListOp)
+    {
+      InstructionNode* instrNode = (InstructionNode*)treeRoot;
+      PostprocessMachineCodeForTree(instrNode, ruleForNode, nts, target);
+    }
+  
   return false;                                // success
 }
 
index 685463c49fe1065e0637d981d95dd602bb56594a..7fe91643a2ffabd4d84167953389e654734bb588 100644 (file)
 
 //*************************** Local Functions ******************************/
 
-inline int64_t
-GetSignedIntConstantValue(Value* val, bool& isValidConstant)
+
+static TmpInstruction*
+InsertCodeToLoadConstant(Value* opValue,
+                         Instruction* vmInstr,
+                         vector<MachineInstr*>& loadConstVec,
+                         TargetMachine& target)
 {
-  int64_t intValue = 0;
-  isValidConstant = false;
+  vector<TmpInstruction*> tempVec;
   
-  if (val->getValueType() == Value::ConstantVal)
-    {
-      switch(val->getType()->getPrimitiveID())
-       {
-       case Type::BoolTyID:
-         intValue = ((ConstPoolBool*) val)->getValue()? 1 : 0;
-         isValidConstant = true;
-         break;
-       case Type::SByteTyID:
-       case Type::ShortTyID:
-       case Type::IntTyID:
-       case Type::LongTyID:
-         intValue = ((ConstPoolSInt*) val)->getValue();
-         isValidConstant = true;
-         break;
-       default:
-         break;
-       }
-    }
+  // Create a tmp virtual register to hold the constant.
+  TmpInstruction* tmpReg =
+    new TmpInstruction(TMP_INSTRUCTION_OPCODE, opValue, NULL);
+  vmInstr->getMachineInstrVec().addTempValue(tmpReg);
   
-  return intValue;
-}
-
-inline uint64_t
-GetUnsignedIntConstantValue(Value* val, bool& isValidConstant)
-{
-  uint64_t intValue = 0;
-  isValidConstant = false;
+  target.getInstrInfo().CreateCodeToLoadConst(opValue, tmpReg,
+                                              loadConstVec, tempVec);
   
-  if (val->getValueType() == Value::ConstantVal)
-    {
-      switch(val->getType()->getPrimitiveID())
-       {
-       case Type::BoolTyID:
-         intValue = ((ConstPoolBool*) val)->getValue()? 1 : 0;
-         isValidConstant = true;
-         break;
-       case Type::UByteTyID:
-       case Type::UShortTyID:
-       case Type::UIntTyID:
-       case Type::ULongTyID:
-         intValue = ((ConstPoolUInt*) val)->getValue();
-         isValidConstant = true;
-         break;
-       default:
-         break;
-       }
-    }
+  // Register the new tmp values created for this m/c instruction sequence
+  for (unsigned i=0; i < tempVec.size(); i++)
+    vmInstr->getMachineInstrVec().addTempValue(tempVec[i]);
+  
+  // Record the mapping from the tmp VM instruction to machine instruction.
+  // Do this for all machine instructions that were not mapped to any
+  // other temp values created by 
+  // tmpReg->addMachineInstruction(loadConstVec.back());
   
-  return intValue;
+  return tmpReg;
 }
 
 
-inline int64_t
-GetConstantValueAsSignedInt(Value* val, bool& isValidConstant)
+//---------------------------------------------------------------------------
+// Function GetConstantValueAsSignedInt
+// 
+// Convenience function to get the value of an integer constant, for an
+// appropriate integer or non-integer type that can be held in an integer.
+// The type of the argument must be the following:
+//      Signed or unsigned integer
+//      Boolean
+//      Pointer
+// 
+// isValidConstant is set to true if a valid constant was found.
+//---------------------------------------------------------------------------
+
+int64_t
+GetConstantValueAsSignedInt(const Value *V,
+                            bool &isValidConstant)
 {
-  int64_t intValue = 0;
-  
-  if (val->getType()->isSigned())
+  if (!isa<ConstPoolVal>(V))
     {
-      intValue = GetSignedIntConstantValue(val, isValidConstant);
+      isValidConstant = false;
+      return 0;
     }
-  else                         // non-numeric types will fall here
+  
+  isValidConstant = true;
+  
+  if (V->getType() == Type::BoolTy)
+    return (int64_t) ((ConstPoolBool*)V)->getValue();
+  
+  if (V->getType()->isIntegral())
     {
-      uint64_t uintValue = GetUnsignedIntConstantValue(val, isValidConstant);
-      if (isValidConstant && uintValue < INT64_MAX)    // safe to use signed
-       intValue = (int64_t) uintValue;
-      else 
-       isValidConstant = false;
+      if (V->getType()->isSigned())
+        return ((ConstPoolSInt*)V)->getValue();
+      
+      assert(V->getType()->isUnsigned());
+      uint64_t Val = ((ConstPoolUInt*)V)->getValue();
+      if (Val < INT64_MAX)     // then safe to cast to signed
+        return (int64_t)Val;
     }
-  
-  return intValue;
+
+  isValidConstant = false;
+  return 0;
 }
 
 
@@ -183,81 +176,6 @@ Set2OperandsFromInstr(MachineInstr* minstr,
                        /*op2Position*/ -1, resultPosition);
 }
 
-#undef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
-#ifdef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
-unsigned
-Set3OperandsFromInstrJUNK(MachineInstr* minstr,
-                         InstructionNode* vmInstrNode,
-                         const TargetMachine& target,
-                         bool canDiscardResult,
-                         int op1Position,
-                         int op2Position,
-                         int resultPosition)
-{
-  assert(op1Position >= 0);
-  assert(resultPosition >= 0);
-  
-  unsigned returnFlags = 0x0;
-  
-  // Check if operand 1 is 0.  If so, try to use a hardwired 0 register.
-  Value* op1Value = vmInstrNode->leftChild()->getValue();
-  bool isValidConstant;
-  int64_t intValue = GetConstantValueAsSignedInt(op1Value, isValidConstant);
-  if (isValidConstant && intValue == 0 && target.zeroRegNum >= 0)
-    minstr->SetMachineOperand(op1Position, /*regNum*/ target.zeroRegNum);
-  else
-    {
-      if (isa<ConstPoolVal>(op1Value))
-       {
-         // value is constant and must be loaded from constant pool
-         returnFlags = returnFlags | (1 << op1Position);
-       }
-      minstr->SetMachineOperand(op1Position, MachineOperand::MO_VirtualRegister,
-                               op1Value);
-    }
-  
-  // Check if operand 2 (if any) fits in the immed. field of the instruction,
-  // or if it is 0 and can use a dedicated machine register
-  if (op2Position >= 0)
-    {
-      Value* op2Value = vmInstrNode->rightChild()->getValue();
-      int64_t immedValue;
-      unsigned int machineRegNum;
-      
-      MachineOperand::MachineOperandType
-       op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(), target,
-                                  /*canUseImmed*/ true,
-                                  machineRegNum, immedValue);
-      
-      if (op2type == MachineOperand::MO_MachineRegister)
-       minstr->SetMachineOperand(op2Position, machineRegNum);
-      else if (op2type == MachineOperand::MO_VirtualRegister)
-       {
-         if (isa<ConstPoolVal>(op2Value))
-           {
-             // value is constant and must be loaded from constant pool
-             returnFlags = returnFlags | (1 << op2Position);
-           }
-         minstr->SetMachineOperand(op2Position, op2type, op2Value);
-       }
-      else
-       {
-         assert(op2type != MO_CCRegister);
-         minstr->SetMachineOperand(op2Position, op2type, immedValue);
-       }
-    }
-  
-  // If operand 3 (result) can be discarded, use a dead register if one exists
-  if (canDiscardResult && target.zeroRegNum >= 0)
-    minstr->SetMachineOperand(resultPosition, target.zeroRegNum);
-  else
-    minstr->SetMachineOperand(resultPosition,
-                  MachineOperand::MO_VirtualRegister, vmInstrNode->getValue());
-  
-  return returnFlags;
-}
-#endif
-
 
 void
 Set3OperandsFromInstr(MachineInstr* minstr,
@@ -355,3 +273,132 @@ ChooseRegOrImmed(Value* val,
   return opType;
 }
 
+
+//---------------------------------------------------------------------------
+// Function: FixConstantOperandsForInstr
+// 
+// Purpose:
+// Special handling for constant operands of a machine instruction
+// -- if the constant is 0, use the hardwired 0 register, if any;
+// -- if the constant fits in the IMMEDIATE field, use that field;
+// -- else create instructions to put the constant into a register, either
+//    directly or by loading explicitly from the constant pool.
+// 
+// In the first 2 cases, the operand of `minstr' is modified in place.
+// Returns a vector of machine instructions generated for operands that
+// fall under case 3; these must be inserted before `minstr'.
+//---------------------------------------------------------------------------
+
+vector<MachineInstr*>
+FixConstantOperandsForInstr(Instruction* vmInstr,
+                            MachineInstr* minstr,
+                            TargetMachine& target)
+{
+  vector<MachineInstr*> loadConstVec;
+  
+  const MachineInstrDescriptor& instrDesc =
+    target.getInstrInfo().getDescriptor(minstr->getOpCode());
+  
+  for (unsigned op=0; op < minstr->getNumOperands(); op++)
+    {
+      const MachineOperand& mop = minstr->getOperand(op);
+          
+      // skip the result position (for efficiency below) and any other
+      // positions already marked as not a virtual register
+      if (instrDesc.resultPos == (int) op || 
+          mop.getOperandType() != MachineOperand::MO_VirtualRegister ||
+          mop.getVRegValue() == NULL)
+        {
+          continue;
+        }
+          
+      Value* opValue = mop.getVRegValue();
+      bool constantThatMustBeLoaded = false;
+      
+      if (isa<ConstPoolVal>(opValue))
+        {
+          unsigned int machineRegNum;
+          int64_t immedValue;
+          MachineOperand::MachineOperandType opType =
+            ChooseRegOrImmed(opValue, minstr->getOpCode(), target,
+                             /*canUseImmed*/ (op == 1),
+                             machineRegNum, immedValue);
+              
+          if (opType == MachineOperand::MO_MachineRegister)
+            minstr->SetMachineOperand(op, machineRegNum);
+          else if (opType == MachineOperand::MO_VirtualRegister)
+            constantThatMustBeLoaded = true; // load is generated below
+          else
+            minstr->SetMachineOperand(op, opType, immedValue);
+        }
+
+      if (constantThatMustBeLoaded || isa<GlobalValue>(opValue))
+        { // opValue is a constant that must be explicitly loaded into a reg.
+          TmpInstruction* tmpReg = InsertCodeToLoadConstant(opValue, vmInstr,
+                                                        loadConstVec, target);
+          minstr->SetMachineOperand(op, MachineOperand::MO_VirtualRegister,
+                                        tmpReg);
+        }
+    }
+  
+  // 
+  // Also, check for implicit operands used (not those defined) by the
+  // machine instruction.  These include:
+  // -- arguments to a Call
+  // -- return value of a Return
+  // Any such operand that is a constant value needs to be fixed also.
+  // The current instructions with implicit refs (viz., Call and Return)
+  // have no immediate fields, so the constant always needs to be loaded
+  // into a register.
+  // 
+  for (unsigned i=0, N=minstr->getNumImplicitRefs(); i < N; ++i)
+    if (isa<ConstPoolVal>(minstr->getImplicitRef(i)) ||
+        isa<GlobalValue>(minstr->getImplicitRef(i)))
+      {
+        TmpInstruction* tmpReg =
+          InsertCodeToLoadConstant(minstr->getImplicitRef(i), vmInstr,
+                                   loadConstVec, target);
+        minstr->setImplicitRef(i, tmpReg);
+      }
+  
+  return loadConstVec;
+}
+
+
+#undef SAVE_TO_MOVE_BACK_TO_SPARCISSCPP
+#ifdef SAVE_TO_MOVE_BACK_TO_SPARCISSCPP
+unsigned
+FixConstantOperands(const InstructionNode* vmInstrNode,
+                    TargetMachine& target)
+{
+  Instruction* vmInstr = vmInstrNode->getInstruction();
+  MachineCodeForVMInstr& mvec = vmInstr->getMachineInstrVec();
+  
+  for (unsigned i=0; i < mvec.size(); i++)
+    {
+      vector<MachineInsr*> loadConstVec =
+        FixConstantOperandsForInstr(mvec[i], target);
+    }
+  
+  // 
+  // Finally, inserted the generated instructions in the vector
+  // to be returned.
+  // 
+  unsigned numNew = loadConstVec.size();
+  if (numNew > 0)
+    {
+      // Insert the new instructions *before* the old ones by moving
+      // the old ones over `numNew' positions (last-to-first, of course!).
+      // We do check *after* returning that we did not exceed the vector mvec.
+      for (int i=numInstr-1; i >= 0; i--)
+        mvec[i+numNew] = mvec[i];
+      
+      for (unsigned i=0; i < numNew; i++)
+        mvec[i] = loadConstVec[i];
+    }
+  
+  return (numInstr + numNew);
+}
+#endif SAVE_TO_MOVE_BACK_TO_SPARCISSCPP
+
+
index 8cbf55e840f3e9fc1814c9e589664ef784916c39..76fd4e7c8357b5a10a852e77dba0bc0cac4ef190 100644 (file)
@@ -98,9 +98,10 @@ operator<< (ostream& os, const MachineInstr& minstr)
       const Value* val = *vo;
       os << val << (vo.isDef()? "(def), " : ", ");
     }
-  os << endl;
 #endif
   
+  os << endl;
+  
   return os;
 }
 
@@ -170,7 +171,7 @@ PrintMachineInstructions(const Method *const method)
       
       MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
       for (unsigned i=0; i < mvec.size(); i++)
-       cout << "\t" << *mvec[i] << endl;
+       cout << "\t" << *mvec[i];
     } 
   cout << endl << "End method \"" << method->getName() << "\""
        << endl << endl;
index d52088c0eb6474c715144e323e16c0fac2c0f83d..df9098f21918322b23974d87a2810b22e12e782f 100644 (file)
@@ -15,6 +15,7 @@
 
 
 #include "llvm/CodeGen/InstrSelection.h"
+#include "llvm/CodeGen/InstrSelectionSupport.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Instruction.h"
@@ -22,7 +23,7 @@
 #include "llvm/Method.h"
 
 static bool SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
-                                     TargetMachine &Target);
+                                     TargetMachine &target);
 
 
 enum SelectDebugLevel_t {
@@ -48,7 +49,7 @@ cl::Enum<enum SelectDebugLevel_t> SelectDebugLevel("dselect", cl::NoFlags,
 //---------------------------------------------------------------------------
 
 bool
-SelectInstructionsForMethod(Method* method, TargetMachine &Target)
+SelectInstructionsForMethod(Method* method, TargetMachine &target)
 {
   bool failed = false;
   
@@ -86,7 +87,7 @@ SelectInstructionsForMethod(Method* method, TargetMachine &Target)
        }
       
       // Then recursively walk the tree to select instructions
-      if (SelectInstructionsForTree(basicNode, /*goalnt*/1, Target))
+      if (SelectInstructionsForTree(basicNode, /*goalnt*/1, target))
        {
          failed = true;
          break;
@@ -120,6 +121,35 @@ SelectInstructionsForMethod(Method* method, TargetMachine &Target)
 //*********************** Private Functions *****************************/
 
 
+//---------------------------------------------------------------------------
+// Function PostprocessMachineCodeForTree
+// 
+// Apply any final cleanups to machine code for the root of a subtree
+// after selection for all its children has been completed.
+//---------------------------------------------------------------------------
+
+void
+PostprocessMachineCodeForTree(InstructionNode* instrNode,
+                              int ruleForNode,
+                              short* nts,
+                              TargetMachine &target)
+{
+  // Fix up any constant operands in the machine instructions to either
+  // use an immediate field or to load the constant into a register
+  // Walk backwards and use direct indexes to allow insertion before current
+  // 
+  Instruction* vmInstr = instrNode->getInstruction();
+  MachineCodeForVMInstr& mvec = vmInstr->getMachineInstrVec();
+  for (int i = (int) mvec.size()-1; i >= 0; i--)
+    {
+      vector<MachineInstr*> loadConstVec =
+        FixConstantOperandsForInstr(vmInstr, mvec[i], target);
+      
+      if (loadConstVec.size() > 0)
+        mvec.insert(mvec.begin()+i, loadConstVec.begin(), loadConstVec.end());
+    }
+}
+
 //---------------------------------------------------------------------------
 // Function SelectInstructionsForTree 
 // 
@@ -138,7 +168,7 @@ SelectInstructionsForMethod(Method* method, TargetMachine &Target)
 
 bool
 SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
-                         TargetMachine &Target)
+                         TargetMachine &target)
 {
   // Use a static vector to avoid allocating a new one per VM instruction
   static MachineInstr* minstrVec[MAX_INSTR_PER_VMINSTR];
@@ -158,7 +188,6 @@ SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
   // 
   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.
@@ -168,7 +197,7 @@ SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
       InstructionNode* instrNode = (InstructionNode*)treeRoot;
       assert(instrNode->getNodeType() == InstrTreeNode::NTInstructionNode);
     
-      unsigned N = GetInstructionsByRule(instrNode, ruleForNode, nts, Target,
+      unsigned N = GetInstructionsByRule(instrNode, ruleForNode, nts, target,
                                         minstrVec);
       assert(N <= MAX_INSTR_PER_VMINSTR);
       for (unsigned i=0; i < N; i++)
@@ -206,12 +235,21 @@ SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt,
          if (nodeType == InstrTreeNode::NTVRegListNode ||
              nodeType == InstrTreeNode::NTInstructionNode)
            {
-             if (SelectInstructionsForTree(kids[i], nts[i], Target))
+             if (SelectInstructionsForTree(kids[i], nts[i], target))
                return true;                    // failure
            }
        }
     }
   
+  // Finally, do any postprocessing on this node after its children
+  // have been translated
+  // 
+  if (treeRoot->opLabel != VRegListOp)
+    {
+      InstructionNode* instrNode = (InstructionNode*)treeRoot;
+      PostprocessMachineCodeForTree(instrNode, ruleForNode, nts, target);
+    }
+  
   return false;                                // success
 }
 
index 685463c49fe1065e0637d981d95dd602bb56594a..7fe91643a2ffabd4d84167953389e654734bb588 100644 (file)
 
 //*************************** Local Functions ******************************/
 
-inline int64_t
-GetSignedIntConstantValue(Value* val, bool& isValidConstant)
+
+static TmpInstruction*
+InsertCodeToLoadConstant(Value* opValue,
+                         Instruction* vmInstr,
+                         vector<MachineInstr*>& loadConstVec,
+                         TargetMachine& target)
 {
-  int64_t intValue = 0;
-  isValidConstant = false;
+  vector<TmpInstruction*> tempVec;
   
-  if (val->getValueType() == Value::ConstantVal)
-    {
-      switch(val->getType()->getPrimitiveID())
-       {
-       case Type::BoolTyID:
-         intValue = ((ConstPoolBool*) val)->getValue()? 1 : 0;
-         isValidConstant = true;
-         break;
-       case Type::SByteTyID:
-       case Type::ShortTyID:
-       case Type::IntTyID:
-       case Type::LongTyID:
-         intValue = ((ConstPoolSInt*) val)->getValue();
-         isValidConstant = true;
-         break;
-       default:
-         break;
-       }
-    }
+  // Create a tmp virtual register to hold the constant.
+  TmpInstruction* tmpReg =
+    new TmpInstruction(TMP_INSTRUCTION_OPCODE, opValue, NULL);
+  vmInstr->getMachineInstrVec().addTempValue(tmpReg);
   
-  return intValue;
-}
-
-inline uint64_t
-GetUnsignedIntConstantValue(Value* val, bool& isValidConstant)
-{
-  uint64_t intValue = 0;
-  isValidConstant = false;
+  target.getInstrInfo().CreateCodeToLoadConst(opValue, tmpReg,
+                                              loadConstVec, tempVec);
   
-  if (val->getValueType() == Value::ConstantVal)
-    {
-      switch(val->getType()->getPrimitiveID())
-       {
-       case Type::BoolTyID:
-         intValue = ((ConstPoolBool*) val)->getValue()? 1 : 0;
-         isValidConstant = true;
-         break;
-       case Type::UByteTyID:
-       case Type::UShortTyID:
-       case Type::UIntTyID:
-       case Type::ULongTyID:
-         intValue = ((ConstPoolUInt*) val)->getValue();
-         isValidConstant = true;
-         break;
-       default:
-         break;
-       }
-    }
+  // Register the new tmp values created for this m/c instruction sequence
+  for (unsigned i=0; i < tempVec.size(); i++)
+    vmInstr->getMachineInstrVec().addTempValue(tempVec[i]);
+  
+  // Record the mapping from the tmp VM instruction to machine instruction.
+  // Do this for all machine instructions that were not mapped to any
+  // other temp values created by 
+  // tmpReg->addMachineInstruction(loadConstVec.back());
   
-  return intValue;
+  return tmpReg;
 }
 
 
-inline int64_t
-GetConstantValueAsSignedInt(Value* val, bool& isValidConstant)
+//---------------------------------------------------------------------------
+// Function GetConstantValueAsSignedInt
+// 
+// Convenience function to get the value of an integer constant, for an
+// appropriate integer or non-integer type that can be held in an integer.
+// The type of the argument must be the following:
+//      Signed or unsigned integer
+//      Boolean
+//      Pointer
+// 
+// isValidConstant is set to true if a valid constant was found.
+//---------------------------------------------------------------------------
+
+int64_t
+GetConstantValueAsSignedInt(const Value *V,
+                            bool &isValidConstant)
 {
-  int64_t intValue = 0;
-  
-  if (val->getType()->isSigned())
+  if (!isa<ConstPoolVal>(V))
     {
-      intValue = GetSignedIntConstantValue(val, isValidConstant);
+      isValidConstant = false;
+      return 0;
     }
-  else                         // non-numeric types will fall here
+  
+  isValidConstant = true;
+  
+  if (V->getType() == Type::BoolTy)
+    return (int64_t) ((ConstPoolBool*)V)->getValue();
+  
+  if (V->getType()->isIntegral())
     {
-      uint64_t uintValue = GetUnsignedIntConstantValue(val, isValidConstant);
-      if (isValidConstant && uintValue < INT64_MAX)    // safe to use signed
-       intValue = (int64_t) uintValue;
-      else 
-       isValidConstant = false;
+      if (V->getType()->isSigned())
+        return ((ConstPoolSInt*)V)->getValue();
+      
+      assert(V->getType()->isUnsigned());
+      uint64_t Val = ((ConstPoolUInt*)V)->getValue();
+      if (Val < INT64_MAX)     // then safe to cast to signed
+        return (int64_t)Val;
     }
-  
-  return intValue;
+
+  isValidConstant = false;
+  return 0;
 }
 
 
@@ -183,81 +176,6 @@ Set2OperandsFromInstr(MachineInstr* minstr,
                        /*op2Position*/ -1, resultPosition);
 }
 
-#undef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
-#ifdef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
-unsigned
-Set3OperandsFromInstrJUNK(MachineInstr* minstr,
-                         InstructionNode* vmInstrNode,
-                         const TargetMachine& target,
-                         bool canDiscardResult,
-                         int op1Position,
-                         int op2Position,
-                         int resultPosition)
-{
-  assert(op1Position >= 0);
-  assert(resultPosition >= 0);
-  
-  unsigned returnFlags = 0x0;
-  
-  // Check if operand 1 is 0.  If so, try to use a hardwired 0 register.
-  Value* op1Value = vmInstrNode->leftChild()->getValue();
-  bool isValidConstant;
-  int64_t intValue = GetConstantValueAsSignedInt(op1Value, isValidConstant);
-  if (isValidConstant && intValue == 0 && target.zeroRegNum >= 0)
-    minstr->SetMachineOperand(op1Position, /*regNum*/ target.zeroRegNum);
-  else
-    {
-      if (isa<ConstPoolVal>(op1Value))
-       {
-         // value is constant and must be loaded from constant pool
-         returnFlags = returnFlags | (1 << op1Position);
-       }
-      minstr->SetMachineOperand(op1Position, MachineOperand::MO_VirtualRegister,
-                               op1Value);
-    }
-  
-  // Check if operand 2 (if any) fits in the immed. field of the instruction,
-  // or if it is 0 and can use a dedicated machine register
-  if (op2Position >= 0)
-    {
-      Value* op2Value = vmInstrNode->rightChild()->getValue();
-      int64_t immedValue;
-      unsigned int machineRegNum;
-      
-      MachineOperand::MachineOperandType
-       op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(), target,
-                                  /*canUseImmed*/ true,
-                                  machineRegNum, immedValue);
-      
-      if (op2type == MachineOperand::MO_MachineRegister)
-       minstr->SetMachineOperand(op2Position, machineRegNum);
-      else if (op2type == MachineOperand::MO_VirtualRegister)
-       {
-         if (isa<ConstPoolVal>(op2Value))
-           {
-             // value is constant and must be loaded from constant pool
-             returnFlags = returnFlags | (1 << op2Position);
-           }
-         minstr->SetMachineOperand(op2Position, op2type, op2Value);
-       }
-      else
-       {
-         assert(op2type != MO_CCRegister);
-         minstr->SetMachineOperand(op2Position, op2type, immedValue);
-       }
-    }
-  
-  // If operand 3 (result) can be discarded, use a dead register if one exists
-  if (canDiscardResult && target.zeroRegNum >= 0)
-    minstr->SetMachineOperand(resultPosition, target.zeroRegNum);
-  else
-    minstr->SetMachineOperand(resultPosition,
-                  MachineOperand::MO_VirtualRegister, vmInstrNode->getValue());
-  
-  return returnFlags;
-}
-#endif
-
 
 void
 Set3OperandsFromInstr(MachineInstr* minstr,
@@ -355,3 +273,132 @@ ChooseRegOrImmed(Value* val,
   return opType;
 }
 
+
+//---------------------------------------------------------------------------
+// Function: FixConstantOperandsForInstr
+// 
+// Purpose:
+// Special handling for constant operands of a machine instruction
+// -- if the constant is 0, use the hardwired 0 register, if any;
+// -- if the constant fits in the IMMEDIATE field, use that field;
+// -- else create instructions to put the constant into a register, either
+//    directly or by loading explicitly from the constant pool.
+// 
+// In the first 2 cases, the operand of `minstr' is modified in place.
+// Returns a vector of machine instructions generated for operands that
+// fall under case 3; these must be inserted before `minstr'.
+//---------------------------------------------------------------------------
+
+vector<MachineInstr*>
+FixConstantOperandsForInstr(Instruction* vmInstr,
+                            MachineInstr* minstr,
+                            TargetMachine& target)
+{
+  vector<MachineInstr*> loadConstVec;
+  
+  const MachineInstrDescriptor& instrDesc =
+    target.getInstrInfo().getDescriptor(minstr->getOpCode());
+  
+  for (unsigned op=0; op < minstr->getNumOperands(); op++)
+    {
+      const MachineOperand& mop = minstr->getOperand(op);
+          
+      // skip the result position (for efficiency below) and any other
+      // positions already marked as not a virtual register
+      if (instrDesc.resultPos == (int) op || 
+          mop.getOperandType() != MachineOperand::MO_VirtualRegister ||
+          mop.getVRegValue() == NULL)
+        {
+          continue;
+        }
+          
+      Value* opValue = mop.getVRegValue();
+      bool constantThatMustBeLoaded = false;
+      
+      if (isa<ConstPoolVal>(opValue))
+        {
+          unsigned int machineRegNum;
+          int64_t immedValue;
+          MachineOperand::MachineOperandType opType =
+            ChooseRegOrImmed(opValue, minstr->getOpCode(), target,
+                             /*canUseImmed*/ (op == 1),
+                             machineRegNum, immedValue);
+              
+          if (opType == MachineOperand::MO_MachineRegister)
+            minstr->SetMachineOperand(op, machineRegNum);
+          else if (opType == MachineOperand::MO_VirtualRegister)
+            constantThatMustBeLoaded = true; // load is generated below
+          else
+            minstr->SetMachineOperand(op, opType, immedValue);
+        }
+
+      if (constantThatMustBeLoaded || isa<GlobalValue>(opValue))
+        { // opValue is a constant that must be explicitly loaded into a reg.
+          TmpInstruction* tmpReg = InsertCodeToLoadConstant(opValue, vmInstr,
+                                                        loadConstVec, target);
+          minstr->SetMachineOperand(op, MachineOperand::MO_VirtualRegister,
+                                        tmpReg);
+        }
+    }
+  
+  // 
+  // Also, check for implicit operands used (not those defined) by the
+  // machine instruction.  These include:
+  // -- arguments to a Call
+  // -- return value of a Return
+  // Any such operand that is a constant value needs to be fixed also.
+  // The current instructions with implicit refs (viz., Call and Return)
+  // have no immediate fields, so the constant always needs to be loaded
+  // into a register.
+  // 
+  for (unsigned i=0, N=minstr->getNumImplicitRefs(); i < N; ++i)
+    if (isa<ConstPoolVal>(minstr->getImplicitRef(i)) ||
+        isa<GlobalValue>(minstr->getImplicitRef(i)))
+      {
+        TmpInstruction* tmpReg =
+          InsertCodeToLoadConstant(minstr->getImplicitRef(i), vmInstr,
+                                   loadConstVec, target);
+        minstr->setImplicitRef(i, tmpReg);
+      }
+  
+  return loadConstVec;
+}
+
+
+#undef SAVE_TO_MOVE_BACK_TO_SPARCISSCPP
+#ifdef SAVE_TO_MOVE_BACK_TO_SPARCISSCPP
+unsigned
+FixConstantOperands(const InstructionNode* vmInstrNode,
+                    TargetMachine& target)
+{
+  Instruction* vmInstr = vmInstrNode->getInstruction();
+  MachineCodeForVMInstr& mvec = vmInstr->getMachineInstrVec();
+  
+  for (unsigned i=0; i < mvec.size(); i++)
+    {
+      vector<MachineInsr*> loadConstVec =
+        FixConstantOperandsForInstr(mvec[i], target);
+    }
+  
+  // 
+  // Finally, inserted the generated instructions in the vector
+  // to be returned.
+  // 
+  unsigned numNew = loadConstVec.size();
+  if (numNew > 0)
+    {
+      // Insert the new instructions *before* the old ones by moving
+      // the old ones over `numNew' positions (last-to-first, of course!).
+      // We do check *after* returning that we did not exceed the vector mvec.
+      for (int i=numInstr-1; i >= 0; i--)
+        mvec[i+numNew] = mvec[i];
+      
+      for (unsigned i=0; i < numNew; i++)
+        mvec[i] = loadConstVec[i];
+    }
+  
+  return (numInstr + numNew);
+}
+#endif SAVE_TO_MOVE_BACK_TO_SPARCISSCPP
+
+