Add a new TargetInstrInfo MachineInstr opcode, COPY_TO_SUBCLASS.
authorDan Gohman <gohman@apple.com>
Mon, 13 Apr 2009 15:38:05 +0000 (15:38 +0000)
committerDan Gohman <gohman@apple.com>
Mon, 13 Apr 2009 15:38:05 +0000 (15:38 +0000)
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.

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

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

index 99b314c29b86a2c9834eb566b24f1d4ff60dc53c..3ce360bce749052a97b11f0513f3b2e075af3e69 100644 (file)
@@ -400,6 +400,14 @@ def SUBREG_TO_REG : Instruction {
   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
index 6637424bf55aa50595f819ae4def4d74bc14eb2d..fb41e4d3e556df38b10c3272d00d49f5110752de 100644 (file)
@@ -73,7 +73,14 @@ public:
     /// 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; }
index 69011477ca76b783f600244346444deae0b03ab2..92f709fbb83e2376a086e328abd6f69bb5bf9304 100644 (file)
@@ -62,6 +62,8 @@ private:
   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 @@ public:
                       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 @@ public:
     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 @@ public:
     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 @@ public:
   }
   
   /// 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 @@ public:
     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 @@ public:
     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;
   }
index af3adaafa5c84d88f563f2b529ef2c39359f56ab..cd969dc7333be6ec34857c96b480434856e8a391 100644 (file)
@@ -134,6 +134,12 @@ namespace llvm {
     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 @@ namespace llvm {
                     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,
index abeb7f4dbf7ce4436f422a80d3f6b97ef87b1365..084ecb755502b42320e8792cf36620c95ff816f0 100644 (file)
@@ -93,9 +93,13 @@ void ScheduleDAGSDNodes::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
               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 @@ void ScheduleDAGSDNodes::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
     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 @@ void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
 
   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 @@ void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
             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 @@ void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
     // 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 @@ unsigned ScheduleDAGSDNodes::getVR(SDValue Op,
 }
 
 
+/// 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 @@ void ScheduleDAGSDNodes::AddOperand(MachineInstr *MI, SDValue Op,
                                     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 @@ void ScheduleDAGSDNodes::AddOperand(MachineInstr *MI, SDValue Op,
     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 @@ void ScheduleDAGSDNodes::AddOperand(MachineInstr *MI, SDValue Op,
     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 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
                                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 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
     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 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
     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 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
   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 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
       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 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
     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: {
index ae4a6aa445b1ca0f80316202f0a61b2f0751f8e5..912617bc01d6f107214c39f0ade2b70167e3ce8d 100644 (file)
@@ -33,8 +33,9 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
         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 @@ void CodeEmitterGen::run(std::ostream &o) {
         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 @@ void CodeEmitterGen::run(std::ostream &o) {
         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);
index 5bb4ddb2234979dfff51e3d92e16d71de79aabc8..eb0b0990488bc3d8ae74e30f9df9ac7deb8b3784 100644 (file)
@@ -884,6 +884,12 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
       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;
 
index 9ef64d66b5ccbbcb1d834c370c685f5390e8cf0d..c5d4c494c030a64768f086236e290a8b9ca97861 100644 (file)
@@ -344,7 +344,12 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
   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 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
   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 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
         &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);
 }
 
index 63912a1e4edcf9e0acb133770f64854cad70dca2..3335d00f729cfd6f2b29623fbd760c8dbf1f86f5 100644 (file)
@@ -918,6 +918,15 @@ public:
                    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++;
index 6201690b10ef75c62daaa5f1fd15d3dcd2aa110e..1a32828e7ddc32018d5e9963fa9f8ca90bf2d3db 100644 (file)
@@ -340,7 +340,8 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
         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;
index d45f565e25c2214c9e75ba8f5414d5a44aaac420..3c3b2e8ff4109c4e44482622d1e997875239a526 100644 (file)
@@ -240,8 +240,85 @@ void RegisterInfoEmitter::run(std::ostream &OS) {
          << 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 @@ void RegisterInfoEmitter::run(std::ostream &OS) {
          << RC.getName() + "VTs" << ", "
          << RC.getName() + "Subclasses" << ", "
          << RC.getName() + "Superclasses" << ", "
+         << RC.getName() + "SubRegClasses" << ", "
+         << RC.getName() + "SuperRegClasses" << ", "
          << RC.SpillSize/8 << ", "
          << RC.SpillAlignment/8 << ", "
          << RC.CopyCost << ", "