diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h index 58cf89f77070d..93dfcfc399247 100644 --- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -1150,6 +1150,10 @@ class TargetInstrInfo : public MCInstrInfo { MachineInstr &LoadMI, LiveIntervals *LIS = nullptr) const; + /// This function defines the logic to lower COPY instruction to + /// target specific instruction(s). + void lowerCopy(MachineInstr *MI, const TargetRegisterInfo *TRI) const; + /// Return true when there is potentially a faster code sequence /// for an instruction chain ending in \p Root. All potential patterns are /// returned in the \p Pattern vector. Pattern should be sorted in priority diff --git a/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp b/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp index 68a11b4742395..3a79f20f47322 100644 --- a/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp +++ b/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp @@ -47,9 +47,6 @@ struct ExpandPostRA : public MachineFunctionPass { private: bool LowerSubregToReg(MachineInstr *MI); - bool LowerCopy(MachineInstr *MI); - - void TransferImplicitOperands(MachineInstr *MI); }; } // end anonymous namespace @@ -59,25 +56,6 @@ char &llvm::ExpandPostRAPseudosID = ExpandPostRA::ID; INITIALIZE_PASS(ExpandPostRA, DEBUG_TYPE, "Post-RA pseudo instruction expansion pass", false, false) -/// TransferImplicitOperands - MI is a pseudo-instruction, and the lowered -/// replacement instructions immediately precede it. Copy any implicit -/// operands from MI to the replacement instruction. -void ExpandPostRA::TransferImplicitOperands(MachineInstr *MI) { - MachineBasicBlock::iterator CopyMI = MI; - --CopyMI; - - Register DstReg = MI->getOperand(0).getReg(); - for (const MachineOperand &MO : MI->implicit_operands()) { - CopyMI->addOperand(MO); - - // Be conservative about preserving kills when subregister defs are - // involved. If there was implicit kill of a super-register overlapping the - // copy result, we would kill the subregisters previous copies defined. - if (MO.isKill() && TRI->regsOverlap(DstReg, MO.getReg())) - CopyMI->getOperand(CopyMI->getNumOperands() - 1).setIsKill(false); - } -} - bool ExpandPostRA::LowerSubregToReg(MachineInstr *MI) { MachineBasicBlock *MBB = MI->getParent(); assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) && @@ -137,50 +115,6 @@ bool ExpandPostRA::LowerSubregToReg(MachineInstr *MI) { return true; } -bool ExpandPostRA::LowerCopy(MachineInstr *MI) { - - if (MI->allDefsAreDead()) { - LLVM_DEBUG(dbgs() << "dead copy: " << *MI); - MI->setDesc(TII->get(TargetOpcode::KILL)); - LLVM_DEBUG(dbgs() << "replaced by: " << *MI); - return true; - } - - MachineOperand &DstMO = MI->getOperand(0); - MachineOperand &SrcMO = MI->getOperand(1); - - bool IdentityCopy = (SrcMO.getReg() == DstMO.getReg()); - if (IdentityCopy || SrcMO.isUndef()) { - LLVM_DEBUG(dbgs() << (IdentityCopy ? "identity copy: " : "undef copy: ") - << *MI); - // No need to insert an identity copy instruction, but replace with a KILL - // if liveness is changed. - if (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)); - LLVM_DEBUG(dbgs() << "replaced by: " << *MI); - return true; - } - // Vanilla identity copy. - MI->eraseFromParent(); - return true; - } - - LLVM_DEBUG(dbgs() << "real copy: " << *MI); - TII->copyPhysReg(*MI->getParent(), MI, MI->getDebugLoc(), - DstMO.getReg(), SrcMO.getReg(), SrcMO.isKill()); - - if (MI->getNumOperands() > 2) - TransferImplicitOperands(MI); - LLVM_DEBUG({ - MachineBasicBlock::iterator dMI = MI; - dbgs() << "replaced by: " << *(--dMI); - }); - MI->eraseFromParent(); - return true; -} - /// runOnMachineFunction - Reduce subregister inserts and extracts to register /// copies. /// @@ -211,7 +145,8 @@ bool ExpandPostRA::runOnMachineFunction(MachineFunction &MF) { MadeChange |= LowerSubregToReg(&MI); break; case TargetOpcode::COPY: - MadeChange |= LowerCopy(&MI); + TII->lowerCopy(&MI, TRI); + MadeChange = true; break; case TargetOpcode::DBG_VALUE: continue; diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp index c3a79933136b6..b29404b425190 100644 --- a/llvm/lib/CodeGen/TargetInstrInfo.cpp +++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp @@ -696,6 +696,61 @@ MachineInstr *TargetInstrInfo::foldMemoryOperand(MachineInstr &MI, return NewMI; } +/// transferImplicitOperands - MI is a pseudo-instruction, and the lowered +/// replacement instructions immediately precede it. Copy any implicit +/// operands from MI to the replacement instruction. +static void transferImplicitOperands(MachineInstr *MI, + const TargetRegisterInfo *TRI) { + MachineBasicBlock::iterator CopyMI = MI; + --CopyMI; + + Register DstReg = MI->getOperand(0).getReg(); + for (const MachineOperand &MO : MI->implicit_operands()) { + CopyMI->addOperand(MO); + + // Be conservative about preserving kills when subregister defs are + // involved. If there was implicit kill of a super-register overlapping the + // copy result, we would kill the subregisters previous copies defined. + + if (MO.isKill() && TRI->regsOverlap(DstReg, MO.getReg())) + CopyMI->getOperand(CopyMI->getNumOperands() - 1).setIsKill(false); + } +} + +void TargetInstrInfo::lowerCopy(MachineInstr *MI, + const TargetRegisterInfo *TRI) const { + if (MI->allDefsAreDead()) { + MI->setDesc(get(TargetOpcode::KILL)); + return; + } + + MachineOperand &DstMO = MI->getOperand(0); + MachineOperand &SrcMO = MI->getOperand(1); + + bool IdentityCopy = (SrcMO.getReg() == DstMO.getReg()); + if (IdentityCopy || SrcMO.isUndef()) { + // No need to insert an identity copy instruction, but replace with a KILL + // if liveness is changed. + if (SrcMO.isUndef() || MI->getNumOperands() > 2) { + // We must make sure the super-register gets killed. Replace the + // instruction with KILL. + MI->setDesc(get(TargetOpcode::KILL)); + return; + } + // Vanilla identity copy. + MI->eraseFromParent(); + return; + } + + copyPhysReg(*MI->getParent(), MI, MI->getDebugLoc(), DstMO.getReg(), + SrcMO.getReg(), SrcMO.isKill()); + + if (MI->getNumOperands() > 2) + transferImplicitOperands(MI, TRI); + MI->eraseFromParent(); + return; +} + bool TargetInstrInfo::hasReassociableOperands( const MachineInstr &Inst, const MachineBasicBlock *MBB) const { const MachineOperand &Op1 = Inst.getOperand(1);