brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · 3b3d25d Raw
190 lines · cpp
1//===- HexagonVExtract.cpp ------------------------------------------------===//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// This pass will replace multiple occurrences of V6_extractw from the same9// vector register with a combination of a vector store and scalar loads.10//===----------------------------------------------------------------------===//11 12#include "Hexagon.h"13#include "HexagonInstrInfo.h"14#include "HexagonMachineFunctionInfo.h"15#include "HexagonRegisterInfo.h"16#include "HexagonSubtarget.h"17#include "llvm/ADT/SmallVector.h"18#include "llvm/Pass.h"19#include "llvm/CodeGen/MachineBasicBlock.h"20#include "llvm/CodeGen/MachineFunction.h"21#include "llvm/CodeGen/MachineFunctionPass.h"22#include "llvm/CodeGen/MachineInstrBuilder.h"23#include "llvm/CodeGen/MachineRegisterInfo.h"24#include "llvm/Support/CommandLine.h"25 26#include <map>27 28using namespace llvm;29 30static cl::opt<unsigned> VExtractThreshold(31    "hexagon-vextract-threshold", cl::Hidden, cl::init(1),32    cl::desc("Threshold for triggering vextract replacement"));33 34namespace {35  class HexagonVExtract : public MachineFunctionPass {36  public:37    static char ID;38    HexagonVExtract() : MachineFunctionPass(ID) {}39 40    StringRef getPassName() const override {41      return "Hexagon optimize vextract";42    }43    void getAnalysisUsage(AnalysisUsage &AU) const override {44      MachineFunctionPass::getAnalysisUsage(AU);45    }46    bool runOnMachineFunction(MachineFunction &MF) override;47 48  private:49    const HexagonSubtarget *HST = nullptr;50    const HexagonInstrInfo *HII = nullptr;51 52    unsigned genElemLoad(MachineInstr *ExtI, unsigned BaseR,53                         MachineRegisterInfo &MRI);54  };55 56  char HexagonVExtract::ID = 0;57}58 59INITIALIZE_PASS(HexagonVExtract, "hexagon-vextract",60  "Hexagon optimize vextract", false, false)61 62unsigned HexagonVExtract::genElemLoad(MachineInstr *ExtI, unsigned BaseR,63                                      MachineRegisterInfo &MRI) {64  MachineBasicBlock &ExtB = *ExtI->getParent();65  DebugLoc DL = ExtI->getDebugLoc();66  Register ElemR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);67 68  Register ExtIdxR = ExtI->getOperand(2).getReg();69  unsigned ExtIdxS = ExtI->getOperand(2).getSubReg();70 71  // Simplified check for a compile-time constant value of ExtIdxR.72  if (ExtIdxS == 0) {73    MachineInstr *DI = MRI.getVRegDef(ExtIdxR);74    if (DI->getOpcode() == Hexagon::A2_tfrsi) {75      unsigned V = DI->getOperand(1).getImm();76      V &= (HST->getVectorLength()-1) & -4u;77 78      BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::L2_loadri_io), ElemR)79        .addReg(BaseR)80        .addImm(V);81      return ElemR;82    }83  }84 85  Register IdxR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);86  BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::A2_andir), IdxR)87    .add(ExtI->getOperand(2))88    .addImm(-4);89  BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::L4_loadri_rr), ElemR)90    .addReg(BaseR)91    .addReg(IdxR)92    .addImm(0);93  return ElemR;94}95 96bool HexagonVExtract::runOnMachineFunction(MachineFunction &MF) {97  HST = &MF.getSubtarget<HexagonSubtarget>();98  HII = HST->getInstrInfo();99  const auto &HRI = *HST->getRegisterInfo();100  MachineRegisterInfo &MRI = MF.getRegInfo();101  MachineFrameInfo &MFI = MF.getFrameInfo();102  Register AR =103      MF.getInfo<HexagonMachineFunctionInfo>()->getStackAlignBaseReg();104  std::map<unsigned, SmallVector<MachineInstr *, 4>> VExtractMap;105  bool Changed = false;106 107  for (MachineBasicBlock &MBB : MF) {108    for (MachineInstr &MI : MBB) {109      unsigned Opc = MI.getOpcode();110      if (Opc != Hexagon::V6_extractw)111        continue;112      Register VecR = MI.getOperand(1).getReg();113      VExtractMap[VecR].push_back(&MI);114    }115  }116 117  auto EmitAddr = [&] (MachineBasicBlock &BB, MachineBasicBlock::iterator At,118                       DebugLoc dl, int FI, unsigned Offset) {119    Register AddrR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);120    unsigned FiOpc = AR != 0 ? Hexagon::PS_fia : Hexagon::PS_fi;121    auto MIB = BuildMI(BB, At, dl, HII->get(FiOpc), AddrR);122    if (AR)123      MIB.addReg(AR);124    MIB.addFrameIndex(FI).addImm(Offset);125    return AddrR;126  };127 128  MaybeAlign MaxAlign;129  for (auto &P : VExtractMap) {130    unsigned VecR = P.first;131    if (P.second.size() <= VExtractThreshold)132      continue;133 134    const auto &VecRC = *MRI.getRegClass(VecR);135    Align Alignment = HRI.getSpillAlign(VecRC);136    MaxAlign = std::max(MaxAlign.valueOrOne(), Alignment);137    // Make sure this is not a spill slot: spill slots cannot be aligned138    // if there are variable-sized objects on the stack. They must be139    // accessible via FP (which is not aligned), because SP is unknown,140    // and AP may not be available at the location of the load/store.141    int FI = MFI.CreateStackObject(HRI.getSpillSize(VecRC), Alignment,142                                   /*isSpillSlot*/ false);143 144    MachineInstr *DefI = MRI.getVRegDef(VecR);145    MachineBasicBlock::iterator At = std::next(DefI->getIterator());146    MachineBasicBlock &DefB = *DefI->getParent();147    unsigned StoreOpc = VecRC.getID() == Hexagon::HvxVRRegClassID148                          ? Hexagon::V6_vS32b_ai149                          : Hexagon::PS_vstorerw_ai;150    Register AddrR = EmitAddr(DefB, At, DefI->getDebugLoc(), FI, 0);151    BuildMI(DefB, At, DefI->getDebugLoc(), HII->get(StoreOpc))152      .addReg(AddrR)153      .addImm(0)154      .addReg(VecR);155 156    unsigned VecSize = HRI.getRegSizeInBits(VecRC) / 8;157 158    for (MachineInstr *ExtI : P.second) {159      assert(ExtI->getOpcode() == Hexagon::V6_extractw);160      unsigned SR = ExtI->getOperand(1).getSubReg();161      assert(ExtI->getOperand(1).getReg() == VecR);162 163      MachineBasicBlock &ExtB = *ExtI->getParent();164      Register BaseR = EmitAddr(ExtB, ExtI, ExtI->getDebugLoc(), FI,165                                SR == 0 ? 0 : VecSize/2);166 167      unsigned ElemR = genElemLoad(ExtI, BaseR, MRI);168      Register ExtR = ExtI->getOperand(0).getReg();169      MRI.replaceRegWith(ExtR, ElemR);170      ExtB.erase(ExtI);171      Changed = true;172    }173  }174 175  if (AR && MaxAlign) {176    // Update the required stack alignment.177    MachineInstr *AlignaI = MRI.getVRegDef(AR);178    assert(AlignaI->getOpcode() == Hexagon::PS_aligna);179    MachineOperand &Op = AlignaI->getOperand(1);180    if (*MaxAlign > Op.getImm())181      Op.setImm(MaxAlign->value());182  }183 184  return Changed;185}186 187FunctionPass *llvm::createHexagonVExtract() {188  return new HexagonVExtract();189}190