Record implicitRefs for each machine instruction instead of
authorVikram S. Adve <vadve@cs.uiuc.edu>
Thu, 11 Oct 2001 04:23:19 +0000 (04:23 +0000)
committerVikram S. Adve <vadve@cs.uiuc.edu>
Thu, 11 Oct 2001 04:23:19 +0000 (04:23 +0000)
each VM instruction.

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

include/llvm/CodeGen/MachineInstr.h
lib/Target/SparcV9/SparcV9InstrSelection.cpp

index a679590851f1bebf8feffed0d95af4f7feafded5..0efd8abb79c0e8dceca058598ed169b5c1c61614 100644 (file)
@@ -234,13 +234,23 @@ MachineOperand::InitializeReg(unsigned int _regNum)
 //     PREDICT-NOT-TAKEN: if 1: predict branch not taken.
 //   Instead of creating 4 different opcodes for BNZ, we create a single
 //   opcode and set bits in opCodeMask for each of these flags.
+//
+//  There are 2 kinds of operands:
+// 
+//  (1) Explicit operands of the machine instruction in vector operands[] 
+// 
+//  (2) "Implicit operands" are values implicitly used or defined by the
+//      machine instruction, such as arguments to a CALL, return value of
+//      a CALL (if any), and return value of a RETURN.
 //---------------------------------------------------------------------------
 
 class MachineInstr : public NonCopyable {
 private:
-  MachineOpCode        opCode;
-  OpCodeMask   opCodeMask;             // extra bits for variants of an opcode
+  MachineOpCode         opCode;
+  OpCodeMask            opCodeMask;    // extra bits for variants of an opcode
   vector<MachineOperand> operands;
+  vector<Value*>       implicitRefs;   // values implicitly referenced by this
+  vector<bool>          implicitIsDef;  // machine instruction (eg, call args)
   
 public:
   typedef ValOpIterator<const MachineInstr, const Value> val_op_const_iterator;
@@ -254,20 +264,33 @@ public:
                                         OpCodeMask    _opCodeMask = 0x0);
   inline               ~MachineInstr   () {}
   
-  const MachineOpCode  getOpCode       () const;
+  const MachineOpCode  getOpCode       () const { return opCode; }
   
-  unsigned int         getNumOperands  () const;
+  //
+  // Information about explicit operands of the instruction
+  // 
+  unsigned int         getNumOperands  () const { return operands.size(); }
+  
+  bool                 operandIsDefined(unsigned int i) const;
   
   const MachineOperand& getOperand     (unsigned int i) const;
         MachineOperand& getOperand     (unsigned int i);
   
-  bool                 operandIsDefined(unsigned int i) const;
+  //
+  // Information about implicit operands of the instruction
+  // 
+  unsigned int         getNumImplicitRefs() const{return implicitRefs.size();}
+  
+  bool                 implicitRefIsDefined(unsigned int i) const;
   
+  const Value*          getImplicitRef  (unsigned int i) const;
+        Value*          getImplicitRef  (unsigned int i);
+  
+  //
+  // Debugging support
+  // 
   void                 dump            (unsigned int indent = 0) const;
 
-
-
-
   
 public:
   friend ostream& operator<<(ostream& os, const MachineInstr& minstr);
@@ -285,19 +308,15 @@ public:
   void                 SetMachineOperand(unsigned int i,
                                          unsigned int regNum, 
                                          bool isDef=false);
-};
 
-inline const MachineOpCode
-MachineInstr::getOpCode() const
-{
-  return opCode;
-}
+  void                  addImplicitRef  (Value* val, 
+                                          bool isDef=false);
+  
+  void                  setImplicitRef  (unsigned int i,
+                                          Value* val, 
+                                          bool isDef=false);
+};
 
-inline unsigned int
-MachineInstr::getNumOperands() const
-{
-  return operands.size();
-}
 
 inline MachineOperand&
 MachineInstr::getOperand(unsigned int i)
@@ -319,6 +338,45 @@ MachineInstr::operandIsDefined(unsigned int i) const
   return getOperand(i).opIsDef();
 }
 
