LLVM 23.0.0git
PPCVSXWACCCopy.cpp
Go to the documentation of this file.
1//===--------- PPCVSXWACCCopy.cpp - VSX and WACC Copy Legalization --------===//
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// A pass which deals with the complexity of generating legal VSX register
10// copies to/from register classes which partially overlap with the VSX
11// register file and combines the wacc/wacc_hi copies when needed.
12//
13//===----------------------------------------------------------------------===//
14
15#include "PPC.h"
16#include "PPCInstrInfo.h"
17#include "PPCTargetMachine.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/Statistic.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "ppc-vsx-copy"
30
31namespace {
32// PPCVSXWACCCopy pass - For copies between VSX registers and non-VSX registers
33// (Altivec and scalar floating-point registers), we need to transform the
34// copies into subregister copies with other restrictions.
35struct PPCVSXWACCCopy : public MachineFunctionPass {
36 static char ID;
37 PPCVSXWACCCopy() : MachineFunctionPass(ID) {}
38
39 const TargetInstrInfo *TII;
40
41 bool IsRegInClass(unsigned Reg, const TargetRegisterClass *RC,
44 return RC->hasSubClassEq(MRI.getRegClass(Reg));
45 } else if (RC->contains(Reg)) {
46 return true;
47 }
48
49 return false;
50 }
51
52 bool IsVSReg(unsigned Reg, MachineRegisterInfo &MRI) {
53 return IsRegInClass(Reg, &PPC::VSRCRegClass, MRI);
54 }
55
56 bool IsVRReg(unsigned Reg, MachineRegisterInfo &MRI) {
57 return IsRegInClass(Reg, &PPC::VRRCRegClass, MRI);
58 }
59
60 bool IsF8Reg(unsigned Reg, MachineRegisterInfo &MRI) {
61 return IsRegInClass(Reg, &PPC::F8RCRegClass, MRI);
62 }
63
64 bool IsVSFReg(unsigned Reg, MachineRegisterInfo &MRI) {
65 return IsRegInClass(Reg, &PPC::VSFRCRegClass, MRI);
66 }
67
68 bool IsVSSReg(unsigned Reg, MachineRegisterInfo &MRI) {
69 return IsRegInClass(Reg, &PPC::VSSRCRegClass, MRI);
70 }
71
72protected:
73 bool processBlock(MachineBasicBlock &MBB) {
74 bool Changed = false;
75
76 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
77 for (MachineInstr &MI : MBB) {
78 if (!MI.isFullCopy())
79 continue;
80
81 MachineOperand &DstMO = MI.getOperand(0);
82 MachineOperand &SrcMO = MI.getOperand(1);
83
84 if (IsVSReg(DstMO.getReg(), MRI) && !IsVSReg(SrcMO.getReg(), MRI)) {
85 // This is a copy *to* a VSX register from a non-VSX register.
86 Changed = true;
87
88 const TargetRegisterClass *SrcRC = &PPC::VSLRCRegClass;
89 assert((IsF8Reg(SrcMO.getReg(), MRI) || IsVSSReg(SrcMO.getReg(), MRI) ||
90 IsVSFReg(SrcMO.getReg(), MRI)) &&
91 "Unknown source for a VSX copy");
92
93 Register NewVReg = MRI.createVirtualRegister(SrcRC);
94 BuildMI(MBB, MI, MI.getDebugLoc(),
95 TII->get(TargetOpcode::SUBREG_TO_REG), NewVReg)
96 .add(SrcMO)
97 .addImm(PPC::sub_64);
98
99 // The source of the original copy is now the new virtual register.
100 SrcMO.setReg(NewVReg);
101 } else if (!IsVSReg(DstMO.getReg(), MRI) &&
102 IsVSReg(SrcMO.getReg(), MRI)) {
103 // This is a copy *from* a VSX register to a non-VSX register.
104 Changed = true;
105
106 const TargetRegisterClass *DstRC = &PPC::VSLRCRegClass;
107 assert((IsF8Reg(DstMO.getReg(), MRI) || IsVSFReg(DstMO.getReg(), MRI) ||
108 IsVSSReg(DstMO.getReg(), MRI)) &&
109 "Unknown destination for a VSX copy");
110
111 // Copy the VSX value into a new VSX register of the correct subclass.
112 Register NewVReg = MRI.createVirtualRegister(DstRC);
113 BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
114 NewVReg)
115 .add(SrcMO);
116
117 // Transform the original copy into a subregister extraction copy.
118 SrcMO.setReg(NewVReg);
119 SrcMO.setSubReg(PPC::sub_64);
120 } else if (IsRegInClass(DstMO.getReg(), &PPC::WACC_HIRCRegClass, MRI) &&
121 IsRegInClass(SrcMO.getReg(), &PPC::WACCRCRegClass, MRI)) {
122 // Matches the pattern:
123 // %a:waccrc = COPY %b.sub_wacc_hi:dmrrc
124 // %c:wacc_hirc = COPY %a:waccrc
125 // And replaces it with:
126 // %c:wacc_hirc = COPY %b.sub_wacc_hi:dmrrc
127 MachineInstr *DefMI = MRI.getUniqueVRegDef(SrcMO.getReg());
128 if (!DefMI || !DefMI->isCopy())
129 continue;
130
131 MachineOperand &OrigSrc = DefMI->getOperand(1);
132
133 if (!IsRegInClass(OrigSrc.getReg(), &PPC::DMRRCRegClass, MRI))
134 continue;
135
136 if (OrigSrc.getSubReg() != PPC::sub_wacc_hi)
137 continue;
138
139 // Rewrite the second copy to use the original register's subreg
140 SrcMO.setReg(OrigSrc.getReg());
141 SrcMO.setSubReg(PPC::sub_wacc_hi);
142 Changed = true;
143
144 // Remove the intermediate copy if safe
145 if (MRI.use_nodbg_empty(DefMI->getOperand(0).getReg()))
146 DefMI->eraseFromParent();
147 }
148 }
149
150 return Changed;
151 }
152
153public:
154 bool runOnMachineFunction(MachineFunction &MF) override {
155 // If we don't have VSX on the subtarget, don't do anything.
156 const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
157 if (!STI.hasVSX())
158 return false;
159 TII = STI.getInstrInfo();
160
161 bool Changed = false;
162
164 if (processBlock(B))
165 Changed = true;
166
167 return Changed;
168 }
169
170 void getAnalysisUsage(AnalysisUsage &AU) const override {
172 }
173};
174} // end anonymous namespace
175
176INITIALIZE_PASS(PPCVSXWACCCopy, DEBUG_TYPE, "PowerPC VSX Copy Legalization",
177 false, false)
178
179char PPCVSXWACCCopy::ID = 0;
180FunctionPass *llvm::createPPCVSXWACCCopyPass() { return new PPCVSXWACCCopy(); }
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Register Reg
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file contains some templates that are useful if you are working with the STL at all.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const PPCInstrInfo * getInstrInfo() const override
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:66
TargetInstrInfo - Interface to description of machine instruction set.
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
bool hasSubClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
Changed
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:634
FunctionPass * createPPCVSXWACCCopyPass()