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