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