1*0b57cec5SDimitry Andric //===-------------- PPCVSXCopy.cpp - VSX Copy Legalization ----------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // A pass which deals with the complexity of generating legal VSX register
10*0b57cec5SDimitry Andric // copies to/from register classes which partially overlap with the VSX
11*0b57cec5SDimitry Andric // register file.
12*0b57cec5SDimitry Andric //
13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14*0b57cec5SDimitry Andric 
15*0b57cec5SDimitry Andric #include "MCTargetDesc/PPCPredicates.h"
16*0b57cec5SDimitry Andric #include "PPC.h"
17*0b57cec5SDimitry Andric #include "PPCHazardRecognizers.h"
18*0b57cec5SDimitry Andric #include "PPCInstrBuilder.h"
19*0b57cec5SDimitry Andric #include "PPCInstrInfo.h"
20*0b57cec5SDimitry Andric #include "PPCMachineFunctionInfo.h"
21*0b57cec5SDimitry Andric #include "PPCTargetMachine.h"
22*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
23*0b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
24*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
25*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
26*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
27*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
28*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
29*0b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
30*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
31*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
32*0b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
33*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
34*0b57cec5SDimitry Andric 
35*0b57cec5SDimitry Andric using namespace llvm;
36*0b57cec5SDimitry Andric 
37*0b57cec5SDimitry Andric #define DEBUG_TYPE "ppc-vsx-copy"
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric namespace {
40*0b57cec5SDimitry Andric   // PPCVSXCopy pass - For copies between VSX registers and non-VSX registers
41*0b57cec5SDimitry Andric   // (Altivec and scalar floating-point registers), we need to transform the
42*0b57cec5SDimitry Andric   // copies into subregister copies with other restrictions.
43*0b57cec5SDimitry Andric   struct PPCVSXCopy : public MachineFunctionPass {
44*0b57cec5SDimitry Andric     static char ID;
PPCVSXCopy__anon5fd4e0480111::PPCVSXCopy45*0b57cec5SDimitry Andric     PPCVSXCopy() : MachineFunctionPass(ID) {
46*0b57cec5SDimitry Andric       initializePPCVSXCopyPass(*PassRegistry::getPassRegistry());
47*0b57cec5SDimitry Andric     }
48*0b57cec5SDimitry Andric 
49*0b57cec5SDimitry Andric     const TargetInstrInfo *TII;
50*0b57cec5SDimitry Andric 
IsRegInClass__anon5fd4e0480111::PPCVSXCopy51*0b57cec5SDimitry Andric     bool IsRegInClass(unsigned Reg, const TargetRegisterClass *RC,
52*0b57cec5SDimitry Andric                       MachineRegisterInfo &MRI) {
53*0b57cec5SDimitry Andric       if (Register::isVirtualRegister(Reg)) {
54*0b57cec5SDimitry Andric         return RC->hasSubClassEq(MRI.getRegClass(Reg));
55*0b57cec5SDimitry Andric       } else if (RC->contains(Reg)) {
56*0b57cec5SDimitry Andric         return true;
57*0b57cec5SDimitry Andric       }
58*0b57cec5SDimitry Andric 
59*0b57cec5SDimitry Andric       return false;
60*0b57cec5SDimitry Andric     }
61*0b57cec5SDimitry Andric 
IsVSReg__anon5fd4e0480111::PPCVSXCopy62*0b57cec5SDimitry Andric     bool IsVSReg(unsigned Reg, MachineRegisterInfo &MRI) {
63*0b57cec5SDimitry Andric       return IsRegInClass(Reg, &PPC::VSRCRegClass, MRI);
64*0b57cec5SDimitry Andric     }
65*0b57cec5SDimitry Andric 
IsVRReg__anon5fd4e0480111::PPCVSXCopy66*0b57cec5SDimitry Andric     bool IsVRReg(unsigned Reg, MachineRegisterInfo &MRI) {
67*0b57cec5SDimitry Andric       return IsRegInClass(Reg, &PPC::VRRCRegClass, MRI);
68*0b57cec5SDimitry Andric     }
69*0b57cec5SDimitry Andric 
IsF8Reg__anon5fd4e0480111::PPCVSXCopy70*0b57cec5SDimitry Andric     bool IsF8Reg(unsigned Reg, MachineRegisterInfo &MRI) {
71*0b57cec5SDimitry Andric       return IsRegInClass(Reg, &PPC::F8RCRegClass, MRI);
72*0b57cec5SDimitry Andric     }
73*0b57cec5SDimitry Andric 
IsVSFReg__anon5fd4e0480111::PPCVSXCopy74*0b57cec5SDimitry Andric     bool IsVSFReg(unsigned Reg, MachineRegisterInfo &MRI) {
75*0b57cec5SDimitry Andric       return IsRegInClass(Reg, &PPC::VSFRCRegClass, MRI);
76*0b57cec5SDimitry Andric     }
77*0b57cec5SDimitry Andric 
IsVSSReg__anon5fd4e0480111::PPCVSXCopy78*0b57cec5SDimitry Andric     bool IsVSSReg(unsigned Reg, MachineRegisterInfo &MRI) {
79*0b57cec5SDimitry Andric       return IsRegInClass(Reg, &PPC::VSSRCRegClass, MRI);
80*0b57cec5SDimitry Andric     }
81*0b57cec5SDimitry Andric 
82*0b57cec5SDimitry Andric protected:
processBlock__anon5fd4e0480111::PPCVSXCopy83*0b57cec5SDimitry Andric     bool processBlock(MachineBasicBlock &MBB) {
84*0b57cec5SDimitry Andric       bool Changed = false;
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric       MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
87*0b57cec5SDimitry Andric       for (MachineInstr &MI : MBB) {
88*0b57cec5SDimitry Andric         if (!MI.isFullCopy())
89*0b57cec5SDimitry Andric           continue;
90*0b57cec5SDimitry Andric 
91*0b57cec5SDimitry Andric         MachineOperand &DstMO = MI.getOperand(0);
92*0b57cec5SDimitry Andric         MachineOperand &SrcMO = MI.getOperand(1);
93*0b57cec5SDimitry Andric 
94*0b57cec5SDimitry Andric         if ( IsVSReg(DstMO.getReg(), MRI) &&
95*0b57cec5SDimitry Andric             !IsVSReg(SrcMO.getReg(), MRI)) {
96*0b57cec5SDimitry Andric           // This is a copy *to* a VSX register from a non-VSX register.
97*0b57cec5SDimitry Andric           Changed = true;
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric           const TargetRegisterClass *SrcRC = &PPC::VSLRCRegClass;
100*0b57cec5SDimitry Andric           assert((IsF8Reg(SrcMO.getReg(), MRI) ||
101*0b57cec5SDimitry Andric                   IsVSSReg(SrcMO.getReg(), MRI) ||
102*0b57cec5SDimitry Andric                   IsVSFReg(SrcMO.getReg(), MRI)) &&
103*0b57cec5SDimitry Andric                  "Unknown source for a VSX copy");
104*0b57cec5SDimitry Andric 
105*0b57cec5SDimitry Andric           Register NewVReg = MRI.createVirtualRegister(SrcRC);
106*0b57cec5SDimitry Andric           BuildMI(MBB, MI, MI.getDebugLoc(),
107*0b57cec5SDimitry Andric                   TII->get(TargetOpcode::SUBREG_TO_REG), NewVReg)
108*0b57cec5SDimitry Andric               .addImm(1) // add 1, not 0, because there is no implicit clearing
109*0b57cec5SDimitry Andric                          // of the high bits.
110*0b57cec5SDimitry Andric               .add(SrcMO)
111*0b57cec5SDimitry Andric               .addImm(PPC::sub_64);
112*0b57cec5SDimitry Andric 
113*0b57cec5SDimitry Andric           // The source of the original copy is now the new virtual register.
114*0b57cec5SDimitry Andric           SrcMO.setReg(NewVReg);
115*0b57cec5SDimitry Andric         } else if (!IsVSReg(DstMO.getReg(), MRI) &&
116*0b57cec5SDimitry Andric                     IsVSReg(SrcMO.getReg(), MRI)) {
117*0b57cec5SDimitry Andric           // This is a copy *from* a VSX register to a non-VSX register.
118*0b57cec5SDimitry Andric           Changed = true;
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric           const TargetRegisterClass *DstRC = &PPC::VSLRCRegClass;
121*0b57cec5SDimitry Andric           assert((IsF8Reg(DstMO.getReg(), MRI) ||
122*0b57cec5SDimitry Andric                   IsVSFReg(DstMO.getReg(), MRI) ||
123*0b57cec5SDimitry Andric                   IsVSSReg(DstMO.getReg(), MRI)) &&
124*0b57cec5SDimitry Andric                  "Unknown destination for a VSX copy");
125*0b57cec5SDimitry Andric 
126*0b57cec5SDimitry Andric           // Copy the VSX value into a new VSX register of the correct subclass.
127*0b57cec5SDimitry Andric           Register NewVReg = MRI.createVirtualRegister(DstRC);
128*0b57cec5SDimitry Andric           BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
129*0b57cec5SDimitry Andric                   NewVReg)
130*0b57cec5SDimitry Andric               .add(SrcMO);
131*0b57cec5SDimitry Andric 
132*0b57cec5SDimitry Andric           // Transform the original copy into a subregister extraction copy.
133*0b57cec5SDimitry Andric           SrcMO.setReg(NewVReg);
134*0b57cec5SDimitry Andric           SrcMO.setSubReg(PPC::sub_64);
135*0b57cec5SDimitry Andric         }
136*0b57cec5SDimitry Andric       }
137*0b57cec5SDimitry Andric 
138*0b57cec5SDimitry Andric       return Changed;
139*0b57cec5SDimitry Andric     }
140*0b57cec5SDimitry Andric 
141*0b57cec5SDimitry Andric public:
runOnMachineFunction__anon5fd4e0480111::PPCVSXCopy142*0b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override {
143*0b57cec5SDimitry Andric       // If we don't have VSX on the subtarget, don't do anything.
144*0b57cec5SDimitry Andric       const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
145*0b57cec5SDimitry Andric       if (!STI.hasVSX())
146*0b57cec5SDimitry Andric         return false;
147*0b57cec5SDimitry Andric       TII = STI.getInstrInfo();
148*0b57cec5SDimitry Andric 
149*0b57cec5SDimitry Andric       bool Changed = false;
150*0b57cec5SDimitry Andric 
151*0b57cec5SDimitry Andric       for (MachineFunction::iterator I = MF.begin(); I != MF.end();) {
152*0b57cec5SDimitry Andric         MachineBasicBlock &B = *I++;
153*0b57cec5SDimitry Andric         if (processBlock(B))
154*0b57cec5SDimitry Andric           Changed = true;
155*0b57cec5SDimitry Andric       }
156*0b57cec5SDimitry Andric 
157*0b57cec5SDimitry Andric       return Changed;
158*0b57cec5SDimitry Andric     }
159*0b57cec5SDimitry Andric 
getAnalysisUsage__anon5fd4e0480111::PPCVSXCopy160*0b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
161*0b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
162*0b57cec5SDimitry Andric     }
163*0b57cec5SDimitry Andric   };
164*0b57cec5SDimitry Andric }
165*0b57cec5SDimitry Andric 
166*0b57cec5SDimitry Andric INITIALIZE_PASS(PPCVSXCopy, DEBUG_TYPE,
167*0b57cec5SDimitry Andric                 "PowerPC VSX Copy Legalization", false, false)
168*0b57cec5SDimitry Andric 
169*0b57cec5SDimitry Andric char PPCVSXCopy::ID = 0;
170*0b57cec5SDimitry Andric FunctionPass*
createPPCVSXCopyPass()171*0b57cec5SDimitry Andric llvm::createPPCVSXCopyPass() { return new PPCVSXCopy(); }
172*0b57cec5SDimitry Andric 
173