+inline bool
+MachineInstr::implicitRefIsDefined(unsigned int i) const
+{
+  assert(i < implicitIsDef.size() && "operand out of range!");
+  return implicitIsDef[i];
+}
+
+inline const Value*
+MachineInstr::getImplicitRef(unsigned int i) const
+{
+  assert(i < implicitRefs.size() && "getImplicitRef() out of range!");
+  return implicitRefs[i];
+}
+
+inline Value*
+MachineInstr::getImplicitRef(unsigned int i)
+{
+  assert(i < implicitRefs.size() && "getImplicitRef() out of range!");
+  return implicitRefs[i];
+}
+
+inline void
+MachineInstr::addImplicitRef(Value* val, 
+                             bool isDef)
+{
+  implicitRefs.push_back(val);
+  implicitIsDef.push_back(isDef);
+}
+
+inline void
+MachineInstr::setImplicitRef(unsigned int i,
+                             Value* val, 
+                             bool isDef)
+{
+  assert(i < implicitRefs.size() && "setImplicitRef() out of range!");
+  implicitRefs[i] = val;
+  implicitIsDef[i] = isDef;
+}
+
 
 template<class _MI, class _V>
 class ValOpIterator : public std::forward_iterator<_V, ptrdiff_t> {
@@ -364,16 +422,13 @@ public:
 // Purpose:
 //   Representation of the sequence of machine instructions created
 //   for a single VM instruction.  Additionally records information
-//   about hidden and implicit values used by the machine instructions:
+//   about hidden values used by the machine instructions:
 // 
-//   (1) "Temporary values" are intermediate values used in the machine
-//       instruction sequence, but not in the VM instruction
-//       Note that such values should be treated as pure SSA values with
-//       no interpretation of their operands (i.e., as a TmpInstruction
-//       object which actually represents such a value).
-// 
-//   (2) "Implicit uses" are values used in the VM instruction but not in
-//       the machine instruction sequence
+//   "Temporary values" are intermediate values used in the machine
+//   instruction sequence, but not in the VM instruction
+//   Note that such values should be treated as pure SSA values with
+//   no interpretation of their operands (i.e., as a TmpInstruction
+//   object which actually represents such a value).
 // 
 //---------------------------------------------------------------------------
 
@@ -381,7 +436,6 @@ class MachineCodeForVMInstr: public vector<MachineInstr*>
 {
 private:
   vector<Value*> tempVec;         // used by m/c instr but not VM instr
-  vector<Value*> implicitUses;    // used by VM instr but not m/c instr
   
 public:
   /*ctor*/     MachineCodeForVMInstr   ()      {}
@@ -390,11 +444,7 @@ public:
   const vector<Value*>& getTempValues  () const { return tempVec; }
         vector<Value*>& getTempValues  ()       { return tempVec; }
   
-  const vector<Value*>& getImplicitUses() const { return implicitUses; }
-        vector<Value*>& getImplicitUses()       { return implicitUses; }
-  
   void    addTempValue  (Value* val)            { tempVec.push_back(val); }
-  void    addImplicitUse(Value* val)            { implicitUses.push_back(val);}
   
   // dropAllReferences() - This function drops all references within
   // temporary (hidden) instructions created in implementing the original
index 48a038d68289c4b573a79b4bf3731a398d30444c..6f8edf57246c8363840f0a8c5f3e2c996671bd19 100644 (file)
@@ -1233,33 +1233,24 @@ FixConstantOperands(const InstructionNode* vmInstrNode,
                 minstr->SetMachineOperand(op, opType, immedValue);
             }
         }
-    }
-  
-  // 
-  // Also, check for operands of the VM instruction that are implicit
-  // operands of 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.
-  // At least these instructions with implicit uses (viz., Call and Return)
-  // have no immediate fields, so the constant needs to be loaded into
-  // a register.
-  // 
-  vector<Value*>& implUseVec = vmInstr->getMachineInstrVec().getImplicitUses();
-  if (implUseVec.size() > 0)
-    {
-      assert((vmInstr->getOpcode() == Instruction::Call ||
-              vmInstr->getOpcode() == Instruction::Ret)
-             && "May need to check immediate fields for other instructions");
       
-      for (unsigned i=1, N=implUseVec.size(); i < N; ++i)
-        if (isa<ConstPoolVal>(implUseVec[i]))
+      // 
+      // 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=1, N=minstr->getNumImplicitRefs(); i < N; ++i)
+        if (isa<ConstPoolVal>(minstr->getImplicitRef(i)))
           {
-            TmpInstruction* tmpReg =
-              InsertCodeToLoadConstant((ConstPoolVal*) implUseVec[i],
-                                       vmInstr, loadConstVec, target);
-            implUseVec[i] = tmpReg;
+            TmpInstruction* tmpReg = InsertCodeToLoadConstant((ConstPoolVal*)
+                                           minstr->getImplicitRef(i),
+                                           vmInstr, loadConstVec, target);
+            minstr->setImplicitRef(i, tmpReg);
           }
     }
   
