[llvm-commits] [llvm] r68961 - in /llvm/trunk: include/llvm/Target/Target.td include/llvm/Target/TargetInstrInfo.h include/llvm/Target/TargetRegisterInfo.h lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp utils/TableGen/CodeEmitterGen.cpp utils/TableGen/CodeGenDAGPatterns.cpp utils/TableGen/CodeGenTarget.cpp utils/TableGen/DAGISelEmitter.cpp utils/TableGen/InstrInfoEmitter.cpp utils/TableGen/RegisterInfoEmitter.cpp

Dan Gohman gohman at apple.com
Mon Apr 13 08:38:05 PDT 2009


Author: djg
Date: Mon Apr 13 10:38:05 2009
New Revision: 68961

URL: http://llvm.org/viewvc/llvm-project?rev=68961&view=rev
Log:
Add a new TargetInstrInfo MachineInstr opcode, COPY_TO_SUBCLASS.
This will be used to replace things like X86's MOV32to32_.

Enhance ScheduleDAGSDNodesEmit to be more flexible and robust
in the presense of subregister superclasses and subclasses. It
can now cope with the definition of a virtual register being in
a subclass of a use.

Re-introduce the code for recording register superreg classes and
subreg classes. This is needed because when subreg extracts and
inserts get coalesced away, the virtual registers are left in
the correct subclass.

Modified:
    llvm/trunk/include/llvm/Target/Target.td
    llvm/trunk/include/llvm/Target/TargetInstrInfo.h
    llvm/trunk/include/llvm/Target/TargetRegisterInfo.h
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
    llvm/trunk/utils/TableGen/CodeEmitterGen.cpp
    llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp
    llvm/trunk/utils/TableGen/CodeGenTarget.cpp
    llvm/trunk/utils/TableGen/DAGISelEmitter.cpp
    llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp
    llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp

Modified: llvm/trunk/include/llvm/Target/Target.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Target/Target.td (original)
+++ llvm/trunk/include/llvm/Target/Target.td Mon Apr 13 10:38:05 2009
@@ -400,6 +400,14 @@
   let Namespace = "TargetInstrInfo";
   let neverHasSideEffects = 1;
 }
+def COPY_TO_SUBCLASS : Instruction {
+  let OutOperandList = (ops unknown:$dst);
+  let InOperandList = (ops unknown:$src, i32imm:$regclass);
+  let AsmString = "";
+  let Namespace = "TargetInstrInfo";
+  let neverHasSideEffects = 1;
+  let isAsCheapAsAMove = 1;
+}
 
 //===----------------------------------------------------------------------===//
 // AsmWriter - This class can be implemented by targets that need to customize

Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Target/TargetInstrInfo.h (original)
+++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h Mon Apr 13 10:38:05 2009
@@ -73,7 +73,14 @@
     /// is often zero, as is commonly used to implement zext operations on
     /// target architectures which support it, such as with x86-64 (with
     /// zext from i32 to i64 via implicit zero-extension).
-    SUBREG_TO_REG = 9
+    SUBREG_TO_REG = 9,
+
+    /// COPY_TO_SUBCLASS - This instruction is a placeholder for a plain
+    /// register-to-register copy into a specific register class. This is only
+    /// used between instruction selection and MachineInstr creation, before
+    /// virtual registers have been created for all the instructions. As with
+    /// normal copies, these may be optimized away by the coalescer.
+    COPY_TO_SUBCLASS = 10
   };
 
   unsigned getNumOpcodes() const { return NumOpcodes; }

Modified: llvm/trunk/include/llvm/Target/TargetRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetRegisterInfo.h?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Target/TargetRegisterInfo.h (original)
+++ llvm/trunk/include/llvm/Target/TargetRegisterInfo.h Mon Apr 13 10:38:05 2009
@@ -62,6 +62,8 @@
   const vt_iterator VTs;
   const sc_iterator SubClasses;
   const sc_iterator SuperClasses;
+  const sc_iterator SubRegClasses;
+  const sc_iterator SuperRegClasses;
   const unsigned RegSize, Alignment;    // Size & Alignment of register in bytes
   const int CopyCost;
   const iterator RegsBegin, RegsEnd;
