[llvm-commits] [llvm] r40520 - in /llvm/trunk: include/llvm/CodeGen/ScheduleDAG.h lib/CodeGen/SelectionDAG/ScheduleDAG.cpp

Christopher Lamb christopher.lamb at gmail.com
Thu Jul 26 01:12:10 PDT 2007


Author: clamb
Date: Thu Jul 26 03:12:07 2007
New Revision: 40520

URL: http://llvm.org/viewvc/llvm-project?rev=40520&view=rev
Log:
Teach DAG scheduling how to properly emit subreg insert/extract machine instructions. PR1350

Modified:
    llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp

Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h?rev=40520&r1=40519&r2=40520&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h (original)
+++ llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h Thu Jul 26 03:12:07 2007
@@ -255,6 +255,11 @@
     virtual void Schedule() {}
 
   private:
+    /// EmitSubregNode - Generate machine code for subreg nodes.
+    ///
+    void EmitSubregNode(SDNode *Node, 
+                        DenseMap<SDOperand, unsigned> &VRBaseMap);
+  
     void AddOperand(MachineInstr *MI, SDOperand Op, unsigned IIOpNum,
                     const TargetInstrDescriptor *II,
                     DenseMap<SDOperand, unsigned> &VRBaseMap);

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

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Thu Jul 26 03:12:07 2007
@@ -429,6 +429,148 @@
   return 0;
 }
 
+// Returns the Register Class of a subregister
+static const TargetRegisterClass *getSubRegisterRegClass(
+        const TargetRegisterClass *TRC,
+        unsigned SubIdx) {
+  // Pick the register class of the subregister
+  MRegisterInfo::regclass_iterator I = TRC->subregclasses_begin() + SubIdx-1;
+  assert(I < TRC->subregclasses_end() && 
+         "Invalid subregister index for register class");
+  return *I;
+}
+
+static const TargetRegisterClass *getSuperregRegisterClass(
+        const TargetRegisterClass *TRC,
+        unsigned SubIdx,
+        MVT::ValueType VT) {
+  // Pick the register class of the superegister for this type
+  for (MRegisterInfo::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.
+///
+void ScheduleDAG::EmitSubregNode(SDNode *Node, 
+                           DenseMap<SDOperand, unsigned> &VRBaseMap) {
+  unsigned VRBase = 0;
+  unsigned Opc = Node->getTargetOpcode();
+  if (Opc == TargetInstrInfo::EXTRACT_SUBREG) {
+    // If the node 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.
+    for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
+         UI != E; ++UI) {
+      SDNode *Use = *UI;
+      if (Use->getOpcode() == ISD::CopyToReg && 
+          Use->getOperand(2).Val == Node) {
+        unsigned DestReg = cast<RegisterSDNode>(Use->getOperand(1))->getReg();
+        if (MRegisterInfo::isVirtualRegister(DestReg)) {
+          VRBase = DestReg;
+          break;
+        }
+      }
+    }
+    
+    unsigned SubIdx = cast<ConstantSDNode>(Node->getOperand(1))->getValue();
+    
+    // TODO: If the node is a use of a CopyFromReg from a physical register
+    // fold the extract into the copy now
+
+    // TODO: Add tracking info to SSARegMap of which vregs are subregs
+    // to allow coalescing in the allocator
+    
+    // Create the extract_subreg machine instruction.
+    MachineInstr *MI =
+      new MachineInstr(BB, TII->get(TargetInstrInfo::EXTRACT_SUBREG));
+
+    // Figure out the register class to create for the destreg.
+    unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
+    const TargetRegisterClass *TRC = RegMap->getRegClass(VReg);
+    const TargetRegisterClass *SRC = getSubRegisterRegClass(TRC, SubIdx);
+
+    if (VRBase) {
+      // Grab the destination register
+      const TargetRegisterClass *DRC = 0;
+      DRC = RegMap->getRegClass(VRBase);
+      assert(SRC == DRC && 
+             "Source subregister and destination must have the same class");
+    } else {
+      // Create the reg
+      VRBase = RegMap->createVirtualRegister(SRC);
+    }
+    
+    // Add def, source, and subreg index
+    MI->addRegOperand(VRBase, true);
+    AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap);
+    MI->addImmOperand(SubIdx);
+    
+  } else if (Opc == TargetInstrInfo::INSERT_SUBREG) {
+    assert((Node->getNumOperands() == 2 || Node->getNumOperands() == 3) &&
+            "Malformed insert_subreg node");
+    bool isUndefInput = (Node->getNumOperands() == 2);
+    unsigned SubReg = 0;
+    unsigned SubIdx = 0;
+    
+    if (isUndefInput) {
+      SubReg = getVR(Node->getOperand(0), VRBaseMap);
+      SubIdx = cast<ConstantSDNode>(Node->getOperand(1))->getValue();
+    } else {
+      SubReg = getVR(Node->getOperand(1), VRBaseMap);
+      SubIdx = cast<ConstantSDNode>(Node->getOperand(2))->getValue();
+    }
+    
+    // TODO: Add tracking info to SSARegMap of which vregs are subregs
+    // to allow coalescing in the allocator
+          
+    // If the node 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.
+    // If the CopyToReg'd destination register is physical, then fold the
+    // insert into the copy
+    for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
+         UI != E; ++UI) {
+      SDNode *Use = *UI;
+      if (Use->getOpcode() == ISD::CopyToReg && 
+          Use->getOperand(2).Val == Node) {
+        unsigned DestReg = cast<RegisterSDNode>(Use->getOperand(1))->getReg();
+        if (MRegisterInfo::isVirtualRegister(DestReg)) {
+          VRBase = DestReg;
+          break;
+        }
+      }
+    }
+    
+    // Create the insert_subreg machine instruction.
+    MachineInstr *MI =
+      new MachineInstr(BB, TII->get(TargetInstrInfo::INSERT_SUBREG));
+      
+    // Figure out the register class to create for the destreg.
+    const TargetRegisterClass *TRC = 0;
+    if (VRBase) {
+      TRC = RegMap->getRegClass(VRBase);
+    } else {
+      TRC = getSuperregRegisterClass(RegMap->getRegClass(SubReg), 
+                                     SubIdx, 
+                                     Node->getValueType(0));
+      assert(TRC && "Couldn't determine register class for insert_subreg");
+      VRBase = RegMap->createVirtualRegister(TRC); // Create the reg
+    }
+    
+    MI->addRegOperand(VRBase, true);
+    AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap);
+    if (!isUndefInput)
+      AddOperand(MI, Node->getOperand(1), 0, 0, VRBaseMap);
+    MI->addImmOperand(SubIdx);
+  } else
+    assert(0 && "Node is not a subreg insert or extract");
+     
+  bool isNew = VRBaseMap.insert(std::make_pair(SDOperand(Node,0), VRBase));
+  assert(isNew && "Node emitted out of order - early");
+}
+
 /// EmitNode - Generate machine code for an node and needed dependencies.
 ///
 void ScheduleDAG::EmitNode(SDNode *Node, 
@@ -436,6 +578,14 @@
   // If machine instruction
   if (Node->isTargetOpcode()) {
     unsigned Opc = Node->getTargetOpcode();
+    
+    // Handle subreg insert/extract specially
+    if (Opc == TargetInstrInfo::EXTRACT_SUBREG || 
+        Opc == TargetInstrInfo::INSERT_SUBREG) {
+      EmitSubregNode(Node, VRBaseMap);
+      return;
+    }
+    
     const TargetInstrDescriptor &II = TII->get(Opc);
 
     unsigned NumResults = CountResults(Node);





More information about the llvm-commits mailing list