@@ -1452,7 +1443,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
                 // 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 use.
+                // Mark the return value   register as an implicit ref of
+                // the machine instruction.
         {              
         ReturnInst* returnInstr = (ReturnInst*) subtreeRoot->getInstruction();
         assert(returnInstr->getOpcode() == Instruction::Ret);
@@ -1461,15 +1453,14 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
                                                     returnInstr, NULL);
         returnInstr->getMachineInstrVec().addTempValue(returnReg);
 
-        if (returnInstr->getReturnValue() != NULL)
-          returnInstr->getMachineInstrVec().addImplicitUse(
-                                             returnInstr->getReturnValue());
-        
         mvec[0] = new MachineInstr(RETURN);
         mvec[0]->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
                                       returnReg);
         mvec[0]->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,s8);
         
+        if (returnInstr->getReturnValue() != NULL)
+          mvec[0]->addImplicitRef(returnInstr->getReturnValue());
+        
         returnReg->addMachineInstruction(mvec[0]);
         
         mvec[numInstr++] = new MachineInstr(NOP); // delay slot
@@ -2055,8 +2046,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
                 // is available, replace this with a CALL instruction.
                 // Mark both the indirection register and the return-address
                // register as hidden virtual registers.
-                // Also, mark the operands of the Call and the return value
-                // as implicit operands of the machine instruction.
+                // Also, mark the operands of the Call and return value (if
+                // any) as implicit operands of the CALL machine instruction.
         {
         CallInst *callInstr = cast<CallInst>(subtreeRoot->getInstruction());
         Method* callee = callInstr->getCalledMethod();
@@ -2066,7 +2057,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         Instruction* retAddrReg = new TmpInstruction(Instruction::UserOp1,
                                                      callInstr, NULL);
         
-        // Note temporary values and implicit uses in mvec
+        // Note temporary values in the machineInstrVec for the VM instr.
         //
         // WARNING: Operands 0..N-1 must go in slots 0..N-1 of implicitUses.
         //          The result value must go in slot N.  This is assumed
@@ -2074,12 +2065,6 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         // 
         callInstr->getMachineInstrVec().addTempValue(jmpAddrReg);
         callInstr->getMachineInstrVec().addTempValue(retAddrReg);
-        for (unsigned i=0, N=callInstr->getNumOperands(); i < N; ++i)
-          if (callInstr->getOperand(i) != callee)
-            callInstr->getMachineInstrVec().addImplicitUse(
-                                                   callInstr->getOperand(i));
-        if (callInstr->getCalledMethod()->getReturnType() == Type::VoidTy)
-          callInstr->getMachineInstrVec().addImplicitUse(callInstr);
         
         // Generate the machine instruction and its operands
         mvec[0] = new MachineInstr(JMPL);
@@ -2090,6 +2075,14 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         mvec[0]->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
                                       retAddrReg);
         
+        // Add the call operands and return value as implicit refs
+        for (unsigned i=0, N=callInstr->getNumOperands(); i < N; ++i)
+          if (callInstr->getOperand(i) != callee)
+            mvec[0]->addImplicitRef(callInstr->getOperand(i));
+        
+        if (callInstr->getCalledMethod()->getReturnType() != Type::VoidTy)
+          mvec[0]->addImplicitRef(callInstr, /*isDef*/ true);
+        
         // NOTE: jmpAddrReg will be loaded by a different instruction generated
         //   by the final code generator, so we just mark the CALL instruction
         //   as computing that value.