@@ -72,9 +74,12 @@
                       const MVT *vts,
                       const TargetRegisterClass * const *subcs,
                       const TargetRegisterClass * const *supcs,
+                      const TargetRegisterClass * const *subregcs,
+                      const TargetRegisterClass * const *superregcs,
                       unsigned RS, unsigned Al, int CC,
                       iterator RB, iterator RE)
     : ID(id), Name(name), VTs(vts), SubClasses(subcs), SuperClasses(supcs),
+    SubRegClasses(subregcs), SuperRegClasses(superregcs),
     RegSize(RS), Alignment(Al), CopyCost(CC), RegsBegin(RB), RegsEnd(RE) {
       for (iterator I = RegsBegin, E = RegsEnd; I != E; ++I)
         RegSet.insert(*I);
@@ -132,8 +137,32 @@
     return I;
   }
 
-  /// hasSubClass - return true if the specified TargetRegisterClass is a
-  /// sub-register class of this TargetRegisterClass.
+  /// subregclasses_begin / subregclasses_end - Loop over all of
+  /// the subreg register classes of this register class.
+  sc_iterator subregclasses_begin() const {
+    return SubRegClasses;
+  }
+
+  sc_iterator subregclasses_end() const {
+    sc_iterator I = SubRegClasses;
+    while (*I != NULL) ++I;
+    return I;
+  }
+
+  /// superregclasses_begin / superregclasses_end - Loop over all of
+  /// the superreg register classes of this register class.
+  sc_iterator superregclasses_begin() const {
+    return SuperRegClasses;
+  }
+
+  sc_iterator superregclasses_end() const {
+    sc_iterator I = SuperRegClasses;
+    while (*I != NULL) ++I;
+    return I;
+  }
+
+  /// hasSubClass - return true if the the specified TargetRegisterClass
+  /// is a proper subset of this TargetRegisterClass.
   bool hasSubClass(const TargetRegisterClass *cs) const {
     for (int i = 0; SubClasses[i] != NULL; ++i) 
       if (SubClasses[i] == cs)
@@ -141,8 +170,8 @@
     return false;
   }
 
-  /// subclasses_begin / subclasses_end - Loop over all of the sub-classes of
-  /// this register class.
+  /// subclasses_begin / subclasses_end - Loop over all of the classes
+  /// that are proper subsets of this register class.
   sc_iterator subclasses_begin() const {
     return SubClasses;
   }
@@ -154,7 +183,7 @@
   }
   
   /// hasSuperClass - return true if the specified TargetRegisterClass is a
-  /// super-register class of this TargetRegisterClass.
+  /// proper superset of this TargetRegisterClass.
   bool hasSuperClass(const TargetRegisterClass *cs) const {
     for (int i = 0; SuperClasses[i] != NULL; ++i) 
       if (SuperClasses[i] == cs)
@@ -162,8 +191,8 @@
     return false;
   }
 
-  /// superclasses_begin / superclasses_end - Loop over all of the super-classes
-  /// of this register class.
+  /// superclasses_begin / superclasses_end - Loop over all of the classes
+  /// that are proper supersets of this register class.
   sc_iterator superclasses_begin() const {
     return SuperClasses;
   }
@@ -174,8 +203,8 @@
     return I;
   }
 
-  /// isASubClass - return true if this TargetRegisterClass is a sub-class of at
-  /// least one other TargetRegisterClass.
+  /// isASubClass - return true if this TargetRegisterClass is a subset
+  /// class of at least one other TargetRegisterClass.
   bool isASubClass() const {
     return SuperClasses[0] != 0;
   }

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h Mon Apr 13 10:38:05 2009
@@ -134,6 +134,12 @@
     void EmitSubregNode(SDNode *Node, 
                         DenseMap<SDValue, unsigned> &VRBaseMap);
 
+    /// EmitCopyToSubclassNode - Generate machine code for COPY_TO_SUBCLASS
+    /// nodes.
+    ///
+    void EmitCopyToSubclassNode(SDNode *Node,
+                                DenseMap<SDValue, unsigned> &VRBaseMap);
+
     /// getVR - Return the virtual register corresponding to the specified result
     /// of the specified node.
     unsigned getVR(SDValue Op, DenseMap<SDValue, unsigned> &VRBaseMap);
