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
) {
26 initializeRISCVMoveMergePass(*PassRegistry::getPassRegistry());
29 const RISCVInstrInfo
*TII
;
30 const TargetRegisterInfo
*TRI
;
32 // Track which register units have been modified and used.
33 LiveRegUnits ModifiedRegUnits
, UsedRegUnits
;
35 bool isCandidateToMergeMVA01S(const DestSourcePair
&RegPair
);
36 bool isCandidateToMergeMVSA01(const DestSourcePair
&RegPair
);
37 // Merge the two instructions indicated into a single pair instruction.
38 MachineBasicBlock::iterator
39 mergePairedInsns(MachineBasicBlock::iterator I
,
40 MachineBasicBlock::iterator Paired
, unsigned Opcode
);
42 // Look for C.MV instruction that can be combined with
43 // the given instruction into CM.MVA01S or CM.MVSA01. Return the matching
44 // instruction if one exists.
45 MachineBasicBlock::iterator
46 findMatchingInst(MachineBasicBlock::iterator
&MBBI
, unsigned InstOpcode
,
47 const DestSourcePair
&RegPair
);
48 bool mergeMoveSARegPair(MachineBasicBlock
&MBB
);
49 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
51 StringRef
getPassName() const override
{ return RISCV_MOVE_MERGE_NAME
; }
54 char RISCVMoveMerge::ID
= 0;
56 } // end of anonymous namespace
58 INITIALIZE_PASS(RISCVMoveMerge
, "riscv-move-merge", RISCV_MOVE_MERGE_NAME
,
61 // Check if registers meet CM.MVA01S constraints.
62 bool RISCVMoveMerge::isCandidateToMergeMVA01S(const DestSourcePair
&RegPair
) {
63 Register Destination
= RegPair
.Destination
->getReg();
64 Register Source
= RegPair
.Source
->getReg();
65 // If destination is not a0 or a1.
66 if ((Destination
== RISCV::X10
|| Destination
== RISCV::X11
) &&
67 RISCV::SR07RegClass
.contains(Source
))
72 // Check if registers meet CM.MVSA01 constraints.
73 bool RISCVMoveMerge::isCandidateToMergeMVSA01(const DestSourcePair
&RegPair
) {
74 Register Destination
= RegPair
.Destination
->getReg();
75 Register Source
= RegPair
.Source
->getReg();
76 // If Source is s0 - s7.
77 if ((Source
== RISCV::X10
|| Source
== RISCV::X11
) &&
78 RISCV::SR07RegClass
.contains(Destination
))
83 MachineBasicBlock::iterator
84 RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I
,
85 MachineBasicBlock::iterator Paired
,
87 const MachineOperand
*Sreg1
, *Sreg2
;
88 MachineBasicBlock::iterator E
= I
->getParent()->end();
89 MachineBasicBlock::iterator NextI
= next_nodbg(I
, E
);
90 DestSourcePair FirstPair
= TII
->isCopyInstrImpl(*I
).value();
91 DestSourcePair PairedRegs
= TII
->isCopyInstrImpl(*Paired
).value();
92 Register ARegInFirstPair
= Opcode
== RISCV::CM_MVA01S
93 ? FirstPair
.Destination
->getReg()
94 : FirstPair
.Source
->getReg();
97 NextI
= next_nodbg(NextI
, E
);
98 DebugLoc DL
= I
->getDebugLoc();
100 // The order of S-reg depends on which instruction holds A0, instead of
101 // the order of register pair.
104 // mv a0, s2 => cm.mva01s s2,s1
107 // mv a1, s1 => cm.mva01s s2,s1
108 bool StartWithX10
= ARegInFirstPair
== RISCV::X10
;
109 if (Opcode
== RISCV::CM_MVA01S
) {
110 Sreg1
= StartWithX10
? FirstPair
.Source
: PairedRegs
.Source
;
111 Sreg2
= StartWithX10
? PairedRegs
.Source
: FirstPair
.Source
;
113 Sreg1
= StartWithX10
? FirstPair
.Destination
: PairedRegs
.Destination
;
114 Sreg2
= StartWithX10
? PairedRegs
.Destination
: FirstPair
.Destination
;
117 BuildMI(*I
->getParent(), I
, DL
, TII
->get(Opcode
)).add(*Sreg1
).add(*Sreg2
);
119 I
->eraseFromParent();
120 Paired
->eraseFromParent();
124 MachineBasicBlock::iterator
125 RISCVMoveMerge::findMatchingInst(MachineBasicBlock::iterator
&MBBI
,
127 const DestSourcePair
&RegPair
) {
128 MachineBasicBlock::iterator E
= MBBI
->getParent()->end();
130 // Track which register units have been modified and used between the first
131 // insn and the second insn.
132 ModifiedRegUnits
.clear();
133 UsedRegUnits
.clear();
135 for (MachineBasicBlock::iterator I
= next_nodbg(MBBI
, E
); I
!= E
;
136 I
= next_nodbg(I
, E
)) {
138 MachineInstr
&MI
= *I
;
140 if (auto SecondPair
= TII
->isCopyInstrImpl(MI
)) {
141 Register SourceReg
= SecondPair
->Source
->getReg();
142 Register DestReg
= SecondPair
->Destination
->getReg();
144 if (InstOpcode
== RISCV::CM_MVA01S
&&
145 isCandidateToMergeMVA01S(*SecondPair
)) {
146 // If register pair is valid and destination registers are different.
147 if ((RegPair
.Destination
->getReg() == DestReg
))
150 // If paired destination register was modified or used, the source reg
151 // was modified, there is no possibility of finding matching
152 // instruction so exit early.
153 if (!ModifiedRegUnits
.available(DestReg
) ||
154 !UsedRegUnits
.available(DestReg
) ||
155 !ModifiedRegUnits
.available(SourceReg
))
159 } else if (InstOpcode
== RISCV::CM_MVSA01
&&
160 isCandidateToMergeMVSA01(*SecondPair
)) {
161 if ((RegPair
.Source
->getReg() == SourceReg
) ||
162 (RegPair
.Destination
->getReg() == DestReg
))
165 if (!ModifiedRegUnits
.available(DestReg
) ||
166 !UsedRegUnits
.available(DestReg
) ||
167 !ModifiedRegUnits
.available(SourceReg
))
173 // Update modified / used register units.
174 LiveRegUnits::accumulateUsedDefed(MI
, ModifiedRegUnits
, UsedRegUnits
, TRI
);
179 // Finds instructions, which could be represented as C.MV instructions and
180 // merged into CM.MVA01S or CM.MVSA01.
181 bool RISCVMoveMerge::mergeMoveSARegPair(MachineBasicBlock
&MBB
) {
182 bool Modified
= false;
184 for (MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
186 // Check if the instruction can be compressed to C.MV instruction. If it
187 // can, return Dest/Src register pair.
188 auto RegPair
= TII
->isCopyInstrImpl(*MBBI
);
189 if (RegPair
.has_value()) {
192 if (isCandidateToMergeMVA01S(*RegPair
))
193 Opcode
= RISCV::CM_MVA01S
;
194 else if (isCandidateToMergeMVSA01(*RegPair
))
195 Opcode
= RISCV::CM_MVSA01
;
201 MachineBasicBlock::iterator Paired
=
202 findMatchingInst(MBBI
, Opcode
, RegPair
.value());
203 // If matching instruction can be found merge them.
205 MBBI
= mergePairedInsns(MBBI
, Paired
, Opcode
);
215 bool RISCVMoveMerge::runOnMachineFunction(MachineFunction
&Fn
) {
216 if (skipFunction(Fn
.getFunction()))
219 const RISCVSubtarget
*Subtarget
= &Fn
.getSubtarget
<RISCVSubtarget
>();
220 if (!Subtarget
->hasStdExtZcmp())
223 TII
= Subtarget
->getInstrInfo();
224 TRI
= Subtarget
->getRegisterInfo();
225 // Resize the modified and used register unit trackers. We do this once
226 // per function and then clear the register units each time we optimize a
228 ModifiedRegUnits
.init(*TRI
);
229 UsedRegUnits
.init(*TRI
);
230 bool Modified
= false;
232 Modified
|= mergeMoveSARegPair(MBB
);
236 /// createRISCVMoveMergePass - returns an instance of the
238 FunctionPass
*llvm::createRISCVMoveMergePass() { return new RISCVMoveMerge(); }