diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 44d716e7344..003ed15f056 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -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. diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 51a501ed207..9a89dc942d6 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -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; +} } //===----------------------------------------------------------------------===// diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h index 55e93eccc3c..e710c702194 100644 --- a/include/llvm/Target/TargetOpcodes.h +++ b/include/llvm/Target/TargetOpcodes.h @@ -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 diff --git a/lib/CodeGen/LowerSubregs.cpp b/lib/CodeGen/LowerSubregs.cpp index 2dfd07f7f23..172e4b57950 100644 --- a/lib/CodeGen/LowerSubregs.cpp +++ b/lib/CodeGen/LowerSubregs.cpp @@ -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; } diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 72cea14ea6b..d8130fb36dd 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -344,6 +344,7 @@ void CodeGenTarget::ComputeInstrsByEnum() const { "COPY_TO_REGCLASS", "DBG_VALUE", "REG_SEQUENCE", + "COPY", 0 }; const DenseMap &Insts = getInstructions();