@@ -146,6 +152,13 @@
                     const TargetInstrDesc *II,
                     DenseMap<SDValue, unsigned> &VRBaseMap);
 
+    /// AddRegisterOperand - Add the specified register as an operand to the
+    /// specified machine instr. Insert register copies if the register is
+    /// not in the required register class.
+    void AddRegisterOperand(MachineInstr *MI, SDValue Op,
+                            unsigned IIOpNum, const TargetInstrDesc *II,
+                            DenseMap<SDValue, unsigned> &VRBaseMap);
+
     /// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
     /// implicit physical register output.
     void EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone,

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp Mon Apr 13 10:38:05 2009
@@ -93,9 +93,13 @@
               getInstrOperandRegClass(TRI, II, i+II.getNumDefs());
             if (!UseRC)
               UseRC = RC;
-            else if (RC)
-              assert(UseRC == RC &&
-                     "Multiple uses expecting different register classes!");
+            else if (RC) {
+              if (UseRC->hasSuperClass(RC))
+                UseRC = RC;
+              else
+                assert((UseRC == RC || RC->hasSuperClass(UseRC)) &&
+                       "Multiple uses expecting different register classes!");
+            }
           }
         }
       }
@@ -127,10 +131,14 @@
     VRBase = MRI.createVirtualRegister(DstRC);
     bool Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg,
                                      DstRC, SrcRC);
-    if (!Emitted) {
-      cerr << "Unable to issue a copy instruction!\n";
-      abort();
-    }
+    // If the target didn't handle the copy with different register
+    // classes and the destination is a subset of the source,
+    // try a normal same-RC copy.
+    if (!Emitted && DstRC->hasSuperClass(SrcRC))
+      Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg,
+                                  SrcRC, SrcRC);
+
+    assert(Emitted && "Unable to issue a copy instruction!\n");
   }
 
   SDValue Op(Node, ResNo);
@@ -168,9 +176,10 @@
 
   for (unsigned i = 0; i < II.getNumDefs(); ++i) {
     // If the specific node value is only used by a CopyToReg and the dest reg
-    // is a vreg, use the CopyToReg'd destination register instead of creating
-    // a new vreg.
+    // is a vreg in the same register class, use the CopyToReg'd destination
+    // register instead of creating a new vreg.
     unsigned VRBase = 0;
+    const TargetRegisterClass *RC = getInstrOperandRegClass(TRI, II, i);
 
     if (!IsClone && !IsCloned)
       for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
@@ -181,9 +190,12 @@
             User->getOperand(2).getResNo() == i) {
           unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
           if (TargetRegisterInfo::isVirtualRegister(Reg)) {
-            VRBase = Reg;
-            MI->addOperand(MachineOperand::CreateReg(Reg, true));
-            break;
+            const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
+            if (RegRC == RC) {
+              VRBase = Reg;
+              MI->addOperand(MachineOperand::CreateReg(Reg, true));
+              break;
+            }
           }
         }
       }
@@ -191,7 +203,6 @@
     // Create the result registers for this node and add the result regs to
     // the machine instruction.
     if (VRBase == 0) {
-      const TargetRegisterClass *RC = getInstrOperandRegClass(TRI, II, i);
       assert(RC && "Isn't a register operand!");
       VRBase = MRI.createVirtualRegister(RC);
       MI->addOperand(MachineOperand::CreateReg(VRBase, true));
@@ -230,6 +241,52 @@
 }
 
 
