176c751dcSHal Finkel //===-------------- PPCVSXCopy.cpp - VSX Copy Legalization ----------------===//
276c751dcSHal Finkel //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
676c751dcSHal Finkel //
776c751dcSHal Finkel //===----------------------------------------------------------------------===//
876c751dcSHal Finkel //
976c751dcSHal Finkel // A pass which deals with the complexity of generating legal VSX register
1076c751dcSHal Finkel // copies to/from register classes which partially overlap with the VSX
1176c751dcSHal Finkel // register file.
1276c751dcSHal Finkel //
1376c751dcSHal Finkel //===----------------------------------------------------------------------===//
1476c751dcSHal Finkel 
15b550cb17SMehdi Amini #include "MCTargetDesc/PPCPredicates.h"
166bda14b3SChandler Carruth #include "PPC.h"
1776c751dcSHal Finkel #include "PPCHazardRecognizers.h"
1876c751dcSHal Finkel #include "PPCInstrBuilder.h"
19b550cb17SMehdi Amini #include "PPCInstrInfo.h"
2076c751dcSHal Finkel #include "PPCMachineFunctionInfo.h"
2176c751dcSHal Finkel #include "PPCTargetMachine.h"
2276c751dcSHal Finkel #include "llvm/ADT/STLExtras.h"
2376c751dcSHal Finkel #include "llvm/ADT/Statistic.h"
2476c751dcSHal Finkel #include "llvm/CodeGen/MachineFrameInfo.h"
2576c751dcSHal Finkel #include "llvm/CodeGen/MachineFunctionPass.h"
2676c751dcSHal Finkel #include "llvm/CodeGen/MachineInstrBuilder.h"
2776c751dcSHal Finkel #include "llvm/CodeGen/MachineMemOperand.h"
2876c751dcSHal Finkel #include "llvm/CodeGen/MachineRegisterInfo.h"
2976c751dcSHal Finkel #include "llvm/MC/MCAsmInfo.h"
3089b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
3176c751dcSHal Finkel #include "llvm/Support/Debug.h"
3276c751dcSHal Finkel #include "llvm/Support/ErrorHandling.h"
3376c751dcSHal Finkel #include "llvm/Support/raw_ostream.h"
3476c751dcSHal Finkel 
3576c751dcSHal Finkel using namespace llvm;
3676c751dcSHal Finkel 
3776c751dcSHal Finkel #define DEBUG_TYPE "ppc-vsx-copy"
3876c751dcSHal Finkel 
3976c751dcSHal Finkel namespace {
4076c751dcSHal Finkel   // PPCVSXCopy pass - For copies between VSX registers and non-VSX registers
4176c751dcSHal Finkel   // (Altivec and scalar floating-point registers), we need to transform the
4276c751dcSHal Finkel   // copies into subregister copies with other restrictions.
4376c751dcSHal Finkel   struct PPCVSXCopy : public MachineFunctionPass {
4476c751dcSHal Finkel     static char ID;
PPCVSXCopy__anone636b9440111::PPCVSXCopy4576c751dcSHal Finkel     PPCVSXCopy() : MachineFunctionPass(ID) {
4676c751dcSHal Finkel       initializePPCVSXCopyPass(*PassRegistry::getPassRegistry());
4776c751dcSHal Finkel     }
4876c751dcSHal Finkel 
4976c751dcSHal Finkel     const TargetInstrInfo *TII;
5076c751dcSHal Finkel 
IsRegInClass__anone636b9440111::PPCVSXCopy5176c751dcSHal Finkel     bool IsRegInClass(unsigned Reg, const TargetRegisterClass *RC,
5276c751dcSHal Finkel                       MachineRegisterInfo &MRI) {
532bea69bfSDaniel Sanders       if (Register::isVirtualRegister(Reg)) {
5476c751dcSHal Finkel         return RC->hasSubClassEq(MRI.getRegClass(Reg));
5576c751dcSHal Finkel       } else if (RC->contains(Reg)) {
5676c751dcSHal Finkel         return true;
5776c751dcSHal Finkel       }
5876c751dcSHal Finkel 
5976c751dcSHal Finkel       return false;
6076c751dcSHal Finkel     }
6176c751dcSHal Finkel 
IsVSReg__anone636b9440111::PPCVSXCopy6276c751dcSHal Finkel     bool IsVSReg(unsigned Reg, MachineRegisterInfo &MRI) {
6376c751dcSHal Finkel       return IsRegInClass(Reg, &PPC::VSRCRegClass, MRI);
6476c751dcSHal Finkel     }
6576c751dcSHal Finkel 
IsVRReg__anone636b9440111::PPCVSXCopy6676c751dcSHal Finkel     bool IsVRReg(unsigned Reg, MachineRegisterInfo &MRI) {
6776c751dcSHal Finkel       return IsRegInClass(Reg, &PPC::VRRCRegClass, MRI);
6876c751dcSHal Finkel     }
6976c751dcSHal Finkel 
IsF8Reg__anone636b9440111::PPCVSXCopy7076c751dcSHal Finkel     bool IsF8Reg(unsigned Reg, MachineRegisterInfo &MRI) {
7176c751dcSHal Finkel       return IsRegInClass(Reg, &PPC::F8RCRegClass, MRI);
7276c751dcSHal Finkel     }
7376c751dcSHal Finkel 
IsVSFReg__anone636b9440111::PPCVSXCopy741c39ca65SNemanja Ivanovic     bool IsVSFReg(unsigned Reg, MachineRegisterInfo &MRI) {
751c39ca65SNemanja Ivanovic       return IsRegInClass(Reg, &PPC::VSFRCRegClass, MRI);
761c39ca65SNemanja Ivanovic     }
771c39ca65SNemanja Ivanovic 
IsVSSReg__anone636b9440111::PPCVSXCopy788922476bSNemanja Ivanovic     bool IsVSSReg(unsigned Reg, MachineRegisterInfo &MRI) {
798922476bSNemanja Ivanovic       return IsRegInClass(Reg, &PPC::VSSRCRegClass, MRI);
808922476bSNemanja Ivanovic     }
818922476bSNemanja Ivanovic 
8276c751dcSHal Finkel protected:
processBlock__anone636b9440111::PPCVSXCopy8376c751dcSHal Finkel     bool processBlock(MachineBasicBlock &MBB) {
8476c751dcSHal Finkel       bool Changed = false;
8576c751dcSHal Finkel 
8676c751dcSHal Finkel       MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
87e5a22f44SDuncan P. N. Exon Smith       for (MachineInstr &MI : MBB) {
88e5a22f44SDuncan P. N. Exon Smith         if (!MI.isFullCopy())
8976c751dcSHal Finkel           continue;
9076c751dcSHal Finkel 
91e5a22f44SDuncan P. N. Exon Smith         MachineOperand &DstMO = MI.getOperand(0);
92e5a22f44SDuncan P. N. Exon Smith         MachineOperand &SrcMO = MI.getOperand(1);
9376c751dcSHal Finkel 
9476c751dcSHal Finkel         if ( IsVSReg(DstMO.getReg(), MRI) &&
9576c751dcSHal Finkel             !IsVSReg(SrcMO.getReg(), MRI)) {
9676c751dcSHal Finkel           // This is a copy *to* a VSX register from a non-VSX register.
9776c751dcSHal Finkel           Changed = true;
9876c751dcSHal Finkel 
9911049f8fSNemanja Ivanovic           const TargetRegisterClass *SrcRC = &PPC::VSLRCRegClass;
10076c751dcSHal Finkel           assert((IsF8Reg(SrcMO.getReg(), MRI) ||
1018922476bSNemanja Ivanovic                   IsVSSReg(SrcMO.getReg(), MRI) ||
1021c39ca65SNemanja Ivanovic                   IsVSFReg(SrcMO.getReg(), MRI)) &&
10376c751dcSHal Finkel                  "Unknown source for a VSX copy");
10476c751dcSHal Finkel 
1050c476111SDaniel Sanders           Register NewVReg = MRI.createVirtualRegister(SrcRC);
106e5a22f44SDuncan P. N. Exon Smith           BuildMI(MBB, MI, MI.getDebugLoc(),
10776c751dcSHal Finkel                   TII->get(TargetOpcode::SUBREG_TO_REG), NewVReg)
10876c751dcSHal Finkel               .addImm(1) // add 1, not 0, because there is no implicit clearing
10976c751dcSHal Finkel                          // of the high bits.
110116bbab4SDiana Picus               .add(SrcMO)
11111049f8fSNemanja Ivanovic               .addImm(PPC::sub_64);
11276c751dcSHal Finkel 
11376c751dcSHal Finkel           // The source of the original copy is now the new virtual register.
11476c751dcSHal Finkel           SrcMO.setReg(NewVReg);
11576c751dcSHal Finkel         } else if (!IsVSReg(DstMO.getReg(), MRI) &&
11676c751dcSHal Finkel                     IsVSReg(SrcMO.getReg(), MRI)) {
11776c751dcSHal Finkel           // This is a copy *from* a VSX register to a non-VSX register.
11876c751dcSHal Finkel           Changed = true;
11976c751dcSHal Finkel 
12011049f8fSNemanja Ivanovic           const TargetRegisterClass *DstRC = &PPC::VSLRCRegClass;
12176c751dcSHal Finkel           assert((IsF8Reg(DstMO.getReg(), MRI) ||
122d3896573SNemanja Ivanovic                   IsVSFReg(DstMO.getReg(), MRI) ||
12311049f8fSNemanja Ivanovic                   IsVSSReg(DstMO.getReg(), MRI)) &&
12476c751dcSHal Finkel                  "Unknown destination for a VSX copy");
12576c751dcSHal Finkel 
12676c751dcSHal Finkel           // Copy the VSX value into a new VSX register of the correct subclass.
1270c476111SDaniel Sanders           Register NewVReg = MRI.createVirtualRegister(DstRC);
128e5a22f44SDuncan P. N. Exon Smith           BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
129e5a22f44SDuncan P. N. Exon Smith                   NewVReg)
130116bbab4SDiana Picus               .add(SrcMO);
13176c751dcSHal Finkel 
13276c751dcSHal Finkel           // Transform the original copy into a subregister extraction copy.
13376c751dcSHal Finkel           SrcMO.setReg(NewVReg);
13411049f8fSNemanja Ivanovic           SrcMO.setSubReg(PPC::sub_64);
13576c751dcSHal Finkel         }
13676c751dcSHal Finkel       }
13776c751dcSHal Finkel 
13876c751dcSHal Finkel       return Changed;
13976c751dcSHal Finkel     }
14076c751dcSHal Finkel 
14176c751dcSHal Finkel public:
runOnMachineFunction__anone636b9440111::PPCVSXCopy14276c751dcSHal Finkel     bool runOnMachineFunction(MachineFunction &MF) override {
14376c751dcSHal Finkel       // If we don't have VSX on the subtarget, don't do anything.
14476c751dcSHal Finkel       const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
14576c751dcSHal Finkel       if (!STI.hasVSX())
14676c751dcSHal Finkel         return false;
14776c751dcSHal Finkel       TII = STI.getInstrInfo();
14876c751dcSHal Finkel 
14976c751dcSHal Finkel       bool Changed = false;
15076c751dcSHal Finkel 
151*2c4ba3e9SKazu Hirata       for (MachineBasicBlock &B : llvm::make_early_inc_range(MF))
15276c751dcSHal Finkel         if (processBlock(B))
15376c751dcSHal Finkel           Changed = true;
15476c751dcSHal Finkel 
15576c751dcSHal Finkel       return Changed;
15676c751dcSHal Finkel     }
15776c751dcSHal Finkel 
getAnalysisUsage__anone636b9440111::PPCVSXCopy15876c751dcSHal Finkel     void getAnalysisUsage(AnalysisUsage &AU) const override {
15976c751dcSHal Finkel       MachineFunctionPass::getAnalysisUsage(AU);
16076c751dcSHal Finkel     }
16176c751dcSHal Finkel   };
162f00654e3SAlexander Kornienko }
16376c751dcSHal Finkel 
16476c751dcSHal Finkel INITIALIZE_PASS(PPCVSXCopy, DEBUG_TYPE,
16576c751dcSHal Finkel                 "PowerPC VSX Copy Legalization", false, false)
16676c751dcSHal Finkel 
16776c751dcSHal Finkel char PPCVSXCopy::ID = 0;
16876c751dcSHal Finkel FunctionPass*
createPPCVSXCopyPass()16976c751dcSHal Finkel llvm::createPPCVSXCopyPass() { return new PPCVSXCopy(); }
170