brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.8 KiB · efea1b4 Raw
263 lines · cpp
1//===-- RISCVMoveMerger.cpp - RISC-V move merge pass ----------------------===//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// This file contains a pass that performs move related peephole optimizations10// as Zcmp has specified. This pass should be run after register allocation.11//12// This pass also supports Xqccmp, which has identical instructions.13//14//===----------------------------------------------------------------------===//15 16#include "RISCVInstrInfo.h"17#include "RISCVSubtarget.h"18 19using namespace llvm;20 21#define RISCV_MOVE_MERGE_NAME "RISC-V Zcmp move merging pass"22 23namespace {24struct RISCVMoveMerge : public MachineFunctionPass {25  static char ID;26 27  RISCVMoveMerge() : MachineFunctionPass(ID) {}28 29  const RISCVSubtarget *ST;30  const RISCVInstrInfo *TII;31  const TargetRegisterInfo *TRI;32 33  // Track which register units have been modified and used.34  LiveRegUnits ModifiedRegUnits, UsedRegUnits;35 36  bool isCandidateToMergeMVA01S(const DestSourcePair &RegPair);37  bool isCandidateToMergeMVSA01(const DestSourcePair &RegPair);38  // Merge the two instructions indicated into a single pair instruction.39  MachineBasicBlock::iterator40  mergePairedInsns(MachineBasicBlock::iterator I,41                   MachineBasicBlock::iterator Paired, bool MoveFromSToA);42 43  // Look for C.MV instruction that can be combined with44  // the given instruction into CM.MVA01S or CM.MVSA01. Return the matching45  // instruction if one exists.46  MachineBasicBlock::iterator47  findMatchingInst(MachineBasicBlock::iterator &MBBI, bool MoveFromSToA,48                   const DestSourcePair &RegPair);49  bool mergeMoveSARegPair(MachineBasicBlock &MBB);50  bool runOnMachineFunction(MachineFunction &Fn) override;51 52  StringRef getPassName() const override { return RISCV_MOVE_MERGE_NAME; }53};54 55char RISCVMoveMerge::ID = 0;56 57} // end of anonymous namespace58 59INITIALIZE_PASS(RISCVMoveMerge, "riscv-move-merge", RISCV_MOVE_MERGE_NAME,60                false, false)61 62static unsigned getMoveFromSToAOpcode(const RISCVSubtarget &ST) {63  if (ST.hasStdExtZcmp())64    return RISCV::CM_MVA01S;65 66  if (ST.hasVendorXqccmp())67    return RISCV::QC_CM_MVA01S;68 69  llvm_unreachable("Unhandled subtarget with paired A to S move.");70}71 72static unsigned getMoveFromAToSOpcode(const RISCVSubtarget &ST) {73  if (ST.hasStdExtZcmp())74    return RISCV::CM_MVSA01;75 76  if (ST.hasVendorXqccmp())77    return RISCV::QC_CM_MVSA01;78 79  llvm_unreachable("Unhandled subtarget with paired S to A move");80}81 82// Check if registers meet CM.MVA01S constraints.83bool RISCVMoveMerge::isCandidateToMergeMVA01S(const DestSourcePair &RegPair) {84  Register Destination = RegPair.Destination->getReg();85  Register Source = RegPair.Source->getReg();86  // If destination is not a0 or a1.87  if ((Destination == RISCV::X10 || Destination == RISCV::X11) &&88      RISCV::SR07RegClass.contains(Source))89    return true;90  return false;91}92 93// Check if registers meet CM.MVSA01 constraints.94bool RISCVMoveMerge::isCandidateToMergeMVSA01(const DestSourcePair &RegPair) {95  Register Destination = RegPair.Destination->getReg();96  Register Source = RegPair.Source->getReg();97  // If Source is s0 - s7.98  if ((Source == RISCV::X10 || Source == RISCV::X11) &&99      RISCV::SR07RegClass.contains(Destination))100    return true;101  return false;102}103 104MachineBasicBlock::iterator105RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I,106                                 MachineBasicBlock::iterator Paired,107                                 bool MoveFromSToA) {108  const MachineOperand *Sreg1, *Sreg2;109  MachineBasicBlock::iterator E = I->getParent()->end();110  MachineBasicBlock::iterator NextI = next_nodbg(I, E);111  DestSourcePair FirstPair = TII->isCopyInstrImpl(*I).value();112  DestSourcePair PairedRegs = TII->isCopyInstrImpl(*Paired).value();113 114  if (NextI == Paired)115    NextI = next_nodbg(NextI, E);116  DebugLoc DL = I->getDebugLoc();117 118  // Make a copy so we can update the kill flag in the MoveFromSToA case. The119  // copied operand needs to be scoped outside the if since we make a pointer120  // to it.121  MachineOperand PairedSource = *PairedRegs.Source;122 123  // The order of S-reg depends on which instruction holds A0, instead of124  // the order of register pair.125  // e,g.126  //   mv a1, s1127  //   mv a0, s2    =>  cm.mva01s s2,s1128  //129  //   mv a0, s2130  //   mv a1, s1    =>  cm.mva01s s2,s1131  unsigned Opcode;132  if (MoveFromSToA) {133    // We are moving one of the copies earlier so its kill flag may become134    // invalid. Clear the copied kill flag if there are any reads of the135    // register between the new location and the old location.136    for (auto It = std::next(I); It != Paired && PairedSource.isKill(); ++It)137      if (It->readsRegister(PairedSource.getReg(), TRI))138        PairedSource.setIsKill(false);139 140    Opcode = getMoveFromSToAOpcode(*ST);141    Sreg1 = FirstPair.Source;142    Sreg2 = &PairedSource;143    if (FirstPair.Destination->getReg() != RISCV::X10)144      std::swap(Sreg1, Sreg2);145  } else {146    Opcode = getMoveFromAToSOpcode(*ST);147    Sreg1 = FirstPair.Destination;148    Sreg2 = PairedRegs.Destination;149    if (FirstPair.Source->getReg() != RISCV::X10)150      std::swap(Sreg1, Sreg2);151  }152 153  BuildMI(*I->getParent(), I, DL, TII->get(Opcode)).add(*Sreg1).add(*Sreg2);154 155  I->eraseFromParent();156  Paired->eraseFromParent();157  return NextI;158}159 160MachineBasicBlock::iterator161RISCVMoveMerge::findMatchingInst(MachineBasicBlock::iterator &MBBI,162                                 bool MoveFromSToA,163                                 const DestSourcePair &RegPair) {164  MachineBasicBlock::iterator E = MBBI->getParent()->end();165 166  // Track which register units have been modified and used between the first167  // insn and the second insn.168  ModifiedRegUnits.clear();169  UsedRegUnits.clear();170 171  for (MachineBasicBlock::iterator I = next_nodbg(MBBI, E); I != E;172       I = next_nodbg(I, E)) {173 174    MachineInstr &MI = *I;175 176    if (auto SecondPair = TII->isCopyInstrImpl(MI)) {177      Register SourceReg = SecondPair->Source->getReg();178      Register DestReg = SecondPair->Destination->getReg();179 180      bool IsCandidate = MoveFromSToA ? isCandidateToMergeMVA01S(*SecondPair)181                                      : isCandidateToMergeMVSA01(*SecondPair);182      if (IsCandidate) {183        // Second destination must be different.184        if (RegPair.Destination->getReg() == DestReg)185          return E;186 187        // For AtoS the source must also be different.188        if (!MoveFromSToA && RegPair.Source->getReg() == SourceReg)189          return E;190 191        // If paired destination register was modified or used, the source reg192        // was modified, there is no possibility of finding matching193        // instruction so exit early.194        if (!ModifiedRegUnits.available(DestReg) ||195            !UsedRegUnits.available(DestReg) ||196            !ModifiedRegUnits.available(SourceReg))197          return E;198 199        return I;200      }201    }202    // Update modified / used register units.203    LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);204  }205  return E;206}207 208// Finds instructions, which could be represented as C.MV instructions and209// merged into CM.MVA01S or CM.MVSA01.210bool RISCVMoveMerge::mergeMoveSARegPair(MachineBasicBlock &MBB) {211  bool Modified = false;212 213  for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();214       MBBI != E;) {215    // Check if the instruction can be compressed to C.MV instruction. If it216    // can, return Dest/Src register pair.217    auto RegPair = TII->isCopyInstrImpl(*MBBI);218    if (RegPair.has_value()) {219      bool MoveFromSToA = isCandidateToMergeMVA01S(*RegPair);220      if (!MoveFromSToA && !isCandidateToMergeMVSA01(*RegPair)) {221        ++MBBI;222        continue;223      }224 225      MachineBasicBlock::iterator Paired =226          findMatchingInst(MBBI, MoveFromSToA, RegPair.value());227      // If matching instruction can be found merge them.228      if (Paired != E) {229        MBBI = mergePairedInsns(MBBI, Paired, MoveFromSToA);230        Modified = true;231        continue;232      }233    }234    ++MBBI;235  }236  return Modified;237}238 239bool RISCVMoveMerge::runOnMachineFunction(MachineFunction &Fn) {240  if (skipFunction(Fn.getFunction()))241    return false;242 243  ST = &Fn.getSubtarget<RISCVSubtarget>();244  if (!ST->hasStdExtZcmp() && !ST->hasVendorXqccmp())245    return false;246 247  TII = ST->getInstrInfo();248  TRI = ST->getRegisterInfo();249  // Resize the modified and used register unit trackers.  We do this once250  // per function and then clear the register units each time we optimize a251  // move.252  ModifiedRegUnits.init(*TRI);253  UsedRegUnits.init(*TRI);254  bool Modified = false;255  for (auto &MBB : Fn)256    Modified |= mergeMoveSARegPair(MBB);257  return Modified;258}259 260/// createRISCVMoveMergePass - returns an instance of the261/// move merge pass.262FunctionPass *llvm::createRISCVMoveMergePass() { return new RISCVMoveMerge(); }263