+/// AddRegisterOperand - Add the specified register as an operand to the
+/// specified machine instr. Insert register copies if the register is
+/// not in the required register class.
+void
+ScheduleDAGSDNodes::AddRegisterOperand(MachineInstr *MI, SDValue Op,
+                                       unsigned IIOpNum,
+                                       const TargetInstrDesc *II,
+                                       DenseMap<SDValue, unsigned> &VRBaseMap) {
+  assert(Op.getValueType() != MVT::Other &&
+         Op.getValueType() != MVT::Flag &&
+         "Chain and flag operands should occur at end of operand list!");
+  // Get/emit the operand.
+  unsigned VReg = getVR(Op, VRBaseMap);
+  assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");
+
+  const TargetInstrDesc &TID = MI->getDesc();
+  bool isOptDef = IIOpNum < TID.getNumOperands() &&
+    TID.OpInfo[IIOpNum].isOptionalDef();
+
+  // If the instruction requires a register in a different class, create
+  // a new virtual register and copy the value into it.
+  if (II) {
+    const TargetRegisterClass *SrcRC =
+      MRI.getRegClass(VReg);
+    const TargetRegisterClass *DstRC =
+      getInstrOperandRegClass(TRI, *II, IIOpNum);
+    assert((DstRC || (TID.isVariadic() && IIOpNum >= TID.getNumOperands())) &&
+           "Don't have operand info for this instruction!");
+    if (DstRC && SrcRC != DstRC && !SrcRC->hasSuperClass(DstRC)) {
+      unsigned NewVReg = MRI.createVirtualRegister(DstRC);
+      bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
+                                       DstRC, SrcRC);
+      // If the target didn't handle the copy with different register
+      // classes and the destination is a subset of the source,
+      // try a normal same-RC copy.
+      if (!Emitted && DstRC->hasSuperClass(SrcRC))
+        Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
+                                    SrcRC, SrcRC);
+      assert(Emitted && "Unable to issue a copy instruction!\n");
+      VReg = NewVReg;
+    }
+  }
+
+  MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef));
+}
+
 /// AddOperand - Add the specified operand to the specified machine instr.  II
 /// specifies the instruction information for the node, and IIOpNum is the
 /// operand number (in the II) that we are adding. IIOpNum and II are used for 
@@ -239,46 +296,7 @@
                                     const TargetInstrDesc *II,
                                     DenseMap<SDValue, unsigned> &VRBaseMap) {
   if (Op.isMachineOpcode()) {
-    // Note that this case is redundant with the final else block, but we
-    // include it because it is the most common and it makes the logic
-    // simpler here.
-    assert(Op.getValueType() != MVT::Other &&
-           Op.getValueType() != MVT::Flag &&
-           "Chain and flag operands should occur at end of operand list!");
-    // Get/emit the operand.
-    unsigned VReg = getVR(Op, VRBaseMap);
-    const TargetInstrDesc &TID = MI->getDesc();
-    bool isOptDef = IIOpNum < TID.getNumOperands() &&
-      TID.OpInfo[IIOpNum].isOptionalDef();
-    MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef));
-    
-    // Verify that it is right.
-    assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");
-#ifndef NDEBUG
-    if (II) {
-      // There may be no register class for this operand if it is a variadic
-      // argument (RC will be NULL in this case).  In this case, we just assume
-      // the regclass is ok.
-      const TargetRegisterClass *RC= getInstrOperandRegClass(TRI, *II, IIOpNum);
-      assert((RC || II->isVariadic()) && "Expected reg class info!");
-      const TargetRegisterClass *VRC = MRI.getRegClass(VReg);
-      if (RC && VRC != RC) {
-        cerr << "Register class of operand and regclass of use don't agree!\n";
-        cerr << "Operand = " << IIOpNum << "\n";
-        cerr << "Op->Val = "; Op.getNode()->dump(DAG); cerr << "\n";
-        cerr << "MI = "; MI->print(cerr);
-        cerr << "VReg = " << VReg << "\n";
-        cerr << "VReg RegClass " << VRC->getName()
-             << "     size = " << VRC->getSize()
-             << ", align = " << VRC->getAlignment() << "\n";
-        cerr << "Expected RegClass " << RC->getName()
-             << " size = " << RC->getSize()
-             << ", align = " << RC->getAlignment() << "\n";
-        cerr << "Fatal error, aborting.\n";
-        abort();
-      }
-    }
-#endif
+    AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap);
   } else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
     MI->addOperand(MachineOperand::CreateImm(C->getZExtValue()));
   } else if (ConstantFPSDNode *F = dyn_cast<ConstantFPSDNode>(Op)) {
@@ -288,8 +306,8 @@
     MI->addOperand(MachineOperand::CreateReg(R->getReg(), false));
   } else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) {
     MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(),TGA->getOffset()));
