brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · 2ec566d Raw
183 lines · cpp
1//===--------- PPCVSXWACCCopy.cpp - VSX and WACC 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-exception6//7//===----------------------------------------------------------------------===//8//9// A pass which deals with the complexity of generating legal VSX register10// copies to/from register classes which partially overlap with the VSX11// register file and combines the wacc/wacc_hi copies when needed.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 27using namespace llvm;28 29#define DEBUG_TYPE "ppc-vsx-copy"30 31namespace {32// PPCVSXWACCCopy pass - For copies between VSX registers and non-VSX registers33// (Altivec and scalar floating-point registers), we need to transform the34// copies into subregister copies with other restrictions.35struct PPCVSXWACCCopy : public MachineFunctionPass {36  static char ID;37  PPCVSXWACCCopy() : 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 72protected: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) && !IsVSReg(SrcMO.getReg(), MRI)) {85        // This is a copy *to* a VSX register from a non-VSX register.86        Changed = true;87 88        const TargetRegisterClass *SrcRC = &PPC::VSLRCRegClass;89        assert((IsF8Reg(SrcMO.getReg(), MRI) || IsVSSReg(SrcMO.getReg(), MRI) ||90                IsVSFReg(SrcMO.getReg(), MRI)) &&91               "Unknown source for a VSX copy");92 93        Register NewVReg = MRI.createVirtualRegister(SrcRC);94        BuildMI(MBB, MI, MI.getDebugLoc(),95                TII->get(TargetOpcode::SUBREG_TO_REG), NewVReg)96            .addImm(1) // add 1, not 0, because there is no implicit clearing97                       // of the high bits.98            .add(SrcMO)99            .addImm(PPC::sub_64);100 101        // The source of the original copy is now the new virtual register.102        SrcMO.setReg(NewVReg);103      } else if (!IsVSReg(DstMO.getReg(), MRI) &&104                 IsVSReg(SrcMO.getReg(), MRI)) {105        // This is a copy *from* a VSX register to a non-VSX register.106        Changed = true;107 108        const TargetRegisterClass *DstRC = &PPC::VSLRCRegClass;109        assert((IsF8Reg(DstMO.getReg(), MRI) || IsVSFReg(DstMO.getReg(), MRI) ||110                IsVSSReg(DstMO.getReg(), MRI)) &&111               "Unknown destination for a VSX copy");112 113        // Copy the VSX value into a new VSX register of the correct subclass.114        Register NewVReg = MRI.createVirtualRegister(DstRC);115        BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),116                NewVReg)117            .add(SrcMO);118 119        // Transform the original copy into a subregister extraction copy.120        SrcMO.setReg(NewVReg);121        SrcMO.setSubReg(PPC::sub_64);122      } else if (IsRegInClass(DstMO.getReg(), &PPC::WACC_HIRCRegClass, MRI) &&123                 IsRegInClass(SrcMO.getReg(), &PPC::WACCRCRegClass, MRI)) {124        // Matches the pattern:125        //   %a:waccrc = COPY %b.sub_wacc_hi:dmrrc126        //   %c:wacc_hirc = COPY %a:waccrc127        // And replaces it with:128        //   %c:wacc_hirc = COPY %b.sub_wacc_hi:dmrrc129        MachineInstr *DefMI = MRI.getUniqueVRegDef(SrcMO.getReg());130        if (!DefMI || !DefMI->isCopy())131          continue;132 133        MachineOperand &OrigSrc = DefMI->getOperand(1);134 135        if (!IsRegInClass(OrigSrc.getReg(), &PPC::DMRRCRegClass, MRI))136          continue;137 138        if (OrigSrc.getSubReg() != PPC::sub_wacc_hi)139          continue;140 141        // Rewrite the second copy to use the original register's subreg142        SrcMO.setReg(OrigSrc.getReg());143        SrcMO.setSubReg(PPC::sub_wacc_hi);144        Changed = true;145 146        // Remove the intermediate copy if safe147        if (MRI.use_nodbg_empty(DefMI->getOperand(0).getReg()))148          DefMI->eraseFromParent();149      }150    }151 152    return Changed;153  }154 155public:156  bool runOnMachineFunction(MachineFunction &MF) override {157    // If we don't have VSX on the subtarget, don't do anything.158    const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();159    if (!STI.hasVSX())160      return false;161    TII = STI.getInstrInfo();162 163    bool Changed = false;164 165    for (MachineBasicBlock &B : llvm::make_early_inc_range(MF))166      if (processBlock(B))167        Changed = true;168 169    return Changed;170  }171 172  void getAnalysisUsage(AnalysisUsage &AU) const override {173    MachineFunctionPass::getAnalysisUsage(AU);174  }175};176} // end anonymous namespace177 178INITIALIZE_PASS(PPCVSXWACCCopy, DEBUG_TYPE, "PowerPC VSX Copy Legalization",179                false, false)180 181char PPCVSXWACCCopy::ID = 0;182FunctionPass *llvm::createPPCVSXWACCCopyPass() { return new PPCVSXWACCCopy(); }183