1ff0cc061SDimitry Andric //===-------------- PPCVSXCopy.cpp - VSX Copy Legalization ----------------===//
2ff0cc061SDimitry Andric //
3ff0cc061SDimitry Andric // The LLVM Compiler Infrastructure
4ff0cc061SDimitry Andric //
5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source
6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details.
7ff0cc061SDimitry Andric //
8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
9ff0cc061SDimitry Andric //
10ff0cc061SDimitry Andric // A pass which deals with the complexity of generating legal VSX register
11ff0cc061SDimitry Andric // copies to/from register classes which partially overlap with the VSX
12ff0cc061SDimitry Andric // register file.
13ff0cc061SDimitry Andric //
14ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
15ff0cc061SDimitry Andric
163ca95b02SDimitry Andric #include "MCTargetDesc/PPCPredicates.h"
17*db17bf38SDimitry Andric #include "PPC.h"
18ff0cc061SDimitry Andric #include "PPCHazardRecognizers.h"
19ff0cc061SDimitry Andric #include "PPCInstrBuilder.h"
203ca95b02SDimitry Andric #include "PPCInstrInfo.h"
21ff0cc061SDimitry Andric #include "PPCMachineFunctionInfo.h"
22ff0cc061SDimitry Andric #include "PPCTargetMachine.h"
23ff0cc061SDimitry Andric #include "llvm/ADT/STLExtras.h"
24ff0cc061SDimitry Andric #include "llvm/ADT/Statistic.h"
25ff0cc061SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
26ff0cc061SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
27ff0cc061SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
28ff0cc061SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
29ff0cc061SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
30ff0cc061SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
31ff0cc061SDimitry Andric #include "llvm/Support/Debug.h"
32ff0cc061SDimitry Andric #include "llvm/Support/ErrorHandling.h"
33ff0cc061SDimitry Andric #include "llvm/Support/TargetRegistry.h"
34ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h"
35ff0cc061SDimitry Andric
36ff0cc061SDimitry Andric using namespace llvm;
37ff0cc061SDimitry Andric
38ff0cc061SDimitry Andric #define DEBUG_TYPE "ppc-vsx-copy"
39ff0cc061SDimitry Andric
40ff0cc061SDimitry Andric namespace llvm {
41ff0cc061SDimitry Andric void initializePPCVSXCopyPass(PassRegistry&);
42ff0cc061SDimitry Andric }
43ff0cc061SDimitry Andric
44ff0cc061SDimitry Andric namespace {
45ff0cc061SDimitry Andric // PPCVSXCopy pass - For copies between VSX registers and non-VSX registers
46ff0cc061SDimitry Andric // (Altivec and scalar floating-point registers), we need to transform the
47ff0cc061SDimitry Andric // copies into subregister copies with other restrictions.
48ff0cc061SDimitry Andric struct PPCVSXCopy : public MachineFunctionPass {
49ff0cc061SDimitry Andric static char ID;
PPCVSXCopy__anon00432fd90111::PPCVSXCopy50ff0cc061SDimitry Andric PPCVSXCopy() : MachineFunctionPass(ID) {
51ff0cc061SDimitry Andric initializePPCVSXCopyPass(*PassRegistry::getPassRegistry());
52ff0cc061SDimitry Andric }
53ff0cc061SDimitry Andric
54ff0cc061SDimitry Andric const TargetInstrInfo *TII;
55ff0cc061SDimitry Andric
IsRegInClass__anon00432fd90111::PPCVSXCopy56ff0cc061SDimitry Andric bool IsRegInClass(unsigned Reg, const TargetRegisterClass *RC,
57ff0cc061SDimitry Andric MachineRegisterInfo &MRI) {
58ff0cc061SDimitry Andric if (TargetRegisterInfo::isVirtualRegister(Reg)) {
59ff0cc061SDimitry Andric return RC->hasSubClassEq(MRI.getRegClass(Reg));
60ff0cc061SDimitry Andric } else if (RC->contains(Reg)) {
61ff0cc061SDimitry Andric return true;
62ff0cc061SDimitry Andric }
63ff0cc061SDimitry Andric
64ff0cc061SDimitry Andric return false;
65ff0cc061SDimitry Andric }
66ff0cc061SDimitry Andric
IsVSReg__anon00432fd90111::PPCVSXCopy67ff0cc061SDimitry Andric bool IsVSReg(unsigned Reg, MachineRegisterInfo &MRI) {
68ff0cc061SDimitry Andric return IsRegInClass(Reg, &PPC::VSRCRegClass, MRI);
69ff0cc061SDimitry Andric }
70ff0cc061SDimitry Andric
IsVRReg__anon00432fd90111::PPCVSXCopy71ff0cc061SDimitry Andric bool IsVRReg(unsigned Reg, MachineRegisterInfo &MRI) {
72ff0cc061SDimitry Andric return IsRegInClass(Reg, &PPC::VRRCRegClass, MRI);
73ff0cc061SDimitry Andric }
74ff0cc061SDimitry Andric
IsF8Reg__anon00432fd90111::PPCVSXCopy75ff0cc061SDimitry Andric bool IsF8Reg(unsigned Reg, MachineRegisterInfo &MRI) {
76ff0cc061SDimitry Andric return IsRegInClass(Reg, &PPC::F8RCRegClass, MRI);
77ff0cc061SDimitry Andric }
78ff0cc061SDimitry Andric
IsVSFReg__anon00432fd90111::PPCVSXCopy797d523365SDimitry Andric bool IsVSFReg(unsigned Reg, MachineRegisterInfo &MRI) {
807d523365SDimitry Andric return IsRegInClass(Reg, &PPC::VSFRCRegClass, MRI);
817d523365SDimitry Andric }
827d523365SDimitry Andric
IsVSSReg__anon00432fd90111::PPCVSXCopy837d523365SDimitry Andric bool IsVSSReg(unsigned Reg, MachineRegisterInfo &MRI) {
847d523365SDimitry Andric return IsRegInClass(Reg, &PPC::VSSRCRegClass, MRI);
857d523365SDimitry Andric }
867d523365SDimitry Andric
87ff0cc061SDimitry Andric protected:
processBlock__anon00432fd90111::PPCVSXCopy88ff0cc061SDimitry Andric bool processBlock(MachineBasicBlock &MBB) {
89ff0cc061SDimitry Andric bool Changed = false;
90ff0cc061SDimitry Andric
91ff0cc061SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
92d88c1a5aSDimitry Andric for (MachineInstr &MI : MBB) {
93d88c1a5aSDimitry Andric if (!MI.isFullCopy())
94ff0cc061SDimitry Andric continue;
95ff0cc061SDimitry Andric
96d88c1a5aSDimitry Andric MachineOperand &DstMO = MI.getOperand(0);
97d88c1a5aSDimitry Andric MachineOperand &SrcMO = MI.getOperand(1);
98ff0cc061SDimitry Andric
99ff0cc061SDimitry Andric if ( IsVSReg(DstMO.getReg(), MRI) &&
100ff0cc061SDimitry Andric !IsVSReg(SrcMO.getReg(), MRI)) {
101ff0cc061SDimitry Andric // This is a copy *to* a VSX register from a non-VSX register.
102ff0cc061SDimitry Andric Changed = true;
103ff0cc061SDimitry Andric
104d88c1a5aSDimitry Andric const TargetRegisterClass *SrcRC = &PPC::VSLRCRegClass;
105ff0cc061SDimitry Andric assert((IsF8Reg(SrcMO.getReg(), MRI) ||
1067d523365SDimitry Andric IsVSSReg(SrcMO.getReg(), MRI) ||
1077d523365SDimitry Andric IsVSFReg(SrcMO.getReg(), MRI)) &&
108ff0cc061SDimitry Andric "Unknown source for a VSX copy");
109ff0cc061SDimitry Andric
110ff0cc061SDimitry Andric unsigned NewVReg = MRI.createVirtualRegister(SrcRC);
111d88c1a5aSDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(),
112ff0cc061SDimitry Andric TII->get(TargetOpcode::SUBREG_TO_REG), NewVReg)
113ff0cc061SDimitry Andric .addImm(1) // add 1, not 0, because there is no implicit clearing
114ff0cc061SDimitry Andric // of the high bits.
1157a7e6055SDimitry Andric .add(SrcMO)
116d88c1a5aSDimitry Andric .addImm(PPC::sub_64);
117ff0cc061SDimitry Andric
118ff0cc061SDimitry Andric // The source of the original copy is now the new virtual register.
119ff0cc061SDimitry Andric SrcMO.setReg(NewVReg);
120ff0cc061SDimitry Andric } else if (!IsVSReg(DstMO.getReg(), MRI) &&
121ff0cc061SDimitry Andric IsVSReg(SrcMO.getReg(), MRI)) {
122ff0cc061SDimitry Andric // This is a copy *from* a VSX register to a non-VSX register.
123ff0cc061SDimitry Andric Changed = true;
124ff0cc061SDimitry Andric
125d88c1a5aSDimitry Andric const TargetRegisterClass *DstRC = &PPC::VSLRCRegClass;
126ff0cc061SDimitry Andric assert((IsF8Reg(DstMO.getReg(), MRI) ||
1277d523365SDimitry Andric IsVSFReg(DstMO.getReg(), MRI) ||
128d88c1a5aSDimitry Andric IsVSSReg(DstMO.getReg(), MRI)) &&
129ff0cc061SDimitry Andric "Unknown destination for a VSX copy");
130ff0cc061SDimitry Andric
131ff0cc061SDimitry Andric // Copy the VSX value into a new VSX register of the correct subclass.
132ff0cc061SDimitry Andric unsigned NewVReg = MRI.createVirtualRegister(DstRC);
133d88c1a5aSDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
134d88c1a5aSDimitry Andric NewVReg)
1357a7e6055SDimitry Andric .add(SrcMO);
136ff0cc061SDimitry Andric
137ff0cc061SDimitry Andric // Transform the original copy into a subregister extraction copy.
138ff0cc061SDimitry Andric SrcMO.setReg(NewVReg);
139d88c1a5aSDimitry Andric SrcMO.setSubReg(PPC::sub_64);
140ff0cc061SDimitry Andric }
141ff0cc061SDimitry Andric }
142ff0cc061SDimitry Andric
143ff0cc061SDimitry Andric return Changed;
144ff0cc061SDimitry Andric }
145ff0cc061SDimitry Andric
146ff0cc061SDimitry Andric public:
runOnMachineFunction__anon00432fd90111::PPCVSXCopy147ff0cc061SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override {
148ff0cc061SDimitry Andric // If we don't have VSX on the subtarget, don't do anything.
149ff0cc061SDimitry Andric const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
150ff0cc061SDimitry Andric if (!STI.hasVSX())
151ff0cc061SDimitry Andric return false;
152ff0cc061SDimitry Andric TII = STI.getInstrInfo();
153ff0cc061SDimitry Andric
154ff0cc061SDimitry Andric bool Changed = false;
155ff0cc061SDimitry Andric
156ff0cc061SDimitry Andric for (MachineFunction::iterator I = MF.begin(); I != MF.end();) {
157ff0cc061SDimitry Andric MachineBasicBlock &B = *I++;
158ff0cc061SDimitry Andric if (processBlock(B))
159ff0cc061SDimitry Andric Changed = true;
160ff0cc061SDimitry Andric }
161ff0cc061SDimitry Andric
162ff0cc061SDimitry Andric return Changed;
163ff0cc061SDimitry Andric }
164ff0cc061SDimitry Andric
getAnalysisUsage__anon00432fd90111::PPCVSXCopy165ff0cc061SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
166ff0cc061SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
167ff0cc061SDimitry Andric }
168ff0cc061SDimitry Andric };
1693dac3a9bSDimitry Andric }
170ff0cc061SDimitry Andric
171ff0cc061SDimitry Andric INITIALIZE_PASS(PPCVSXCopy, DEBUG_TYPE,
172ff0cc061SDimitry Andric "PowerPC VSX Copy Legalization", false, false)
173ff0cc061SDimitry Andric
174ff0cc061SDimitry Andric char PPCVSXCopy::ID = 0;
175ff0cc061SDimitry Andric FunctionPass*
createPPCVSXCopyPass()176ff0cc061SDimitry Andric llvm::createPPCVSXCopyPass() { return new PPCVSXCopy(); }
177ff0cc061SDimitry Andric
178