-  } else if (BasicBlockSDNode *BB = dyn_cast<BasicBlockSDNode>(Op)) {
-    MI->addOperand(MachineOperand::CreateMBB(BB->getBasicBlock()));
+  } else if (BasicBlockSDNode *BBNode = dyn_cast<BasicBlockSDNode>(Op)) {
+    MI->addOperand(MachineOperand::CreateMBB(BBNode->getBasicBlock()));
   } else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) {
     MI->addOperand(MachineOperand::CreateFI(FI->getIndex()));
   } else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) {
@@ -319,19 +337,35 @@
     assert(Op.getValueType() != MVT::Other &&
            Op.getValueType() != MVT::Flag &&
            "Chain and flag operands should occur at end of operand list!");
-    unsigned VReg = getVR(Op, VRBaseMap);
-    MI->addOperand(MachineOperand::CreateReg(VReg, false));
-    
-    // Verify that it is right.  Note that the reg class of the physreg and the
-    // vreg don't necessarily need to match, but the target copy insertion has
-    // to be able to handle it.  This handles things like copies from ST(0) to
-    // an FP vreg on x86.
-    assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");
-    if (II && !II->isVariadic()) {
-      assert(getInstrOperandRegClass(TRI, *II, IIOpNum) &&
-             "Don't have operand info for this instruction!");
-    }
-  }  
+    AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap);
+  }
+}
+
+/// getSubRegisterRegClass - Returns the register class of specified register
+/// class' "SubIdx"'th sub-register class.
+static const TargetRegisterClass*
+getSubRegisterRegClass(const TargetRegisterClass *TRC, unsigned SubIdx) {
+  // Pick the register class of the subregister
+  TargetRegisterInfo::regclass_iterator I =
+    TRC->subregclasses_begin() + SubIdx-1;
+  assert(I < TRC->subregclasses_end() &&
+         "Invalid subregister index for register class");
+  return *I;
+}
+
+/// getSuperRegisterRegClass - Returns the register class of a superreg A whose
+/// "SubIdx"'th sub-register class is the specified register class and whose
+/// type matches the specified type.
+static const TargetRegisterClass*
+getSuperRegisterRegClass(const TargetRegisterClass *TRC,
+                         unsigned SubIdx, MVT VT) {
+  // Pick the register class of the superegister for this type
+  for (TargetRegisterInfo::regclass_iterator I = TRC->superregclasses_begin(),
+         E = TRC->superregclasses_end(); I != E; ++I)
+    if ((*I)->hasType(VT) && getSubRegisterRegClass(*I, SubIdx) == TRC)
+      return *I;
+  assert(false && "Couldn't find the register class");
+  return 0;
 }
 
 /// EmitSubregNode - Generate machine code for subreg nodes.
@@ -364,13 +398,15 @@
                                TII->get(TargetInstrInfo::EXTRACT_SUBREG));
 
     // Figure out the register class to create for the destreg.
