Add a new target independent COPY instruction and code to lower it.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 2 Jul 2010 22:29:50 +0000 (22:29 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 2 Jul 2010 22:29:50 +0000 (22:29 +0000)
The COPY instruction is intended to replace the target specific copy
instructions for virtual registers as well as the EXTRACT_SUBREG and
INSERT_SUBREG instructions in MachineFunctions. It won't we used in a selection
DAG.

COPY is lowered to native register copies by LowerSubregs.

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

include/llvm/CodeGen/MachineInstr.h
include/llvm/Target/Target.td
include/llvm/Target/TargetOpcodes.h
lib/CodeGen/LowerSubregs.cpp
utils/TableGen/CodeGenTarget.cpp

index 44d716e7344f27d7647314402dd1e08b64cbf6ab..003ed15f056a3a6a0616c21cb086ccf218e095b6 100644 (file)
@@ -227,7 +227,10 @@ public:
   bool isRegSequence() const {
     return getOpcode() == TargetOpcode::REG_SEQUENCE;
   }
-  
+  bool isCopy() const {
+    return getOpcode() == TargetOpcode::COPY;
+  }
+
   /// readsRegister - Return true if the MachineInstr reads the specified
   /// register. If TargetRegisterInfo is passed, then it also checks if there
   /// is a read of a super-register.
index 51a501ed207a50bd9cf339ca3b23bd6296b78416..9a89dc942d6c4f968606578bc63f2682940cc43e 100644 (file)
@@ -476,7 +476,6 @@ def DBG_VALUE : Instruction {
   let AsmString = "DBG_VALUE";
   let isAsCheapAsAMove = 1;
 }
-
 def REG_SEQUENCE : Instruction {
   let OutOperandList = (outs unknown:$dst);
   let InOperandList = (ins variable_ops);
@@ -484,6 +483,13 @@ def REG_SEQUENCE : Instruction {
   let neverHasSideEffects = 1;
   let isAsCheapAsAMove = 1;
 }
+def COPY : Instruction {
+  let OutOperandList = (outs unknown:$dst);
+  let InOperandList = (ins unknown:$src);
+  let AsmString = "";
+  let neverHasSideEffects = 1;
+  let isAsCheapAsAMove = 1;
+}
 }
 
 //===----------------------------------------------------------------------===//
index 55e93eccc3cbc3018f9ff59ded3f314027eafe66..e710c702194b91cad68bd69073333e48a93b7f12 100644 (file)
@@ -75,7 +75,11 @@ namespace TargetOpcode {
     /// e.g. v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5
     /// After register coalescing references of v1024 should be replace with
     /// v1027:3, v1025 with v1027:4, etc.
-    REG_SEQUENCE = 12
+    REG_SEQUENCE = 12,
+
+    /// COPY - Target-independent register copy. This instruction can also be
+    /// used to copy between subregisters of virtual registers.
+    COPY = 13
   };
 } // end namespace TargetOpcode
 } // end namespace llvm
index 2dfd07f7f23147a0ddfc82a365e2f72ea56d97d7..172e4b579505db76b85037bfa9ac953e6a86dfc6 100644 (file)
@@ -56,6 +56,7 @@ namespace {
     bool LowerExtract(MachineInstr *MI);
     bool LowerInsert(MachineInstr *MI);
     bool LowerSubregToReg(MachineInstr *MI);
+    bool LowerCopy(MachineInstr *MI);
 
     void TransferDeadFlag(MachineInstr *MI, unsigned DstReg,
                           const TargetRegisterInfo *TRI);
@@ -321,6 +322,52 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
   return true;
 }
 
+bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) {
+  MachineOperand &DstMO = MI->getOperand(0);
+  MachineOperand &SrcMO = MI->getOperand(1);
+
+  if (SrcMO.getReg() == DstMO.getReg()) {
+    DEBUG(dbgs() << "identity copy: " << *MI);
+    // No need to insert an identity copy instruction, but replace with a KILL
+    // if liveness is changed.
+    if (DstMO.isDead() || SrcMO.isUndef() || MI->getNumOperands() > 2) {
+      // We must make sure the super-register gets killed. Replace the
+      // instruction with KILL.
+      MI->setDesc(TII->get(TargetOpcode::KILL));
+      DEBUG(dbgs() << "replaced by:   " << *MI);
+      return true;
+    }
+    // Vanilla identity copy.
+    MI->eraseFromParent();
+    return true;
+  }
+
+  DEBUG(dbgs() << "real copy:   " << *MI);
+  // Ask target for a lowered copy instruction.
+  const TargetRegisterClass *DstRC =
+    TRI->getPhysicalRegisterRegClass(DstMO.getReg());
+  const TargetRegisterClass *SrcRC =
+    TRI->getPhysicalRegisterRegClass(SrcMO.getReg());
+  bool Emitted = TII->copyRegToReg(*MI->getParent(), MI,
+                                   DstMO.getReg(), SrcMO.getReg(),
+                                   DstRC, SrcRC, MI->getDebugLoc());
+  (void)Emitted;
+  assert(Emitted && "Cannot emit copy");
+
+  if (DstMO.isDead())
+    TransferDeadFlag(MI, DstMO.getReg(), TRI);
+  if (SrcMO.isKill())
+    TransferKillFlag(MI, SrcMO.getReg(), TRI, true);
+  if (MI->getNumOperands() > 2)
+    TransferImplicitDefs(MI);
+  DEBUG({
+    MachineBasicBlock::iterator dMI = MI;
+    dbgs() << "replaced by: " << *(--dMI);
+  });
+  MI->eraseFromParent();
+  return true;
+}
+
 /// runOnMachineFunction - Reduce subregister inserts and extracts to register
 /// copies.
 ///
@@ -346,6 +393,8 @@ bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) {
         MadeChange |= LowerInsert(MI);
       } else if (MI->isSubregToReg()) {
         MadeChange |= LowerSubregToReg(MI);
+      } else if (MI->isCopy()) {
+        MadeChange |= LowerCopy(MI);
       }
       mi = nmi;
     }
index 72cea14ea6bf2cf238efa6864f2b04bd44767cb6..d8130fb36ddecd606df78002c6c2d4539271c2c0 100644 (file)
@@ -344,6 +344,7 @@ void CodeGenTarget::ComputeInstrsByEnum() const {
     "COPY_TO_REGCLASS",
     "DBG_VALUE",
     "REG_SEQUENCE",
+    "COPY",
     0
   };
   const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();