1//===---------- SystemZPhysRegCopy.cpp - Handle phys reg copies -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass makes sure that a COPY of a physical register will be
10// implementable after register allocation in copyPhysReg() (this could be
11// done in EmitInstrWithCustomInserter() instead if COPY instructions would
12// be passed to it).
13//
14//===----------------------------------------------------------------------===//
15
16#include "SystemZTargetMachine.h"
17#include "llvm/CodeGen/MachineDominators.h"
18#include "llvm/CodeGen/MachineFunctionPass.h"
19#include "llvm/CodeGen/MachineInstrBuilder.h"
20#include "llvm/CodeGen/MachineRegisterInfo.h"
21#include "llvm/CodeGen/TargetInstrInfo.h"
22#include "llvm/CodeGen/TargetRegisterInfo.h"
23
24using namespace llvm;
25
26namespace {
27
28class SystemZCopyPhysRegs : public MachineFunctionPass {
29public:
30 static char ID;
31 SystemZCopyPhysRegs() : MachineFunctionPass(ID), TII(nullptr), MRI(nullptr) {}
32
33 bool runOnMachineFunction(MachineFunction &MF) override;
34 void getAnalysisUsage(AnalysisUsage &AU) const override;
35
36private:
37
38 bool visitMBB(MachineBasicBlock &MBB);
39
40 const SystemZInstrInfo *TII;
41 MachineRegisterInfo *MRI;
42};
43
44char SystemZCopyPhysRegs::ID = 0;
45
46} // end anonymous namespace
47
48INITIALIZE_PASS(SystemZCopyPhysRegs, "systemz-copy-physregs",
49 "SystemZ Copy Physregs", false, false)
50
51FunctionPass *llvm::createSystemZCopyPhysRegsPass(SystemZTargetMachine &TM) {
52 return new SystemZCopyPhysRegs();
53}
54
55void SystemZCopyPhysRegs::getAnalysisUsage(AnalysisUsage &AU) const {
56 AU.setPreservesCFG();
57 MachineFunctionPass::getAnalysisUsage(AU);
58}
59
60bool SystemZCopyPhysRegs::visitMBB(MachineBasicBlock &MBB) {
61 bool Modified = false;
62
63 // Certain special registers can only be copied from a subset of the
64 // default register class of the type. It is therefore necessary to create
65 // the target copy instructions before regalloc instead of in copyPhysReg().
66 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
67 MBBI != E; ) {
68 MachineInstr *MI = &*MBBI++;
69 if (!MI->isCopy())
70 continue;
71
72 DebugLoc DL = MI->getDebugLoc();
73 Register SrcReg = MI->getOperand(i: 1).getReg();
74 Register DstReg = MI->getOperand(i: 0).getReg();
75
76 if (DstReg.isVirtual() &&
77 (SrcReg == SystemZ::CC || SystemZ::AR32BitRegClass.contains(Reg: SrcReg))) {
78 Register Tmp = MRI->createVirtualRegister(RegClass: &SystemZ::GR32BitRegClass);
79 if (SrcReg == SystemZ::CC)
80 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII->get(Opcode: SystemZ::IPM), DestReg: Tmp);
81 else
82 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII->get(Opcode: SystemZ::EAR), DestReg: Tmp).addReg(RegNo: SrcReg);
83 MI->getOperand(i: 1).setReg(Tmp);
84 Modified = true;
85 }
86 else if (SrcReg.isVirtual() &&
87 SystemZ::AR32BitRegClass.contains(Reg: DstReg)) {
88 Register Tmp = MRI->createVirtualRegister(RegClass: &SystemZ::GR32BitRegClass);
89 MI->getOperand(i: 0).setReg(Tmp);
90 MachineInstr *NMI =
91 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: SystemZ::SAR), DestReg: DstReg).addReg(RegNo: Tmp);
92 // SAR now writes the final value to DstReg, so update debug values.
93 MBB.getParent()->substituteDebugValuesForInst(Old: *MI, New&: *NMI);
94 Modified = true;
95 }
96 }
97
98 return Modified;
99}
100
101bool SystemZCopyPhysRegs::runOnMachineFunction(MachineFunction &F) {
102 TII = F.getSubtarget<SystemZSubtarget>().getInstrInfo();
103 MRI = &F.getRegInfo();
104
105 bool Modified = false;
106 for (auto &MBB : F)
107 Modified |= visitMBB(MBB);
108
109 return Modified;
110}
111
112