-    const TargetRegisterClass *SRC = TLI->getRegClassFor(Node->getValueType(0));
+    unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
+    const TargetRegisterClass *TRC = MRI.getRegClass(VReg);
+    const TargetRegisterClass *SRC = getSubRegisterRegClass(TRC, SubIdx);
 
     if (VRBase) {
       // Grab the destination register
 #ifndef NDEBUG
       const TargetRegisterClass *DRC = MRI.getRegClass(VRBase);
-      assert(SRC && DRC && SRC == DRC && 
+      assert(SRC && DRC && (SRC == DRC || DRC->hasSubClass(SRC)) &&
              "Source subregister and destination must have the same class");
 #endif
     } else {
@@ -389,6 +425,7 @@
     SDValue N0 = Node->getOperand(0);
     SDValue N1 = Node->getOperand(1);
     SDValue N2 = Node->getOperand(2);
+    unsigned SubReg = getVR(N1, VRBaseMap);
     unsigned SubIdx = cast<ConstantSDNode>(N2)->getZExtValue();
     
       
@@ -397,7 +434,8 @@
     if (VRBase) {
       TRC = MRI.getRegClass(VRBase);
     } else {
-      TRC = TLI->getRegClassFor(Node->getValueType(0));
+      TRC = getSuperRegisterRegClass(MRI.getRegClass(SubReg), SubIdx,
+                                     Node->getValueType(0));
       assert(TRC && "Couldn't determine register class for insert_subreg");
       VRBase = MRI.createVirtualRegister(TRC); // Create the reg
     }
@@ -426,6 +464,39 @@
   assert(isNew && "Node emitted out of order - early");
 }
 
+/// EmitCopyToSubclassNode - Generate machine code for COPY_TO_SUBCLASS nodes.
+/// COPY_TO_SUBCLASS is just a normal copy, except that the destination
+/// register is constrained to be in a particular register class.
+///
+void
+ScheduleDAGSDNodes::EmitCopyToSubclassNode(SDNode *Node,
+                                       DenseMap<SDValue, unsigned> &VRBaseMap) {
+  unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
+  const TargetRegisterClass *SrcRC = MRI.getRegClass(VReg);
+
+  unsigned DstRCIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
+  const TargetRegisterClass *DstRC = TRI->getRegClass(DstRCIdx);
+
+  assert(SrcRC->hasSubClass(DstRC) &&
+         "COPY_TO_SUBCLASS destination class is not a proper subclass!");
+
+  // Create the new VReg in the destination class and emit a copy.
+  unsigned NewVReg = MRI.createVirtualRegister(DstRC);
+  bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
+                                   DstRC, SrcRC);
+  // If the target didn't handle that, emit a plain copy.
+  if (!Emitted)
+    Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
+                                SrcRC, SrcRC);
+  assert(Emitted &&
+         "Unable to issue a copy instruction for a COPY_TO_SUBCLASS node!\n");
+
+  SDValue Op(Node, 0);
+  bool isNew = VRBaseMap.insert(std::make_pair(Op, NewVReg)).second;
+  isNew = isNew; // Silence compiler warning.
+  assert(isNew && "Node emitted out of order - early");
+}
+
 /// EmitNode - Generate machine code for an node and needed dependencies.
 ///
 void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
@@ -442,6 +513,12 @@
       return;
     }
 
+    // Handle COPY_TO_SUBCLASS specially.
+    if (Opc == TargetInstrInfo::COPY_TO_SUBCLASS) {
+      EmitCopyToSubclassNode(Node, VRBaseMap);
+      return;
+    }
+
     if (Opc == TargetInstrInfo::IMPLICIT_DEF)
       // We want a unique VR for each IMPLICIT_DEF use.
       return;
@@ -532,12 +609,17 @@
     else
       DstTRC = TRI->getPhysicalRegisterRegClass(DestReg,
                                             Node->getOperand(1).getValueType());
+
     bool Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg,
                                      DstTRC, SrcTRC);
-    if (!Emitted) {
-      cerr << "Unable to issue a copy instruction!\n";
-      abort();
-    }
+    // If the target didn't handle the copy with different register
+    // classes and the destination is a subset of the source,
+    // try a normal same-RC copy.
+    if (!Emitted && DstTRC->hasSubClass(SrcTRC))
+      Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg,
+                                  DstTRC, DstTRC);
+
+    assert(Emitted && "Unable to issue a copy instruction!\n");
     break;
   }
   case ISD::CopyFromReg: {

Modified: llvm/trunk/utils/TableGen/CodeEmitterGen.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeEmitterGen.cpp?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/CodeEmitterGen.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeEmitterGen.cpp Mon Apr 13 10:38:05 2009
@@ -33,8 +33,9 @@
         R->getName() == "EXTRACT_SUBREG" ||
         R->getName() == "INSERT_SUBREG" ||
         R->getName() == "IMPLICIT_DEF" ||
-        R->getName() == "SUBREG_TO_REG") continue;
-    
+        R->getName() == "SUBREG_TO_REG" ||
+        R->getName() == "COPY_TO_SUBCLASS") continue;
+
     BitsInit *BI = R->getValueAsBitsInit("Inst");
 
     unsigned numBits = BI->getNumBits();
