| //===---------- SystemZPhysRegCopy.cpp - Handle phys reg copies -----------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This pass makes sure that a COPY of a physical register will be | |
| // implementable after register allocation in copyPhysReg() (this could be | |
| // done in EmitInstrWithCustomInserter() instead if COPY instructions would | |
| // be passed to it). | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "SystemZTargetMachine.h" | |
| #include "llvm/CodeGen/MachineDominators.h" | |
| #include "llvm/CodeGen/MachineFunctionPass.h" | |
| #include "llvm/CodeGen/MachineInstrBuilder.h" | |
| #include "llvm/CodeGen/MachineRegisterInfo.h" | |
| #include "llvm/CodeGen/TargetInstrInfo.h" | |
| #include "llvm/CodeGen/TargetRegisterInfo.h" | |
| using namespace llvm; | |
| namespace { | |
| class SystemZCopyPhysRegs : public MachineFunctionPass { | |
| public: | |
| static char ID; | |
| SystemZCopyPhysRegs() : MachineFunctionPass(ID), TII(nullptr), MRI(nullptr) {} | |
| bool runOnMachineFunction(MachineFunction &MF) override; | |
| void getAnalysisUsage(AnalysisUsage &AU) const override; | |
| private: | |
| bool visitMBB(MachineBasicBlock &MBB); | |
| const SystemZInstrInfo *TII; | |
| MachineRegisterInfo *MRI; | |
| }; | |
| char SystemZCopyPhysRegs::ID = 0; | |
| } // end anonymous namespace | |
| INITIALIZE_PASS(SystemZCopyPhysRegs, "systemz-copy-physregs", | |
| "SystemZ Copy Physregs", false, false) | |
| FunctionPass *llvm::createSystemZCopyPhysRegsPass(SystemZTargetMachine &TM) { | |
| return new SystemZCopyPhysRegs(); | |
| } | |
| void SystemZCopyPhysRegs::getAnalysisUsage(AnalysisUsage &AU) const { | |
| AU.setPreservesCFG(); | |
| MachineFunctionPass::getAnalysisUsage(AU); | |
| } | |
| bool SystemZCopyPhysRegs::visitMBB(MachineBasicBlock &MBB) { | |
| bool Modified = false; | |
| // Certain special registers can only be copied from a subset of the | |
| // default register class of the type. It is therefore necessary to create | |
| // the target copy instructions before regalloc instead of in copyPhysReg(). | |
| for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); | |
| MBBI != E; ) { | |
| MachineInstr *MI = &*MBBI++; | |
| if (!MI->isCopy()) | |
| continue; | |
| DebugLoc DL = MI->getDebugLoc(); | |
| Register SrcReg = MI->getOperand(1).getReg(); | |
| Register DstReg = MI->getOperand(0).getReg(); | |
| if (DstReg.isVirtual() && | |
| (SrcReg == SystemZ::CC || SystemZ::AR32BitRegClass.contains(SrcReg))) { | |
| Register Tmp = MRI->createVirtualRegister(&SystemZ::GR32BitRegClass); | |
| if (SrcReg == SystemZ::CC) | |
| BuildMI(MBB, MI, DL, TII->get(SystemZ::IPM), Tmp); | |
| else | |
| BuildMI(MBB, MI, DL, TII->get(SystemZ::EAR), Tmp).addReg(SrcReg); | |
| MI->getOperand(1).setReg(Tmp); | |
| Modified = true; | |
| } | |
| else if (SrcReg.isVirtual() && | |
| SystemZ::AR32BitRegClass.contains(DstReg)) { | |
| Register Tmp = MRI->createVirtualRegister(&SystemZ::GR32BitRegClass); | |
| MI->getOperand(0).setReg(Tmp); | |
| MachineInstr *NMI = | |
| BuildMI(MBB, MBBI, DL, TII->get(SystemZ::SAR), DstReg).addReg(Tmp); | |
| // SAR now writes the final value to DstReg, so update debug values. | |
| MBB.getParent()->substituteDebugValuesForInst(*MI, *NMI); | |
| Modified = true; | |
| } | |
| } | |
| return Modified; | |
| } | |
| bool SystemZCopyPhysRegs::runOnMachineFunction(MachineFunction &F) { | |
| TII = F.getSubtarget<SystemZSubtarget>().getInstrInfo(); | |
| MRI = &F.getRegInfo(); | |
| bool Modified = false; | |
| for (auto &MBB : F) | |
| Modified |= visitMBB(MBB); | |
| return Modified; | |
| } | |