LLVM 23.0.0git
RISCVMoveMerger.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a pass that performs move related peephole optimizations
10// 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;
32
33 // Track which register units have been modified and used.
34 LiveRegUnits ModifiedRegUnits, UsedRegUnits;
35
36 bool isGPRPairCopyCandidate(const DestSourcePair &RegPair, bool EvenRegPair);
37
38 bool isCandidateToMergeMVA01S(const DestSourcePair &RegPair);
39 bool isCandidateToMergeMVSA01(const DestSourcePair &RegPair);
40
41 bool isPLIPairCandidate(const MachineInstr &MI, bool EvenRegPair);
42
43 // Merge the two instructions indicated into a single pair instruction.
45 mergeGPRPairInsns(MachineBasicBlock::iterator I,
46 MachineBasicBlock::iterator Paired, bool RegPairIsEven);
48 mergePairedInsns(MachineBasicBlock::iterator I,
52 bool RegPairIsEven);
53
55 findMatchingGPRPairCopy(MachineBasicBlock::iterator &MBBI, bool EvenRegPair,
56 const DestSourcePair &RegPair);
57 // Look for C.MV instruction that can be combined with
58 // the given instruction into CM.MVA01S or CM.MVSA01. Return the matching
59 // instruction if one exists.
61 findMatchingSACopy(MachineBasicBlock::iterator &MBBI, bool MoveFromSToA,
62 const DestSourcePair &RegPair);
64 bool EvenRegPair);
65 bool mergeMovePairs(MachineBasicBlock &MBB);
66 bool runOnMachineFunction(MachineFunction &Fn) override;
67
68 StringRef getPassName() const override { return RISCV_MOVE_MERGE_NAME; }
69};
70
71char RISCVMoveMerge::ID = 0;
72
73} // end of anonymous namespace
74
75INITIALIZE_PASS(RISCVMoveMerge, "riscv-move-merge", RISCV_MOVE_MERGE_NAME,
76 false, false)
77
78static unsigned getCM_MVOpcode(const RISCVSubtarget &ST, bool MoveFromSToA) {
79 if (ST.hasStdExtZcmp())
80 return MoveFromSToA ? RISCV::CM_MVA01S : RISCV::CM_MVSA01;
81
82 if (ST.hasVendorXqccmp())
83 return MoveFromSToA ? RISCV::QC_CM_MVA01S : RISCV::QC_CM_MVSA01;
84
85 llvm_unreachable("Unhandled subtarget with paired move.");
86}
87
88// Returns 0 if Opc has no paired form.
89static unsigned getPairedPLIOpcode(unsigned Opc) {
90 switch (Opc) {
91 case RISCV::PLI_B:
92 return RISCV::PLI_DB;
93 case RISCV::PLI_H:
94 return RISCV::PLI_DH;
95 case RISCV::PLUI_H:
96 return RISCV::PLUI_DH;
97 default:
98 return 0;
99 }
100}
101
102bool RISCVMoveMerge::isGPRPairCopyCandidate(const DestSourcePair &RegPair,
103 bool EvenRegPair) {
104 Register Destination = RegPair.Destination->getReg();
105 Register Source = RegPair.Source->getReg();
106
107 if (Source == Destination)
108 return false;
109
110 if ((!ST->hasStdExtZdinx() && !ST->hasStdExtP()) || ST->is64Bit())
111 return false;
112
113 unsigned SubIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
114
115 Register SrcPair =
116 TRI->getMatchingSuperReg(Source, SubIdx, &RISCV::GPRPairRegClass);
117 Register DestPair =
118 TRI->getMatchingSuperReg(Destination, SubIdx, &RISCV::GPRPairRegClass);
119
120 return SrcPair.isValid() && DestPair.isValid();
121}
122
123// Check if registers meet CM.MVA01S constraints.
124bool RISCVMoveMerge::isCandidateToMergeMVA01S(const DestSourcePair &RegPair) {
125 Register Destination = RegPair.Destination->getReg();
126 Register Source = RegPair.Source->getReg();
127 // If destination is not a0 or a1.
128 if ((ST->hasStdExtZcmp() || ST->hasVendorXqccmp()) &&
129 (Destination == RISCV::X10 || Destination == RISCV::X11) &&
130 RISCV::SR07RegClass.contains(Source))
131 return true;
132 return false;
133}
134
135// Check if registers meet CM.MVSA01 constraints.
136bool RISCVMoveMerge::isCandidateToMergeMVSA01(const DestSourcePair &RegPair) {
137 Register Destination = RegPair.Destination->getReg();
138 Register Source = RegPair.Source->getReg();
139 // If Source is s0 - s7.
140 if ((ST->hasStdExtZcmp() || ST->hasVendorXqccmp()) &&
141 (Source == RISCV::X10 || Source == RISCV::X11) &&
142 RISCV::SR07RegClass.contains(Destination))
143 return true;
144 return false;
145}
146
147// Check if MI is a single-reg pli/plui whose destination is a half of a
148// GPRPair.
149bool RISCVMoveMerge::isPLIPairCandidate(const MachineInstr &MI,
150 bool EvenRegPair) {
151 if (!ST->hasStdExtP() || ST->is64Bit())
152 return false;
153 if (!getPairedPLIOpcode(MI.getOpcode()))
154 return false;
155 unsigned SubIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
156 return TRI
157 ->getMatchingSuperReg(MI.getOperand(0).getReg(), SubIdx,
158 &RISCV::GPRPairRegClass)
159 .isValid();
160}
161
163RISCVMoveMerge::mergeGPRPairInsns(MachineBasicBlock::iterator I,
165 bool RegPairIsEven) {
166 MachineBasicBlock::iterator E = I->getParent()->end();
168 DestSourcePair FirstPair = *TII->isCopyInstrImpl(*I);
169 DestSourcePair SecondPair = *TII->isCopyInstrImpl(*Paired);
170
171 if (NextI == Paired)
172 NextI = next_nodbg(NextI, E);
173 DebugLoc DL = I->getDebugLoc();
174
175 // Make a copy of the second instruction to update the kill
176 // flag.
177 MachineOperand PairedSource = *SecondPair.Source;
178
179 for (auto It = std::next(I); It != Paired && PairedSource.isKill(); ++It)
180 if (It->readsRegister(PairedSource.getReg(), TRI))
181 PairedSource.setIsKill(false);
182
183 unsigned GPRPairIdx =
184 RegPairIsEven ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
185 MCRegister SrcReg = TRI->getMatchingSuperReg(
186 FirstPair.Source->getReg(), GPRPairIdx, &RISCV::GPRPairRegClass);
187 MCRegister DestReg = TRI->getMatchingSuperReg(
188 FirstPair.Destination->getReg(), GPRPairIdx, &RISCV::GPRPairRegClass);
189 bool KillSrc = PairedSource.isKill() && FirstPair.Source->isKill();
190
191 TII->copyPhysReg(*I->getParent(), I, DL, DestReg, SrcReg, KillSrc);
192
193 I->eraseFromParent();
194 Paired->eraseFromParent();
195 return NextI;
196}
197
199RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I,
201 bool MoveFromSToA) {
202 const MachineOperand *Sreg1, *Sreg2;
203 MachineBasicBlock::iterator E = I->getParent()->end();
205 DestSourcePair FirstPair = *TII->isCopyInstrImpl(*I);
206 DestSourcePair PairedRegs = *TII->isCopyInstrImpl(*Paired);
207
208 if (NextI == Paired)
209 NextI = next_nodbg(NextI, E);
210 DebugLoc DL = I->getDebugLoc();
211
212 // Make a copy so we can update the kill flag in the MoveFromSToA case. The
213 // copied operand needs to be scoped outside the if since we make a pointer
214 // to it.
215 MachineOperand PairedSource = *PairedRegs.Source;
216
217 // The order of S-reg depends on which instruction holds A0, instead of
218 // the order of register pair.
219 // e,g.
220 // mv a1, s1
221 // mv a0, s2 => cm.mva01s s2,s1
222 //
223 // mv a0, s2
224 // mv a1, s1 => cm.mva01s s2,s1
225 unsigned Opcode = getCM_MVOpcode(*ST, MoveFromSToA);
226 if (MoveFromSToA) {
227 // We are moving one of the copies earlier so its kill flag may become
228 // invalid. Clear the copied kill flag if there are any reads of the
229 // register between the new location and the old location.
230 for (auto It = std::next(I); It != Paired && PairedSource.isKill(); ++It)
231 if (It->readsRegister(PairedSource.getReg(), TRI))
232 PairedSource.setIsKill(false);
233
234 Sreg1 = FirstPair.Source;
235 Sreg2 = &PairedSource;
236 if (FirstPair.Destination->getReg() != RISCV::X10)
237 std::swap(Sreg1, Sreg2);
238 } else {
239 Sreg1 = FirstPair.Destination;
240 Sreg2 = PairedRegs.Destination;
241 if (FirstPair.Source->getReg() != RISCV::X10)
242 std::swap(Sreg1, Sreg2);
243 }
244
245 BuildMI(*I->getParent(), I, DL, TII->get(Opcode)).add(*Sreg1).add(*Sreg2);
246
248 Paired->eraseFromParent();
249 return NextI;
250}
251
253RISCVMoveMerge::mergePLIPair(MachineBasicBlock::iterator I,
255 bool RegPairIsEven) {
256 MachineBasicBlock::iterator E = I->getParent()->end();
258
259 if (NextI == Paired)
260 NextI = next_nodbg(NextI, E);
261 DebugLoc DL = I->getDebugLoc();
262
263 unsigned Opcode = getPairedPLIOpcode(I->getOpcode());
264 unsigned GPRPairIdx =
265 RegPairIsEven ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
266 Register DestReg = TRI->getMatchingSuperReg(
267 I->getOperand(0).getReg(), GPRPairIdx, &RISCV::GPRPairRegClass);
268
269 BuildMI(*I->getParent(), I, DL, TII->get(Opcode), DestReg)
270 .addImm(I->getOperand(1).getImm());
271
273 Paired->eraseFromParent();
274 return NextI;
275}
276
278RISCVMoveMerge::findMatchingGPRPairCopy(MachineBasicBlock::iterator &MBBI,
279 bool EvenRegPair,
280 const DestSourcePair &RegPair) {
282 ModifiedRegUnits.clear();
283 UsedRegUnits.clear();
284 unsigned RegPairIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
285 unsigned SecondPairIdx =
286 !EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
287
288 // Get the expected source/destination registers of the matching lane.
289 Register SrcGPRPair = TRI->getMatchingSuperReg(
290 RegPair.Source->getReg(), RegPairIdx, &RISCV::GPRPairRegClass);
291 Register DestGPRPair = TRI->getMatchingSuperReg(
292 RegPair.Destination->getReg(), RegPairIdx, &RISCV::GPRPairRegClass);
293 Register ExpectedSourceReg = TRI->getSubReg(SrcGPRPair, SecondPairIdx);
294 Register ExpectedDestReg = TRI->getSubReg(DestGPRPair, SecondPairIdx);
295
297 I = next_nodbg(I, E)) {
298
299 MachineInstr &MI = *I;
300
301 if (auto SecondPair = TII->isCopyInstrImpl(MI)) {
302 Register SourceReg = SecondPair->Source->getReg();
303 Register DestReg = SecondPair->Destination->getReg();
304
305 if (RegPair.Destination->getReg() == DestReg ||
306 RegPair.Source->getReg() == SourceReg)
307 return E;
308
309 // Check if the second pair's registers match the other lane of the
310 // GPRPairs.
311 if (SourceReg == ExpectedSourceReg && DestReg == ExpectedDestReg)
312 return I;
313 }
314 // Update modified / used register units.
315 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
316 // Once expected lane registers are clobbered/read in-between, we can stop
317 // scanning since the pair cannot be legally merged anymore.
318 if (!ModifiedRegUnits.available(ExpectedDestReg) ||
319 !UsedRegUnits.available(ExpectedDestReg) ||
320 !ModifiedRegUnits.available(ExpectedSourceReg))
321 return E;
322 }
323 return E;
324}
325
327RISCVMoveMerge::findMatchingSACopy(MachineBasicBlock::iterator &MBBI,
328 bool MoveFromSToA,
329 const DestSourcePair &RegPair) {
331
332 // Track which register units have been modified and used between the first
333 // insn and the second insn.
334 ModifiedRegUnits.clear();
335 UsedRegUnits.clear();
336
338 I = next_nodbg(I, E)) {
339
340 MachineInstr &MI = *I;
341
342 if (auto SecondPair = TII->isCopyInstrImpl(MI)) {
343 Register SourceReg = SecondPair->Source->getReg();
344 Register DestReg = SecondPair->Destination->getReg();
345
346 bool IsCandidate = MoveFromSToA ? isCandidateToMergeMVA01S(*SecondPair)
347 : isCandidateToMergeMVSA01(*SecondPair);
348 if (IsCandidate) {
349 // Second destination must be different.
350 if (RegPair.Destination->getReg() == DestReg)
351 return E;
352
353 // For AtoS the source must also be different.
354 if (!MoveFromSToA && RegPair.Source->getReg() == SourceReg)
355 return E;
356
357 // If paired destination register was modified or used, the source reg
358 // was modified, there is no possibility of finding matching
359 // instruction so exit early.
360 if (!ModifiedRegUnits.available(DestReg) ||
361 !UsedRegUnits.available(DestReg) ||
362 !ModifiedRegUnits.available(SourceReg))
363 return E;
364
365 return I;
366 }
367 }
368 // Update modified / used register units.
369 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
370 }
371 return E;
372}
373
374// Look for a same-opcode pli/plui writing the other lane of the same GPRPair
375// with the same immediate. Return the matching instruction if one exists.
377RISCVMoveMerge::findMatchingPLI(MachineBasicBlock::iterator &MBBI,
378 bool EvenRegPair) {
380 ModifiedRegUnits.clear();
381 UsedRegUnits.clear();
382 unsigned Opc = MBBI->getOpcode();
383 Register FirstDestReg = MBBI->getOperand(0).getReg();
384 int64_t FirstImm = MBBI->getOperand(1).getImm();
385 unsigned RegPairIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
386 unsigned SecondPairIdx =
387 !EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
388
389 // Get the expected destination register of the matching lane.
390 Register DestGPRPair = TRI->getMatchingSuperReg(FirstDestReg, RegPairIdx,
391 &RISCV::GPRPairRegClass);
392 Register ExpectedDestReg = TRI->getSubReg(DestGPRPair, SecondPairIdx);
393
395 I = next_nodbg(I, E)) {
396
397 MachineInstr &MI = *I;
398
399 if (MI.getOpcode() == Opc) {
400 Register DestReg = MI.getOperand(0).getReg();
401 int64_t Imm = MI.getOperand(1).getImm();
402
403 if (FirstDestReg == DestReg)
404 return E;
405
406 // Check if the second PLI matches the other lane and immediate.
407 if (DestReg == ExpectedDestReg && Imm == FirstImm)
408 return I;
409 }
410 // Update modified / used register units.
411 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
412 // Once the expected lane register is clobbered/read in-between, we can
413 // stop scanning since the pair cannot be legally merged anymore.
414 if (!ModifiedRegUnits.available(ExpectedDestReg) ||
415 !UsedRegUnits.available(ExpectedDestReg))
416 return E;
417 }
418 return E;
419}
420
421// Finds instructions, which could be represented as C.MV instructions and
422// merged into CM.MVA01S or CM.MVSA01.
423bool RISCVMoveMerge::mergeMovePairs(MachineBasicBlock &MBB) {
424 bool Modified = false;
425
427 MBBI != E;) {
428 // Try merging a pair of single-reg PLI/PLUI into a paired form.
429 bool IsPLIEven = isPLIPairCandidate(*MBBI, /*EvenRegPair=*/true);
430 bool IsPLIOdd = isPLIPairCandidate(*MBBI, /*EvenRegPair=*/false);
431 if (IsPLIEven != IsPLIOdd) {
432 MachineBasicBlock::iterator Paired = findMatchingPLI(MBBI, IsPLIEven);
433 if (Paired != E) {
434 MBBI = mergePLIPair(MBBI, Paired, IsPLIEven);
435 Modified = true;
436 continue;
437 }
438 }
439
440 // Check if the instruction can be compressed to C.MV instruction. If it
441 // can, return Dest/Src register pair.
442 auto RegPair = TII->isCopyInstrImpl(*MBBI);
443 if (RegPair.has_value()) {
444 bool MoveFromSToA = isCandidateToMergeMVA01S(*RegPair);
445 bool MoveFromAToS = isCandidateToMergeMVSA01(*RegPair);
446 bool IsEven = isGPRPairCopyCandidate(*RegPair, /*EvenRegPair=*/true);
447 bool IsOdd = isGPRPairCopyCandidate(*RegPair, /*EvenRegPair=*/false);
448 if (!MoveFromSToA && !MoveFromAToS && !IsEven && !IsOdd) {
449 ++MBBI;
450 continue;
451 }
452
454 if (MoveFromSToA || MoveFromAToS) {
455 Paired = findMatchingSACopy(MBBI, MoveFromSToA, *RegPair);
456 if (Paired != E) {
457 MBBI = mergePairedInsns(MBBI, Paired, MoveFromSToA);
458 Modified = true;
459 continue;
460 }
461 }
462 if (IsEven != IsOdd) {
463 Paired = findMatchingGPRPairCopy(MBBI, IsEven, *RegPair);
464 if (Paired != E) {
465 MBBI = mergeGPRPairInsns(MBBI, Paired, IsEven);
466 Modified = true;
467 continue;
468 }
469 }
470 }
471 ++MBBI;
472 }
473 return Modified;
474}
475
476bool RISCVMoveMerge::runOnMachineFunction(MachineFunction &Fn) {
477 if (skipFunction(Fn.getFunction()))
478 return false;
479
480 ST = &Fn.getSubtarget<RISCVSubtarget>();
481 bool HasGPRPairCopy =
482 !ST->is64Bit() && (ST->hasStdExtZdinx() || ST->hasStdExtP());
483 if (!ST->hasStdExtZcmp() && !ST->hasVendorXqccmp() && !HasGPRPairCopy)
484 return false;
485
486 TII = ST->getInstrInfo();
487 TRI = ST->getRegisterInfo();
488 // Resize the modified and used register unit trackers. We do this once
489 // per function and then clear the register units each time we optimize a
490 // move.
491 ModifiedRegUnits.init(*TRI);
492 UsedRegUnits.init(*TRI);
493 bool Modified = false;
494 for (auto &MBB : Fn)
495 Modified |= mergeMovePairs(MBB);
496 return Modified;
497}
498
499/// createRISCVMoveMergePass - returns an instance of the
500/// move merge pass.
501FunctionPass *llvm::createRISCVMoveMergePass() { return new RISCVMoveMerge(); }
aarch64 promote const
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
if(PassOpts->AAPipeline)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
bool MoveFromSToA
#define RISCV_MOVE_MERGE_NAME
static unsigned getPairedPLIOpcode(unsigned Opc)
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
Emit instructions to copy a pair of physical registers.
A set of register units used to track register liveness.
static void accumulateUsedDefed(const MachineInstr &MI, LiveRegUnits &ModifiedRegUnits, LiveRegUnits &UsedRegUnits, const TargetRegisterInfo *TRI)
For a machine instruction MI, adds all register units used in UsedRegUnits and defined or clobbered i...
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
void init(const TargetRegisterInfo &TRI)
Initialize and clear the set.
void clear()
Clears the set.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
constexpr bool isValid() const
Definition Register.h:112
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
FunctionPass * createRISCVMoveMergePass()
createRISCVMoveMergePass - returns an instance of the move merge pass.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:862
const MachineOperand * Source
const MachineOperand * Destination