1 //===-------------- PPCVSXCopy.cpp - VSX 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. 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" 20 #include "llvm/CodeGen/MachineFrameInfo.h" 21 #include "llvm/CodeGen/MachineFunctionPass.h" 22 #include "llvm/CodeGen/MachineInstrBuilder.h" 23 #include "llvm/CodeGen/MachineMemOperand.h" 24 #include "llvm/CodeGen/MachineRegisterInfo.h" 25 #include "llvm/Support/ErrorHandling.h" 26 27 using namespace llvm; 28 29 #define DEBUG_TYPE "ppc-vsx-copy" 30 31 namespace { 32 // PPCVSXCopy 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. 35 struct PPCVSXCopy : public MachineFunctionPass { 36 static char ID; 37 PPCVSXCopy() : MachineFunctionPass(ID) { 38 initializePPCVSXCopyPass(*PassRegistry::getPassRegistry()); 39 } 40 41 const TargetInstrInfo *TII; 42 43 bool IsRegInClass(unsigned Reg, const TargetRegisterClass *RC, 44 MachineRegisterInfo &MRI) { 45 if (Register::isVirtualRegister(Reg)) { 46 return RC->hasSubClassEq(MRI.getRegClass(Reg)); 47 } else if (RC->contains(Reg)) { 48 return true; 49 } 50 51 return false; 52 } 53 54 bool IsVSReg(unsigned Reg, MachineRegisterInfo &MRI) { 55 return IsRegInClass(Reg, &PPC::VSRCRegClass, MRI); 56 } 57 58 bool IsVRReg(unsigned Reg, MachineRegisterInfo &MRI) { 59 return IsRegInClass(Reg, &PPC::VRRCRegClass, MRI); 60 } 61 62 bool IsF8Reg(unsigned Reg, MachineRegisterInfo &MRI) { 63 return IsRegInClass(Reg, &PPC::F8RCRegClass, MRI); 64 } 65 66 bool IsVSFReg(unsigned Reg, MachineRegisterInfo &MRI) { 67 return IsRegInClass(Reg, &PPC::VSFRCRegClass, MRI); 68 } 69 70 bool IsVSSReg(unsigned Reg, MachineRegisterInfo &MRI) { 71 return IsRegInClass(Reg, &PPC::VSSRCRegClass, MRI); 72 } 73 74 protected: 75 bool processBlock(MachineBasicBlock &MBB) { 76 bool Changed = false; 77 78 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 79 for (MachineInstr &MI : MBB) { 80 if (!MI.isFullCopy()) 81 continue; 82 83 MachineOperand &DstMO = MI.getOperand(0); 84 MachineOperand &SrcMO = MI.getOperand(1); 85 86 if ( IsVSReg(DstMO.getReg(), MRI) && 87 !IsVSReg(SrcMO.getReg(), MRI)) { 88 // This is a copy *to* a VSX register from a non-VSX register. 89 Changed = true; 90 91 const TargetRegisterClass *SrcRC = &PPC::VSLRCRegClass; 92 assert((IsF8Reg(SrcMO.getReg(), MRI) || 93 IsVSSReg(SrcMO.getReg(), MRI) || 94 IsVSFReg(SrcMO.getReg(), MRI)) && 95 "Unknown source for a VSX copy"); 96 97 Register NewVReg = MRI.createVirtualRegister(SrcRC); 98 BuildMI(MBB, MI, MI.getDebugLoc(), 99 TII->get(TargetOpcode::SUBREG_TO_REG), NewVReg) 100 .addImm(1) // add 1, not 0, because there is no implicit clearing 101 // of the high bits. 102 .add(SrcMO) 103 .addImm(PPC::sub_64); 104 105 // The source of the original copy is now the new virtual register. 106 SrcMO.setReg(NewVReg); 107 } else if (!IsVSReg(DstMO.getReg(), MRI) && 108 IsVSReg(SrcMO.getReg(), MRI)) { 109 // This is a copy *from* a VSX register to a non-VSX register. 110 Changed = true; 111 112 const TargetRegisterClass *DstRC = &PPC::VSLRCRegClass; 113 assert((IsF8Reg(DstMO.getReg(), MRI) || 114 IsVSFReg(DstMO.getReg(), MRI) || 115 IsVSSReg(DstMO.getReg(), MRI)) && 116 "Unknown destination for a VSX copy"); 117 118 // Copy the VSX value into a new VSX register of the correct subclass. 119 Register NewVReg = MRI.createVirtualRegister(DstRC); 120 BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY), 121 NewVReg) 122 .add(SrcMO); 123 124 // Transform the original copy into a subregister extraction copy. 125 SrcMO.setReg(NewVReg); 126 SrcMO.setSubReg(PPC::sub_64); 127 } 128 } 129 130 return Changed; 131 } 132 133 public: 134 bool runOnMachineFunction(MachineFunction &MF) override { 135 // If we don't have VSX on the subtarget, don't do anything. 136 const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>(); 137 if (!STI.hasVSX()) 138 return false; 139 TII = STI.getInstrInfo(); 140 141 bool Changed = false; 142 143 for (MachineBasicBlock &B : llvm::make_early_inc_range(MF)) 144 if (processBlock(B)) 145 Changed = true; 146 147 return Changed; 148 } 149 150 void getAnalysisUsage(AnalysisUsage &AU) const override { 151 MachineFunctionPass::getAnalysisUsage(AU); 152 } 153 }; 154 } 155 156 INITIALIZE_PASS(PPCVSXCopy, DEBUG_TYPE, 157 "PowerPC VSX Copy Legalization", false, false) 158 159 char PPCVSXCopy::ID = 0; 160 FunctionPass* 161 llvm::createPPCVSXCopyPass() { return new PPCVSXCopy(); } 162