@@ -109,7 +110,8 @@
         R->getName() == "EXTRACT_SUBREG" ||
         R->getName() == "INSERT_SUBREG" ||
         R->getName() == "IMPLICIT_DEF" ||
-        R->getName() == "SUBREG_TO_REG") {
+        R->getName() == "SUBREG_TO_REG" ||
+        R->getName() == "COPY_TO_SUBCLASS") {
       o << "    0U,\n";
       continue;
     }
@@ -146,8 +148,9 @@
         InstName == "EXTRACT_SUBREG" ||
         InstName == "INSERT_SUBREG" ||
         InstName == "IMPLICIT_DEF" ||
-        InstName == "SUBREG_TO_REG") continue;
-    
+        InstName == "SUBREG_TO_REG" ||
+        InstName == "COPY_TO_SUBCLASS") continue;
+
     BitsInit *BI = R->getValueAsBitsInit("Inst");
     const std::vector<RecordVal> &Vals = R->getValues();
     CodeGenInstruction &CGI = Target.getInstruction(InstName);

Modified: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp Mon Apr 13 10:38:05 2009
@@ -884,6 +884,12 @@
       MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
     MadeChange |= UpdateNodeType(MVT::isVoid, TP);
     return MadeChange;
+  } else if (getOperator()->getName() == "COPY_TO_SUBCLASS") {
+    bool MadeChange = false;
+    MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
+    MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters);
+    MadeChange |= UpdateNodeType(getChild(1)->getTypeNum(0), TP);
+    return MadeChange;
   } else if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
     bool MadeChange = false;
 

Modified: llvm/trunk/utils/TableGen/CodeGenTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenTarget.cpp?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenTarget.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenTarget.cpp Mon Apr 13 10:38:05 2009
@@ -344,7 +344,12 @@
   if (I == Instructions.end())
     throw "Could not find 'SUBREG_TO_REG' instruction!";
   const CodeGenInstruction *SUBREG_TO_REG = &I->second;
-  
+
+  I = getInstructions().find("COPY_TO_SUBCLASS");
+  if (I == Instructions.end())
+    throw "Could not find 'COPY_TO_SUBCLASS' instruction!";
+  const CodeGenInstruction *COPY_TO_SUBCLASS = &I->second;
+
   // Print out the rest of the instructions now.
   NumberedInstructions.push_back(PHI);
   NumberedInstructions.push_back(INLINEASM);
@@ -356,6 +361,7 @@
   NumberedInstructions.push_back(INSERT_SUBREG);
   NumberedInstructions.push_back(IMPLICIT_DEF);
   NumberedInstructions.push_back(SUBREG_TO_REG);
+  NumberedInstructions.push_back(COPY_TO_SUBCLASS);
   for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II)
     if (&II->second != PHI &&
         &II->second != INLINEASM &&
@@ -366,7 +372,8 @@
         &II->second != EXTRACT_SUBREG &&
         &II->second != INSERT_SUBREG &&
         &II->second != IMPLICIT_DEF &&
-        &II->second != SUBREG_TO_REG)
+        &II->second != SUBREG_TO_REG &&
+        &II->second != COPY_TO_SUBCLASS)
       NumberedInstructions.push_back(&II->second);
 }
 

Modified: llvm/trunk/utils/TableGen/DAGISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DAGISelEmitter.cpp?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/DAGISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/DAGISelEmitter.cpp Mon Apr 13 10:38:05 2009
@@ -918,6 +918,15 @@
                    getEnumName(N->getTypeNum(0)) + ");");
           NodeOps.push_back("Tmp" + utostr(ResNo));
           return NodeOps;
+        } else if (DI->getDef()->isSubClassOf("RegisterClass")) {
+          // Handle a reference to a register class. This is used
+          // in COPY_TO_SUBREG instructions.
+          emitCode("SDValue Tmp" + utostr(ResNo) +
+                   " = CurDAG->getTargetConstant(" +
+                   getQualifiedName(DI->getDef()) + "RegClassID, " +
+                   "MVT::i32);");
+          NodeOps.push_back("Tmp" + utostr(ResNo));
+          return NodeOps;
         }
       } else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
         unsigned ResNo = TmpNo++;

