brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.0 KiB · c6fffde Raw
375 lines · cpp
1//===- HexagonGenMux.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 9// During instruction selection, MUX instructions are generated for10// conditional assignments. Since such assignments often present an11// opportunity to predicate instructions, HexagonExpandCondsets12// expands MUXes into pairs of conditional transfers, and then proceeds13// with predication of the producers/consumers of the registers involved.14// This happens after exiting from the SSA form, but before the machine15// instruction scheduler. After the scheduler and after the register16// allocation there can be cases of pairs of conditional transfers17// resulting from a MUX where neither of them was further predicated. If18// these transfers are now placed far enough from the instruction defining19// the predicate register, they cannot use the .new form. In such cases it20// is better to collapse them back to a single MUX instruction.21 22#include "Hexagon.h"23#include "HexagonInstrInfo.h"24#include "HexagonRegisterInfo.h"25#include "HexagonSubtarget.h"26#include "llvm/ADT/BitVector.h"27#include "llvm/ADT/DenseMap.h"28#include "llvm/ADT/SmallVector.h"29#include "llvm/ADT/StringRef.h"30#include "llvm/CodeGen/LiveRegUnits.h"31#include "llvm/CodeGen/MachineBasicBlock.h"32#include "llvm/CodeGen/MachineFunction.h"33#include "llvm/CodeGen/MachineFunctionPass.h"34#include "llvm/CodeGen/MachineInstr.h"35#include "llvm/CodeGen/MachineInstrBuilder.h"36#include "llvm/CodeGen/MachineOperand.h"37#include "llvm/IR/DebugLoc.h"38#include "llvm/MC/MCInstrDesc.h"39#include "llvm/Pass.h"40#include "llvm/Support/CommandLine.h"41#include "llvm/Support/MathExtras.h"42#include <algorithm>43#include <cassert>44#include <iterator>45#include <limits>46 47#define DEBUG_TYPE "hexmux"48 49using namespace llvm;50 51// Initialize this to 0 to always prefer generating mux by default.52static cl::opt<unsigned> MinPredDist("hexagon-gen-mux-threshold", cl::Hidden,53  cl::init(0), cl::desc("Minimum distance between predicate definition and "54  "farther of the two predicated uses"));55 56namespace {57 58  class HexagonGenMux : public MachineFunctionPass {59  public:60    static char ID;61 62    HexagonGenMux() : MachineFunctionPass(ID) {}63 64    StringRef getPassName() const override {65      return "Hexagon generate mux instructions";66    }67 68    void getAnalysisUsage(AnalysisUsage &AU) const override {69      MachineFunctionPass::getAnalysisUsage(AU);70    }71 72    bool runOnMachineFunction(MachineFunction &MF) override;73 74    MachineFunctionProperties getRequiredProperties() const override {75      return MachineFunctionProperties().setNoVRegs();76    }77 78  private:79    const HexagonInstrInfo *HII = nullptr;80    const HexagonRegisterInfo *HRI = nullptr;81 82    struct CondsetInfo {83      unsigned PredR = 0;84      unsigned TrueX = std::numeric_limits<unsigned>::max();85      unsigned FalseX = std::numeric_limits<unsigned>::max();86 87      CondsetInfo() = default;88    };89 90    struct DefUseInfo {91      BitVector Defs, Uses;92 93      DefUseInfo() = default;94      DefUseInfo(const BitVector &D, const BitVector &U) : Defs(D), Uses(U) {}95    };96 97    struct MuxInfo {98      MachineBasicBlock::iterator At;99      unsigned DefR, PredR;100      MachineOperand *SrcT, *SrcF;101      MachineInstr *Def1, *Def2;102 103      MuxInfo(MachineBasicBlock::iterator It, unsigned DR, unsigned PR,104              MachineOperand *TOp, MachineOperand *FOp, MachineInstr &D1,105              MachineInstr &D2)106          : At(It), DefR(DR), PredR(PR), SrcT(TOp), SrcF(FOp), Def1(&D1),107            Def2(&D2) {}108    };109 110    using InstrIndexMap = DenseMap<MachineInstr *, unsigned>;111    using DefUseInfoMap = DenseMap<unsigned, DefUseInfo>;112    using MuxInfoList = SmallVector<MuxInfo, 4>;113 114    bool isRegPair(unsigned Reg) const {115      return Hexagon::DoubleRegsRegClass.contains(Reg);116    }117 118    void getSubRegs(unsigned Reg, BitVector &SRs) const;119    void expandReg(unsigned Reg, BitVector &Set) const;120    void getDefsUses(const MachineInstr *MI, BitVector &Defs,121          BitVector &Uses) const;122    void buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X,123          DefUseInfoMap &DUM);124    bool isCondTransfer(unsigned Opc) const;125    unsigned getMuxOpcode(const MachineOperand &Src1,126          const MachineOperand &Src2) const;127    bool genMuxInBlock(MachineBasicBlock &B);128  };129 130} // end anonymous namespace131 132char HexagonGenMux::ID = 0;133 134INITIALIZE_PASS(HexagonGenMux, "hexagon-gen-mux",135  "Hexagon generate mux instructions", false, false)136 137void HexagonGenMux::getSubRegs(unsigned Reg, BitVector &SRs) const {138  for (MCPhysReg I : HRI->subregs(Reg))139    SRs[I] = true;140}141 142void HexagonGenMux::expandReg(unsigned Reg, BitVector &Set) const {143  if (isRegPair(Reg))144    getSubRegs(Reg, Set);145  else146    Set[Reg] = true;147}148 149void HexagonGenMux::getDefsUses(const MachineInstr *MI, BitVector &Defs,150      BitVector &Uses) const {151  // First, get the implicit defs and uses for this instruction.152  unsigned Opc = MI->getOpcode();153  const MCInstrDesc &D = HII->get(Opc);154  for (MCPhysReg R : D.implicit_defs())155    expandReg(R, Defs);156  for (MCPhysReg R : D.implicit_uses())157    expandReg(R, Uses);158 159  // Look over all operands, and collect explicit defs and uses.160  for (const MachineOperand &MO : MI->operands()) {161    if (!MO.isReg() || MO.isImplicit())162      continue;163    Register R = MO.getReg();164    BitVector &Set = MO.isDef() ? Defs : Uses;165    expandReg(R, Set);166  }167}168 169void HexagonGenMux::buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X,170      DefUseInfoMap &DUM) {171  unsigned Index = 0;172  unsigned NR = HRI->getNumRegs();173  BitVector Defs(NR), Uses(NR);174 175  for (MachineInstr &MI : B) {176    I2X.insert(std::make_pair(&MI, Index));177    Defs.reset();178    Uses.reset();179    getDefsUses(&MI, Defs, Uses);180    DUM.insert(std::make_pair(Index, DefUseInfo(Defs, Uses)));181    Index++;182  }183}184 185bool HexagonGenMux::isCondTransfer(unsigned Opc) const {186  switch (Opc) {187    case Hexagon::A2_tfrt:188    case Hexagon::A2_tfrf:189    case Hexagon::C2_cmoveit:190    case Hexagon::C2_cmoveif:191      return true;192  }193  return false;194}195 196unsigned HexagonGenMux::getMuxOpcode(const MachineOperand &Src1,197      const MachineOperand &Src2) const {198  bool IsReg1 = Src1.isReg(), IsReg2 = Src2.isReg();199  if (IsReg1)200    return IsReg2 ? Hexagon::C2_mux : Hexagon::C2_muxir;201  if (IsReg2)202    return Hexagon::C2_muxri;203 204  // Neither is a register. The first source is extendable, but the second205  // is not (s8).206  if (Src2.isImm() && isInt<8>(Src2.getImm()))207    return Hexagon::C2_muxii;208 209  return 0;210}211 212bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) {213  bool Changed = false;214  InstrIndexMap I2X;215  DefUseInfoMap DUM;216  buildMaps(B, I2X, DUM);217 218  using CondsetMap = DenseMap<unsigned, CondsetInfo>;219 220  CondsetMap CM;221  MuxInfoList ML;222 223  for (MachineInstr &MI : llvm::make_early_inc_range(B)) {224    unsigned Opc = MI.getOpcode();225    if (!isCondTransfer(Opc))226      continue;227    Register DR = MI.getOperand(0).getReg();228    if (isRegPair(DR))229      continue;230    MachineOperand &PredOp = MI.getOperand(1);231    if (PredOp.isUndef())232      continue;233 234    Register PR = PredOp.getReg();235    unsigned Idx = I2X.lookup(&MI);236    CondsetMap::iterator F = CM.find(DR);237    bool IfTrue = HII->isPredicatedTrue(Opc);238 239    // If there is no record of a conditional transfer for this register,240    // or the predicate register differs, create a new record for it.241    if (F != CM.end() && F->second.PredR != PR) {242      CM.erase(F);243      F = CM.end();244    }245    if (F == CM.end()) {246      F = CM.try_emplace(DR).first;247      F->second.PredR = PR;248    }249    CondsetInfo &CI = F->second;250    if (IfTrue)251      CI.TrueX = Idx;252    else253      CI.FalseX = Idx;254    if (CI.TrueX == std::numeric_limits<unsigned>::max() ||255        CI.FalseX == std::numeric_limits<unsigned>::max())256      continue;257 258    // There is now a complete definition of DR, i.e. we have the predicate259    // register, the definition if-true, and definition if-false.260 261    // First, check if the definitions are far enough from the definition262    // of the predicate register.263    unsigned MinX = std::min(CI.TrueX, CI.FalseX);264    unsigned MaxX = std::max(CI.TrueX, CI.FalseX);265    // Specifically, check if the predicate definition is within a prescribed266    // distance from the farther of the two predicated instructions.267    unsigned SearchX = (MaxX >= MinPredDist) ? MaxX-MinPredDist : 0;268    bool NearDef = false;269    for (unsigned X = SearchX; X < MaxX; ++X) {270      const DefUseInfo &DU = DUM.lookup(X);271      if (!DU.Defs[PR])272        continue;273      NearDef = true;274      break;275    }276    if (NearDef)277      continue;278 279    // The predicate register is not defined in the last few instructions.280    // Check if the conversion to MUX is possible (either "up", i.e. at the281    // place of the earlier partial definition, or "down", where the later282    // definition is located). Examine all defs and uses between these two283    // definitions.284    // SR1, SR2 - source registers from the first and the second definition.285    MachineBasicBlock::iterator It1 = B.begin(), It2 = B.begin();286    std::advance(It1, MinX);287    std::advance(It2, MaxX);288    MachineInstr &Def1 = *It1, &Def2 = *It2;289    MachineOperand *Src1 = &Def1.getOperand(2), *Src2 = &Def2.getOperand(2);290    Register SR1 = Src1->isReg() ? Src1->getReg() : Register();291    Register SR2 = Src2->isReg() ? Src2->getReg() : Register();292    bool Failure = false, CanUp = true, CanDown = true;293    for (unsigned X = MinX+1; X < MaxX; X++) {294      const DefUseInfo &DU = DUM.lookup(X);295      if (DU.Defs[PR] || DU.Defs[DR] || DU.Uses[DR]) {296        Failure = true;297        break;298      }299      if (CanDown && DU.Defs[SR1])300        CanDown = false;301      if (CanUp && DU.Defs[SR2])302        CanUp = false;303    }304    if (Failure || (!CanUp && !CanDown))305      continue;306 307    MachineOperand *SrcT = (MinX == CI.TrueX) ? Src1 : Src2;308    MachineOperand *SrcF = (MinX == CI.FalseX) ? Src1 : Src2;309    // Prefer "down", since this will move the MUX farther away from the310    // predicate definition.311    MachineBasicBlock::iterator At = CanDown ? Def2 : Def1;312    ML.push_back(MuxInfo(At, DR, PR, SrcT, SrcF, Def1, Def2));313  }314 315  for (MuxInfo &MX : ML) {316    unsigned MxOpc = getMuxOpcode(*MX.SrcT, *MX.SrcF);317    if (!MxOpc)318      continue;319    // Basic correctness check: since we are deleting instructions, validate the320    // iterators. There is a possibility that one of Def1 or Def2 is translated321    // to "mux" and being considered for other "mux" instructions.322    if (!MX.At->getParent() || !MX.Def1->getParent() || !MX.Def2->getParent())323      continue;324 325    MachineBasicBlock &B = *MX.At->getParent();326    const DebugLoc &DL = B.findDebugLoc(MX.At);327    auto NewMux = BuildMI(B, MX.At, DL, HII->get(MxOpc), MX.DefR)328                      .addReg(MX.PredR)329                      .add(*MX.SrcT)330                      .add(*MX.SrcF);331    NewMux->clearKillInfo();332    B.remove(MX.Def1);333    B.remove(MX.Def2);334    Changed = true;335  }336 337  // Fix up kill flags.338 339  LiveRegUnits LPR(*HRI);340  LPR.addLiveOuts(B);341  for (MachineInstr &I : llvm::reverse(B)) {342    if (I.isDebugInstr())343      continue;344    // This isn't 100% accurate, but it's safe.345    // It won't detect (as a kill) a case like this346    //   r0 = add r0, 1    <-- r0 should be "killed"347    //   ... = r0348    for (MachineOperand &Op : I.operands()) {349      if (!Op.isReg() || !Op.isUse())350        continue;351      assert(Op.getSubReg() == 0 && "Should have physical registers only");352      bool Live = !LPR.available(Op.getReg());353      Op.setIsKill(!Live);354    }355    LPR.stepBackward(I);356  }357 358  return Changed;359}360 361bool HexagonGenMux::runOnMachineFunction(MachineFunction &MF) {362  if (skipFunction(MF.getFunction()))363    return false;364  HII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();365  HRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();366  bool Changed = false;367  for (auto &I : MF)368    Changed |= genMuxInBlock(I);369  return Changed;370}371 372FunctionPass *llvm::createHexagonGenMux() {373  return new HexagonGenMux();374}375