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