Modified: llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp Mon Apr 13 10:38:05 2009
@@ -340,7 +340,8 @@
         R->getName() != "EXTRACT_SUBREG" &&
         R->getName() != "INSERT_SUBREG" &&
         R->getName() != "IMPLICIT_DEF" &&
-        R->getName() != "SUBREG_TO_REG")
+        R->getName() != "SUBREG_TO_REG" &&
+        R->getName() != "COPY_TO_SUBCLASS")
       throw R->getName() + " doesn't have a field named '" + 
             Val->getValue() + "'!";
     return;

Modified: llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp?rev=68961&r1=68960&r2=68961&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp Mon Apr 13 10:38:05 2009
@@ -240,8 +240,85 @@
          << RegisterClasses[i].getName() << "RegClass;\n";
          
     std::map<unsigned, std::set<unsigned> > SuperClassMap;
+    std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
     OS << "\n";
 
+    // Emit the sub-register classes for each RegisterClass
+    for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+      const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+      // Give the register class a legal C name if it's anonymous.
+      std::string Name = RC.TheDef->getName();
+
+      OS << "  // " << Name
+         << " Sub-register Classes...\n"
+         << "  static const TargetRegisterClass* const "
+         << Name << "SubRegClasses [] = {\n    ";
+
+      bool Empty = true;
+
+      for (unsigned subrc = 0, subrcMax = RC.SubRegClasses.size();
+            subrc != subrcMax; ++subrc) {
+        unsigned rc2 = 0, e2 = RegisterClasses.size();
+        for (; rc2 != e2; ++rc2) {
+          const CodeGenRegisterClass &RC2 =  RegisterClasses[rc2];
+          if (RC.SubRegClasses[subrc]->getName() == RC2.getName()) {
+            if (!Empty)
+              OS << ", ";
+            OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+            Empty = false;
+
+            std::map<unsigned, std::set<unsigned> >::iterator SCMI =
+              SuperRegClassMap.find(rc2);
+            if (SCMI == SuperRegClassMap.end()) {
+              SuperRegClassMap.insert(std::make_pair(rc2,
+                                                     std::set<unsigned>()));
+              SCMI = SuperRegClassMap.find(rc2);
+            }
+            SCMI->second.insert(rc);
+            break;
+          }
+        }
+        if (rc2 == e2)
+          throw "Register Class member '" +
+            RC.SubRegClasses[subrc]->getName() +
+            "' is not a valid RegisterClass!";
+      }
+
+      OS << (!Empty ? ", " : "") << "NULL";
+      OS << "\n  };\n\n";
+    }
+
+    // Emit the super-register classes for each RegisterClass
+    for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+      const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+      // Give the register class a legal C name if it's anonymous.
+      std::string Name = RC.TheDef->getName();
+
+      OS << "  // " << Name
+         << " Super-register Classes...\n"
+         << "  static const TargetRegisterClass* const "
+         << Name << "SuperRegClasses [] = {\n    ";
+
+      bool Empty = true;
+      std::map<unsigned, std::set<unsigned> >::iterator I =
+        SuperRegClassMap.find(rc);
+      if (I != SuperRegClassMap.end()) {
+        for (std::set<unsigned>::iterator II = I->second.begin(),
+               EE = I->second.end(); II != EE; ++II) {
+          const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
+          if (!Empty)
+            OS << ", ";
+          OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+          Empty = false;
+        }
+      }
+
+      OS << (!Empty ? ", " : "") << "NULL";
+      OS << "\n  };\n\n";
+    }
+
     // Emit the sub-classes array for each RegisterClass
     for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
       const CodeGenRegisterClass &RC = RegisterClasses[rc];
@@ -323,6 +400,8 @@
          << RC.getName() + "VTs" << ", "
          << RC.getName() + "Subclasses" << ", "
          << RC.getName() + "Superclasses" << ", "
+         << RC.getName() + "SubRegClasses" << ", "
+         << RC.getName() + "SuperRegClasses" << ", "
          << RC.SpillSize/8 << ", "
          << RC.SpillAlignment/8 << ", "
          << RC.CopyCost << ", "





More information about the llvm-commits mailing list