1 //===-- RISCVMoveMerger.cpp - RISC-V move merge pass ----------------------===//
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
7 //===----------------------------------------------------------------------===//
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.
12 //===----------------------------------------------------------------------===//
14 #include "RISCVInstrInfo.h"
15 #include "RISCVMachineFunctionInfo.h"
19 #define RISCV_MOVE_MERGE_NAME "RISC-V Zcmp move merging pass"
22 struct RISCVMoveMerge
: public MachineFunctionPass
{
25 RISCVMoveMerge() : MachineFunctionPass(ID
) {}
27 const RISCVInstrInfo
*TII
;
28 const TargetRegisterInfo
*TRI
;
30 // Track which register units have been modified and used.
31 LiveRegUnits ModifiedRegUnits
, UsedRegUnits
;
33 bool isCandidateToMergeMVA01S(const DestSourcePair
&RegPair
);
34 bool isCandidateToMergeMVSA01(const DestSourcePair
&RegPair
);
35 // Merge the two instructions indicated into a single pair instruction.
36 MachineBasicBlock::iterator
37 mergePairedInsns(MachineBasicBlock::iterator I
,
38 MachineBasicBlock::iterator Paired
, unsigned Opcode
);
40 // Look for C.MV instruction that can be combined with
41 // the given instruction into CM.MVA01S or CM.MVSA01. Return the matching
42 // instruction if one exists.
43 MachineBasicBlock::iterator
44 findMatchingInst(MachineBasicBlock::iterator
&MBBI
, unsigned InstOpcode
,
45 const DestSourcePair
&RegPair
);
46 bool mergeMoveSARegPair(MachineBasicBlock
&MBB
);
47 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
49 StringRef
getPassName() const override
{ return RISCV_MOVE_MERGE_NAME
; }
52 char RISCVMoveMerge::ID
= 0;
54 } // end of anonymous namespace
56 INITIALIZE_PASS(RISCVMoveMerge
, "riscv-move-merge", RISCV_MOVE_MERGE_NAME
,
59 // Check if registers meet CM.MVA01S constraints.
60 bool RISCVMoveMerge::isCandidateToMergeMVA01S(const DestSourcePair
&RegPair
) {
61 Register Destination
= RegPair
.Destination
->getReg();
62 Register Source
= RegPair
.Source
->getReg();
63 // If destination is not a0 or a1.
64 if ((Destination
== RISCV::X10
|| Destination
== RISCV::X11
) &&
65 RISCV::SR07RegClass
.contains(Source
))
70 // Check if registers meet CM.MVSA01 constraints.
71 bool RISCVMoveMerge::isCandidateToMergeMVSA01(const DestSourcePair
&RegPair
) {
72 Register Destination
= RegPair
.Destination
->getReg();
73 Register Source
= RegPair
.Source
->getReg();
74 // If Source is s0 - s7.
75 if ((Source
== RISCV::X10
|| Source
== RISCV::X11
) &&
76 RISCV::SR07RegClass
.contains(Destination
))
81 MachineBasicBlock::iterator
82 RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I
,
83 MachineBasicBlock::iterator Paired
,
85 const MachineOperand
*Sreg1
, *Sreg2
;
86 MachineBasicBlock::iterator E
= I
->getParent()->end();
87 MachineBasicBlock::iterator NextI
= next_nodbg(I
, E
);
88 DestSourcePair FirstPair
= TII
->isCopyInstrImpl(*I
).value();
89 DestSourcePair PairedRegs
= TII
->isCopyInstrImpl(*Paired
).value();
90 Register ARegInFirstPair
= Opcode
== RISCV::CM_MVA01S
91 ? FirstPair
.Destination
->getReg()
92 : FirstPair
.Source
->getReg();
95 NextI
= next_nodbg(NextI
, E
);
96 DebugLoc DL
= I
->getDebugLoc();
98 // The order of S-reg depends on which instruction holds A0, instead of
99 // the order of register pair.
102 // mv a0, s2 => cm.mva01s s2,s1
105 // mv a1, s1 => cm.mva01s s2,s1
106 bool StartWithX10
= ARegInFirstPair
== RISCV::X10
;
107 if (Opcode
== RISCV::CM_MVA01S
) {
108 Sreg1
= StartWithX10
? FirstPair
.Source
: PairedRegs
.Source
;
109 Sreg2
= StartWithX10
? PairedRegs
.Source
: FirstPair
.Source
;
111 Sreg1
= StartWithX10
? FirstPair
.Destination
: PairedRegs
.Destination
;
112 Sreg2
= StartWithX10
? PairedRegs
.Destination
: FirstPair
.Destination
;
115 BuildMI(*I
->getParent(), I
, DL
, TII
->get(Opcode
)).add(*Sreg1
).add(*Sreg2
);
117 I
->eraseFromParent();
118 Paired
->eraseFromParent();
122 MachineBasicBlock::iterator
123 RISCVMoveMerge::findMatchingInst(MachineBasicBlock::iterator
&MBBI
,
125 const DestSourcePair
&RegPair
) {
126 MachineBasicBlock::iterator E
= MBBI
->getParent()->end();
128 // Track which register units have been modified and used between the first
129 // insn and the second insn.
130 ModifiedRegUnits
.clear();
131 UsedRegUnits
.clear();
133 for (MachineBasicBlock::iterator I
= next_nodbg(MBBI
, E
); I
!= E
;
134 I
= next_nodbg(I
, E
)) {
136 MachineInstr
&MI
= *I
;
138 if (auto SecondPair
= TII
->isCopyInstrImpl(MI
)) {
139 Register SourceReg
= SecondPair
->Source
->getReg();
140 Register DestReg
= SecondPair
->Destination
->getReg();
142 if (InstOpcode
== RISCV::CM_MVA01S
&&
143 isCandidateToMergeMVA01S(*SecondPair
)) {
144 // If register pair is valid and destination registers are different.
145 if ((RegPair
.Destination
->getReg() == DestReg
))
148 // If paired destination register was modified or used, the source reg
149 // was modified, there is no possibility of finding matching
150 // instruction so exit early.
151 if (!ModifiedRegUnits
.available(DestReg
) ||
152 !UsedRegUnits
.available(DestReg
) ||
153 !ModifiedRegUnits
.available(SourceReg
))
157 } else if (InstOpcode
== RISCV::CM_MVSA01
&&
158 isCandidateToMergeMVSA01(*SecondPair
)) {
159 if ((RegPair
.Source
->getReg() == SourceReg
) ||
160 (RegPair
.Destination
->getReg() == DestReg
))
163 if (!ModifiedRegUnits
.available(DestReg
) ||
164 !UsedRegUnits
.available(DestReg
) ||
165 !ModifiedRegUnits
.available(SourceReg
))
171 // Update modified / used register units.
172 LiveRegUnits::accumulateUsedDefed(MI
, ModifiedRegUnits
, UsedRegUnits
, TRI
);
177 // Finds instructions, which could be represented as C.MV instructions and
178 // merged into CM.MVA01S or CM.MVSA01.
179 bool RISCVMoveMerge::mergeMoveSARegPair(MachineBasicBlock
&MBB
) {
180 bool Modified
= false;
182 for (MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
184 // Check if the instruction can be compressed to C.MV instruction. If it
185 // can, return Dest/Src register pair.
186 auto RegPair
= TII
->isCopyInstrImpl(*MBBI
);
187 if (RegPair
.has_value()) {
190 if (isCandidateToMergeMVA01S(*RegPair
))
191 Opcode
= RISCV::CM_MVA01S
;
192 else if (isCandidateToMergeMVSA01(*RegPair
))
193 Opcode
= RISCV::CM_MVSA01
;
199 MachineBasicBlock::iterator Paired
=
200 findMatchingInst(MBBI
, Opcode
, RegPair
.value());
201 // If matching instruction can be found merge them.
203 MBBI
= mergePairedInsns(MBBI
, Paired
, Opcode
);
213 bool RISCVMoveMerge::runOnMachineFunction(MachineFunction
&Fn
) {
214 if (skipFunction(Fn
.getFunction()))
217 const RISCVSubtarget
*Subtarget
= &Fn
.getSubtarget
<RISCVSubtarget
>();
218 if (!Subtarget
->hasStdExtZcmp())
221 TII
= Subtarget
->getInstrInfo();
222 TRI
= Subtarget
->getRegisterInfo();
223 // Resize the modified and used register unit trackers. We do this once
224 // per function and then clear the register units each time we optimize a
226 ModifiedRegUnits
.init(*TRI
);
227 UsedRegUnits
.init(*TRI
);
228 bool Modified
= false;
230 Modified
|= mergeMoveSARegPair(MBB
);
234 /// createRISCVMoveMergePass - returns an instance of the
236 FunctionPass
*llvm::createRISCVMoveMergePass() { return new RISCVMoveMerge(); }