106c3fb27SDimitry Andric //===-- RISCVInstrInfo.cpp - RISC-V Instruction Information -----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
906c3fb27SDimitry Andric // This file contains the RISC-V implementation of the TargetInstrInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "RISCVInstrInfo.h"
14e8d8bef9SDimitry Andric #include "MCTargetDesc/RISCVMatInt.h"
150b57cec5SDimitry Andric #include "RISCV.h"
16fe6060f1SDimitry Andric #include "RISCVMachineFunctionInfo.h"
170b57cec5SDimitry Andric #include "RISCVSubtarget.h"
180b57cec5SDimitry Andric #include "RISCVTargetMachine.h"
190b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
21fe6060f1SDimitry Andric #include "llvm/Analysis/MemoryLocation.h"
225f757f3fSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
23349cc55cSDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
24fe6060f1SDimitry Andric #include "llvm/CodeGen/LiveVariables.h"
25bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineCombinerPattern.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
2906c3fb27SDimitry Andric #include "llvm/CodeGen/MachineTraceMetrics.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h"
315f757f3fSDimitry Andric #include "llvm/CodeGen/StackMaps.h"
32bdd1243dSDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
33fe6060f1SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
34349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
350b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
360b57cec5SDimitry Andric 
3755e4f9d5SDimitry Andric using namespace llvm;
3855e4f9d5SDimitry Andric 
39480093f4SDimitry Andric #define GEN_CHECK_COMPRESS_INSTR
40480093f4SDimitry Andric #include "RISCVGenCompressInstEmitter.inc"
41480093f4SDimitry Andric 
420b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
430eae32dcSDimitry Andric #define GET_INSTRINFO_NAMED_OPS
440b57cec5SDimitry Andric #include "RISCVGenInstrInfo.inc"
450b57cec5SDimitry Andric 
46349cc55cSDimitry Andric static cl::opt<bool> PreferWholeRegisterMove(
47349cc55cSDimitry Andric     "riscv-prefer-whole-register-move", cl::init(false), cl::Hidden,
48349cc55cSDimitry Andric     cl::desc("Prefer whole register move for vector registers."));
49349cc55cSDimitry Andric 
5006c3fb27SDimitry Andric static cl::opt<MachineTraceStrategy> ForceMachineCombinerStrategy(
5106c3fb27SDimitry Andric     "riscv-force-machine-combiner-strategy", cl::Hidden,
5206c3fb27SDimitry Andric     cl::desc("Force machine combiner to use a specific strategy for machine "
5306c3fb27SDimitry Andric              "trace metrics evaluation."),
5406c3fb27SDimitry Andric     cl::init(MachineTraceStrategy::TS_NumStrategies),
5506c3fb27SDimitry Andric     cl::values(clEnumValN(MachineTraceStrategy::TS_Local, "local",
5606c3fb27SDimitry Andric                           "Local strategy."),
5706c3fb27SDimitry Andric                clEnumValN(MachineTraceStrategy::TS_MinInstrCount, "min-instr",
5806c3fb27SDimitry Andric                           "MinInstrCount strategy.")));
5906c3fb27SDimitry Andric 
60bdd1243dSDimitry Andric namespace llvm::RISCVVPseudosTable {
61fe6060f1SDimitry Andric 
62fe6060f1SDimitry Andric using namespace RISCV;
63fe6060f1SDimitry Andric 
64fe6060f1SDimitry Andric #define GET_RISCVVPseudosTable_IMPL
65fe6060f1SDimitry Andric #include "RISCVGenSearchableTables.inc"
66fe6060f1SDimitry Andric 
67bdd1243dSDimitry Andric } // namespace llvm::RISCVVPseudosTable
68fe6060f1SDimitry Andric 
RISCVInstrInfo(RISCVSubtarget & STI)698bcb0991SDimitry Andric RISCVInstrInfo::RISCVInstrInfo(RISCVSubtarget &STI)
708bcb0991SDimitry Andric     : RISCVGenInstrInfo(RISCV::ADJCALLSTACKDOWN, RISCV::ADJCALLSTACKUP),
718bcb0991SDimitry Andric       STI(STI) {}
720b57cec5SDimitry Andric 
getNop() const73fe6060f1SDimitry Andric MCInst RISCVInstrInfo::getNop() const {
74bdd1243dSDimitry Andric   if (STI.hasStdExtCOrZca())
75fe6060f1SDimitry Andric     return MCInstBuilder(RISCV::C_NOP);
76fe6060f1SDimitry Andric   return MCInstBuilder(RISCV::ADDI)
77fe6060f1SDimitry Andric       .addReg(RISCV::X0)
78fe6060f1SDimitry Andric       .addReg(RISCV::X0)
79fe6060f1SDimitry Andric       .addImm(0);
80fe6060f1SDimitry Andric }
81fe6060f1SDimitry Andric 
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const820b57cec5SDimitry Andric unsigned RISCVInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
830b57cec5SDimitry Andric                                              int &FrameIndex) const {
8406c3fb27SDimitry Andric   unsigned Dummy;
8506c3fb27SDimitry Andric   return isLoadFromStackSlot(MI, FrameIndex, Dummy);
8606c3fb27SDimitry Andric }
8706c3fb27SDimitry Andric 
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex,unsigned & MemBytes) const8806c3fb27SDimitry Andric unsigned RISCVInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
8906c3fb27SDimitry Andric                                              int &FrameIndex,
9006c3fb27SDimitry Andric                                              unsigned &MemBytes) const {
910b57cec5SDimitry Andric   switch (MI.getOpcode()) {
920b57cec5SDimitry Andric   default:
930b57cec5SDimitry Andric     return 0;
940b57cec5SDimitry Andric   case RISCV::LB:
950b57cec5SDimitry Andric   case RISCV::LBU:
9606c3fb27SDimitry Andric     MemBytes = 1;
9706c3fb27SDimitry Andric     break;
980b57cec5SDimitry Andric   case RISCV::LH:
990b57cec5SDimitry Andric   case RISCV::LHU:
100e8d8bef9SDimitry Andric   case RISCV::FLH:
10106c3fb27SDimitry Andric     MemBytes = 2;
10206c3fb27SDimitry Andric     break;
1030b57cec5SDimitry Andric   case RISCV::LW:
1040b57cec5SDimitry Andric   case RISCV::FLW:
1050b57cec5SDimitry Andric   case RISCV::LWU:
10606c3fb27SDimitry Andric     MemBytes = 4;
10706c3fb27SDimitry Andric     break;
1080b57cec5SDimitry Andric   case RISCV::LD:
1090b57cec5SDimitry Andric   case RISCV::FLD:
11006c3fb27SDimitry Andric     MemBytes = 8;
1110b57cec5SDimitry Andric     break;
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
1150b57cec5SDimitry Andric       MI.getOperand(2).getImm() == 0) {
1160b57cec5SDimitry Andric     FrameIndex = MI.getOperand(1).getIndex();
1170b57cec5SDimitry Andric     return MI.getOperand(0).getReg();
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   return 0;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const1230b57cec5SDimitry Andric unsigned RISCVInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
1240b57cec5SDimitry Andric                                             int &FrameIndex) const {
12506c3fb27SDimitry Andric   unsigned Dummy;
12606c3fb27SDimitry Andric   return isStoreToStackSlot(MI, FrameIndex, Dummy);
12706c3fb27SDimitry Andric }
12806c3fb27SDimitry Andric 
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex,unsigned & MemBytes) const12906c3fb27SDimitry Andric unsigned RISCVInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
13006c3fb27SDimitry Andric                                             int &FrameIndex,
13106c3fb27SDimitry Andric                                             unsigned &MemBytes) const {
1320b57cec5SDimitry Andric   switch (MI.getOpcode()) {
1330b57cec5SDimitry Andric   default:
1340b57cec5SDimitry Andric     return 0;
1350b57cec5SDimitry Andric   case RISCV::SB:
13606c3fb27SDimitry Andric     MemBytes = 1;
13706c3fb27SDimitry Andric     break;
1380b57cec5SDimitry Andric   case RISCV::SH:
139e8d8bef9SDimitry Andric   case RISCV::FSH:
14006c3fb27SDimitry Andric     MemBytes = 2;
14106c3fb27SDimitry Andric     break;
14206c3fb27SDimitry Andric   case RISCV::SW:
1430b57cec5SDimitry Andric   case RISCV::FSW:
14406c3fb27SDimitry Andric     MemBytes = 4;
14506c3fb27SDimitry Andric     break;
1460b57cec5SDimitry Andric   case RISCV::SD:
1470b57cec5SDimitry Andric   case RISCV::FSD:
14806c3fb27SDimitry Andric     MemBytes = 8;
1490b57cec5SDimitry Andric     break;
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1525ffd83dbSDimitry Andric   if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
1535ffd83dbSDimitry Andric       MI.getOperand(2).getImm() == 0) {
1545ffd83dbSDimitry Andric     FrameIndex = MI.getOperand(1).getIndex();
1555ffd83dbSDimitry Andric     return MI.getOperand(0).getReg();
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   return 0;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
forwardCopyWillClobberTuple(unsigned DstReg,unsigned SrcReg,unsigned NumRegs)161fe6060f1SDimitry Andric static bool forwardCopyWillClobberTuple(unsigned DstReg, unsigned SrcReg,
162fe6060f1SDimitry Andric                                         unsigned NumRegs) {
163349cc55cSDimitry Andric   return DstReg > SrcReg && (DstReg - SrcReg) < NumRegs;
164349cc55cSDimitry Andric }
165349cc55cSDimitry Andric 
isConvertibleToVMV_V_V(const RISCVSubtarget & STI,const MachineBasicBlock & MBB,MachineBasicBlock::const_iterator MBBI,MachineBasicBlock::const_iterator & DefMBBI,RISCVII::VLMUL LMul)166349cc55cSDimitry Andric static bool isConvertibleToVMV_V_V(const RISCVSubtarget &STI,
167349cc55cSDimitry Andric                                    const MachineBasicBlock &MBB,
168349cc55cSDimitry Andric                                    MachineBasicBlock::const_iterator MBBI,
169349cc55cSDimitry Andric                                    MachineBasicBlock::const_iterator &DefMBBI,
170349cc55cSDimitry Andric                                    RISCVII::VLMUL LMul) {
171349cc55cSDimitry Andric   if (PreferWholeRegisterMove)
172349cc55cSDimitry Andric     return false;
173349cc55cSDimitry Andric 
174349cc55cSDimitry Andric   assert(MBBI->getOpcode() == TargetOpcode::COPY &&
175349cc55cSDimitry Andric          "Unexpected COPY instruction.");
176349cc55cSDimitry Andric   Register SrcReg = MBBI->getOperand(1).getReg();
177349cc55cSDimitry Andric   const TargetRegisterInfo *TRI = STI.getRegisterInfo();
178349cc55cSDimitry Andric 
179349cc55cSDimitry Andric   bool FoundDef = false;
180349cc55cSDimitry Andric   bool FirstVSetVLI = false;
181349cc55cSDimitry Andric   unsigned FirstSEW = 0;
182349cc55cSDimitry Andric   while (MBBI != MBB.begin()) {
183349cc55cSDimitry Andric     --MBBI;
184349cc55cSDimitry Andric     if (MBBI->isMetaInstruction())
185349cc55cSDimitry Andric       continue;
186349cc55cSDimitry Andric 
187349cc55cSDimitry Andric     if (MBBI->getOpcode() == RISCV::PseudoVSETVLI ||
188349cc55cSDimitry Andric         MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 ||
189349cc55cSDimitry Andric         MBBI->getOpcode() == RISCV::PseudoVSETIVLI) {
190349cc55cSDimitry Andric       // There is a vsetvli between COPY and source define instruction.
191349cc55cSDimitry Andric       // vy = def_vop ...  (producing instruction)
192349cc55cSDimitry Andric       // ...
193349cc55cSDimitry Andric       // vsetvli
194349cc55cSDimitry Andric       // ...
195349cc55cSDimitry Andric       // vx = COPY vy
196349cc55cSDimitry Andric       if (!FoundDef) {
197349cc55cSDimitry Andric         if (!FirstVSetVLI) {
198349cc55cSDimitry Andric           FirstVSetVLI = true;
199349cc55cSDimitry Andric           unsigned FirstVType = MBBI->getOperand(2).getImm();
200349cc55cSDimitry Andric           RISCVII::VLMUL FirstLMul = RISCVVType::getVLMUL(FirstVType);
201349cc55cSDimitry Andric           FirstSEW = RISCVVType::getSEW(FirstVType);
202349cc55cSDimitry Andric           // The first encountered vsetvli must have the same lmul as the
203349cc55cSDimitry Andric           // register class of COPY.
204349cc55cSDimitry Andric           if (FirstLMul != LMul)
205349cc55cSDimitry Andric             return false;
206349cc55cSDimitry Andric         }
207349cc55cSDimitry Andric         // Only permit `vsetvli x0, x0, vtype` between COPY and the source
208349cc55cSDimitry Andric         // define instruction.
209349cc55cSDimitry Andric         if (MBBI->getOperand(0).getReg() != RISCV::X0)
210349cc55cSDimitry Andric           return false;
211349cc55cSDimitry Andric         if (MBBI->getOperand(1).isImm())
212349cc55cSDimitry Andric           return false;
213349cc55cSDimitry Andric         if (MBBI->getOperand(1).getReg() != RISCV::X0)
214349cc55cSDimitry Andric           return false;
215349cc55cSDimitry Andric         continue;
216349cc55cSDimitry Andric       }
217349cc55cSDimitry Andric 
218349cc55cSDimitry Andric       // MBBI is the first vsetvli before the producing instruction.
219349cc55cSDimitry Andric       unsigned VType = MBBI->getOperand(2).getImm();
220349cc55cSDimitry Andric       // If there is a vsetvli between COPY and the producing instruction.
221349cc55cSDimitry Andric       if (FirstVSetVLI) {
222349cc55cSDimitry Andric         // If SEW is different, return false.
223349cc55cSDimitry Andric         if (RISCVVType::getSEW(VType) != FirstSEW)
224349cc55cSDimitry Andric           return false;
225349cc55cSDimitry Andric       }
226349cc55cSDimitry Andric 
227349cc55cSDimitry Andric       // If the vsetvli is tail undisturbed, keep the whole register move.
228349cc55cSDimitry Andric       if (!RISCVVType::isTailAgnostic(VType))
229349cc55cSDimitry Andric         return false;
230349cc55cSDimitry Andric 
231349cc55cSDimitry Andric       // The checking is conservative. We only have register classes for
232349cc55cSDimitry Andric       // LMUL = 1/2/4/8. We should be able to convert vmv1r.v to vmv.v.v
233349cc55cSDimitry Andric       // for fractional LMUL operations. However, we could not use the vsetvli
234349cc55cSDimitry Andric       // lmul for widening operations. The result of widening operation is
235349cc55cSDimitry Andric       // 2 x LMUL.
236349cc55cSDimitry Andric       return LMul == RISCVVType::getVLMUL(VType);
237349cc55cSDimitry Andric     } else if (MBBI->isInlineAsm() || MBBI->isCall()) {
238349cc55cSDimitry Andric       return false;
239349cc55cSDimitry Andric     } else if (MBBI->getNumDefs()) {
240349cc55cSDimitry Andric       // Check all the instructions which will change VL.
241349cc55cSDimitry Andric       // For example, vleff has implicit def VL.
242349cc55cSDimitry Andric       if (MBBI->modifiesRegister(RISCV::VL))
243349cc55cSDimitry Andric         return false;
244349cc55cSDimitry Andric 
24504eeddc0SDimitry Andric       // Only converting whole register copies to vmv.v.v when the defining
24604eeddc0SDimitry Andric       // value appears in the explicit operands.
24704eeddc0SDimitry Andric       for (const MachineOperand &MO : MBBI->explicit_operands()) {
248349cc55cSDimitry Andric         if (!MO.isReg() || !MO.isDef())
249349cc55cSDimitry Andric           continue;
25006c3fb27SDimitry Andric         if (!FoundDef && TRI->regsOverlap(MO.getReg(), SrcReg)) {
251349cc55cSDimitry Andric           // We only permit the source of COPY has the same LMUL as the defined
252349cc55cSDimitry Andric           // operand.
253349cc55cSDimitry Andric           // There are cases we need to keep the whole register copy if the LMUL
254349cc55cSDimitry Andric           // is different.
255349cc55cSDimitry Andric           // For example,
256349cc55cSDimitry Andric           // $x0 = PseudoVSETIVLI 4, 73   // vsetivli zero, 4, e16,m2,ta,m
257349cc55cSDimitry Andric           // $v28m4 = PseudoVWADD_VV_M2 $v26m2, $v8m2
258349cc55cSDimitry Andric           // # The COPY may be created by vlmul_trunc intrinsic.
259349cc55cSDimitry Andric           // $v26m2 = COPY renamable $v28m2, implicit killed $v28m4
260349cc55cSDimitry Andric           //
261349cc55cSDimitry Andric           // After widening, the valid value will be 4 x e32 elements. If we
262349cc55cSDimitry Andric           // convert the COPY to vmv.v.v, it will only copy 4 x e16 elements.
263349cc55cSDimitry Andric           // FIXME: The COPY of subregister of Zvlsseg register will not be able
264349cc55cSDimitry Andric           // to convert to vmv.v.[v|i] under the constraint.
265349cc55cSDimitry Andric           if (MO.getReg() != SrcReg)
266349cc55cSDimitry Andric             return false;
267349cc55cSDimitry Andric 
268349cc55cSDimitry Andric           // In widening reduction instructions with LMUL_1 input vector case,
269349cc55cSDimitry Andric           // only checking the LMUL is insufficient due to reduction result is
270349cc55cSDimitry Andric           // always LMUL_1.
271349cc55cSDimitry Andric           // For example,
272349cc55cSDimitry Andric           // $x11 = PseudoVSETIVLI 1, 64 // vsetivli a1, 1, e8, m1, ta, mu
273349cc55cSDimitry Andric           // $v8m1 = PseudoVWREDSUM_VS_M1 $v26, $v27
274349cc55cSDimitry Andric           // $v26 = COPY killed renamable $v8
275349cc55cSDimitry Andric           // After widening, The valid value will be 1 x e16 elements. If we
276349cc55cSDimitry Andric           // convert the COPY to vmv.v.v, it will only copy 1 x e8 elements.
277349cc55cSDimitry Andric           uint64_t TSFlags = MBBI->getDesc().TSFlags;
278349cc55cSDimitry Andric           if (RISCVII::isRVVWideningReduction(TSFlags))
279349cc55cSDimitry Andric             return false;
280349cc55cSDimitry Andric 
281bdd1243dSDimitry Andric           // If the producing instruction does not depend on vsetvli, do not
282bdd1243dSDimitry Andric           // convert COPY to vmv.v.v. For example, VL1R_V or PseudoVRELOAD.
283bdd1243dSDimitry Andric           if (!RISCVII::hasSEWOp(TSFlags) || !RISCVII::hasVLOp(TSFlags))
284bdd1243dSDimitry Andric             return false;
285bdd1243dSDimitry Andric 
286349cc55cSDimitry Andric           // Found the definition.
287349cc55cSDimitry Andric           FoundDef = true;
288349cc55cSDimitry Andric           DefMBBI = MBBI;
289349cc55cSDimitry Andric           break;
290349cc55cSDimitry Andric         }
291349cc55cSDimitry Andric       }
292349cc55cSDimitry Andric     }
293349cc55cSDimitry Andric   }
294349cc55cSDimitry Andric 
295349cc55cSDimitry Andric   return false;
296fe6060f1SDimitry Andric }
297fe6060f1SDimitry Andric 
copyPhysRegVector(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,MCRegister DstReg,MCRegister SrcReg,bool KillSrc,unsigned Opc,unsigned NF) const2985f757f3fSDimitry Andric void RISCVInstrInfo::copyPhysRegVector(MachineBasicBlock &MBB,
2995f757f3fSDimitry Andric                                        MachineBasicBlock::iterator MBBI,
3005f757f3fSDimitry Andric                                        const DebugLoc &DL, MCRegister DstReg,
3015f757f3fSDimitry Andric                                        MCRegister SrcReg, bool KillSrc,
3025f757f3fSDimitry Andric                                        unsigned Opc, unsigned NF) const {
3035f757f3fSDimitry Andric   const TargetRegisterInfo *TRI = STI.getRegisterInfo();
3045f757f3fSDimitry Andric 
3055f757f3fSDimitry Andric   RISCVII::VLMUL LMul;
3065f757f3fSDimitry Andric   unsigned SubRegIdx;
3075f757f3fSDimitry Andric   unsigned VVOpc, VIOpc;
3085f757f3fSDimitry Andric   switch (Opc) {
3095f757f3fSDimitry Andric   default:
3105f757f3fSDimitry Andric     llvm_unreachable("Impossible LMUL for vector register copy.");
3115f757f3fSDimitry Andric   case RISCV::VMV1R_V:
3125f757f3fSDimitry Andric     LMul = RISCVII::LMUL_1;
3135f757f3fSDimitry Andric     SubRegIdx = RISCV::sub_vrm1_0;
3145f757f3fSDimitry Andric     VVOpc = RISCV::PseudoVMV_V_V_M1;
3155f757f3fSDimitry Andric     VIOpc = RISCV::PseudoVMV_V_I_M1;
3165f757f3fSDimitry Andric     break;
3175f757f3fSDimitry Andric   case RISCV::VMV2R_V:
3185f757f3fSDimitry Andric     LMul = RISCVII::LMUL_2;
3195f757f3fSDimitry Andric     SubRegIdx = RISCV::sub_vrm2_0;
3205f757f3fSDimitry Andric     VVOpc = RISCV::PseudoVMV_V_V_M2;
3215f757f3fSDimitry Andric     VIOpc = RISCV::PseudoVMV_V_I_M2;
3225f757f3fSDimitry Andric     break;
3235f757f3fSDimitry Andric   case RISCV::VMV4R_V:
3245f757f3fSDimitry Andric     LMul = RISCVII::LMUL_4;
3255f757f3fSDimitry Andric     SubRegIdx = RISCV::sub_vrm4_0;
3265f757f3fSDimitry Andric     VVOpc = RISCV::PseudoVMV_V_V_M4;
3275f757f3fSDimitry Andric     VIOpc = RISCV::PseudoVMV_V_I_M4;
3285f757f3fSDimitry Andric     break;
3295f757f3fSDimitry Andric   case RISCV::VMV8R_V:
3305f757f3fSDimitry Andric     assert(NF == 1);
3315f757f3fSDimitry Andric     LMul = RISCVII::LMUL_8;
3325f757f3fSDimitry Andric     SubRegIdx = RISCV::sub_vrm1_0; // There is no sub_vrm8_0.
3335f757f3fSDimitry Andric     VVOpc = RISCV::PseudoVMV_V_V_M8;
3345f757f3fSDimitry Andric     VIOpc = RISCV::PseudoVMV_V_I_M8;
3355f757f3fSDimitry Andric     break;
3365f757f3fSDimitry Andric   }
3375f757f3fSDimitry Andric 
3385f757f3fSDimitry Andric   bool UseVMV_V_V = false;
3395f757f3fSDimitry Andric   bool UseVMV_V_I = false;
3405f757f3fSDimitry Andric   MachineBasicBlock::const_iterator DefMBBI;
3415f757f3fSDimitry Andric   if (isConvertibleToVMV_V_V(STI, MBB, MBBI, DefMBBI, LMul)) {
3425f757f3fSDimitry Andric     UseVMV_V_V = true;
3435f757f3fSDimitry Andric     Opc = VVOpc;
3445f757f3fSDimitry Andric 
3455f757f3fSDimitry Andric     if (DefMBBI->getOpcode() == VIOpc) {
3465f757f3fSDimitry Andric       UseVMV_V_I = true;
3475f757f3fSDimitry Andric       Opc = VIOpc;
3485f757f3fSDimitry Andric     }
3495f757f3fSDimitry Andric   }
3505f757f3fSDimitry Andric 
3515f757f3fSDimitry Andric   if (NF == 1) {
3525f757f3fSDimitry Andric     auto MIB = BuildMI(MBB, MBBI, DL, get(Opc), DstReg);
3535f757f3fSDimitry Andric     if (UseVMV_V_V)
3545f757f3fSDimitry Andric       MIB.addReg(DstReg, RegState::Undef);
3555f757f3fSDimitry Andric     if (UseVMV_V_I)
3565f757f3fSDimitry Andric       MIB = MIB.add(DefMBBI->getOperand(2));
3575f757f3fSDimitry Andric     else
3585f757f3fSDimitry Andric       MIB = MIB.addReg(SrcReg, getKillRegState(KillSrc));
3595f757f3fSDimitry Andric     if (UseVMV_V_V) {
3605f757f3fSDimitry Andric       const MCInstrDesc &Desc = DefMBBI->getDesc();
3615f757f3fSDimitry Andric       MIB.add(DefMBBI->getOperand(RISCVII::getVLOpNum(Desc)));  // AVL
3625f757f3fSDimitry Andric       MIB.add(DefMBBI->getOperand(RISCVII::getSEWOpNum(Desc))); // SEW
3635f757f3fSDimitry Andric       MIB.addImm(0);                                            // tu, mu
3645f757f3fSDimitry Andric       MIB.addReg(RISCV::VL, RegState::Implicit);
3655f757f3fSDimitry Andric       MIB.addReg(RISCV::VTYPE, RegState::Implicit);
3665f757f3fSDimitry Andric     }
3675f757f3fSDimitry Andric     return;
3685f757f3fSDimitry Andric   }
3695f757f3fSDimitry Andric 
3705f757f3fSDimitry Andric   int I = 0, End = NF, Incr = 1;
3715f757f3fSDimitry Andric   unsigned SrcEncoding = TRI->getEncodingValue(SrcReg);
3725f757f3fSDimitry Andric   unsigned DstEncoding = TRI->getEncodingValue(DstReg);
3735f757f3fSDimitry Andric   unsigned LMulVal;
3745f757f3fSDimitry Andric   bool Fractional;
3755f757f3fSDimitry Andric   std::tie(LMulVal, Fractional) = RISCVVType::decodeVLMUL(LMul);
3765f757f3fSDimitry Andric   assert(!Fractional && "It is impossible be fractional lmul here.");
3775f757f3fSDimitry Andric   if (forwardCopyWillClobberTuple(DstEncoding, SrcEncoding, NF * LMulVal)) {
3785f757f3fSDimitry Andric     I = NF - 1;
3795f757f3fSDimitry Andric     End = -1;
3805f757f3fSDimitry Andric     Incr = -1;
3815f757f3fSDimitry Andric   }
3825f757f3fSDimitry Andric 
3835f757f3fSDimitry Andric   for (; I != End; I += Incr) {
3845f757f3fSDimitry Andric     auto MIB =
3855f757f3fSDimitry Andric         BuildMI(MBB, MBBI, DL, get(Opc), TRI->getSubReg(DstReg, SubRegIdx + I));
3865f757f3fSDimitry Andric     if (UseVMV_V_V)
3875f757f3fSDimitry Andric       MIB.addReg(TRI->getSubReg(DstReg, SubRegIdx + I), RegState::Undef);
3885f757f3fSDimitry Andric     if (UseVMV_V_I)
3895f757f3fSDimitry Andric       MIB = MIB.add(DefMBBI->getOperand(2));
3905f757f3fSDimitry Andric     else
3915f757f3fSDimitry Andric       MIB = MIB.addReg(TRI->getSubReg(SrcReg, SubRegIdx + I),
3925f757f3fSDimitry Andric                        getKillRegState(KillSrc));
3935f757f3fSDimitry Andric     if (UseVMV_V_V) {
3945f757f3fSDimitry Andric       const MCInstrDesc &Desc = DefMBBI->getDesc();
3955f757f3fSDimitry Andric       MIB.add(DefMBBI->getOperand(RISCVII::getVLOpNum(Desc)));  // AVL
3965f757f3fSDimitry Andric       MIB.add(DefMBBI->getOperand(RISCVII::getSEWOpNum(Desc))); // SEW
3975f757f3fSDimitry Andric       MIB.addImm(0);                                            // tu, mu
3985f757f3fSDimitry Andric       MIB.addReg(RISCV::VL, RegState::Implicit);
3995f757f3fSDimitry Andric       MIB.addReg(RISCV::VTYPE, RegState::Implicit);
4005f757f3fSDimitry Andric     }
4015f757f3fSDimitry Andric   }
4025f757f3fSDimitry Andric }
4035f757f3fSDimitry Andric 
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,MCRegister DstReg,MCRegister SrcReg,bool KillSrc) const4040b57cec5SDimitry Andric void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
4050b57cec5SDimitry Andric                                  MachineBasicBlock::iterator MBBI,
406480093f4SDimitry Andric                                  const DebugLoc &DL, MCRegister DstReg,
407480093f4SDimitry Andric                                  MCRegister SrcReg, bool KillSrc) const {
40806c3fb27SDimitry Andric   const TargetRegisterInfo *TRI = STI.getRegisterInfo();
40906c3fb27SDimitry Andric 
4100b57cec5SDimitry Andric   if (RISCV::GPRRegClass.contains(DstReg, SrcReg)) {
4110b57cec5SDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::ADDI), DstReg)
4120b57cec5SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc))
4130b57cec5SDimitry Andric         .addImm(0);
4140b57cec5SDimitry Andric     return;
4150b57cec5SDimitry Andric   }
4160b57cec5SDimitry Andric 
417297eecfbSDimitry Andric   if (RISCV::GPRPairRegClass.contains(DstReg, SrcReg)) {
418297eecfbSDimitry Andric     // Emit an ADDI for both parts of GPRPair.
419b121cb00SDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::ADDI),
420297eecfbSDimitry Andric             TRI->getSubReg(DstReg, RISCV::sub_gpr_even))
421297eecfbSDimitry Andric         .addReg(TRI->getSubReg(SrcReg, RISCV::sub_gpr_even),
422297eecfbSDimitry Andric                 getKillRegState(KillSrc))
423b121cb00SDimitry Andric         .addImm(0);
424b121cb00SDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::ADDI),
425297eecfbSDimitry Andric             TRI->getSubReg(DstReg, RISCV::sub_gpr_odd))
426297eecfbSDimitry Andric         .addReg(TRI->getSubReg(SrcReg, RISCV::sub_gpr_odd),
427b121cb00SDimitry Andric                 getKillRegState(KillSrc))
428b121cb00SDimitry Andric         .addImm(0);
429b121cb00SDimitry Andric     return;
430b121cb00SDimitry Andric   }
431b121cb00SDimitry Andric 
43281ad6265SDimitry Andric   // Handle copy from csr
43381ad6265SDimitry Andric   if (RISCV::VCSRRegClass.contains(SrcReg) &&
43481ad6265SDimitry Andric       RISCV::GPRRegClass.contains(DstReg)) {
43581ad6265SDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::CSRRS), DstReg)
43606c3fb27SDimitry Andric         .addImm(RISCVSysReg::lookupSysRegByName(TRI->getName(SrcReg))->Encoding)
43781ad6265SDimitry Andric         .addReg(RISCV::X0);
43881ad6265SDimitry Andric     return;
43981ad6265SDimitry Andric   }
44081ad6265SDimitry Andric 
441fe6060f1SDimitry Andric   if (RISCV::FPR16RegClass.contains(DstReg, SrcReg)) {
4425f757f3fSDimitry Andric     unsigned Opc;
44306c3fb27SDimitry Andric     if (STI.hasStdExtZfh()) {
44406c3fb27SDimitry Andric       Opc = RISCV::FSGNJ_H;
44506c3fb27SDimitry Andric     } else {
4465f757f3fSDimitry Andric       assert(STI.hasStdExtF() &&
4475f757f3fSDimitry Andric              (STI.hasStdExtZfhmin() || STI.hasStdExtZfbfmin()) &&
44806c3fb27SDimitry Andric              "Unexpected extensions");
4495f757f3fSDimitry Andric       // Zfhmin/Zfbfmin doesn't have FSGNJ_H, replace FSGNJ_H with FSGNJ_S.
450bdd1243dSDimitry Andric       DstReg = TRI->getMatchingSuperReg(DstReg, RISCV::sub_16,
451bdd1243dSDimitry Andric                                         &RISCV::FPR32RegClass);
452bdd1243dSDimitry Andric       SrcReg = TRI->getMatchingSuperReg(SrcReg, RISCV::sub_16,
453bdd1243dSDimitry Andric                                         &RISCV::FPR32RegClass);
454bdd1243dSDimitry Andric       Opc = RISCV::FSGNJ_S;
455bdd1243dSDimitry Andric     }
4560b57cec5SDimitry Andric     BuildMI(MBB, MBBI, DL, get(Opc), DstReg)
4570b57cec5SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc))
4580b57cec5SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
4595f757f3fSDimitry Andric     return;
4600b57cec5SDimitry Andric   }
4615f757f3fSDimitry Andric 
4625f757f3fSDimitry Andric   if (RISCV::FPR32RegClass.contains(DstReg, SrcReg)) {
4635f757f3fSDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::FSGNJ_S), DstReg)
4645f757f3fSDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc))
4655f757f3fSDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
4665f757f3fSDimitry Andric     return;
4675f757f3fSDimitry Andric   }
4685f757f3fSDimitry Andric 
4695f757f3fSDimitry Andric   if (RISCV::FPR64RegClass.contains(DstReg, SrcReg)) {
4705f757f3fSDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::FSGNJ_D), DstReg)
4715f757f3fSDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc))
4725f757f3fSDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
4735f757f3fSDimitry Andric     return;
4745f757f3fSDimitry Andric   }
4755f757f3fSDimitry Andric 
4765f757f3fSDimitry Andric   if (RISCV::FPR32RegClass.contains(DstReg) &&
4775f757f3fSDimitry Andric       RISCV::GPRRegClass.contains(SrcReg)) {
4785f757f3fSDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::FMV_W_X), DstReg)
4795f757f3fSDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
4805f757f3fSDimitry Andric     return;
4815f757f3fSDimitry Andric   }
4825f757f3fSDimitry Andric 
4835f757f3fSDimitry Andric   if (RISCV::GPRRegClass.contains(DstReg) &&
4845f757f3fSDimitry Andric       RISCV::FPR32RegClass.contains(SrcReg)) {
4855f757f3fSDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::FMV_X_W), DstReg)
4865f757f3fSDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
4875f757f3fSDimitry Andric     return;
4885f757f3fSDimitry Andric   }
4895f757f3fSDimitry Andric 
4905f757f3fSDimitry Andric   if (RISCV::FPR64RegClass.contains(DstReg) &&
4915f757f3fSDimitry Andric       RISCV::GPRRegClass.contains(SrcReg)) {
4925f757f3fSDimitry Andric     assert(STI.getXLen() == 64 && "Unexpected GPR size");
4935f757f3fSDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::FMV_D_X), DstReg)
4945f757f3fSDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
4955f757f3fSDimitry Andric     return;
4965f757f3fSDimitry Andric   }
4975f757f3fSDimitry Andric 
4985f757f3fSDimitry Andric   if (RISCV::GPRRegClass.contains(DstReg) &&
4995f757f3fSDimitry Andric       RISCV::FPR64RegClass.contains(SrcReg)) {
5005f757f3fSDimitry Andric     assert(STI.getXLen() == 64 && "Unexpected GPR size");
5015f757f3fSDimitry Andric     BuildMI(MBB, MBBI, DL, get(RISCV::FMV_X_D), DstReg)
5025f757f3fSDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
5035f757f3fSDimitry Andric     return;
5045f757f3fSDimitry Andric   }
5055f757f3fSDimitry Andric 
5065f757f3fSDimitry Andric   // VR->VR copies.
5075f757f3fSDimitry Andric   if (RISCV::VRRegClass.contains(DstReg, SrcReg)) {
5085f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V);
5095f757f3fSDimitry Andric     return;
5105f757f3fSDimitry Andric   }
5115f757f3fSDimitry Andric 
5125f757f3fSDimitry Andric   if (RISCV::VRM2RegClass.contains(DstReg, SrcReg)) {
5135f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV2R_V);
5145f757f3fSDimitry Andric     return;
5155f757f3fSDimitry Andric   }
5165f757f3fSDimitry Andric 
5175f757f3fSDimitry Andric   if (RISCV::VRM4RegClass.contains(DstReg, SrcReg)) {
5185f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV4R_V);
5195f757f3fSDimitry Andric     return;
5205f757f3fSDimitry Andric   }
5215f757f3fSDimitry Andric 
5225f757f3fSDimitry Andric   if (RISCV::VRM8RegClass.contains(DstReg, SrcReg)) {
5235f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV8R_V);
5245f757f3fSDimitry Andric     return;
5255f757f3fSDimitry Andric   }
5265f757f3fSDimitry Andric 
5275f757f3fSDimitry Andric   if (RISCV::VRN2M1RegClass.contains(DstReg, SrcReg)) {
5285f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V,
5295f757f3fSDimitry Andric                       /*NF=*/2);
5305f757f3fSDimitry Andric     return;
5315f757f3fSDimitry Andric   }
5325f757f3fSDimitry Andric 
5335f757f3fSDimitry Andric   if (RISCV::VRN2M2RegClass.contains(DstReg, SrcReg)) {
5345f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV2R_V,
5355f757f3fSDimitry Andric                       /*NF=*/2);
5365f757f3fSDimitry Andric     return;
5375f757f3fSDimitry Andric   }
5385f757f3fSDimitry Andric 
5395f757f3fSDimitry Andric   if (RISCV::VRN2M4RegClass.contains(DstReg, SrcReg)) {
5405f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV4R_V,
5415f757f3fSDimitry Andric                       /*NF=*/2);
5425f757f3fSDimitry Andric     return;
5435f757f3fSDimitry Andric   }
5445f757f3fSDimitry Andric 
5455f757f3fSDimitry Andric   if (RISCV::VRN3M1RegClass.contains(DstReg, SrcReg)) {
5465f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V,
5475f757f3fSDimitry Andric                       /*NF=*/3);
5485f757f3fSDimitry Andric     return;
5495f757f3fSDimitry Andric   }
5505f757f3fSDimitry Andric 
5515f757f3fSDimitry Andric   if (RISCV::VRN3M2RegClass.contains(DstReg, SrcReg)) {
5525f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV2R_V,
5535f757f3fSDimitry Andric                       /*NF=*/3);
5545f757f3fSDimitry Andric     return;
5555f757f3fSDimitry Andric   }
5565f757f3fSDimitry Andric 
5575f757f3fSDimitry Andric   if (RISCV::VRN4M1RegClass.contains(DstReg, SrcReg)) {
5585f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V,
5595f757f3fSDimitry Andric                       /*NF=*/4);
5605f757f3fSDimitry Andric     return;
5615f757f3fSDimitry Andric   }
5625f757f3fSDimitry Andric 
5635f757f3fSDimitry Andric   if (RISCV::VRN4M2RegClass.contains(DstReg, SrcReg)) {
5645f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV2R_V,
5655f757f3fSDimitry Andric                       /*NF=*/4);
5665f757f3fSDimitry Andric     return;
5675f757f3fSDimitry Andric   }
5685f757f3fSDimitry Andric 
5695f757f3fSDimitry Andric   if (RISCV::VRN5M1RegClass.contains(DstReg, SrcReg)) {
5705f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V,
5715f757f3fSDimitry Andric                       /*NF=*/5);
5725f757f3fSDimitry Andric     return;
5735f757f3fSDimitry Andric   }
5745f757f3fSDimitry Andric 
5755f757f3fSDimitry Andric   if (RISCV::VRN6M1RegClass.contains(DstReg, SrcReg)) {
5765f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V,
5775f757f3fSDimitry Andric                       /*NF=*/6);
5785f757f3fSDimitry Andric     return;
5795f757f3fSDimitry Andric   }
5805f757f3fSDimitry Andric 
5815f757f3fSDimitry Andric   if (RISCV::VRN7M1RegClass.contains(DstReg, SrcReg)) {
5825f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V,
5835f757f3fSDimitry Andric                       /*NF=*/7);
5845f757f3fSDimitry Andric     return;
5855f757f3fSDimitry Andric   }
5865f757f3fSDimitry Andric 
5875f757f3fSDimitry Andric   if (RISCV::VRN8M1RegClass.contains(DstReg, SrcReg)) {
5885f757f3fSDimitry Andric     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V,
5895f757f3fSDimitry Andric                       /*NF=*/8);
5905f757f3fSDimitry Andric     return;
5915f757f3fSDimitry Andric   }
5925f757f3fSDimitry Andric 
5935f757f3fSDimitry Andric   llvm_unreachable("Impossible reg-to-reg copy");
594fe6060f1SDimitry Andric }
5950b57cec5SDimitry Andric 
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register SrcReg,bool IsKill,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const5960b57cec5SDimitry Andric void RISCVInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
5970b57cec5SDimitry Andric                                          MachineBasicBlock::iterator I,
5985ffd83dbSDimitry Andric                                          Register SrcReg, bool IsKill, int FI,
5990b57cec5SDimitry Andric                                          const TargetRegisterClass *RC,
600bdd1243dSDimitry Andric                                          const TargetRegisterInfo *TRI,
601bdd1243dSDimitry Andric                                          Register VReg) const {
602e8d8bef9SDimitry Andric   MachineFunction *MF = MBB.getParent();
603fe6060f1SDimitry Andric   MachineFrameInfo &MFI = MF->getFrameInfo();
604fe6060f1SDimitry Andric 
605fe6060f1SDimitry Andric   unsigned Opcode;
606fe6060f1SDimitry Andric   bool IsScalableVector = true;
607fe6060f1SDimitry Andric   if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
608fe6060f1SDimitry Andric     Opcode = TRI->getRegSizeInBits(RISCV::GPRRegClass) == 32 ?
609fe6060f1SDimitry Andric              RISCV::SW : RISCV::SD;
610fe6060f1SDimitry Andric     IsScalableVector = false;
611297eecfbSDimitry Andric   } else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
61206c3fb27SDimitry Andric     Opcode = RISCV::PseudoRV32ZdinxSD;
61306c3fb27SDimitry Andric     IsScalableVector = false;
614fe6060f1SDimitry Andric   } else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
615fe6060f1SDimitry Andric     Opcode = RISCV::FSH;
616fe6060f1SDimitry Andric     IsScalableVector = false;
617fe6060f1SDimitry Andric   } else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
618fe6060f1SDimitry Andric     Opcode = RISCV::FSW;
619fe6060f1SDimitry Andric     IsScalableVector = false;
620fe6060f1SDimitry Andric   } else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
621fe6060f1SDimitry Andric     Opcode = RISCV::FSD;
622fe6060f1SDimitry Andric     IsScalableVector = false;
623fe6060f1SDimitry Andric   } else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
624bdd1243dSDimitry Andric     Opcode = RISCV::VS1R_V;
625fe6060f1SDimitry Andric   } else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
626bdd1243dSDimitry Andric     Opcode = RISCV::VS2R_V;
627fe6060f1SDimitry Andric   } else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
628bdd1243dSDimitry Andric     Opcode = RISCV::VS4R_V;
629fe6060f1SDimitry Andric   } else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
630bdd1243dSDimitry Andric     Opcode = RISCV::VS8R_V;
631fe6060f1SDimitry Andric   } else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
632fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL2_M1;
633fe6060f1SDimitry Andric   else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
634fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL2_M2;
635fe6060f1SDimitry Andric   else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
636fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL2_M4;
637fe6060f1SDimitry Andric   else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
638fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL3_M1;
639fe6060f1SDimitry Andric   else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
640fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL3_M2;
641fe6060f1SDimitry Andric   else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
642fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL4_M1;
643fe6060f1SDimitry Andric   else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
644fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL4_M2;
645fe6060f1SDimitry Andric   else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
646fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL5_M1;
647fe6060f1SDimitry Andric   else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
648fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL6_M1;
649fe6060f1SDimitry Andric   else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
650fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL7_M1;
651fe6060f1SDimitry Andric   else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
652fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVSPILL8_M1;
653fe6060f1SDimitry Andric   else
654fe6060f1SDimitry Andric     llvm_unreachable("Can't store this register to stack slot");
655fe6060f1SDimitry Andric 
656fe6060f1SDimitry Andric   if (IsScalableVector) {
657fe6060f1SDimitry Andric     MachineMemOperand *MMO = MF->getMachineMemOperand(
658fe6060f1SDimitry Andric         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
659fe6060f1SDimitry Andric         MemoryLocation::UnknownSize, MFI.getObjectAlign(FI));
660fe6060f1SDimitry Andric 
661fe6060f1SDimitry Andric     MFI.setStackID(FI, TargetStackID::ScalableVector);
6625f757f3fSDimitry Andric     BuildMI(MBB, I, DebugLoc(), get(Opcode))
663fe6060f1SDimitry Andric         .addReg(SrcReg, getKillRegState(IsKill))
664fe6060f1SDimitry Andric         .addFrameIndex(FI)
665fe6060f1SDimitry Andric         .addMemOperand(MMO);
666fe6060f1SDimitry Andric   } else {
667e8d8bef9SDimitry Andric     MachineMemOperand *MMO = MF->getMachineMemOperand(
668e8d8bef9SDimitry Andric         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
669e8d8bef9SDimitry Andric         MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6700b57cec5SDimitry Andric 
6715f757f3fSDimitry Andric     BuildMI(MBB, I, DebugLoc(), get(Opcode))
6720b57cec5SDimitry Andric         .addReg(SrcReg, getKillRegState(IsKill))
6730b57cec5SDimitry Andric         .addFrameIndex(FI)
674e8d8bef9SDimitry Andric         .addImm(0)
675e8d8bef9SDimitry Andric         .addMemOperand(MMO);
6760b57cec5SDimitry Andric   }
677fe6060f1SDimitry Andric }
6780b57cec5SDimitry Andric 
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register DstReg,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const6790b57cec5SDimitry Andric void RISCVInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
6800b57cec5SDimitry Andric                                           MachineBasicBlock::iterator I,
6815ffd83dbSDimitry Andric                                           Register DstReg, int FI,
6820b57cec5SDimitry Andric                                           const TargetRegisterClass *RC,
683bdd1243dSDimitry Andric                                           const TargetRegisterInfo *TRI,
684bdd1243dSDimitry Andric                                           Register VReg) const {
685e8d8bef9SDimitry Andric   MachineFunction *MF = MBB.getParent();
686fe6060f1SDimitry Andric   MachineFrameInfo &MFI = MF->getFrameInfo();
687fe6060f1SDimitry Andric 
688fe6060f1SDimitry Andric   unsigned Opcode;
689fe6060f1SDimitry Andric   bool IsScalableVector = true;
690fe6060f1SDimitry Andric   if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
691fe6060f1SDimitry Andric     Opcode = TRI->getRegSizeInBits(RISCV::GPRRegClass) == 32 ?
692fe6060f1SDimitry Andric              RISCV::LW : RISCV::LD;
693fe6060f1SDimitry Andric     IsScalableVector = false;
694297eecfbSDimitry Andric   } else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
69506c3fb27SDimitry Andric     Opcode = RISCV::PseudoRV32ZdinxLD;
69606c3fb27SDimitry Andric     IsScalableVector = false;
697fe6060f1SDimitry Andric   } else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
698fe6060f1SDimitry Andric     Opcode = RISCV::FLH;
699fe6060f1SDimitry Andric     IsScalableVector = false;
700fe6060f1SDimitry Andric   } else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
701fe6060f1SDimitry Andric     Opcode = RISCV::FLW;
702fe6060f1SDimitry Andric     IsScalableVector = false;
703fe6060f1SDimitry Andric   } else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
704fe6060f1SDimitry Andric     Opcode = RISCV::FLD;
705fe6060f1SDimitry Andric     IsScalableVector = false;
706fe6060f1SDimitry Andric   } else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
707bdd1243dSDimitry Andric     Opcode = RISCV::VL1RE8_V;
708fe6060f1SDimitry Andric   } else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
709bdd1243dSDimitry Andric     Opcode = RISCV::VL2RE8_V;
710fe6060f1SDimitry Andric   } else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
711bdd1243dSDimitry Andric     Opcode = RISCV::VL4RE8_V;
712fe6060f1SDimitry Andric   } else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
713bdd1243dSDimitry Andric     Opcode = RISCV::VL8RE8_V;
714fe6060f1SDimitry Andric   } else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
715fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD2_M1;
716fe6060f1SDimitry Andric   else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
717fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD2_M2;
718fe6060f1SDimitry Andric   else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
719fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD2_M4;
720fe6060f1SDimitry Andric   else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
721fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD3_M1;
722fe6060f1SDimitry Andric   else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
723fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD3_M2;
724fe6060f1SDimitry Andric   else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
725fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD4_M1;
726fe6060f1SDimitry Andric   else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
727fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD4_M2;
728fe6060f1SDimitry Andric   else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
729fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD5_M1;
730fe6060f1SDimitry Andric   else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
731fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD6_M1;
732fe6060f1SDimitry Andric   else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
733fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD7_M1;
734fe6060f1SDimitry Andric   else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
735fe6060f1SDimitry Andric     Opcode = RISCV::PseudoVRELOAD8_M1;
736fe6060f1SDimitry Andric   else
737fe6060f1SDimitry Andric     llvm_unreachable("Can't load this register from stack slot");
738fe6060f1SDimitry Andric 
739fe6060f1SDimitry Andric   if (IsScalableVector) {
740fe6060f1SDimitry Andric     MachineMemOperand *MMO = MF->getMachineMemOperand(
741fe6060f1SDimitry Andric         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
742fe6060f1SDimitry Andric         MemoryLocation::UnknownSize, MFI.getObjectAlign(FI));
743fe6060f1SDimitry Andric 
744fe6060f1SDimitry Andric     MFI.setStackID(FI, TargetStackID::ScalableVector);
7455f757f3fSDimitry Andric     BuildMI(MBB, I, DebugLoc(), get(Opcode), DstReg)
746fe6060f1SDimitry Andric         .addFrameIndex(FI)
747fe6060f1SDimitry Andric         .addMemOperand(MMO);
748fe6060f1SDimitry Andric   } else {
749e8d8bef9SDimitry Andric     MachineMemOperand *MMO = MF->getMachineMemOperand(
750e8d8bef9SDimitry Andric         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
751e8d8bef9SDimitry Andric         MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
7520b57cec5SDimitry Andric 
7535f757f3fSDimitry Andric     BuildMI(MBB, I, DebugLoc(), get(Opcode), DstReg)
754e8d8bef9SDimitry Andric         .addFrameIndex(FI)
755e8d8bef9SDimitry Andric         .addImm(0)
756e8d8bef9SDimitry Andric         .addMemOperand(MMO);
7570b57cec5SDimitry Andric   }
758fe6060f1SDimitry Andric }
7590b57cec5SDimitry Andric 
foldMemoryOperandImpl(MachineFunction & MF,MachineInstr & MI,ArrayRef<unsigned> Ops,MachineBasicBlock::iterator InsertPt,int FrameIndex,LiveIntervals * LIS,VirtRegMap * VRM) const760fcaf7f86SDimitry Andric MachineInstr *RISCVInstrInfo::foldMemoryOperandImpl(
761fcaf7f86SDimitry Andric     MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
762fcaf7f86SDimitry Andric     MachineBasicBlock::iterator InsertPt, int FrameIndex, LiveIntervals *LIS,
763fcaf7f86SDimitry Andric     VirtRegMap *VRM) const {
764fcaf7f86SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
765fcaf7f86SDimitry Andric 
766fcaf7f86SDimitry Andric   // The below optimizations narrow the load so they are only valid for little
767fcaf7f86SDimitry Andric   // endian.
768fcaf7f86SDimitry Andric   // TODO: Support big endian by adding an offset into the frame object?
769fcaf7f86SDimitry Andric   if (MF.getDataLayout().isBigEndian())
770fcaf7f86SDimitry Andric     return nullptr;
771fcaf7f86SDimitry Andric 
7725f757f3fSDimitry Andric   // Fold load from stack followed by sext.b/sext.h/sext.w/zext.b/zext.h/zext.w.
773fcaf7f86SDimitry Andric   if (Ops.size() != 1 || Ops[0] != 1)
774fcaf7f86SDimitry Andric    return nullptr;
775fcaf7f86SDimitry Andric 
776fcaf7f86SDimitry Andric   unsigned LoadOpc;
777fcaf7f86SDimitry Andric   switch (MI.getOpcode()) {
778fcaf7f86SDimitry Andric   default:
779fcaf7f86SDimitry Andric     if (RISCV::isSEXT_W(MI)) {
780fcaf7f86SDimitry Andric       LoadOpc = RISCV::LW;
781fcaf7f86SDimitry Andric       break;
782fcaf7f86SDimitry Andric     }
783fcaf7f86SDimitry Andric     if (RISCV::isZEXT_W(MI)) {
784fcaf7f86SDimitry Andric       LoadOpc = RISCV::LWU;
785fcaf7f86SDimitry Andric       break;
786fcaf7f86SDimitry Andric     }
787fcaf7f86SDimitry Andric     if (RISCV::isZEXT_B(MI)) {
788fcaf7f86SDimitry Andric       LoadOpc = RISCV::LBU;
789fcaf7f86SDimitry Andric       break;
790fcaf7f86SDimitry Andric     }
791fcaf7f86SDimitry Andric     return nullptr;
792fcaf7f86SDimitry Andric   case RISCV::SEXT_H:
793fcaf7f86SDimitry Andric     LoadOpc = RISCV::LH;
794fcaf7f86SDimitry Andric     break;
795fcaf7f86SDimitry Andric   case RISCV::SEXT_B:
796fcaf7f86SDimitry Andric     LoadOpc = RISCV::LB;
797fcaf7f86SDimitry Andric     break;
798fcaf7f86SDimitry Andric   case RISCV::ZEXT_H_RV32:
799fcaf7f86SDimitry Andric   case RISCV::ZEXT_H_RV64:
800fcaf7f86SDimitry Andric     LoadOpc = RISCV::LHU;
801fcaf7f86SDimitry Andric     break;
802fcaf7f86SDimitry Andric   }
803fcaf7f86SDimitry Andric 
804fcaf7f86SDimitry Andric   MachineMemOperand *MMO = MF.getMachineMemOperand(
805fcaf7f86SDimitry Andric       MachinePointerInfo::getFixedStack(MF, FrameIndex),
806fcaf7f86SDimitry Andric       MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
807fcaf7f86SDimitry Andric       MFI.getObjectAlign(FrameIndex));
808fcaf7f86SDimitry Andric 
809fcaf7f86SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
810fcaf7f86SDimitry Andric   return BuildMI(*MI.getParent(), InsertPt, MI.getDebugLoc(), get(LoadOpc),
811fcaf7f86SDimitry Andric                  DstReg)
812fcaf7f86SDimitry Andric       .addFrameIndex(FrameIndex)
813fcaf7f86SDimitry Andric       .addImm(0)
814fcaf7f86SDimitry Andric       .addMemOperand(MMO);
815fcaf7f86SDimitry Andric }
816fcaf7f86SDimitry Andric 
movImm(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,Register DstReg,uint64_t Val,MachineInstr::MIFlag Flag,bool DstRenamable,bool DstIsDead) const8178bcb0991SDimitry Andric void RISCVInstrInfo::movImm(MachineBasicBlock &MBB,
8180b57cec5SDimitry Andric                             MachineBasicBlock::iterator MBBI,
8198bcb0991SDimitry Andric                             const DebugLoc &DL, Register DstReg, uint64_t Val,
8205f757f3fSDimitry Andric                             MachineInstr::MIFlag Flag, bool DstRenamable,
8215f757f3fSDimitry Andric                             bool DstIsDead) const {
8228bcb0991SDimitry Andric   Register SrcReg = RISCV::X0;
8230b57cec5SDimitry Andric 
824fe6060f1SDimitry Andric   if (!STI.is64Bit() && !isInt<32>(Val))
8258bcb0991SDimitry Andric     report_fatal_error("Should only materialize 32-bit constants for RV32");
8260b57cec5SDimitry Andric 
8275f757f3fSDimitry Andric   RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(Val, STI);
828fe6060f1SDimitry Andric   assert(!Seq.empty());
8298bcb0991SDimitry Andric 
8305f757f3fSDimitry Andric   bool SrcRenamable = false;
8315f757f3fSDimitry Andric   unsigned Num = 0;
8325f757f3fSDimitry Andric 
83306c3fb27SDimitry Andric   for (const RISCVMatInt::Inst &Inst : Seq) {
8345f757f3fSDimitry Andric     bool LastItem = ++Num == Seq.size();
8355f757f3fSDimitry Andric     unsigned DstRegState = getDeadRegState(DstIsDead && LastItem) |
8365f757f3fSDimitry Andric                            getRenamableRegState(DstRenamable);
8375f757f3fSDimitry Andric     unsigned SrcRegState = getKillRegState(SrcReg != RISCV::X0) |
8385f757f3fSDimitry Andric                            getRenamableRegState(SrcRenamable);
83981ad6265SDimitry Andric     switch (Inst.getOpndKind()) {
84081ad6265SDimitry Andric     case RISCVMatInt::Imm:
8415f757f3fSDimitry Andric       BuildMI(MBB, MBBI, DL, get(Inst.getOpcode()))
8425f757f3fSDimitry Andric           .addReg(DstReg, RegState::Define | DstRegState)
843bdd1243dSDimitry Andric           .addImm(Inst.getImm())
8440b57cec5SDimitry Andric           .setMIFlag(Flag);
84581ad6265SDimitry Andric       break;
84681ad6265SDimitry Andric     case RISCVMatInt::RegX0:
8475f757f3fSDimitry Andric       BuildMI(MBB, MBBI, DL, get(Inst.getOpcode()))
8485f757f3fSDimitry Andric           .addReg(DstReg, RegState::Define | DstRegState)
8495f757f3fSDimitry Andric           .addReg(SrcReg, SrcRegState)
850fe6060f1SDimitry Andric           .addReg(RISCV::X0)
851fe6060f1SDimitry Andric           .setMIFlag(Flag);
85281ad6265SDimitry Andric       break;
85381ad6265SDimitry Andric     case RISCVMatInt::RegReg:
8545f757f3fSDimitry Andric       BuildMI(MBB, MBBI, DL, get(Inst.getOpcode()))
8555f757f3fSDimitry Andric           .addReg(DstReg, RegState::Define | DstRegState)
8565f757f3fSDimitry Andric           .addReg(SrcReg, SrcRegState)
8575f757f3fSDimitry Andric           .addReg(SrcReg, SrcRegState)
858349cc55cSDimitry Andric           .setMIFlag(Flag);
85981ad6265SDimitry Andric       break;
86081ad6265SDimitry Andric     case RISCVMatInt::RegImm:
8615f757f3fSDimitry Andric       BuildMI(MBB, MBBI, DL, get(Inst.getOpcode()))
8625f757f3fSDimitry Andric           .addReg(DstReg, RegState::Define | DstRegState)
8635f757f3fSDimitry Andric           .addReg(SrcReg, SrcRegState)
864bdd1243dSDimitry Andric           .addImm(Inst.getImm())
8650b57cec5SDimitry Andric           .setMIFlag(Flag);
86681ad6265SDimitry Andric       break;
8670b57cec5SDimitry Andric     }
86881ad6265SDimitry Andric 
8698bcb0991SDimitry Andric     // Only the first instruction has X0 as its source.
87081ad6265SDimitry Andric     SrcReg = DstReg;
8715f757f3fSDimitry Andric     SrcRenamable = DstRenamable;
8728bcb0991SDimitry Andric   }
8738bcb0991SDimitry Andric }
8740b57cec5SDimitry Andric 
getCondFromBranchOpc(unsigned Opc)875349cc55cSDimitry Andric static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
876349cc55cSDimitry Andric   switch (Opc) {
877349cc55cSDimitry Andric   default:
878349cc55cSDimitry Andric     return RISCVCC::COND_INVALID;
879349cc55cSDimitry Andric   case RISCV::BEQ:
880349cc55cSDimitry Andric     return RISCVCC::COND_EQ;
881349cc55cSDimitry Andric   case RISCV::BNE:
882349cc55cSDimitry Andric     return RISCVCC::COND_NE;
883349cc55cSDimitry Andric   case RISCV::BLT:
884349cc55cSDimitry Andric     return RISCVCC::COND_LT;
885349cc55cSDimitry Andric   case RISCV::BGE:
886349cc55cSDimitry Andric     return RISCVCC::COND_GE;
887349cc55cSDimitry Andric   case RISCV::BLTU:
888349cc55cSDimitry Andric     return RISCVCC::COND_LTU;
889349cc55cSDimitry Andric   case RISCV::BGEU:
890349cc55cSDimitry Andric     return RISCVCC::COND_GEU;
891349cc55cSDimitry Andric   }
892349cc55cSDimitry Andric }
893349cc55cSDimitry Andric 
8940b57cec5SDimitry Andric // The contents of values added to Cond are not examined outside of
8950b57cec5SDimitry Andric // RISCVInstrInfo, giving us flexibility in what to push to it. For RISCV, we
8960b57cec5SDimitry Andric // push BranchOpcode, Reg1, Reg2.
parseCondBranch(MachineInstr & LastInst,MachineBasicBlock * & Target,SmallVectorImpl<MachineOperand> & Cond)8970b57cec5SDimitry Andric static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
8980b57cec5SDimitry Andric                             SmallVectorImpl<MachineOperand> &Cond) {
8990b57cec5SDimitry Andric   // Block ends with fall-through condbranch.
9000b57cec5SDimitry Andric   assert(LastInst.getDesc().isConditionalBranch() &&
9010b57cec5SDimitry Andric          "Unknown conditional branch");
9020b57cec5SDimitry Andric   Target = LastInst.getOperand(2).getMBB();
903349cc55cSDimitry Andric   unsigned CC = getCondFromBranchOpc(LastInst.getOpcode());
904349cc55cSDimitry Andric   Cond.push_back(MachineOperand::CreateImm(CC));
9050b57cec5SDimitry Andric   Cond.push_back(LastInst.getOperand(0));
9060b57cec5SDimitry Andric   Cond.push_back(LastInst.getOperand(1));
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric 
getBrCond(RISCVCC::CondCode CC)9095f757f3fSDimitry Andric unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC) {
910349cc55cSDimitry Andric   switch (CC) {
911349cc55cSDimitry Andric   default:
912349cc55cSDimitry Andric     llvm_unreachable("Unknown condition code!");
913349cc55cSDimitry Andric   case RISCVCC::COND_EQ:
9145f757f3fSDimitry Andric     return RISCV::BEQ;
915349cc55cSDimitry Andric   case RISCVCC::COND_NE:
9165f757f3fSDimitry Andric     return RISCV::BNE;
917349cc55cSDimitry Andric   case RISCVCC::COND_LT:
9185f757f3fSDimitry Andric     return RISCV::BLT;
919349cc55cSDimitry Andric   case RISCVCC::COND_GE:
9205f757f3fSDimitry Andric     return RISCV::BGE;
921349cc55cSDimitry Andric   case RISCVCC::COND_LTU:
9225f757f3fSDimitry Andric     return RISCV::BLTU;
923349cc55cSDimitry Andric   case RISCVCC::COND_GEU:
9245f757f3fSDimitry Andric     return RISCV::BGEU;
925349cc55cSDimitry Andric   }
926349cc55cSDimitry Andric }
927349cc55cSDimitry Andric 
getBrCond(RISCVCC::CondCode CC) const9285f757f3fSDimitry Andric const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC) const {
9295f757f3fSDimitry Andric   return get(RISCVCC::getBrCond(CC));
9305f757f3fSDimitry Andric }
9315f757f3fSDimitry Andric 
getOppositeBranchCondition(RISCVCC::CondCode CC)932349cc55cSDimitry Andric RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
933349cc55cSDimitry Andric   switch (CC) {
9340b57cec5SDimitry Andric   default:
9350b57cec5SDimitry Andric     llvm_unreachable("Unrecognized conditional branch");
936349cc55cSDimitry Andric   case RISCVCC::COND_EQ:
937349cc55cSDimitry Andric     return RISCVCC::COND_NE;
938349cc55cSDimitry Andric   case RISCVCC::COND_NE:
939349cc55cSDimitry Andric     return RISCVCC::COND_EQ;
940349cc55cSDimitry Andric   case RISCVCC::COND_LT:
941349cc55cSDimitry Andric     return RISCVCC::COND_GE;
942349cc55cSDimitry Andric   case RISCVCC::COND_GE:
943349cc55cSDimitry Andric     return RISCVCC::COND_LT;
944349cc55cSDimitry Andric   case RISCVCC::COND_LTU:
945349cc55cSDimitry Andric     return RISCVCC::COND_GEU;
946349cc55cSDimitry Andric   case RISCVCC::COND_GEU:
947349cc55cSDimitry Andric     return RISCVCC::COND_LTU;
9480b57cec5SDimitry Andric   }
9490b57cec5SDimitry Andric }
9500b57cec5SDimitry Andric 
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const9510b57cec5SDimitry Andric bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
9520b57cec5SDimitry Andric                                    MachineBasicBlock *&TBB,
9530b57cec5SDimitry Andric                                    MachineBasicBlock *&FBB,
9540b57cec5SDimitry Andric                                    SmallVectorImpl<MachineOperand> &Cond,
9550b57cec5SDimitry Andric                                    bool AllowModify) const {
9560b57cec5SDimitry Andric   TBB = FBB = nullptr;
9570b57cec5SDimitry Andric   Cond.clear();
9580b57cec5SDimitry Andric 
9590b57cec5SDimitry Andric   // If the block has no terminators, it just falls into the block after it.
9600b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
9610b57cec5SDimitry Andric   if (I == MBB.end() || !isUnpredicatedTerminator(*I))
9620b57cec5SDimitry Andric     return false;
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric   // Count the number of terminators and find the first unconditional or
9650b57cec5SDimitry Andric   // indirect branch.
9660b57cec5SDimitry Andric   MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
9670b57cec5SDimitry Andric   int NumTerminators = 0;
9680b57cec5SDimitry Andric   for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
9690b57cec5SDimitry Andric        J++) {
9700b57cec5SDimitry Andric     NumTerminators++;
9710b57cec5SDimitry Andric     if (J->getDesc().isUnconditionalBranch() ||
9720b57cec5SDimitry Andric         J->getDesc().isIndirectBranch()) {
9730b57cec5SDimitry Andric       FirstUncondOrIndirectBr = J.getReverse();
9740b57cec5SDimitry Andric     }
9750b57cec5SDimitry Andric   }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   // If AllowModify is true, we can erase any terminators after
9780b57cec5SDimitry Andric   // FirstUncondOrIndirectBR.
9790b57cec5SDimitry Andric   if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
9800b57cec5SDimitry Andric     while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
9810b57cec5SDimitry Andric       std::next(FirstUncondOrIndirectBr)->eraseFromParent();
9820b57cec5SDimitry Andric       NumTerminators--;
9830b57cec5SDimitry Andric     }
9840b57cec5SDimitry Andric     I = FirstUncondOrIndirectBr;
9850b57cec5SDimitry Andric   }
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   // We can't handle blocks that end in an indirect branch.
9880b57cec5SDimitry Andric   if (I->getDesc().isIndirectBranch())
9890b57cec5SDimitry Andric     return true;
9900b57cec5SDimitry Andric 
9915f757f3fSDimitry Andric   // We can't handle Generic branch opcodes from Global ISel.
9925f757f3fSDimitry Andric   if (I->isPreISelOpcode())
9935f757f3fSDimitry Andric     return true;
9945f757f3fSDimitry Andric 
9950b57cec5SDimitry Andric   // We can't handle blocks with more than 2 terminators.
9960b57cec5SDimitry Andric   if (NumTerminators > 2)
9970b57cec5SDimitry Andric     return true;
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric   // Handle a single unconditional branch.
10000b57cec5SDimitry Andric   if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
100175b4d546SDimitry Andric     TBB = getBranchDestBlock(*I);
10020b57cec5SDimitry Andric     return false;
10030b57cec5SDimitry Andric   }
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   // Handle a single conditional branch.
10060b57cec5SDimitry Andric   if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
10070b57cec5SDimitry Andric     parseCondBranch(*I, TBB, Cond);
10080b57cec5SDimitry Andric     return false;
10090b57cec5SDimitry Andric   }
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric   // Handle a conditional branch followed by an unconditional branch.
10120b57cec5SDimitry Andric   if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
10130b57cec5SDimitry Andric       I->getDesc().isUnconditionalBranch()) {
10140b57cec5SDimitry Andric     parseCondBranch(*std::prev(I), TBB, Cond);
101575b4d546SDimitry Andric     FBB = getBranchDestBlock(*I);
10160b57cec5SDimitry Andric     return false;
10170b57cec5SDimitry Andric   }
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   // Otherwise, we can't handle this.
10200b57cec5SDimitry Andric   return true;
10210b57cec5SDimitry Andric }
10220b57cec5SDimitry Andric 
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const10230b57cec5SDimitry Andric unsigned RISCVInstrInfo::removeBranch(MachineBasicBlock &MBB,
10240b57cec5SDimitry Andric                                       int *BytesRemoved) const {
10250b57cec5SDimitry Andric   if (BytesRemoved)
10260b57cec5SDimitry Andric     *BytesRemoved = 0;
10270b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
10280b57cec5SDimitry Andric   if (I == MBB.end())
10290b57cec5SDimitry Andric     return 0;
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric   if (!I->getDesc().isUnconditionalBranch() &&
10320b57cec5SDimitry Andric       !I->getDesc().isConditionalBranch())
10330b57cec5SDimitry Andric     return 0;
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   // Remove the branch.
10360b57cec5SDimitry Andric   if (BytesRemoved)
10370b57cec5SDimitry Andric     *BytesRemoved += getInstSizeInBytes(*I);
10380b57cec5SDimitry Andric   I->eraseFromParent();
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric   I = MBB.end();
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric   if (I == MBB.begin())
10430b57cec5SDimitry Andric     return 1;
10440b57cec5SDimitry Andric   --I;
10450b57cec5SDimitry Andric   if (!I->getDesc().isConditionalBranch())
10460b57cec5SDimitry Andric     return 1;
10470b57cec5SDimitry Andric 
10480b57cec5SDimitry Andric   // Remove the branch.
10490b57cec5SDimitry Andric   if (BytesRemoved)
10500b57cec5SDimitry Andric     *BytesRemoved += getInstSizeInBytes(*I);
10510b57cec5SDimitry Andric   I->eraseFromParent();
10520b57cec5SDimitry Andric   return 2;
10530b57cec5SDimitry Andric }
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric // Inserts a branch into the end of the specific MachineBasicBlock, returning
10560b57cec5SDimitry Andric // the number of instructions inserted.
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const10570b57cec5SDimitry Andric unsigned RISCVInstrInfo::insertBranch(
10580b57cec5SDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
10590b57cec5SDimitry Andric     ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
10600b57cec5SDimitry Andric   if (BytesAdded)
10610b57cec5SDimitry Andric     *BytesAdded = 0;
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric   // Shouldn't be a fall through.
10645ffd83dbSDimitry Andric   assert(TBB && "insertBranch must not be told to insert a fallthrough");
10650b57cec5SDimitry Andric   assert((Cond.size() == 3 || Cond.size() == 0) &&
106606c3fb27SDimitry Andric          "RISC-V branch conditions have two components!");
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric   // Unconditional branch.
10690b57cec5SDimitry Andric   if (Cond.empty()) {
10700b57cec5SDimitry Andric     MachineInstr &MI = *BuildMI(&MBB, DL, get(RISCV::PseudoBR)).addMBB(TBB);
10710b57cec5SDimitry Andric     if (BytesAdded)
10720b57cec5SDimitry Andric       *BytesAdded += getInstSizeInBytes(MI);
10730b57cec5SDimitry Andric     return 1;
10740b57cec5SDimitry Andric   }
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric   // Either a one or two-way conditional branch.
1077349cc55cSDimitry Andric   auto CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
10780b57cec5SDimitry Andric   MachineInstr &CondMI =
1079349cc55cSDimitry Andric       *BuildMI(&MBB, DL, getBrCond(CC)).add(Cond[1]).add(Cond[2]).addMBB(TBB);
10800b57cec5SDimitry Andric   if (BytesAdded)
10810b57cec5SDimitry Andric     *BytesAdded += getInstSizeInBytes(CondMI);
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   // One-way conditional branch.
10840b57cec5SDimitry Andric   if (!FBB)
10850b57cec5SDimitry Andric     return 1;
10860b57cec5SDimitry Andric 
10870b57cec5SDimitry Andric   // Two-way conditional branch.
10880b57cec5SDimitry Andric   MachineInstr &MI = *BuildMI(&MBB, DL, get(RISCV::PseudoBR)).addMBB(FBB);
10890b57cec5SDimitry Andric   if (BytesAdded)
10900b57cec5SDimitry Andric     *BytesAdded += getInstSizeInBytes(MI);
10910b57cec5SDimitry Andric   return 2;
10920b57cec5SDimitry Andric }
10930b57cec5SDimitry Andric 
insertIndirectBranch(MachineBasicBlock & MBB,MachineBasicBlock & DestBB,MachineBasicBlock & RestoreBB,const DebugLoc & DL,int64_t BrOffset,RegScavenger * RS) const1094349cc55cSDimitry Andric void RISCVInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
10950b57cec5SDimitry Andric                                           MachineBasicBlock &DestBB,
1096349cc55cSDimitry Andric                                           MachineBasicBlock &RestoreBB,
1097349cc55cSDimitry Andric                                           const DebugLoc &DL, int64_t BrOffset,
10980b57cec5SDimitry Andric                                           RegScavenger *RS) const {
10990b57cec5SDimitry Andric   assert(RS && "RegScavenger required for long branching");
11000b57cec5SDimitry Andric   assert(MBB.empty() &&
11010b57cec5SDimitry Andric          "new block should be inserted for expanding unconditional branch");
11020b57cec5SDimitry Andric   assert(MBB.pred_size() == 1);
1103bdd1243dSDimitry Andric   assert(RestoreBB.empty() &&
1104bdd1243dSDimitry Andric          "restore block should be inserted for restoring clobbered registers");
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric   MachineFunction *MF = MBB.getParent();
11070b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
1108bdd1243dSDimitry Andric   RISCVMachineFunctionInfo *RVFI = MF->getInfo<RISCVMachineFunctionInfo>();
1109bdd1243dSDimitry Andric   const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric   if (!isInt<32>(BrOffset))
11120b57cec5SDimitry Andric     report_fatal_error(
11130b57cec5SDimitry Andric         "Branch offsets outside of the signed 32-bit range not supported");
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric   // FIXME: A virtual register must be used initially, as the register
11160b57cec5SDimitry Andric   // scavenger won't work with empty blocks (SIInstrInfo::insertIndirectBranch
11170b57cec5SDimitry Andric   // uses the same workaround).
11188bcb0991SDimitry Andric   Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
11190b57cec5SDimitry Andric   auto II = MBB.end();
1120bdd1243dSDimitry Andric   // We may also update the jump target to RestoreBB later.
112175b4d546SDimitry Andric   MachineInstr &MI = *BuildMI(MBB, II, DL, get(RISCV::PseudoJump))
112275b4d546SDimitry Andric                           .addReg(ScratchReg, RegState::Define | RegState::Dead)
112375b4d546SDimitry Andric                           .addMBB(&DestBB, RISCVII::MO_CALL);
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric   RS->enterBasicBlockEnd(MBB);
1126bdd1243dSDimitry Andric   Register TmpGPR =
1127bdd1243dSDimitry Andric       RS->scavengeRegisterBackwards(RISCV::GPRRegClass, MI.getIterator(),
1128bdd1243dSDimitry Andric                                     /*RestoreAfter=*/false, /*SpAdj=*/0,
1129bdd1243dSDimitry Andric                                     /*AllowSpill=*/false);
1130bdd1243dSDimitry Andric   if (TmpGPR != RISCV::NoRegister)
1131bdd1243dSDimitry Andric     RS->setRegUsed(TmpGPR);
1132bdd1243dSDimitry Andric   else {
1133bdd1243dSDimitry Andric     // The case when there is no scavenged register needs special handling.
1134bdd1243dSDimitry Andric 
1135bdd1243dSDimitry Andric     // Pick s11 because it doesn't make a difference.
1136bdd1243dSDimitry Andric     TmpGPR = RISCV::X27;
1137bdd1243dSDimitry Andric 
1138bdd1243dSDimitry Andric     int FrameIndex = RVFI->getBranchRelaxationScratchFrameIndex();
1139bdd1243dSDimitry Andric     if (FrameIndex == -1)
1140bdd1243dSDimitry Andric       report_fatal_error("underestimated function size");
1141bdd1243dSDimitry Andric 
1142bdd1243dSDimitry Andric     storeRegToStackSlot(MBB, MI, TmpGPR, /*IsKill=*/true, FrameIndex,
1143bdd1243dSDimitry Andric                         &RISCV::GPRRegClass, TRI, Register());
1144bdd1243dSDimitry Andric     TRI->eliminateFrameIndex(std::prev(MI.getIterator()),
1145bdd1243dSDimitry Andric                              /*SpAdj=*/0, /*FIOperandNum=*/1);
1146bdd1243dSDimitry Andric 
1147bdd1243dSDimitry Andric     MI.getOperand(1).setMBB(&RestoreBB);
1148bdd1243dSDimitry Andric 
1149bdd1243dSDimitry Andric     loadRegFromStackSlot(RestoreBB, RestoreBB.end(), TmpGPR, FrameIndex,
1150bdd1243dSDimitry Andric                          &RISCV::GPRRegClass, TRI, Register());
1151bdd1243dSDimitry Andric     TRI->eliminateFrameIndex(RestoreBB.back(),
1152bdd1243dSDimitry Andric                              /*SpAdj=*/0, /*FIOperandNum=*/1);
1153bdd1243dSDimitry Andric   }
1154bdd1243dSDimitry Andric 
1155bdd1243dSDimitry Andric   MRI.replaceRegWith(ScratchReg, TmpGPR);
11560b57cec5SDimitry Andric   MRI.clearVirtRegs();
11570b57cec5SDimitry Andric }
11580b57cec5SDimitry Andric 
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const11590b57cec5SDimitry Andric bool RISCVInstrInfo::reverseBranchCondition(
11600b57cec5SDimitry Andric     SmallVectorImpl<MachineOperand> &Cond) const {
11610b57cec5SDimitry Andric   assert((Cond.size() == 3) && "Invalid branch condition!");
1162349cc55cSDimitry Andric   auto CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
1163349cc55cSDimitry Andric   Cond[0].setImm(getOppositeBranchCondition(CC));
11640b57cec5SDimitry Andric   return false;
11650b57cec5SDimitry Andric }
11660b57cec5SDimitry Andric 
optimizeCondBranch(MachineInstr & MI) const11675f757f3fSDimitry Andric bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
11685f757f3fSDimitry Andric   MachineBasicBlock *MBB = MI.getParent();
11695f757f3fSDimitry Andric   MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
11705f757f3fSDimitry Andric 
11715f757f3fSDimitry Andric   MachineBasicBlock *TBB, *FBB;
11725f757f3fSDimitry Andric   SmallVector<MachineOperand, 3> Cond;
11735f757f3fSDimitry Andric   if (analyzeBranch(*MBB, TBB, FBB, Cond, /*AllowModify=*/false))
11745f757f3fSDimitry Andric     return false;
11755f757f3fSDimitry Andric   (void)FBB;
11765f757f3fSDimitry Andric 
11775f757f3fSDimitry Andric   RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
11785f757f3fSDimitry Andric   assert(CC != RISCVCC::COND_INVALID);
11795f757f3fSDimitry Andric 
11805f757f3fSDimitry Andric   if (CC == RISCVCC::COND_EQ || CC == RISCVCC::COND_NE)
11815f757f3fSDimitry Andric     return false;
11825f757f3fSDimitry Andric 
11835f757f3fSDimitry Andric   // For two constants C0 and C1 from
11845f757f3fSDimitry Andric   // ```
11855f757f3fSDimitry Andric   // li Y, C0
11865f757f3fSDimitry Andric   // li Z, C1
11875f757f3fSDimitry Andric   // ```
11885f757f3fSDimitry Andric   // 1. if C1 = C0 + 1
11895f757f3fSDimitry Andric   // we can turn:
11905f757f3fSDimitry Andric   //  (a) blt Y, X -> bge X, Z
11915f757f3fSDimitry Andric   //  (b) bge Y, X -> blt X, Z
11925f757f3fSDimitry Andric   //
11935f757f3fSDimitry Andric   // 2. if C1 = C0 - 1
11945f757f3fSDimitry Andric   // we can turn:
11955f757f3fSDimitry Andric   //  (a) blt X, Y -> bge Z, X
11965f757f3fSDimitry Andric   //  (b) bge X, Y -> blt Z, X
11975f757f3fSDimitry Andric   //
11985f757f3fSDimitry Andric   // To make sure this optimization is really beneficial, we only
11995f757f3fSDimitry Andric   // optimize for cases where Y had only one use (i.e. only used by the branch).
12005f757f3fSDimitry Andric 
12015f757f3fSDimitry Andric   // Right now we only care about LI (i.e. ADDI x0, imm)
12025f757f3fSDimitry Andric   auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
12035f757f3fSDimitry Andric     if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
12045f757f3fSDimitry Andric         MI->getOperand(1).getReg() == RISCV::X0) {
12055f757f3fSDimitry Andric       Imm = MI->getOperand(2).getImm();
12065f757f3fSDimitry Andric       return true;
12075f757f3fSDimitry Andric     }
12085f757f3fSDimitry Andric     return false;
12095f757f3fSDimitry Andric   };
12105f757f3fSDimitry Andric   // Either a load from immediate instruction or X0.
12115f757f3fSDimitry Andric   auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
12125f757f3fSDimitry Andric     if (!Op.isReg())
12135f757f3fSDimitry Andric       return false;
12145f757f3fSDimitry Andric     Register Reg = Op.getReg();
12155f757f3fSDimitry Andric     if (Reg == RISCV::X0) {
12165f757f3fSDimitry Andric       Imm = 0;
12175f757f3fSDimitry Andric       return true;
12185f757f3fSDimitry Andric     }
12195f757f3fSDimitry Andric     if (!Reg.isVirtual())
12205f757f3fSDimitry Andric       return false;
12215f757f3fSDimitry Andric     return isLoadImm(MRI.getVRegDef(Op.getReg()), Imm);
12225f757f3fSDimitry Andric   };
12235f757f3fSDimitry Andric 
12245f757f3fSDimitry Andric   MachineOperand &LHS = MI.getOperand(0);
12255f757f3fSDimitry Andric   MachineOperand &RHS = MI.getOperand(1);
12265f757f3fSDimitry Andric   // Try to find the register for constant Z; return
12275f757f3fSDimitry Andric   // invalid register otherwise.
12285f757f3fSDimitry Andric   auto searchConst = [&](int64_t C1) -> Register {
12295f757f3fSDimitry Andric     MachineBasicBlock::reverse_iterator II(&MI), E = MBB->rend();
12305f757f3fSDimitry Andric     auto DefC1 = std::find_if(++II, E, [&](const MachineInstr &I) -> bool {
12315f757f3fSDimitry Andric       int64_t Imm;
123274626c16SDimitry Andric       return isLoadImm(&I, Imm) && Imm == C1 &&
123374626c16SDimitry Andric              I.getOperand(0).getReg().isVirtual();
12345f757f3fSDimitry Andric     });
12355f757f3fSDimitry Andric     if (DefC1 != E)
12365f757f3fSDimitry Andric       return DefC1->getOperand(0).getReg();
12375f757f3fSDimitry Andric 
12385f757f3fSDimitry Andric     return Register();
12395f757f3fSDimitry Andric   };
12405f757f3fSDimitry Andric 
12415f757f3fSDimitry Andric   bool Modify = false;
12425f757f3fSDimitry Andric   int64_t C0;
12435f757f3fSDimitry Andric   if (isFromLoadImm(LHS, C0) && MRI.hasOneUse(LHS.getReg())) {
12445f757f3fSDimitry Andric     // Might be case 1.
12455f757f3fSDimitry Andric     // Signed integer overflow is UB. (UINT64_MAX is bigger so we don't need
12465f757f3fSDimitry Andric     // to worry about unsigned overflow here)
12475f757f3fSDimitry Andric     if (C0 < INT64_MAX)
12485f757f3fSDimitry Andric       if (Register RegZ = searchConst(C0 + 1)) {
12495f757f3fSDimitry Andric         reverseBranchCondition(Cond);
12505f757f3fSDimitry Andric         Cond[1] = MachineOperand::CreateReg(RHS.getReg(), /*isDef=*/false);
12515f757f3fSDimitry Andric         Cond[2] = MachineOperand::CreateReg(RegZ, /*isDef=*/false);
12525f757f3fSDimitry Andric         // We might extend the live range of Z, clear its kill flag to
12535f757f3fSDimitry Andric         // account for this.
12545f757f3fSDimitry Andric         MRI.clearKillFlags(RegZ);
12555f757f3fSDimitry Andric         Modify = true;
12565f757f3fSDimitry Andric       }
12575f757f3fSDimitry Andric   } else if (isFromLoadImm(RHS, C0) && MRI.hasOneUse(RHS.getReg())) {
12585f757f3fSDimitry Andric     // Might be case 2.
12595f757f3fSDimitry Andric     // For unsigned cases, we don't want C1 to wrap back to UINT64_MAX
12605f757f3fSDimitry Andric     // when C0 is zero.
12615f757f3fSDimitry Andric     if ((CC == RISCVCC::COND_GE || CC == RISCVCC::COND_LT) || C0)
12625f757f3fSDimitry Andric       if (Register RegZ = searchConst(C0 - 1)) {
12635f757f3fSDimitry Andric         reverseBranchCondition(Cond);
12645f757f3fSDimitry Andric         Cond[1] = MachineOperand::CreateReg(RegZ, /*isDef=*/false);
12655f757f3fSDimitry Andric         Cond[2] = MachineOperand::CreateReg(LHS.getReg(), /*isDef=*/false);
12665f757f3fSDimitry Andric         // We might extend the live range of Z, clear its kill flag to
12675f757f3fSDimitry Andric         // account for this.
12685f757f3fSDimitry Andric         MRI.clearKillFlags(RegZ);
12695f757f3fSDimitry Andric         Modify = true;
12705f757f3fSDimitry Andric       }
12715f757f3fSDimitry Andric   }
12725f757f3fSDimitry Andric 
12735f757f3fSDimitry Andric   if (!Modify)
12745f757f3fSDimitry Andric     return false;
12755f757f3fSDimitry Andric 
12765f757f3fSDimitry Andric   // Build the new branch and remove the old one.
12775f757f3fSDimitry Andric   BuildMI(*MBB, MI, MI.getDebugLoc(),
12785f757f3fSDimitry Andric           getBrCond(static_cast<RISCVCC::CondCode>(Cond[0].getImm())))
12795f757f3fSDimitry Andric       .add(Cond[1])
12805f757f3fSDimitry Andric       .add(Cond[2])
12815f757f3fSDimitry Andric       .addMBB(TBB);
12825f757f3fSDimitry Andric   MI.eraseFromParent();
12835f757f3fSDimitry Andric 
12845f757f3fSDimitry Andric   return true;
12855f757f3fSDimitry Andric }
12865f757f3fSDimitry Andric 
12870b57cec5SDimitry Andric MachineBasicBlock *
getBranchDestBlock(const MachineInstr & MI) const12880b57cec5SDimitry Andric RISCVInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
12890b57cec5SDimitry Andric   assert(MI.getDesc().isBranch() && "Unexpected opcode!");
12900b57cec5SDimitry Andric   // The branch target is always the last operand.
12910b57cec5SDimitry Andric   int NumOp = MI.getNumExplicitOperands();
12920b57cec5SDimitry Andric   return MI.getOperand(NumOp - 1).getMBB();
12930b57cec5SDimitry Andric }
12940b57cec5SDimitry Andric 
isBranchOffsetInRange(unsigned BranchOp,int64_t BrOffset) const12950b57cec5SDimitry Andric bool RISCVInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
12960b57cec5SDimitry Andric                                            int64_t BrOffset) const {
129775b4d546SDimitry Andric   unsigned XLen = STI.getXLen();
12980b57cec5SDimitry Andric   // Ideally we could determine the supported branch offset from the
12990b57cec5SDimitry Andric   // RISCVII::FormMask, but this can't be used for Pseudo instructions like
13000b57cec5SDimitry Andric   // PseudoBR.
13010b57cec5SDimitry Andric   switch (BranchOp) {
13020b57cec5SDimitry Andric   default:
13030b57cec5SDimitry Andric     llvm_unreachable("Unexpected opcode!");
13040b57cec5SDimitry Andric   case RISCV::BEQ:
13050b57cec5SDimitry Andric   case RISCV::BNE:
13060b57cec5SDimitry Andric   case RISCV::BLT:
13070b57cec5SDimitry Andric   case RISCV::BGE:
13080b57cec5SDimitry Andric   case RISCV::BLTU:
13090b57cec5SDimitry Andric   case RISCV::BGEU:
13100b57cec5SDimitry Andric     return isIntN(13, BrOffset);
13110b57cec5SDimitry Andric   case RISCV::JAL:
13120b57cec5SDimitry Andric   case RISCV::PseudoBR:
13130b57cec5SDimitry Andric     return isIntN(21, BrOffset);
131475b4d546SDimitry Andric   case RISCV::PseudoJump:
131575b4d546SDimitry Andric     return isIntN(32, SignExtend64(BrOffset + 0x800, XLen));
13160b57cec5SDimitry Andric   }
13170b57cec5SDimitry Andric }
13180b57cec5SDimitry Andric 
1319bdd1243dSDimitry Andric // If the operation has a predicated pseudo instruction, return the pseudo
1320bdd1243dSDimitry Andric // instruction opcode. Otherwise, return RISCV::INSTRUCTION_LIST_END.
1321bdd1243dSDimitry Andric // TODO: Support more operations.
getPredicatedOpcode(unsigned Opcode)1322bdd1243dSDimitry Andric unsigned getPredicatedOpcode(unsigned Opcode) {
1323bdd1243dSDimitry Andric   switch (Opcode) {
1324bdd1243dSDimitry Andric   case RISCV::ADD:   return RISCV::PseudoCCADD;   break;
1325bdd1243dSDimitry Andric   case RISCV::SUB:   return RISCV::PseudoCCSUB;   break;
13265f757f3fSDimitry Andric   case RISCV::SLL:   return RISCV::PseudoCCSLL;   break;
13275f757f3fSDimitry Andric   case RISCV::SRL:   return RISCV::PseudoCCSRL;   break;
13285f757f3fSDimitry Andric   case RISCV::SRA:   return RISCV::PseudoCCSRA;   break;
1329bdd1243dSDimitry Andric   case RISCV::AND:   return RISCV::PseudoCCAND;   break;
1330bdd1243dSDimitry Andric   case RISCV::OR:    return RISCV::PseudoCCOR;    break;
1331bdd1243dSDimitry Andric   case RISCV::XOR:   return RISCV::PseudoCCXOR;   break;
1332bdd1243dSDimitry Andric 
13335f757f3fSDimitry Andric   case RISCV::ADDI:  return RISCV::PseudoCCADDI;  break;
13345f757f3fSDimitry Andric   case RISCV::SLLI:  return RISCV::PseudoCCSLLI;  break;
13355f757f3fSDimitry Andric   case RISCV::SRLI:  return RISCV::PseudoCCSRLI;  break;
13365f757f3fSDimitry Andric   case RISCV::SRAI:  return RISCV::PseudoCCSRAI;  break;
13375f757f3fSDimitry Andric   case RISCV::ANDI:  return RISCV::PseudoCCANDI;  break;
13385f757f3fSDimitry Andric   case RISCV::ORI:   return RISCV::PseudoCCORI;   break;
13395f757f3fSDimitry Andric   case RISCV::XORI:  return RISCV::PseudoCCXORI;  break;
13405f757f3fSDimitry Andric 
1341bdd1243dSDimitry Andric   case RISCV::ADDW:  return RISCV::PseudoCCADDW;  break;
1342bdd1243dSDimitry Andric   case RISCV::SUBW:  return RISCV::PseudoCCSUBW;  break;
13435f757f3fSDimitry Andric   case RISCV::SLLW:  return RISCV::PseudoCCSLLW;  break;
13445f757f3fSDimitry Andric   case RISCV::SRLW:  return RISCV::PseudoCCSRLW;  break;
13455f757f3fSDimitry Andric   case RISCV::SRAW:  return RISCV::PseudoCCSRAW;  break;
13465f757f3fSDimitry Andric 
13475f757f3fSDimitry Andric   case RISCV::ADDIW: return RISCV::PseudoCCADDIW; break;
13485f757f3fSDimitry Andric   case RISCV::SLLIW: return RISCV::PseudoCCSLLIW; break;
13495f757f3fSDimitry Andric   case RISCV::SRLIW: return RISCV::PseudoCCSRLIW; break;
13505f757f3fSDimitry Andric   case RISCV::SRAIW: return RISCV::PseudoCCSRAIW; break;
13511db9f3b2SDimitry Andric 
13521db9f3b2SDimitry Andric   case RISCV::ANDN:  return RISCV::PseudoCCANDN;  break;
13531db9f3b2SDimitry Andric   case RISCV::ORN:   return RISCV::PseudoCCORN;   break;
13541db9f3b2SDimitry Andric   case RISCV::XNOR:  return RISCV::PseudoCCXNOR;  break;
1355bdd1243dSDimitry Andric   }
1356bdd1243dSDimitry Andric 
1357bdd1243dSDimitry Andric   return RISCV::INSTRUCTION_LIST_END;
1358bdd1243dSDimitry Andric }
1359bdd1243dSDimitry Andric 
1360bdd1243dSDimitry Andric /// Identify instructions that can be folded into a CCMOV instruction, and
1361bdd1243dSDimitry Andric /// return the defining instruction.
canFoldAsPredicatedOp(Register Reg,const MachineRegisterInfo & MRI,const TargetInstrInfo * TII)1362bdd1243dSDimitry Andric static MachineInstr *canFoldAsPredicatedOp(Register Reg,
1363bdd1243dSDimitry Andric                                            const MachineRegisterInfo &MRI,
1364bdd1243dSDimitry Andric                                            const TargetInstrInfo *TII) {
1365bdd1243dSDimitry Andric   if (!Reg.isVirtual())
1366bdd1243dSDimitry Andric     return nullptr;
1367bdd1243dSDimitry Andric   if (!MRI.hasOneNonDBGUse(Reg))
1368bdd1243dSDimitry Andric     return nullptr;
1369bdd1243dSDimitry Andric   MachineInstr *MI = MRI.getVRegDef(Reg);
1370bdd1243dSDimitry Andric   if (!MI)
1371bdd1243dSDimitry Andric     return nullptr;
1372bdd1243dSDimitry Andric   // Check if MI can be predicated and folded into the CCMOV.
1373bdd1243dSDimitry Andric   if (getPredicatedOpcode(MI->getOpcode()) == RISCV::INSTRUCTION_LIST_END)
1374bdd1243dSDimitry Andric     return nullptr;
13755f757f3fSDimitry Andric   // Don't predicate li idiom.
13765f757f3fSDimitry Andric   if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
13775f757f3fSDimitry Andric       MI->getOperand(1).getReg() == RISCV::X0)
13785f757f3fSDimitry Andric     return nullptr;
1379bdd1243dSDimitry Andric   // Check if MI has any other defs or physreg uses.
138006c3fb27SDimitry Andric   for (const MachineOperand &MO : llvm::drop_begin(MI->operands())) {
1381bdd1243dSDimitry Andric     // Reject frame index operands, PEI can't handle the predicated pseudos.
1382bdd1243dSDimitry Andric     if (MO.isFI() || MO.isCPI() || MO.isJTI())
1383bdd1243dSDimitry Andric       return nullptr;
1384bdd1243dSDimitry Andric     if (!MO.isReg())
1385bdd1243dSDimitry Andric       continue;
1386bdd1243dSDimitry Andric     // MI can't have any tied operands, that would conflict with predication.
1387bdd1243dSDimitry Andric     if (MO.isTied())
1388bdd1243dSDimitry Andric       return nullptr;
1389bdd1243dSDimitry Andric     if (MO.isDef())
1390bdd1243dSDimitry Andric       return nullptr;
1391bdd1243dSDimitry Andric     // Allow constant physregs.
1392bdd1243dSDimitry Andric     if (MO.getReg().isPhysical() && !MRI.isConstantPhysReg(MO.getReg()))
1393bdd1243dSDimitry Andric       return nullptr;
1394bdd1243dSDimitry Andric   }
1395bdd1243dSDimitry Andric   bool DontMoveAcrossStores = true;
1396bdd1243dSDimitry Andric   if (!MI->isSafeToMove(/* AliasAnalysis = */ nullptr, DontMoveAcrossStores))
1397bdd1243dSDimitry Andric     return nullptr;
1398bdd1243dSDimitry Andric   return MI;
1399bdd1243dSDimitry Andric }
1400bdd1243dSDimitry Andric 
analyzeSelect(const MachineInstr & MI,SmallVectorImpl<MachineOperand> & Cond,unsigned & TrueOp,unsigned & FalseOp,bool & Optimizable) const1401bdd1243dSDimitry Andric bool RISCVInstrInfo::analyzeSelect(const MachineInstr &MI,
1402bdd1243dSDimitry Andric                                    SmallVectorImpl<MachineOperand> &Cond,
1403bdd1243dSDimitry Andric                                    unsigned &TrueOp, unsigned &FalseOp,
1404bdd1243dSDimitry Andric                                    bool &Optimizable) const {
1405bdd1243dSDimitry Andric   assert(MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1406bdd1243dSDimitry Andric          "Unknown select instruction");
1407bdd1243dSDimitry Andric   // CCMOV operands:
1408bdd1243dSDimitry Andric   // 0: Def.
1409bdd1243dSDimitry Andric   // 1: LHS of compare.
1410bdd1243dSDimitry Andric   // 2: RHS of compare.
1411bdd1243dSDimitry Andric   // 3: Condition code.
1412bdd1243dSDimitry Andric   // 4: False use.
1413bdd1243dSDimitry Andric   // 5: True use.
1414bdd1243dSDimitry Andric   TrueOp = 5;
1415bdd1243dSDimitry Andric   FalseOp = 4;
1416bdd1243dSDimitry Andric   Cond.push_back(MI.getOperand(1));
1417bdd1243dSDimitry Andric   Cond.push_back(MI.getOperand(2));
1418bdd1243dSDimitry Andric   Cond.push_back(MI.getOperand(3));
1419bdd1243dSDimitry Andric   // We can only fold when we support short forward branch opt.
1420bdd1243dSDimitry Andric   Optimizable = STI.hasShortForwardBranchOpt();
1421bdd1243dSDimitry Andric   return false;
1422bdd1243dSDimitry Andric }
1423bdd1243dSDimitry Andric 
1424bdd1243dSDimitry Andric MachineInstr *
optimizeSelect(MachineInstr & MI,SmallPtrSetImpl<MachineInstr * > & SeenMIs,bool PreferFalse) const1425bdd1243dSDimitry Andric RISCVInstrInfo::optimizeSelect(MachineInstr &MI,
1426bdd1243dSDimitry Andric                                SmallPtrSetImpl<MachineInstr *> &SeenMIs,
1427bdd1243dSDimitry Andric                                bool PreferFalse) const {
1428bdd1243dSDimitry Andric   assert(MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1429bdd1243dSDimitry Andric          "Unknown select instruction");
1430bdd1243dSDimitry Andric   if (!STI.hasShortForwardBranchOpt())
1431bdd1243dSDimitry Andric     return nullptr;
1432bdd1243dSDimitry Andric 
1433bdd1243dSDimitry Andric   MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
1434bdd1243dSDimitry Andric   MachineInstr *DefMI =
1435bdd1243dSDimitry Andric       canFoldAsPredicatedOp(MI.getOperand(5).getReg(), MRI, this);
1436bdd1243dSDimitry Andric   bool Invert = !DefMI;
1437bdd1243dSDimitry Andric   if (!DefMI)
1438bdd1243dSDimitry Andric     DefMI = canFoldAsPredicatedOp(MI.getOperand(4).getReg(), MRI, this);
1439bdd1243dSDimitry Andric   if (!DefMI)
1440bdd1243dSDimitry Andric     return nullptr;
1441bdd1243dSDimitry Andric 
1442bdd1243dSDimitry Andric   // Find new register class to use.
1443bdd1243dSDimitry Andric   MachineOperand FalseReg = MI.getOperand(Invert ? 5 : 4);
1444bdd1243dSDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
1445bdd1243dSDimitry Andric   const TargetRegisterClass *PreviousClass = MRI.getRegClass(FalseReg.getReg());
1446bdd1243dSDimitry Andric   if (!MRI.constrainRegClass(DestReg, PreviousClass))
1447bdd1243dSDimitry Andric     return nullptr;
1448bdd1243dSDimitry Andric 
1449bdd1243dSDimitry Andric   unsigned PredOpc = getPredicatedOpcode(DefMI->getOpcode());
1450bdd1243dSDimitry Andric   assert(PredOpc != RISCV::INSTRUCTION_LIST_END && "Unexpected opcode!");
1451bdd1243dSDimitry Andric 
1452bdd1243dSDimitry Andric   // Create a new predicated version of DefMI.
1453bdd1243dSDimitry Andric   MachineInstrBuilder NewMI =
1454bdd1243dSDimitry Andric       BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), get(PredOpc), DestReg);
1455bdd1243dSDimitry Andric 
1456bdd1243dSDimitry Andric   // Copy the condition portion.
1457bdd1243dSDimitry Andric   NewMI.add(MI.getOperand(1));
1458bdd1243dSDimitry Andric   NewMI.add(MI.getOperand(2));
1459bdd1243dSDimitry Andric 
1460bdd1243dSDimitry Andric   // Add condition code, inverting if necessary.
1461bdd1243dSDimitry Andric   auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
1462bdd1243dSDimitry Andric   if (Invert)
1463bdd1243dSDimitry Andric     CC = RISCVCC::getOppositeBranchCondition(CC);
1464bdd1243dSDimitry Andric   NewMI.addImm(CC);
1465bdd1243dSDimitry Andric 
1466bdd1243dSDimitry Andric   // Copy the false register.
1467bdd1243dSDimitry Andric   NewMI.add(FalseReg);
1468bdd1243dSDimitry Andric 
1469bdd1243dSDimitry Andric   // Copy all the DefMI operands.
1470bdd1243dSDimitry Andric   const MCInstrDesc &DefDesc = DefMI->getDesc();
1471bdd1243dSDimitry Andric   for (unsigned i = 1, e = DefDesc.getNumOperands(); i != e; ++i)
1472bdd1243dSDimitry Andric     NewMI.add(DefMI->getOperand(i));
1473bdd1243dSDimitry Andric 
1474bdd1243dSDimitry Andric   // Update SeenMIs set: register newly created MI and erase removed DefMI.
1475bdd1243dSDimitry Andric   SeenMIs.insert(NewMI);
1476bdd1243dSDimitry Andric   SeenMIs.erase(DefMI);
1477bdd1243dSDimitry Andric 
1478bdd1243dSDimitry Andric   // If MI is inside a loop, and DefMI is outside the loop, then kill flags on
1479bdd1243dSDimitry Andric   // DefMI would be invalid when tranferred inside the loop.  Checking for a
1480bdd1243dSDimitry Andric   // loop is expensive, but at least remove kill flags if they are in different
1481bdd1243dSDimitry Andric   // BBs.
1482bdd1243dSDimitry Andric   if (DefMI->getParent() != MI.getParent())
1483bdd1243dSDimitry Andric     NewMI->clearKillInfo();
1484bdd1243dSDimitry Andric 
1485bdd1243dSDimitry Andric   // The caller will erase MI, but not DefMI.
1486bdd1243dSDimitry Andric   DefMI->eraseFromParent();
1487bdd1243dSDimitry Andric   return NewMI;
1488bdd1243dSDimitry Andric }
1489bdd1243dSDimitry Andric 
getInstSizeInBytes(const MachineInstr & MI) const14900b57cec5SDimitry Andric unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
14911fd87a68SDimitry Andric   if (MI.isMetaInstruction())
14921fd87a68SDimitry Andric     return 0;
14931fd87a68SDimitry Andric 
14940b57cec5SDimitry Andric   unsigned Opcode = MI.getOpcode();
14950b57cec5SDimitry Andric 
14961fd87a68SDimitry Andric   if (Opcode == TargetOpcode::INLINEASM ||
14971fd87a68SDimitry Andric       Opcode == TargetOpcode::INLINEASM_BR) {
14981fd87a68SDimitry Andric     const MachineFunction &MF = *MI.getParent()->getParent();
14991fd87a68SDimitry Andric     const auto &TM = static_cast<const RISCVTargetMachine &>(MF.getTarget());
15001fd87a68SDimitry Andric     return getInlineAsmLength(MI.getOperand(0).getSymbolName(),
15011fd87a68SDimitry Andric                               *TM.getMCAsmInfo());
15021fd87a68SDimitry Andric   }
15031fd87a68SDimitry Andric 
150406c3fb27SDimitry Andric   if (!MI.memoperands_empty()) {
150506c3fb27SDimitry Andric     MachineMemOperand *MMO = *(MI.memoperands_begin());
150606c3fb27SDimitry Andric     const MachineFunction &MF = *MI.getParent()->getParent();
150706c3fb27SDimitry Andric     const auto &ST = MF.getSubtarget<RISCVSubtarget>();
150806c3fb27SDimitry Andric     if (ST.hasStdExtZihintntl() && MMO->isNonTemporal()) {
150906c3fb27SDimitry Andric       if (ST.hasStdExtCOrZca() && ST.enableRVCHintInstrs()) {
151006c3fb27SDimitry Andric         if (isCompressibleInst(MI, STI))
151106c3fb27SDimitry Andric           return 4; // c.ntl.all + c.load/c.store
151206c3fb27SDimitry Andric         return 6;   // c.ntl.all + load/store
151306c3fb27SDimitry Andric       }
151406c3fb27SDimitry Andric       return 8; // ntl.all + load/store
151506c3fb27SDimitry Andric     }
151606c3fb27SDimitry Andric   }
151706c3fb27SDimitry Andric 
151806c3fb27SDimitry Andric   if (Opcode == TargetOpcode::BUNDLE)
151906c3fb27SDimitry Andric     return getInstBundleLength(MI);
152006c3fb27SDimitry Andric 
1521480093f4SDimitry Andric   if (MI.getParent() && MI.getParent()->getParent()) {
1522bdd1243dSDimitry Andric     if (isCompressibleInst(MI, STI))
1523480093f4SDimitry Andric       return 2;
1524480093f4SDimitry Andric   }
15255f757f3fSDimitry Andric 
15265f757f3fSDimitry Andric   switch (Opcode) {
15275f757f3fSDimitry Andric   case TargetOpcode::STACKMAP:
15285f757f3fSDimitry Andric     // The upper bound for a stackmap intrinsic is the full length of its shadow
15295f757f3fSDimitry Andric     return StackMapOpers(&MI).getNumPatchBytes();
15305f757f3fSDimitry Andric   case TargetOpcode::PATCHPOINT:
15315f757f3fSDimitry Andric     // The size of the patchpoint intrinsic is the number of bytes requested
15325f757f3fSDimitry Andric     return PatchPointOpers(&MI).getNumPatchBytes();
15335f757f3fSDimitry Andric   case TargetOpcode::STATEPOINT:
15345f757f3fSDimitry Andric     // The size of the statepoint intrinsic is the number of bytes requested
15355f757f3fSDimitry Andric     return StatepointOpers(&MI).getNumPatchBytes();
15365f757f3fSDimitry Andric   default:
1537480093f4SDimitry Andric     return get(Opcode).getSize();
1538480093f4SDimitry Andric   }
15395f757f3fSDimitry Andric }
15400b57cec5SDimitry Andric 
getInstBundleLength(const MachineInstr & MI) const154106c3fb27SDimitry Andric unsigned RISCVInstrInfo::getInstBundleLength(const MachineInstr &MI) const {
154206c3fb27SDimitry Andric   unsigned Size = 0;
154306c3fb27SDimitry Andric   MachineBasicBlock::const_instr_iterator I = MI.getIterator();
154406c3fb27SDimitry Andric   MachineBasicBlock::const_instr_iterator E = MI.getParent()->instr_end();
154506c3fb27SDimitry Andric   while (++I != E && I->isInsideBundle()) {
154606c3fb27SDimitry Andric     assert(!I->isBundle() && "No nested bundle!");
154706c3fb27SDimitry Andric     Size += getInstSizeInBytes(*I);
154806c3fb27SDimitry Andric   }
154906c3fb27SDimitry Andric   return Size;
155006c3fb27SDimitry Andric }
155106c3fb27SDimitry Andric 
isAsCheapAsAMove(const MachineInstr & MI) const15520b57cec5SDimitry Andric bool RISCVInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const {
15530b57cec5SDimitry Andric   const unsigned Opcode = MI.getOpcode();
15540b57cec5SDimitry Andric   switch (Opcode) {
15550b57cec5SDimitry Andric   default:
15560b57cec5SDimitry Andric     break;
1557e8d8bef9SDimitry Andric   case RISCV::FSGNJ_D:
1558e8d8bef9SDimitry Andric   case RISCV::FSGNJ_S:
15590eae32dcSDimitry Andric   case RISCV::FSGNJ_H:
156006c3fb27SDimitry Andric   case RISCV::FSGNJ_D_INX:
156106c3fb27SDimitry Andric   case RISCV::FSGNJ_D_IN32X:
156206c3fb27SDimitry Andric   case RISCV::FSGNJ_S_INX:
156306c3fb27SDimitry Andric   case RISCV::FSGNJ_H_INX:
1564e8d8bef9SDimitry Andric     // The canonical floating-point move is fsgnj rd, rs, rs.
1565e8d8bef9SDimitry Andric     return MI.getOperand(1).isReg() && MI.getOperand(2).isReg() &&
1566e8d8bef9SDimitry Andric            MI.getOperand(1).getReg() == MI.getOperand(2).getReg();
15670b57cec5SDimitry Andric   case RISCV::ADDI:
15680b57cec5SDimitry Andric   case RISCV::ORI:
15690b57cec5SDimitry Andric   case RISCV::XORI:
1570e8d8bef9SDimitry Andric     return (MI.getOperand(1).isReg() &&
1571e8d8bef9SDimitry Andric             MI.getOperand(1).getReg() == RISCV::X0) ||
1572e8d8bef9SDimitry Andric            (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0);
15730b57cec5SDimitry Andric   }
15740b57cec5SDimitry Andric   return MI.isAsCheapAsAMove();
15750b57cec5SDimitry Andric }
15768bcb0991SDimitry Andric 
1577bdd1243dSDimitry Andric std::optional<DestSourcePair>
isCopyInstrImpl(const MachineInstr & MI) const1578e8d8bef9SDimitry Andric RISCVInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
1579e8d8bef9SDimitry Andric   if (MI.isMoveReg())
1580e8d8bef9SDimitry Andric     return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
1581e8d8bef9SDimitry Andric   switch (MI.getOpcode()) {
1582e8d8bef9SDimitry Andric   default:
1583e8d8bef9SDimitry Andric     break;
1584e8d8bef9SDimitry Andric   case RISCV::ADDI:
1585e8d8bef9SDimitry Andric     // Operand 1 can be a frameindex but callers expect registers
1586e8d8bef9SDimitry Andric     if (MI.getOperand(1).isReg() && MI.getOperand(2).isImm() &&
1587e8d8bef9SDimitry Andric         MI.getOperand(2).getImm() == 0)
1588e8d8bef9SDimitry Andric       return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
1589e8d8bef9SDimitry Andric     break;
1590e8d8bef9SDimitry Andric   case RISCV::FSGNJ_D:
1591e8d8bef9SDimitry Andric   case RISCV::FSGNJ_S:
15920eae32dcSDimitry Andric   case RISCV::FSGNJ_H:
159306c3fb27SDimitry Andric   case RISCV::FSGNJ_D_INX:
159406c3fb27SDimitry Andric   case RISCV::FSGNJ_D_IN32X:
159506c3fb27SDimitry Andric   case RISCV::FSGNJ_S_INX:
159606c3fb27SDimitry Andric   case RISCV::FSGNJ_H_INX:
1597e8d8bef9SDimitry Andric     // The canonical floating-point move is fsgnj rd, rs, rs.
1598e8d8bef9SDimitry Andric     if (MI.getOperand(1).isReg() && MI.getOperand(2).isReg() &&
1599e8d8bef9SDimitry Andric         MI.getOperand(1).getReg() == MI.getOperand(2).getReg())
1600e8d8bef9SDimitry Andric       return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
1601e8d8bef9SDimitry Andric     break;
1602e8d8bef9SDimitry Andric   }
1603bdd1243dSDimitry Andric   return std::nullopt;
1604bdd1243dSDimitry Andric }
1605bdd1243dSDimitry Andric 
getMachineCombinerTraceStrategy() const160606c3fb27SDimitry Andric MachineTraceStrategy RISCVInstrInfo::getMachineCombinerTraceStrategy() const {
160706c3fb27SDimitry Andric   if (ForceMachineCombinerStrategy.getNumOccurrences() == 0) {
160806c3fb27SDimitry Andric     // The option is unused. Choose Local strategy only for in-order cores. When
160906c3fb27SDimitry Andric     // scheduling model is unspecified, use MinInstrCount strategy as more
161006c3fb27SDimitry Andric     // generic one.
161106c3fb27SDimitry Andric     const auto &SchedModel = STI.getSchedModel();
161206c3fb27SDimitry Andric     return (!SchedModel.hasInstrSchedModel() || SchedModel.isOutOfOrder())
161306c3fb27SDimitry Andric                ? MachineTraceStrategy::TS_MinInstrCount
161406c3fb27SDimitry Andric                : MachineTraceStrategy::TS_Local;
161506c3fb27SDimitry Andric   }
161606c3fb27SDimitry Andric   // The strategy was forced by the option.
161706c3fb27SDimitry Andric   return ForceMachineCombinerStrategy;
161806c3fb27SDimitry Andric }
161906c3fb27SDimitry Andric 
finalizeInsInstrs(MachineInstr & Root,MachineCombinerPattern & P,SmallVectorImpl<MachineInstr * > & InsInstrs) const1620bdd1243dSDimitry Andric void RISCVInstrInfo::finalizeInsInstrs(
1621bdd1243dSDimitry Andric     MachineInstr &Root, MachineCombinerPattern &P,
1622bdd1243dSDimitry Andric     SmallVectorImpl<MachineInstr *> &InsInstrs) const {
1623bdd1243dSDimitry Andric   int16_t FrmOpIdx =
1624bdd1243dSDimitry Andric       RISCV::getNamedOperandIdx(Root.getOpcode(), RISCV::OpName::frm);
1625bdd1243dSDimitry Andric   if (FrmOpIdx < 0) {
1626bdd1243dSDimitry Andric     assert(all_of(InsInstrs,
1627bdd1243dSDimitry Andric                   [](MachineInstr *MI) {
1628bdd1243dSDimitry Andric                     return RISCV::getNamedOperandIdx(MI->getOpcode(),
1629bdd1243dSDimitry Andric                                                      RISCV::OpName::frm) < 0;
1630bdd1243dSDimitry Andric                   }) &&
1631bdd1243dSDimitry Andric            "New instructions require FRM whereas the old one does not have it");
1632bdd1243dSDimitry Andric     return;
1633bdd1243dSDimitry Andric   }
1634bdd1243dSDimitry Andric 
1635bdd1243dSDimitry Andric   const MachineOperand &FRM = Root.getOperand(FrmOpIdx);
1636bdd1243dSDimitry Andric   MachineFunction &MF = *Root.getMF();
1637bdd1243dSDimitry Andric 
1638bdd1243dSDimitry Andric   for (auto *NewMI : InsInstrs) {
1639bdd1243dSDimitry Andric     assert(static_cast<unsigned>(RISCV::getNamedOperandIdx(
1640bdd1243dSDimitry Andric                NewMI->getOpcode(), RISCV::OpName::frm)) ==
1641bdd1243dSDimitry Andric                NewMI->getNumOperands() &&
1642bdd1243dSDimitry Andric            "Instruction has unexpected number of operands");
1643bdd1243dSDimitry Andric     MachineInstrBuilder MIB(MF, NewMI);
1644bdd1243dSDimitry Andric     MIB.add(FRM);
1645bdd1243dSDimitry Andric     if (FRM.getImm() == RISCVFPRndMode::DYN)
1646bdd1243dSDimitry Andric       MIB.addUse(RISCV::FRM, RegState::Implicit);
1647bdd1243dSDimitry Andric   }
1648bdd1243dSDimitry Andric }
1649bdd1243dSDimitry Andric 
isFADD(unsigned Opc)1650bdd1243dSDimitry Andric static bool isFADD(unsigned Opc) {
1651bdd1243dSDimitry Andric   switch (Opc) {
1652bdd1243dSDimitry Andric   default:
1653bdd1243dSDimitry Andric     return false;
1654bdd1243dSDimitry Andric   case RISCV::FADD_H:
1655bdd1243dSDimitry Andric   case RISCV::FADD_S:
1656bdd1243dSDimitry Andric   case RISCV::FADD_D:
1657bdd1243dSDimitry Andric     return true;
1658bdd1243dSDimitry Andric   }
1659bdd1243dSDimitry Andric }
1660bdd1243dSDimitry Andric 
isFSUB(unsigned Opc)1661bdd1243dSDimitry Andric static bool isFSUB(unsigned Opc) {
1662bdd1243dSDimitry Andric   switch (Opc) {
1663bdd1243dSDimitry Andric   default:
1664bdd1243dSDimitry Andric     return false;
1665bdd1243dSDimitry Andric   case RISCV::FSUB_H:
1666bdd1243dSDimitry Andric   case RISCV::FSUB_S:
1667bdd1243dSDimitry Andric   case RISCV::FSUB_D:
1668bdd1243dSDimitry Andric     return true;
1669bdd1243dSDimitry Andric   }
1670bdd1243dSDimitry Andric }
1671bdd1243dSDimitry Andric 
isFMUL(unsigned Opc)1672bdd1243dSDimitry Andric static bool isFMUL(unsigned Opc) {
1673bdd1243dSDimitry Andric   switch (Opc) {
1674bdd1243dSDimitry Andric   default:
1675bdd1243dSDimitry Andric     return false;
1676bdd1243dSDimitry Andric   case RISCV::FMUL_H:
1677bdd1243dSDimitry Andric   case RISCV::FMUL_S:
1678bdd1243dSDimitry Andric   case RISCV::FMUL_D:
1679bdd1243dSDimitry Andric     return true;
1680bdd1243dSDimitry Andric   }
1681bdd1243dSDimitry Andric }
1682bdd1243dSDimitry Andric 
hasReassociableSibling(const MachineInstr & Inst,bool & Commuted) const1683bdd1243dSDimitry Andric bool RISCVInstrInfo::hasReassociableSibling(const MachineInstr &Inst,
1684bdd1243dSDimitry Andric                                             bool &Commuted) const {
1685bdd1243dSDimitry Andric   if (!TargetInstrInfo::hasReassociableSibling(Inst, Commuted))
1686bdd1243dSDimitry Andric     return false;
1687bdd1243dSDimitry Andric 
1688bdd1243dSDimitry Andric   const MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
1689bdd1243dSDimitry Andric   unsigned OperandIdx = Commuted ? 2 : 1;
1690bdd1243dSDimitry Andric   const MachineInstr &Sibling =
1691bdd1243dSDimitry Andric       *MRI.getVRegDef(Inst.getOperand(OperandIdx).getReg());
1692bdd1243dSDimitry Andric 
1693bdd1243dSDimitry Andric   int16_t InstFrmOpIdx =
1694bdd1243dSDimitry Andric       RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::frm);
1695bdd1243dSDimitry Andric   int16_t SiblingFrmOpIdx =
1696bdd1243dSDimitry Andric       RISCV::getNamedOperandIdx(Sibling.getOpcode(), RISCV::OpName::frm);
1697bdd1243dSDimitry Andric 
1698bdd1243dSDimitry Andric   return (InstFrmOpIdx < 0 && SiblingFrmOpIdx < 0) ||
1699bdd1243dSDimitry Andric          RISCV::hasEqualFRM(Inst, Sibling);
1700bdd1243dSDimitry Andric }
1701bdd1243dSDimitry Andric 
isAssociativeAndCommutative(const MachineInstr & Inst,bool Invert) const1702bdd1243dSDimitry Andric bool RISCVInstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
1703bdd1243dSDimitry Andric                                                  bool Invert) const {
1704bdd1243dSDimitry Andric   unsigned Opc = Inst.getOpcode();
1705bdd1243dSDimitry Andric   if (Invert) {
1706bdd1243dSDimitry Andric     auto InverseOpcode = getInverseOpcode(Opc);
1707bdd1243dSDimitry Andric     if (!InverseOpcode)
1708bdd1243dSDimitry Andric       return false;
1709bdd1243dSDimitry Andric     Opc = *InverseOpcode;
1710bdd1243dSDimitry Andric   }
1711bdd1243dSDimitry Andric 
1712bdd1243dSDimitry Andric   if (isFADD(Opc) || isFMUL(Opc))
1713bdd1243dSDimitry Andric     return Inst.getFlag(MachineInstr::MIFlag::FmReassoc) &&
1714bdd1243dSDimitry Andric            Inst.getFlag(MachineInstr::MIFlag::FmNsz);
1715bdd1243dSDimitry Andric 
1716bdd1243dSDimitry Andric   switch (Opc) {
1717bdd1243dSDimitry Andric   default:
1718bdd1243dSDimitry Andric     return false;
1719bdd1243dSDimitry Andric   case RISCV::ADD:
1720bdd1243dSDimitry Andric   case RISCV::ADDW:
1721bdd1243dSDimitry Andric   case RISCV::AND:
1722bdd1243dSDimitry Andric   case RISCV::OR:
1723bdd1243dSDimitry Andric   case RISCV::XOR:
1724bdd1243dSDimitry Andric   // From RISC-V ISA spec, if both the high and low bits of the same product
1725bdd1243dSDimitry Andric   // are required, then the recommended code sequence is:
1726bdd1243dSDimitry Andric   //
1727bdd1243dSDimitry Andric   // MULH[[S]U] rdh, rs1, rs2
1728bdd1243dSDimitry Andric   // MUL        rdl, rs1, rs2
1729bdd1243dSDimitry Andric   // (source register specifiers must be in same order and rdh cannot be the
1730bdd1243dSDimitry Andric   //  same as rs1 or rs2)
1731bdd1243dSDimitry Andric   //
1732bdd1243dSDimitry Andric   // Microarchitectures can then fuse these into a single multiply operation
1733bdd1243dSDimitry Andric   // instead of performing two separate multiplies.
1734bdd1243dSDimitry Andric   // MachineCombiner may reassociate MUL operands and lose the fusion
1735bdd1243dSDimitry Andric   // opportunity.
1736bdd1243dSDimitry Andric   case RISCV::MUL:
1737bdd1243dSDimitry Andric   case RISCV::MULW:
1738bdd1243dSDimitry Andric   case RISCV::MIN:
1739bdd1243dSDimitry Andric   case RISCV::MINU:
1740bdd1243dSDimitry Andric   case RISCV::MAX:
1741bdd1243dSDimitry Andric   case RISCV::MAXU:
1742bdd1243dSDimitry Andric   case RISCV::FMIN_H:
1743bdd1243dSDimitry Andric   case RISCV::FMIN_S:
1744bdd1243dSDimitry Andric   case RISCV::FMIN_D:
1745bdd1243dSDimitry Andric   case RISCV::FMAX_H:
1746bdd1243dSDimitry Andric   case RISCV::FMAX_S:
1747bdd1243dSDimitry Andric   case RISCV::FMAX_D:
1748bdd1243dSDimitry Andric     return true;
1749bdd1243dSDimitry Andric   }
1750bdd1243dSDimitry Andric 
1751bdd1243dSDimitry Andric   return false;
1752bdd1243dSDimitry Andric }
1753bdd1243dSDimitry Andric 
1754bdd1243dSDimitry Andric std::optional<unsigned>
getInverseOpcode(unsigned Opcode) const1755bdd1243dSDimitry Andric RISCVInstrInfo::getInverseOpcode(unsigned Opcode) const {
1756bdd1243dSDimitry Andric   switch (Opcode) {
1757bdd1243dSDimitry Andric   default:
1758bdd1243dSDimitry Andric     return std::nullopt;
1759bdd1243dSDimitry Andric   case RISCV::FADD_H:
1760bdd1243dSDimitry Andric     return RISCV::FSUB_H;
1761bdd1243dSDimitry Andric   case RISCV::FADD_S:
1762bdd1243dSDimitry Andric     return RISCV::FSUB_S;
1763bdd1243dSDimitry Andric   case RISCV::FADD_D:
1764bdd1243dSDimitry Andric     return RISCV::FSUB_D;
1765bdd1243dSDimitry Andric   case RISCV::FSUB_H:
1766bdd1243dSDimitry Andric     return RISCV::FADD_H;
1767bdd1243dSDimitry Andric   case RISCV::FSUB_S:
1768bdd1243dSDimitry Andric     return RISCV::FADD_S;
1769bdd1243dSDimitry Andric   case RISCV::FSUB_D:
1770bdd1243dSDimitry Andric     return RISCV::FADD_D;
1771bdd1243dSDimitry Andric   case RISCV::ADD:
1772bdd1243dSDimitry Andric     return RISCV::SUB;
1773bdd1243dSDimitry Andric   case RISCV::SUB:
1774bdd1243dSDimitry Andric     return RISCV::ADD;
1775bdd1243dSDimitry Andric   case RISCV::ADDW:
1776bdd1243dSDimitry Andric     return RISCV::SUBW;
1777bdd1243dSDimitry Andric   case RISCV::SUBW:
1778bdd1243dSDimitry Andric     return RISCV::ADDW;
1779bdd1243dSDimitry Andric   }
1780bdd1243dSDimitry Andric }
1781bdd1243dSDimitry Andric 
canCombineFPFusedMultiply(const MachineInstr & Root,const MachineOperand & MO,bool DoRegPressureReduce)1782bdd1243dSDimitry Andric static bool canCombineFPFusedMultiply(const MachineInstr &Root,
1783bdd1243dSDimitry Andric                                       const MachineOperand &MO,
1784bdd1243dSDimitry Andric                                       bool DoRegPressureReduce) {
1785bdd1243dSDimitry Andric   if (!MO.isReg() || !MO.getReg().isVirtual())
1786bdd1243dSDimitry Andric     return false;
1787bdd1243dSDimitry Andric   const MachineRegisterInfo &MRI = Root.getMF()->getRegInfo();
1788bdd1243dSDimitry Andric   MachineInstr *MI = MRI.getVRegDef(MO.getReg());
1789bdd1243dSDimitry Andric   if (!MI || !isFMUL(MI->getOpcode()))
1790bdd1243dSDimitry Andric     return false;
1791bdd1243dSDimitry Andric 
1792bdd1243dSDimitry Andric   if (!Root.getFlag(MachineInstr::MIFlag::FmContract) ||
1793bdd1243dSDimitry Andric       !MI->getFlag(MachineInstr::MIFlag::FmContract))
1794bdd1243dSDimitry Andric     return false;
1795bdd1243dSDimitry Andric 
1796bdd1243dSDimitry Andric   // Try combining even if fmul has more than one use as it eliminates
1797bdd1243dSDimitry Andric   // dependency between fadd(fsub) and fmul. However, it can extend liveranges
1798bdd1243dSDimitry Andric   // for fmul operands, so reject the transformation in register pressure
1799bdd1243dSDimitry Andric   // reduction mode.
1800bdd1243dSDimitry Andric   if (DoRegPressureReduce && !MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
1801bdd1243dSDimitry Andric     return false;
1802bdd1243dSDimitry Andric 
1803bdd1243dSDimitry Andric   // Do not combine instructions from different basic blocks.
1804bdd1243dSDimitry Andric   if (Root.getParent() != MI->getParent())
1805bdd1243dSDimitry Andric     return false;
1806bdd1243dSDimitry Andric   return RISCV::hasEqualFRM(Root, *MI);
1807bdd1243dSDimitry Andric }
1808bdd1243dSDimitry Andric 
1809bdd1243dSDimitry Andric static bool
getFPFusedMultiplyPatterns(MachineInstr & Root,SmallVectorImpl<MachineCombinerPattern> & Patterns,bool DoRegPressureReduce)1810bdd1243dSDimitry Andric getFPFusedMultiplyPatterns(MachineInstr &Root,
1811bdd1243dSDimitry Andric                            SmallVectorImpl<MachineCombinerPattern> &Patterns,
1812bdd1243dSDimitry Andric                            bool DoRegPressureReduce) {
1813bdd1243dSDimitry Andric   unsigned Opc = Root.getOpcode();
1814bdd1243dSDimitry Andric   bool IsFAdd = isFADD(Opc);
1815bdd1243dSDimitry Andric   if (!IsFAdd && !isFSUB(Opc))
1816bdd1243dSDimitry Andric     return false;
1817bdd1243dSDimitry Andric   bool Added = false;
1818bdd1243dSDimitry Andric   if (canCombineFPFusedMultiply(Root, Root.getOperand(1),
1819bdd1243dSDimitry Andric                                 DoRegPressureReduce)) {
1820bdd1243dSDimitry Andric     Patterns.push_back(IsFAdd ? MachineCombinerPattern::FMADD_AX
1821bdd1243dSDimitry Andric                               : MachineCombinerPattern::FMSUB);
1822bdd1243dSDimitry Andric     Added = true;
1823bdd1243dSDimitry Andric   }
1824bdd1243dSDimitry Andric   if (canCombineFPFusedMultiply(Root, Root.getOperand(2),
1825bdd1243dSDimitry Andric                                 DoRegPressureReduce)) {
1826bdd1243dSDimitry Andric     Patterns.push_back(IsFAdd ? MachineCombinerPattern::FMADD_XA
1827bdd1243dSDimitry Andric                               : MachineCombinerPattern::FNMSUB);
1828bdd1243dSDimitry Andric     Added = true;
1829bdd1243dSDimitry Andric   }
1830bdd1243dSDimitry Andric   return Added;
1831bdd1243dSDimitry Andric }
1832bdd1243dSDimitry Andric 
getFPPatterns(MachineInstr & Root,SmallVectorImpl<MachineCombinerPattern> & Patterns,bool DoRegPressureReduce)1833bdd1243dSDimitry Andric static bool getFPPatterns(MachineInstr &Root,
1834bdd1243dSDimitry Andric                           SmallVectorImpl<MachineCombinerPattern> &Patterns,
1835bdd1243dSDimitry Andric                           bool DoRegPressureReduce) {
1836bdd1243dSDimitry Andric   return getFPFusedMultiplyPatterns(Root, Patterns, DoRegPressureReduce);
1837bdd1243dSDimitry Andric }
1838bdd1243dSDimitry Andric 
getMachineCombinerPatterns(MachineInstr & Root,SmallVectorImpl<MachineCombinerPattern> & Patterns,bool DoRegPressureReduce) const1839bdd1243dSDimitry Andric bool RISCVInstrInfo::getMachineCombinerPatterns(
1840bdd1243dSDimitry Andric     MachineInstr &Root, SmallVectorImpl<MachineCombinerPattern> &Patterns,
1841bdd1243dSDimitry Andric     bool DoRegPressureReduce) const {
1842bdd1243dSDimitry Andric 
1843bdd1243dSDimitry Andric   if (getFPPatterns(Root, Patterns, DoRegPressureReduce))
1844bdd1243dSDimitry Andric     return true;
1845bdd1243dSDimitry Andric 
1846bdd1243dSDimitry Andric   return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns,
1847bdd1243dSDimitry Andric                                                      DoRegPressureReduce);
1848bdd1243dSDimitry Andric }
1849bdd1243dSDimitry Andric 
getFPFusedMultiplyOpcode(unsigned RootOpc,MachineCombinerPattern Pattern)1850bdd1243dSDimitry Andric static unsigned getFPFusedMultiplyOpcode(unsigned RootOpc,
1851bdd1243dSDimitry Andric                                          MachineCombinerPattern Pattern) {
1852bdd1243dSDimitry Andric   switch (RootOpc) {
1853bdd1243dSDimitry Andric   default:
1854bdd1243dSDimitry Andric     llvm_unreachable("Unexpected opcode");
1855bdd1243dSDimitry Andric   case RISCV::FADD_H:
1856bdd1243dSDimitry Andric     return RISCV::FMADD_H;
1857bdd1243dSDimitry Andric   case RISCV::FADD_S:
1858bdd1243dSDimitry Andric     return RISCV::FMADD_S;
1859bdd1243dSDimitry Andric   case RISCV::FADD_D:
1860bdd1243dSDimitry Andric     return RISCV::FMADD_D;
1861bdd1243dSDimitry Andric   case RISCV::FSUB_H:
1862bdd1243dSDimitry Andric     return Pattern == MachineCombinerPattern::FMSUB ? RISCV::FMSUB_H
1863bdd1243dSDimitry Andric                                                     : RISCV::FNMSUB_H;
1864bdd1243dSDimitry Andric   case RISCV::FSUB_S:
1865bdd1243dSDimitry Andric     return Pattern == MachineCombinerPattern::FMSUB ? RISCV::FMSUB_S
1866bdd1243dSDimitry Andric                                                     : RISCV::FNMSUB_S;
1867bdd1243dSDimitry Andric   case RISCV::FSUB_D:
1868bdd1243dSDimitry Andric     return Pattern == MachineCombinerPattern::FMSUB ? RISCV::FMSUB_D
1869bdd1243dSDimitry Andric                                                     : RISCV::FNMSUB_D;
1870bdd1243dSDimitry Andric   }
1871bdd1243dSDimitry Andric }
1872bdd1243dSDimitry Andric 
getAddendOperandIdx(MachineCombinerPattern Pattern)1873bdd1243dSDimitry Andric static unsigned getAddendOperandIdx(MachineCombinerPattern Pattern) {
1874bdd1243dSDimitry Andric   switch (Pattern) {
1875bdd1243dSDimitry Andric   default:
1876bdd1243dSDimitry Andric     llvm_unreachable("Unexpected pattern");
1877bdd1243dSDimitry Andric   case MachineCombinerPattern::FMADD_AX:
1878bdd1243dSDimitry Andric   case MachineCombinerPattern::FMSUB:
1879bdd1243dSDimitry Andric     return 2;
1880bdd1243dSDimitry Andric   case MachineCombinerPattern::FMADD_XA:
1881bdd1243dSDimitry Andric   case MachineCombinerPattern::FNMSUB:
1882bdd1243dSDimitry Andric     return 1;
1883bdd1243dSDimitry Andric   }
1884bdd1243dSDimitry Andric }
1885bdd1243dSDimitry Andric 
combineFPFusedMultiply(MachineInstr & Root,MachineInstr & Prev,MachineCombinerPattern Pattern,SmallVectorImpl<MachineInstr * > & InsInstrs,SmallVectorImpl<MachineInstr * > & DelInstrs)1886bdd1243dSDimitry Andric static void combineFPFusedMultiply(MachineInstr &Root, MachineInstr &Prev,
1887bdd1243dSDimitry Andric                                    MachineCombinerPattern Pattern,
1888bdd1243dSDimitry Andric                                    SmallVectorImpl<MachineInstr *> &InsInstrs,
1889bdd1243dSDimitry Andric                                    SmallVectorImpl<MachineInstr *> &DelInstrs) {
1890bdd1243dSDimitry Andric   MachineFunction *MF = Root.getMF();
1891bdd1243dSDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
1892bdd1243dSDimitry Andric   const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
1893bdd1243dSDimitry Andric 
1894bdd1243dSDimitry Andric   MachineOperand &Mul1 = Prev.getOperand(1);
1895bdd1243dSDimitry Andric   MachineOperand &Mul2 = Prev.getOperand(2);
1896bdd1243dSDimitry Andric   MachineOperand &Dst = Root.getOperand(0);
1897bdd1243dSDimitry Andric   MachineOperand &Addend = Root.getOperand(getAddendOperandIdx(Pattern));
1898bdd1243dSDimitry Andric 
1899bdd1243dSDimitry Andric   Register DstReg = Dst.getReg();
1900bdd1243dSDimitry Andric   unsigned FusedOpc = getFPFusedMultiplyOpcode(Root.getOpcode(), Pattern);
190106c3fb27SDimitry Andric   uint32_t IntersectedFlags = Root.getFlags() & Prev.getFlags();
1902bdd1243dSDimitry Andric   DebugLoc MergedLoc =
1903bdd1243dSDimitry Andric       DILocation::getMergedLocation(Root.getDebugLoc(), Prev.getDebugLoc());
1904bdd1243dSDimitry Andric 
190506c3fb27SDimitry Andric   bool Mul1IsKill = Mul1.isKill();
190606c3fb27SDimitry Andric   bool Mul2IsKill = Mul2.isKill();
190706c3fb27SDimitry Andric   bool AddendIsKill = Addend.isKill();
190806c3fb27SDimitry Andric 
190906c3fb27SDimitry Andric   // We need to clear kill flags since we may be extending the live range past
191006c3fb27SDimitry Andric   // a kill. If the mul had kill flags, we can preserve those since we know
191106c3fb27SDimitry Andric   // where the previous range stopped.
191206c3fb27SDimitry Andric   MRI.clearKillFlags(Mul1.getReg());
191306c3fb27SDimitry Andric   MRI.clearKillFlags(Mul2.getReg());
191406c3fb27SDimitry Andric 
1915bdd1243dSDimitry Andric   MachineInstrBuilder MIB =
1916bdd1243dSDimitry Andric       BuildMI(*MF, MergedLoc, TII->get(FusedOpc), DstReg)
191706c3fb27SDimitry Andric           .addReg(Mul1.getReg(), getKillRegState(Mul1IsKill))
191806c3fb27SDimitry Andric           .addReg(Mul2.getReg(), getKillRegState(Mul2IsKill))
191906c3fb27SDimitry Andric           .addReg(Addend.getReg(), getKillRegState(AddendIsKill))
1920bdd1243dSDimitry Andric           .setMIFlags(IntersectedFlags);
1921bdd1243dSDimitry Andric 
1922bdd1243dSDimitry Andric   InsInstrs.push_back(MIB);
1923bdd1243dSDimitry Andric   if (MRI.hasOneNonDBGUse(Prev.getOperand(0).getReg()))
1924bdd1243dSDimitry Andric     DelInstrs.push_back(&Prev);
1925bdd1243dSDimitry Andric   DelInstrs.push_back(&Root);
1926bdd1243dSDimitry Andric }
1927bdd1243dSDimitry Andric 
genAlternativeCodeSequence(MachineInstr & Root,MachineCombinerPattern Pattern,SmallVectorImpl<MachineInstr * > & InsInstrs,SmallVectorImpl<MachineInstr * > & DelInstrs,DenseMap<unsigned,unsigned> & InstrIdxForVirtReg) const1928bdd1243dSDimitry Andric void RISCVInstrInfo::genAlternativeCodeSequence(
1929bdd1243dSDimitry Andric     MachineInstr &Root, MachineCombinerPattern Pattern,
1930bdd1243dSDimitry Andric     SmallVectorImpl<MachineInstr *> &InsInstrs,
1931bdd1243dSDimitry Andric     SmallVectorImpl<MachineInstr *> &DelInstrs,
1932bdd1243dSDimitry Andric     DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const {
1933bdd1243dSDimitry Andric   MachineRegisterInfo &MRI = Root.getMF()->getRegInfo();
1934bdd1243dSDimitry Andric   switch (Pattern) {
1935bdd1243dSDimitry Andric   default:
1936bdd1243dSDimitry Andric     TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
1937bdd1243dSDimitry Andric                                                 DelInstrs, InstrIdxForVirtReg);
1938bdd1243dSDimitry Andric     return;
1939bdd1243dSDimitry Andric   case MachineCombinerPattern::FMADD_AX:
1940bdd1243dSDimitry Andric   case MachineCombinerPattern::FMSUB: {
1941bdd1243dSDimitry Andric     MachineInstr &Prev = *MRI.getVRegDef(Root.getOperand(1).getReg());
1942bdd1243dSDimitry Andric     combineFPFusedMultiply(Root, Prev, Pattern, InsInstrs, DelInstrs);
1943bdd1243dSDimitry Andric     return;
1944bdd1243dSDimitry Andric   }
1945bdd1243dSDimitry Andric   case MachineCombinerPattern::FMADD_XA:
1946bdd1243dSDimitry Andric   case MachineCombinerPattern::FNMSUB: {
1947bdd1243dSDimitry Andric     MachineInstr &Prev = *MRI.getVRegDef(Root.getOperand(2).getReg());
1948bdd1243dSDimitry Andric     combineFPFusedMultiply(Root, Prev, Pattern, InsInstrs, DelInstrs);
1949bdd1243dSDimitry Andric     return;
1950bdd1243dSDimitry Andric   }
1951bdd1243dSDimitry Andric   }
1952e8d8bef9SDimitry Andric }
1953e8d8bef9SDimitry Andric 
verifyInstruction(const MachineInstr & MI,StringRef & ErrInfo) const19548bcb0991SDimitry Andric bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
19558bcb0991SDimitry Andric                                        StringRef &ErrInfo) const {
1956bdd1243dSDimitry Andric   MCInstrDesc const &Desc = MI.getDesc();
19578bcb0991SDimitry Andric 
195806c3fb27SDimitry Andric   for (const auto &[Index, Operand] : enumerate(Desc.operands())) {
195906c3fb27SDimitry Andric     unsigned OpType = Operand.OperandType;
19608bcb0991SDimitry Andric     if (OpType >= RISCVOp::OPERAND_FIRST_RISCV_IMM &&
19618bcb0991SDimitry Andric         OpType <= RISCVOp::OPERAND_LAST_RISCV_IMM) {
196206c3fb27SDimitry Andric       const MachineOperand &MO = MI.getOperand(Index);
19638bcb0991SDimitry Andric       if (MO.isImm()) {
19648bcb0991SDimitry Andric         int64_t Imm = MO.getImm();
19658bcb0991SDimitry Andric         bool Ok;
19668bcb0991SDimitry Andric         switch (OpType) {
19678bcb0991SDimitry Andric         default:
19688bcb0991SDimitry Andric           llvm_unreachable("Unexpected operand type");
196981ad6265SDimitry Andric 
197081ad6265SDimitry Andric           // clang-format off
197181ad6265SDimitry Andric #define CASE_OPERAND_UIMM(NUM)                                                 \
197281ad6265SDimitry Andric   case RISCVOp::OPERAND_UIMM##NUM:                                             \
197381ad6265SDimitry Andric     Ok = isUInt<NUM>(Imm);                                                     \
1974349cc55cSDimitry Andric     break;
197506c3fb27SDimitry Andric         CASE_OPERAND_UIMM(1)
197681ad6265SDimitry Andric         CASE_OPERAND_UIMM(2)
197781ad6265SDimitry Andric         CASE_OPERAND_UIMM(3)
197881ad6265SDimitry Andric         CASE_OPERAND_UIMM(4)
197981ad6265SDimitry Andric         CASE_OPERAND_UIMM(5)
198006c3fb27SDimitry Andric         CASE_OPERAND_UIMM(6)
198181ad6265SDimitry Andric         CASE_OPERAND_UIMM(7)
198206c3fb27SDimitry Andric         CASE_OPERAND_UIMM(8)
198306c3fb27SDimitry Andric         CASE_OPERAND_UIMM(12)
198406c3fb27SDimitry Andric         CASE_OPERAND_UIMM(20)
198506c3fb27SDimitry Andric           // clang-format on
198606c3fb27SDimitry Andric         case RISCVOp::OPERAND_UIMM2_LSB0:
198706c3fb27SDimitry Andric           Ok = isShiftedUInt<1, 1>(Imm);
198806c3fb27SDimitry Andric           break;
1989bdd1243dSDimitry Andric         case RISCVOp::OPERAND_UIMM7_LSB00:
1990bdd1243dSDimitry Andric           Ok = isShiftedUInt<5, 2>(Imm);
1991bdd1243dSDimitry Andric           break;
1992bdd1243dSDimitry Andric         case RISCVOp::OPERAND_UIMM8_LSB00:
1993bdd1243dSDimitry Andric           Ok = isShiftedUInt<6, 2>(Imm);
1994bdd1243dSDimitry Andric           break;
1995bdd1243dSDimitry Andric         case RISCVOp::OPERAND_UIMM8_LSB000:
1996bdd1243dSDimitry Andric           Ok = isShiftedUInt<5, 3>(Imm);
1997bdd1243dSDimitry Andric           break;
199806c3fb27SDimitry Andric         case RISCVOp::OPERAND_UIMM8_GE32:
199906c3fb27SDimitry Andric           Ok = isUInt<8>(Imm) && Imm >= 32;
200006c3fb27SDimitry Andric           break;
200106c3fb27SDimitry Andric         case RISCVOp::OPERAND_UIMM9_LSB000:
200206c3fb27SDimitry Andric           Ok = isShiftedUInt<6, 3>(Imm);
200306c3fb27SDimitry Andric           break;
2004bdd1243dSDimitry Andric         case RISCVOp::OPERAND_SIMM10_LSB0000_NONZERO:
2005bdd1243dSDimitry Andric           Ok = isShiftedInt<6, 4>(Imm) && (Imm != 0);
2006bdd1243dSDimitry Andric           break;
200706c3fb27SDimitry Andric         case RISCVOp::OPERAND_UIMM10_LSB00_NONZERO:
200806c3fb27SDimitry Andric           Ok = isShiftedUInt<8, 2>(Imm) && (Imm != 0);
200906c3fb27SDimitry Andric           break;
2010bdd1243dSDimitry Andric         case RISCVOp::OPERAND_ZERO:
2011bdd1243dSDimitry Andric           Ok = Imm == 0;
2012bdd1243dSDimitry Andric           break;
2013bdd1243dSDimitry Andric         case RISCVOp::OPERAND_SIMM5:
2014bdd1243dSDimitry Andric           Ok = isInt<5>(Imm);
2015bdd1243dSDimitry Andric           break;
2016bdd1243dSDimitry Andric         case RISCVOp::OPERAND_SIMM5_PLUS1:
2017bdd1243dSDimitry Andric           Ok = (isInt<5>(Imm) && Imm != -16) || Imm == 16;
2018bdd1243dSDimitry Andric           break;
2019bdd1243dSDimitry Andric         case RISCVOp::OPERAND_SIMM6:
2020bdd1243dSDimitry Andric           Ok = isInt<6>(Imm);
2021bdd1243dSDimitry Andric           break;
2022bdd1243dSDimitry Andric         case RISCVOp::OPERAND_SIMM6_NONZERO:
2023bdd1243dSDimitry Andric           Ok = Imm != 0 && isInt<6>(Imm);
2024bdd1243dSDimitry Andric           break;
2025bdd1243dSDimitry Andric         case RISCVOp::OPERAND_VTYPEI10:
2026bdd1243dSDimitry Andric           Ok = isUInt<10>(Imm);
2027bdd1243dSDimitry Andric           break;
2028bdd1243dSDimitry Andric         case RISCVOp::OPERAND_VTYPEI11:
2029bdd1243dSDimitry Andric           Ok = isUInt<11>(Imm);
2030bdd1243dSDimitry Andric           break;
20318bcb0991SDimitry Andric         case RISCVOp::OPERAND_SIMM12:
20328bcb0991SDimitry Andric           Ok = isInt<12>(Imm);
20338bcb0991SDimitry Andric           break;
203481ad6265SDimitry Andric         case RISCVOp::OPERAND_SIMM12_LSB00000:
203581ad6265SDimitry Andric           Ok = isShiftedInt<7, 5>(Imm);
20368bcb0991SDimitry Andric           break;
20378bcb0991SDimitry Andric         case RISCVOp::OPERAND_UIMMLOG2XLEN:
2038bdd1243dSDimitry Andric           Ok = STI.is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
2039bdd1243dSDimitry Andric           break;
2040bdd1243dSDimitry Andric         case RISCVOp::OPERAND_UIMMLOG2XLEN_NONZERO:
2041bdd1243dSDimitry Andric           Ok = STI.is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
2042bdd1243dSDimitry Andric           Ok = Ok && Imm != 0;
2043bdd1243dSDimitry Andric           break;
204406c3fb27SDimitry Andric         case RISCVOp::OPERAND_CLUI_IMM:
204506c3fb27SDimitry Andric           Ok = (isUInt<5>(Imm) && Imm != 0) ||
204606c3fb27SDimitry Andric                (Imm >= 0xfffe0 && Imm <= 0xfffff);
20478bcb0991SDimitry Andric           break;
204804eeddc0SDimitry Andric         case RISCVOp::OPERAND_RVKRNUM:
204904eeddc0SDimitry Andric           Ok = Imm >= 0 && Imm <= 10;
205004eeddc0SDimitry Andric           break;
205106c3fb27SDimitry Andric         case RISCVOp::OPERAND_RVKRNUM_0_7:
205206c3fb27SDimitry Andric           Ok = Imm >= 0 && Imm <= 7;
205306c3fb27SDimitry Andric           break;
205406c3fb27SDimitry Andric         case RISCVOp::OPERAND_RVKRNUM_1_10:
205506c3fb27SDimitry Andric           Ok = Imm >= 1 && Imm <= 10;
205606c3fb27SDimitry Andric           break;
205706c3fb27SDimitry Andric         case RISCVOp::OPERAND_RVKRNUM_2_14:
205806c3fb27SDimitry Andric           Ok = Imm >= 2 && Imm <= 14;
205906c3fb27SDimitry Andric           break;
20608bcb0991SDimitry Andric         }
20618bcb0991SDimitry Andric         if (!Ok) {
20628bcb0991SDimitry Andric           ErrInfo = "Invalid immediate";
20638bcb0991SDimitry Andric           return false;
20648bcb0991SDimitry Andric         }
20658bcb0991SDimitry Andric       }
20668bcb0991SDimitry Andric     }
20678bcb0991SDimitry Andric   }
20688bcb0991SDimitry Andric 
2069bdd1243dSDimitry Andric   const uint64_t TSFlags = Desc.TSFlags;
2070bdd1243dSDimitry Andric   if (RISCVII::hasVLOp(TSFlags)) {
2071bdd1243dSDimitry Andric     const MachineOperand &Op = MI.getOperand(RISCVII::getVLOpNum(Desc));
2072bdd1243dSDimitry Andric     if (!Op.isImm() && !Op.isReg())  {
2073bdd1243dSDimitry Andric       ErrInfo = "Invalid operand type for VL operand";
2074bdd1243dSDimitry Andric       return false;
2075bdd1243dSDimitry Andric     }
2076bdd1243dSDimitry Andric     if (Op.isReg() && Op.getReg() != RISCV::NoRegister) {
2077bdd1243dSDimitry Andric       const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
2078bdd1243dSDimitry Andric       auto *RC = MRI.getRegClass(Op.getReg());
2079bdd1243dSDimitry Andric       if (!RISCV::GPRRegClass.hasSubClassEq(RC)) {
2080bdd1243dSDimitry Andric         ErrInfo = "Invalid register class for VL operand";
2081bdd1243dSDimitry Andric         return false;
2082bdd1243dSDimitry Andric       }
2083bdd1243dSDimitry Andric     }
2084bdd1243dSDimitry Andric     if (!RISCVII::hasSEWOp(TSFlags)) {
2085bdd1243dSDimitry Andric       ErrInfo = "VL operand w/o SEW operand?";
2086bdd1243dSDimitry Andric       return false;
2087bdd1243dSDimitry Andric     }
2088bdd1243dSDimitry Andric   }
2089bdd1243dSDimitry Andric   if (RISCVII::hasSEWOp(TSFlags)) {
2090bdd1243dSDimitry Andric     unsigned OpIdx = RISCVII::getSEWOpNum(Desc);
209106c3fb27SDimitry Andric     if (!MI.getOperand(OpIdx).isImm()) {
209206c3fb27SDimitry Andric       ErrInfo = "SEW value expected to be an immediate";
209306c3fb27SDimitry Andric       return false;
209406c3fb27SDimitry Andric     }
2095bdd1243dSDimitry Andric     uint64_t Log2SEW = MI.getOperand(OpIdx).getImm();
2096bdd1243dSDimitry Andric     if (Log2SEW > 31) {
2097bdd1243dSDimitry Andric       ErrInfo = "Unexpected SEW value";
2098bdd1243dSDimitry Andric       return false;
2099bdd1243dSDimitry Andric     }
2100bdd1243dSDimitry Andric     unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
2101bdd1243dSDimitry Andric     if (!RISCVVType::isValidSEW(SEW)) {
2102bdd1243dSDimitry Andric       ErrInfo = "Unexpected SEW value";
2103bdd1243dSDimitry Andric       return false;
2104bdd1243dSDimitry Andric     }
2105bdd1243dSDimitry Andric   }
2106bdd1243dSDimitry Andric   if (RISCVII::hasVecPolicyOp(TSFlags)) {
2107bdd1243dSDimitry Andric     unsigned OpIdx = RISCVII::getVecPolicyOpNum(Desc);
210806c3fb27SDimitry Andric     if (!MI.getOperand(OpIdx).isImm()) {
210906c3fb27SDimitry Andric       ErrInfo = "Policy operand expected to be an immediate";
211006c3fb27SDimitry Andric       return false;
211106c3fb27SDimitry Andric     }
2112bdd1243dSDimitry Andric     uint64_t Policy = MI.getOperand(OpIdx).getImm();
2113bdd1243dSDimitry Andric     if (Policy > (RISCVII::TAIL_AGNOSTIC | RISCVII::MASK_AGNOSTIC)) {
2114bdd1243dSDimitry Andric       ErrInfo = "Invalid Policy Value";
2115bdd1243dSDimitry Andric       return false;
2116bdd1243dSDimitry Andric     }
2117bdd1243dSDimitry Andric     if (!RISCVII::hasVLOp(TSFlags)) {
2118bdd1243dSDimitry Andric       ErrInfo = "policy operand w/o VL operand?";
2119bdd1243dSDimitry Andric       return false;
2120bdd1243dSDimitry Andric     }
2121bdd1243dSDimitry Andric 
2122bdd1243dSDimitry Andric     // VecPolicy operands can only exist on instructions with passthru/merge
2123bdd1243dSDimitry Andric     // arguments. Note that not all arguments with passthru have vec policy
2124bdd1243dSDimitry Andric     // operands- some instructions have implicit policies.
2125bdd1243dSDimitry Andric     unsigned UseOpIdx;
2126bdd1243dSDimitry Andric     if (!MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
2127bdd1243dSDimitry Andric       ErrInfo = "policy operand w/o tied operand?";
2128bdd1243dSDimitry Andric       return false;
2129bdd1243dSDimitry Andric     }
2130bdd1243dSDimitry Andric   }
2131bdd1243dSDimitry Andric 
21328bcb0991SDimitry Andric   return true;
21338bcb0991SDimitry Andric }
2134480093f4SDimitry Andric 
canFoldIntoAddrMode(const MachineInstr & MemI,Register Reg,const MachineInstr & AddrI,ExtAddrMode & AM) const21355f757f3fSDimitry Andric bool RISCVInstrInfo::canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg,
21365f757f3fSDimitry Andric                                          const MachineInstr &AddrI,
21375f757f3fSDimitry Andric                                          ExtAddrMode &AM) const {
21385f757f3fSDimitry Andric   switch (MemI.getOpcode()) {
21395f757f3fSDimitry Andric   default:
21405f757f3fSDimitry Andric     return false;
21415f757f3fSDimitry Andric   case RISCV::LB:
21425f757f3fSDimitry Andric   case RISCV::LBU:
21435f757f3fSDimitry Andric   case RISCV::LH:
21445f757f3fSDimitry Andric   case RISCV::LHU:
21455f757f3fSDimitry Andric   case RISCV::LW:
21465f757f3fSDimitry Andric   case RISCV::LWU:
21475f757f3fSDimitry Andric   case RISCV::LD:
21485f757f3fSDimitry Andric   case RISCV::FLH:
21495f757f3fSDimitry Andric   case RISCV::FLW:
21505f757f3fSDimitry Andric   case RISCV::FLD:
21515f757f3fSDimitry Andric   case RISCV::SB:
21525f757f3fSDimitry Andric   case RISCV::SH:
21535f757f3fSDimitry Andric   case RISCV::SW:
21545f757f3fSDimitry Andric   case RISCV::SD:
21555f757f3fSDimitry Andric   case RISCV::FSH:
21565f757f3fSDimitry Andric   case RISCV::FSW:
21575f757f3fSDimitry Andric   case RISCV::FSD:
21585f757f3fSDimitry Andric     break;
21595f757f3fSDimitry Andric   }
21605f757f3fSDimitry Andric 
21615f757f3fSDimitry Andric   if (MemI.getOperand(0).getReg() == Reg)
21625f757f3fSDimitry Andric     return false;
21635f757f3fSDimitry Andric 
21645f757f3fSDimitry Andric   if (AddrI.getOpcode() != RISCV::ADDI || !AddrI.getOperand(1).isReg() ||
21655f757f3fSDimitry Andric       !AddrI.getOperand(2).isImm())
21665f757f3fSDimitry Andric     return false;
21675f757f3fSDimitry Andric 
21685f757f3fSDimitry Andric   int64_t OldOffset = MemI.getOperand(2).getImm();
21695f757f3fSDimitry Andric   int64_t Disp = AddrI.getOperand(2).getImm();
21705f757f3fSDimitry Andric   int64_t NewOffset = OldOffset + Disp;
21715f757f3fSDimitry Andric   if (!STI.is64Bit())
21725f757f3fSDimitry Andric     NewOffset = SignExtend64<32>(NewOffset);
21735f757f3fSDimitry Andric 
21745f757f3fSDimitry Andric   if (!isInt<12>(NewOffset))
21755f757f3fSDimitry Andric     return false;
21765f757f3fSDimitry Andric 
21775f757f3fSDimitry Andric   AM.BaseReg = AddrI.getOperand(1).getReg();
21785f757f3fSDimitry Andric   AM.ScaledReg = 0;
21795f757f3fSDimitry Andric   AM.Scale = 0;
21805f757f3fSDimitry Andric   AM.Displacement = NewOffset;
21815f757f3fSDimitry Andric   AM.Form = ExtAddrMode::Formula::Basic;
21825f757f3fSDimitry Andric   return true;
21835f757f3fSDimitry Andric }
21845f757f3fSDimitry Andric 
emitLdStWithAddr(MachineInstr & MemI,const ExtAddrMode & AM) const21855f757f3fSDimitry Andric MachineInstr *RISCVInstrInfo::emitLdStWithAddr(MachineInstr &MemI,
21865f757f3fSDimitry Andric                                                const ExtAddrMode &AM) const {
21875f757f3fSDimitry Andric 
21885f757f3fSDimitry Andric   const DebugLoc &DL = MemI.getDebugLoc();
21895f757f3fSDimitry Andric   MachineBasicBlock &MBB = *MemI.getParent();
21905f757f3fSDimitry Andric 
21915f757f3fSDimitry Andric   assert(AM.ScaledReg == 0 && AM.Scale == 0 &&
21925f757f3fSDimitry Andric          "Addressing mode not supported for folding");
21935f757f3fSDimitry Andric 
21945f757f3fSDimitry Andric   return BuildMI(MBB, MemI, DL, get(MemI.getOpcode()))
21955f757f3fSDimitry Andric       .addReg(MemI.getOperand(0).getReg(),
21965f757f3fSDimitry Andric               MemI.mayLoad() ? RegState::Define : 0)
21975f757f3fSDimitry Andric       .addReg(AM.BaseReg)
21985f757f3fSDimitry Andric       .addImm(AM.Displacement)
21995f757f3fSDimitry Andric       .setMemRefs(MemI.memoperands())
22005f757f3fSDimitry Andric       .setMIFlags(MemI.getFlags());
22015f757f3fSDimitry Andric }
22025f757f3fSDimitry Andric 
getMemOperandsWithOffsetWidth(const MachineInstr & LdSt,SmallVectorImpl<const MachineOperand * > & BaseOps,int64_t & Offset,bool & OffsetIsScalable,unsigned & Width,const TargetRegisterInfo * TRI) const22035f757f3fSDimitry Andric bool RISCVInstrInfo::getMemOperandsWithOffsetWidth(
22045f757f3fSDimitry Andric     const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps,
22055f757f3fSDimitry Andric     int64_t &Offset, bool &OffsetIsScalable, unsigned &Width,
22065f757f3fSDimitry Andric     const TargetRegisterInfo *TRI) const {
22075f757f3fSDimitry Andric   if (!LdSt.mayLoadOrStore())
22085f757f3fSDimitry Andric     return false;
22095f757f3fSDimitry Andric 
22105f757f3fSDimitry Andric   // Conservatively, only handle scalar loads/stores for now.
22115f757f3fSDimitry Andric   switch (LdSt.getOpcode()) {
22125f757f3fSDimitry Andric   case RISCV::LB:
22135f757f3fSDimitry Andric   case RISCV::LBU:
22145f757f3fSDimitry Andric   case RISCV::SB:
22155f757f3fSDimitry Andric   case RISCV::LH:
22165f757f3fSDimitry Andric   case RISCV::LHU:
22175f757f3fSDimitry Andric   case RISCV::FLH:
22185f757f3fSDimitry Andric   case RISCV::SH:
22195f757f3fSDimitry Andric   case RISCV::FSH:
22205f757f3fSDimitry Andric   case RISCV::LW:
22215f757f3fSDimitry Andric   case RISCV::LWU:
22225f757f3fSDimitry Andric   case RISCV::FLW:
22235f757f3fSDimitry Andric   case RISCV::SW:
22245f757f3fSDimitry Andric   case RISCV::FSW:
22255f757f3fSDimitry Andric   case RISCV::LD:
22265f757f3fSDimitry Andric   case RISCV::FLD:
22275f757f3fSDimitry Andric   case RISCV::SD:
22285f757f3fSDimitry Andric   case RISCV::FSD:
22295f757f3fSDimitry Andric     break;
22305f757f3fSDimitry Andric   default:
22315f757f3fSDimitry Andric     return false;
22325f757f3fSDimitry Andric   }
22335f757f3fSDimitry Andric   const MachineOperand *BaseOp;
22345f757f3fSDimitry Andric   OffsetIsScalable = false;
22355f757f3fSDimitry Andric   if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, Width, TRI))
22365f757f3fSDimitry Andric     return false;
22375f757f3fSDimitry Andric   BaseOps.push_back(BaseOp);
22385f757f3fSDimitry Andric   return true;
22395f757f3fSDimitry Andric }
22405f757f3fSDimitry Andric 
22415f757f3fSDimitry Andric // TODO: This was copied from SIInstrInfo. Could it be lifted to a common
22425f757f3fSDimitry Andric // helper?
memOpsHaveSameBasePtr(const MachineInstr & MI1,ArrayRef<const MachineOperand * > BaseOps1,const MachineInstr & MI2,ArrayRef<const MachineOperand * > BaseOps2)22435f757f3fSDimitry Andric static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
22445f757f3fSDimitry Andric                                   ArrayRef<const MachineOperand *> BaseOps1,
22455f757f3fSDimitry Andric                                   const MachineInstr &MI2,
22465f757f3fSDimitry Andric                                   ArrayRef<const MachineOperand *> BaseOps2) {
22475f757f3fSDimitry Andric   // Only examine the first "base" operand of each instruction, on the
22485f757f3fSDimitry Andric   // assumption that it represents the real base address of the memory access.
22495f757f3fSDimitry Andric   // Other operands are typically offsets or indices from this base address.
22505f757f3fSDimitry Andric   if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
22515f757f3fSDimitry Andric     return true;
22525f757f3fSDimitry Andric 
22535f757f3fSDimitry Andric   if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
22545f757f3fSDimitry Andric     return false;
22555f757f3fSDimitry Andric 
22565f757f3fSDimitry Andric   auto MO1 = *MI1.memoperands_begin();
22575f757f3fSDimitry Andric   auto MO2 = *MI2.memoperands_begin();
22585f757f3fSDimitry Andric   if (MO1->getAddrSpace() != MO2->getAddrSpace())
22595f757f3fSDimitry Andric     return false;
22605f757f3fSDimitry Andric 
22615f757f3fSDimitry Andric   auto Base1 = MO1->getValue();
22625f757f3fSDimitry Andric   auto Base2 = MO2->getValue();
22635f757f3fSDimitry Andric   if (!Base1 || !Base2)
22645f757f3fSDimitry Andric     return false;
22655f757f3fSDimitry Andric   Base1 = getUnderlyingObject(Base1);
22665f757f3fSDimitry Andric   Base2 = getUnderlyingObject(Base2);
22675f757f3fSDimitry Andric 
22685f757f3fSDimitry Andric   if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
22695f757f3fSDimitry Andric     return false;
22705f757f3fSDimitry Andric 
22715f757f3fSDimitry Andric   return Base1 == Base2;
22725f757f3fSDimitry Andric }
22735f757f3fSDimitry Andric 
shouldClusterMemOps(ArrayRef<const MachineOperand * > BaseOps1,int64_t Offset1,bool OffsetIsScalable1,ArrayRef<const MachineOperand * > BaseOps2,int64_t Offset2,bool OffsetIsScalable2,unsigned ClusterSize,unsigned NumBytes) const22745f757f3fSDimitry Andric bool RISCVInstrInfo::shouldClusterMemOps(
22755f757f3fSDimitry Andric     ArrayRef<const MachineOperand *> BaseOps1, int64_t Offset1,
22765f757f3fSDimitry Andric     bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2,
22775f757f3fSDimitry Andric     int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize,
22785f757f3fSDimitry Andric     unsigned NumBytes) const {
22795f757f3fSDimitry Andric   // If the mem ops (to be clustered) do not have the same base ptr, then they
22805f757f3fSDimitry Andric   // should not be clustered
22815f757f3fSDimitry Andric   if (!BaseOps1.empty() && !BaseOps2.empty()) {
22825f757f3fSDimitry Andric     const MachineInstr &FirstLdSt = *BaseOps1.front()->getParent();
22835f757f3fSDimitry Andric     const MachineInstr &SecondLdSt = *BaseOps2.front()->getParent();
22845f757f3fSDimitry Andric     if (!memOpsHaveSameBasePtr(FirstLdSt, BaseOps1, SecondLdSt, BaseOps2))
22855f757f3fSDimitry Andric       return false;
22865f757f3fSDimitry Andric   } else if (!BaseOps1.empty() || !BaseOps2.empty()) {
22875f757f3fSDimitry Andric     // If only one base op is empty, they do not have the same base ptr
22885f757f3fSDimitry Andric     return false;
22895f757f3fSDimitry Andric   }
22905f757f3fSDimitry Andric 
2291647cbc5dSDimitry Andric   unsigned CacheLineSize =
2292647cbc5dSDimitry Andric       BaseOps1.front()->getParent()->getMF()->getSubtarget().getCacheLineSize();
2293647cbc5dSDimitry Andric   // Assume a cache line size of 64 bytes if no size is set in RISCVSubtarget.
2294647cbc5dSDimitry Andric   CacheLineSize = CacheLineSize ? CacheLineSize : 64;
2295647cbc5dSDimitry Andric   // Cluster if the memory operations are on the same or a neighbouring cache
2296647cbc5dSDimitry Andric   // line, but limit the maximum ClusterSize to avoid creating too much
2297647cbc5dSDimitry Andric   // additional register pressure.
2298647cbc5dSDimitry Andric   return ClusterSize <= 4 && std::abs(Offset1 - Offset2) < CacheLineSize;
22995f757f3fSDimitry Andric }
23005f757f3fSDimitry Andric 
23015f757f3fSDimitry Andric // Set BaseReg (the base register operand), Offset (the byte offset being
23025f757f3fSDimitry Andric // accessed) and the access Width of the passed instruction that reads/writes
23035f757f3fSDimitry Andric // memory. Returns false if the instruction does not read/write memory or the
23045f757f3fSDimitry Andric // BaseReg/Offset/Width can't be determined. Is not guaranteed to always
23055f757f3fSDimitry Andric // recognise base operands and offsets in all cases.
23065f757f3fSDimitry Andric // TODO: Add an IsScalable bool ref argument (like the equivalent AArch64
23075f757f3fSDimitry Andric // function) and set it as appropriate.
getMemOperandWithOffsetWidth(const MachineInstr & LdSt,const MachineOperand * & BaseReg,int64_t & Offset,unsigned & Width,const TargetRegisterInfo * TRI) const2308480093f4SDimitry Andric bool RISCVInstrInfo::getMemOperandWithOffsetWidth(
2309480093f4SDimitry Andric     const MachineInstr &LdSt, const MachineOperand *&BaseReg, int64_t &Offset,
2310480093f4SDimitry Andric     unsigned &Width, const TargetRegisterInfo *TRI) const {
2311480093f4SDimitry Andric   if (!LdSt.mayLoadOrStore())
2312480093f4SDimitry Andric     return false;
2313480093f4SDimitry Andric 
2314480093f4SDimitry Andric   // Here we assume the standard RISC-V ISA, which uses a base+offset
2315480093f4SDimitry Andric   // addressing mode. You'll need to relax these conditions to support custom
23165f757f3fSDimitry Andric   // load/store instructions.
2317480093f4SDimitry Andric   if (LdSt.getNumExplicitOperands() != 3)
2318480093f4SDimitry Andric     return false;
23195f757f3fSDimitry Andric   if ((!LdSt.getOperand(1).isReg() && !LdSt.getOperand(1).isFI()) ||
23205f757f3fSDimitry Andric       !LdSt.getOperand(2).isImm())
2321480093f4SDimitry Andric     return false;
2322480093f4SDimitry Andric 
2323480093f4SDimitry Andric   if (!LdSt.hasOneMemOperand())
2324480093f4SDimitry Andric     return false;
2325480093f4SDimitry Andric 
2326480093f4SDimitry Andric   Width = (*LdSt.memoperands_begin())->getSize();
2327480093f4SDimitry Andric   BaseReg = &LdSt.getOperand(1);
2328480093f4SDimitry Andric   Offset = LdSt.getOperand(2).getImm();
2329480093f4SDimitry Andric   return true;
2330480093f4SDimitry Andric }
2331480093f4SDimitry Andric 
areMemAccessesTriviallyDisjoint(const MachineInstr & MIa,const MachineInstr & MIb) const2332480093f4SDimitry Andric bool RISCVInstrInfo::areMemAccessesTriviallyDisjoint(
2333480093f4SDimitry Andric     const MachineInstr &MIa, const MachineInstr &MIb) const {
2334480093f4SDimitry Andric   assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
2335480093f4SDimitry Andric   assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
2336480093f4SDimitry Andric 
2337480093f4SDimitry Andric   if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() ||
2338480093f4SDimitry Andric       MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
2339480093f4SDimitry Andric     return false;
2340480093f4SDimitry Andric 
2341480093f4SDimitry Andric   // Retrieve the base register, offset from the base register and width. Width
2342480093f4SDimitry Andric   // is the size of memory that is being loaded/stored (e.g. 1, 2, 4).  If
2343480093f4SDimitry Andric   // base registers are identical, and the offset of a lower memory access +
2344480093f4SDimitry Andric   // the width doesn't overlap the offset of a higher memory access,
2345480093f4SDimitry Andric   // then the memory accesses are different.
2346480093f4SDimitry Andric   const TargetRegisterInfo *TRI = STI.getRegisterInfo();
2347480093f4SDimitry Andric   const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
2348480093f4SDimitry Andric   int64_t OffsetA = 0, OffsetB = 0;
2349480093f4SDimitry Andric   unsigned int WidthA = 0, WidthB = 0;
2350480093f4SDimitry Andric   if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, WidthA, TRI) &&
2351480093f4SDimitry Andric       getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, WidthB, TRI)) {
2352480093f4SDimitry Andric     if (BaseOpA->isIdenticalTo(*BaseOpB)) {
2353480093f4SDimitry Andric       int LowOffset = std::min(OffsetA, OffsetB);
2354480093f4SDimitry Andric       int HighOffset = std::max(OffsetA, OffsetB);
2355480093f4SDimitry Andric       int LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
2356480093f4SDimitry Andric       if (LowOffset + LowWidth <= HighOffset)
2357480093f4SDimitry Andric         return true;
2358480093f4SDimitry Andric     }
2359480093f4SDimitry Andric   }
2360480093f4SDimitry Andric   return false;
2361480093f4SDimitry Andric }
2362480093f4SDimitry Andric 
2363480093f4SDimitry Andric std::pair<unsigned, unsigned>
decomposeMachineOperandsTargetFlags(unsigned TF) const2364480093f4SDimitry Andric RISCVInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
2365480093f4SDimitry Andric   const unsigned Mask = RISCVII::MO_DIRECT_FLAG_MASK;
2366480093f4SDimitry Andric   return std::make_pair(TF & Mask, TF & ~Mask);
2367480093f4SDimitry Andric }
2368480093f4SDimitry Andric 
2369480093f4SDimitry Andric ArrayRef<std::pair<unsigned, const char *>>
getSerializableDirectMachineOperandTargetFlags() const2370480093f4SDimitry Andric RISCVInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
2371480093f4SDimitry Andric   using namespace RISCVII;
2372480093f4SDimitry Andric   static const std::pair<unsigned, const char *> TargetFlags[] = {
2373480093f4SDimitry Andric       {MO_CALL, "riscv-call"},
2374480093f4SDimitry Andric       {MO_LO, "riscv-lo"},
2375480093f4SDimitry Andric       {MO_HI, "riscv-hi"},
2376480093f4SDimitry Andric       {MO_PCREL_LO, "riscv-pcrel-lo"},
2377480093f4SDimitry Andric       {MO_PCREL_HI, "riscv-pcrel-hi"},
2378480093f4SDimitry Andric       {MO_GOT_HI, "riscv-got-hi"},
2379480093f4SDimitry Andric       {MO_TPREL_LO, "riscv-tprel-lo"},
2380480093f4SDimitry Andric       {MO_TPREL_HI, "riscv-tprel-hi"},
2381480093f4SDimitry Andric       {MO_TPREL_ADD, "riscv-tprel-add"},
2382480093f4SDimitry Andric       {MO_TLS_GOT_HI, "riscv-tls-got-hi"},
23837a6dacacSDimitry Andric       {MO_TLS_GD_HI, "riscv-tls-gd-hi"},
23847a6dacacSDimitry Andric       {MO_TLSDESC_HI, "riscv-tlsdesc-hi"},
23857a6dacacSDimitry Andric       {MO_TLSDESC_LOAD_LO, "riscv-tlsdesc-load-lo"},
23867a6dacacSDimitry Andric       {MO_TLSDESC_ADD_LO, "riscv-tlsdesc-add-lo"},
23877a6dacacSDimitry Andric       {MO_TLSDESC_CALL, "riscv-tlsdesc-call"}};
2388bdd1243dSDimitry Andric   return ArrayRef(TargetFlags);
2389480093f4SDimitry Andric }
isFunctionSafeToOutlineFrom(MachineFunction & MF,bool OutlineFromLinkOnceODRs) const2390480093f4SDimitry Andric bool RISCVInstrInfo::isFunctionSafeToOutlineFrom(
2391480093f4SDimitry Andric     MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {
2392480093f4SDimitry Andric   const Function &F = MF.getFunction();
2393480093f4SDimitry Andric 
2394480093f4SDimitry Andric   // Can F be deduplicated by the linker? If it can, don't outline from it.
2395480093f4SDimitry Andric   if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())
2396480093f4SDimitry Andric     return false;
2397480093f4SDimitry Andric 
2398480093f4SDimitry Andric   // Don't outline from functions with section markings; the program could
2399480093f4SDimitry Andric   // expect that all the code is in the named section.
2400480093f4SDimitry Andric   if (F.hasSection())
2401480093f4SDimitry Andric     return false;
2402480093f4SDimitry Andric 
2403480093f4SDimitry Andric   // It's safe to outline from MF.
2404480093f4SDimitry Andric   return true;
2405480093f4SDimitry Andric }
2406480093f4SDimitry Andric 
isMBBSafeToOutlineFrom(MachineBasicBlock & MBB,unsigned & Flags) const2407480093f4SDimitry Andric bool RISCVInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
2408480093f4SDimitry Andric                                             unsigned &Flags) const {
2409480093f4SDimitry Andric   // More accurate safety checking is done in getOutliningCandidateInfo.
24100eae32dcSDimitry Andric   return TargetInstrInfo::isMBBSafeToOutlineFrom(MBB, Flags);
2411480093f4SDimitry Andric }
2412480093f4SDimitry Andric 
2413480093f4SDimitry Andric // Enum values indicating how an outlined call should be constructed.
2414480093f4SDimitry Andric enum MachineOutlinerConstructionID {
2415480093f4SDimitry Andric   MachineOutlinerDefault
2416480093f4SDimitry Andric };
2417480093f4SDimitry Andric 
shouldOutlineFromFunctionByDefault(MachineFunction & MF) const241881ad6265SDimitry Andric bool RISCVInstrInfo::shouldOutlineFromFunctionByDefault(
241981ad6265SDimitry Andric     MachineFunction &MF) const {
242081ad6265SDimitry Andric   return MF.getFunction().hasMinSize();
242181ad6265SDimitry Andric }
242281ad6265SDimitry Andric 
242306c3fb27SDimitry Andric std::optional<outliner::OutlinedFunction>
getOutliningCandidateInfo(std::vector<outliner::Candidate> & RepeatedSequenceLocs) const242406c3fb27SDimitry Andric RISCVInstrInfo::getOutliningCandidateInfo(
2425480093f4SDimitry Andric     std::vector<outliner::Candidate> &RepeatedSequenceLocs) const {
2426480093f4SDimitry Andric 
2427480093f4SDimitry Andric   // First we need to filter out candidates where the X5 register (IE t0) can't
2428480093f4SDimitry Andric   // be used to setup the function call.
2429480093f4SDimitry Andric   auto CannotInsertCall = [](outliner::Candidate &C) {
2430480093f4SDimitry Andric     const TargetRegisterInfo *TRI = C.getMF()->getSubtarget().getRegisterInfo();
243181ad6265SDimitry Andric     return !C.isAvailableAcrossAndOutOfSeq(RISCV::X5, *TRI);
2432480093f4SDimitry Andric   };
2433480093f4SDimitry Andric 
2434e8d8bef9SDimitry Andric   llvm::erase_if(RepeatedSequenceLocs, CannotInsertCall);
2435480093f4SDimitry Andric 
2436480093f4SDimitry Andric   // If the sequence doesn't have enough candidates left, then we're done.
2437480093f4SDimitry Andric   if (RepeatedSequenceLocs.size() < 2)
243806c3fb27SDimitry Andric     return std::nullopt;
2439480093f4SDimitry Andric 
2440480093f4SDimitry Andric   unsigned SequenceSize = 0;
2441480093f4SDimitry Andric 
24427a6dacacSDimitry Andric   for (auto &MI : RepeatedSequenceLocs[0])
24437a6dacacSDimitry Andric     SequenceSize += getInstSizeInBytes(MI);
2444480093f4SDimitry Andric 
2445480093f4SDimitry Andric   // call t0, function = 8 bytes.
2446480093f4SDimitry Andric   unsigned CallOverhead = 8;
2447480093f4SDimitry Andric   for (auto &C : RepeatedSequenceLocs)
2448480093f4SDimitry Andric     C.setCallInfo(MachineOutlinerDefault, CallOverhead);
2449480093f4SDimitry Andric 
2450480093f4SDimitry Andric   // jr t0 = 4 bytes, 2 bytes if compressed instructions are enabled.
2451480093f4SDimitry Andric   unsigned FrameOverhead = 4;
2452bdd1243dSDimitry Andric   if (RepeatedSequenceLocs[0]
2453bdd1243dSDimitry Andric           .getMF()
2454bdd1243dSDimitry Andric           ->getSubtarget<RISCVSubtarget>()
2455bdd1243dSDimitry Andric           .hasStdExtCOrZca())
2456480093f4SDimitry Andric     FrameOverhead = 2;
2457480093f4SDimitry Andric 
2458480093f4SDimitry Andric   return outliner::OutlinedFunction(RepeatedSequenceLocs, SequenceSize,
2459480093f4SDimitry Andric                                     FrameOverhead, MachineOutlinerDefault);
2460480093f4SDimitry Andric }
2461480093f4SDimitry Andric 
2462480093f4SDimitry Andric outliner::InstrType
getOutliningTypeImpl(MachineBasicBlock::iterator & MBBI,unsigned Flags) const246306c3fb27SDimitry Andric RISCVInstrInfo::getOutliningTypeImpl(MachineBasicBlock::iterator &MBBI,
2464480093f4SDimitry Andric                                  unsigned Flags) const {
2465480093f4SDimitry Andric   MachineInstr &MI = *MBBI;
2466480093f4SDimitry Andric   MachineBasicBlock *MBB = MI.getParent();
2467480093f4SDimitry Andric   const TargetRegisterInfo *TRI =
2468480093f4SDimitry Andric       MBB->getParent()->getSubtarget().getRegisterInfo();
2469bdd1243dSDimitry Andric   const auto &F = MI.getMF()->getFunction();
2470480093f4SDimitry Andric 
2471480093f4SDimitry Andric   // We can manually strip out CFI instructions later.
2472480093f4SDimitry Andric   if (MI.isCFIInstruction())
247381ad6265SDimitry Andric     // If current function has exception handling code, we can't outline &
247481ad6265SDimitry Andric     // strip these CFI instructions since it may break .eh_frame section
247581ad6265SDimitry Andric     // needed in unwinding.
2476bdd1243dSDimitry Andric     return F.needsUnwindTableEntry() ? outliner::InstrType::Illegal
247781ad6265SDimitry Andric                                      : outliner::InstrType::Invisible;
2478480093f4SDimitry Andric 
2479480093f4SDimitry Andric   // We need support for tail calls to outlined functions before return
2480480093f4SDimitry Andric   // statements can be allowed.
2481480093f4SDimitry Andric   if (MI.isReturn())
2482480093f4SDimitry Andric     return outliner::InstrType::Illegal;
2483480093f4SDimitry Andric 
2484480093f4SDimitry Andric   // Don't allow modifying the X5 register which we use for return addresses for
2485480093f4SDimitry Andric   // these outlined functions.
2486480093f4SDimitry Andric   if (MI.modifiesRegister(RISCV::X5, TRI) ||
2487480093f4SDimitry Andric       MI.getDesc().hasImplicitDefOfPhysReg(RISCV::X5))
2488480093f4SDimitry Andric     return outliner::InstrType::Illegal;
2489480093f4SDimitry Andric 
2490480093f4SDimitry Andric   // Make sure the operands don't reference something unsafe.
2491bdd1243dSDimitry Andric   for (const auto &MO : MI.operands()) {
2492480093f4SDimitry Andric 
2493bdd1243dSDimitry Andric     // pcrel-hi and pcrel-lo can't put in separate sections, filter that out
2494bdd1243dSDimitry Andric     // if any possible.
2495bdd1243dSDimitry Andric     if (MO.getTargetFlags() == RISCVII::MO_PCREL_LO &&
2496bdd1243dSDimitry Andric         (MI.getMF()->getTarget().getFunctionSections() || F.hasComdat() ||
2497bdd1243dSDimitry Andric          F.hasSection()))
2498bdd1243dSDimitry Andric       return outliner::InstrType::Illegal;
2499bdd1243dSDimitry Andric   }
2500bdd1243dSDimitry Andric 
2501480093f4SDimitry Andric   return outliner::InstrType::Legal;
2502480093f4SDimitry Andric }
2503480093f4SDimitry Andric 
buildOutlinedFrame(MachineBasicBlock & MBB,MachineFunction & MF,const outliner::OutlinedFunction & OF) const2504480093f4SDimitry Andric void RISCVInstrInfo::buildOutlinedFrame(
2505480093f4SDimitry Andric     MachineBasicBlock &MBB, MachineFunction &MF,
2506480093f4SDimitry Andric     const outliner::OutlinedFunction &OF) const {
2507480093f4SDimitry Andric 
2508480093f4SDimitry Andric   // Strip out any CFI instructions
2509480093f4SDimitry Andric   bool Changed = true;
2510480093f4SDimitry Andric   while (Changed) {
2511480093f4SDimitry Andric     Changed = false;
2512480093f4SDimitry Andric     auto I = MBB.begin();
2513480093f4SDimitry Andric     auto E = MBB.end();
2514480093f4SDimitry Andric     for (; I != E; ++I) {
2515480093f4SDimitry Andric       if (I->isCFIInstruction()) {
2516480093f4SDimitry Andric         I->removeFromParent();
2517480093f4SDimitry Andric         Changed = true;
2518480093f4SDimitry Andric         break;
2519480093f4SDimitry Andric       }
2520480093f4SDimitry Andric     }
2521480093f4SDimitry Andric   }
2522480093f4SDimitry Andric 
25235ffd83dbSDimitry Andric   MBB.addLiveIn(RISCV::X5);
25245ffd83dbSDimitry Andric 
2525480093f4SDimitry Andric   // Add in a return instruction to the end of the outlined frame.
2526480093f4SDimitry Andric   MBB.insert(MBB.end(), BuildMI(MF, DebugLoc(), get(RISCV::JALR))
2527480093f4SDimitry Andric       .addReg(RISCV::X0, RegState::Define)
2528480093f4SDimitry Andric       .addReg(RISCV::X5)
2529480093f4SDimitry Andric       .addImm(0));
2530480093f4SDimitry Andric }
2531480093f4SDimitry Andric 
insertOutlinedCall(Module & M,MachineBasicBlock & MBB,MachineBasicBlock::iterator & It,MachineFunction & MF,outliner::Candidate & C) const2532480093f4SDimitry Andric MachineBasicBlock::iterator RISCVInstrInfo::insertOutlinedCall(
2533480093f4SDimitry Andric     Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It,
253481ad6265SDimitry Andric     MachineFunction &MF, outliner::Candidate &C) const {
2535480093f4SDimitry Andric 
2536480093f4SDimitry Andric   // Add in a call instruction to the outlined function at the given location.
2537480093f4SDimitry Andric   It = MBB.insert(It,
2538480093f4SDimitry Andric                   BuildMI(MF, DebugLoc(), get(RISCV::PseudoCALLReg), RISCV::X5)
2539480093f4SDimitry Andric                       .addGlobalAddress(M.getNamedValue(MF.getName()), 0,
2540480093f4SDimitry Andric                                         RISCVII::MO_CALL));
2541480093f4SDimitry Andric   return It;
2542480093f4SDimitry Andric }
2543fe6060f1SDimitry Andric 
isAddImmediate(const MachineInstr & MI,Register Reg) const25445f757f3fSDimitry Andric std::optional<RegImmPair> RISCVInstrInfo::isAddImmediate(const MachineInstr &MI,
25455f757f3fSDimitry Andric                                                          Register Reg) const {
25465f757f3fSDimitry Andric   // TODO: Handle cases where Reg is a super- or sub-register of the
25475f757f3fSDimitry Andric   // destination register.
25485f757f3fSDimitry Andric   const MachineOperand &Op0 = MI.getOperand(0);
25495f757f3fSDimitry Andric   if (!Op0.isReg() || Reg != Op0.getReg())
25505f757f3fSDimitry Andric     return std::nullopt;
25515f757f3fSDimitry Andric 
25525f757f3fSDimitry Andric   // Don't consider ADDIW as a candidate because the caller may not be aware
25535f757f3fSDimitry Andric   // of its sign extension behaviour.
25545f757f3fSDimitry Andric   if (MI.getOpcode() == RISCV::ADDI && MI.getOperand(1).isReg() &&
25555f757f3fSDimitry Andric       MI.getOperand(2).isImm())
25565f757f3fSDimitry Andric     return RegImmPair{MI.getOperand(1).getReg(), MI.getOperand(2).getImm()};
25575f757f3fSDimitry Andric 
25585f757f3fSDimitry Andric   return std::nullopt;
25595f757f3fSDimitry Andric }
25605f757f3fSDimitry Andric 
256181ad6265SDimitry Andric // MIR printer helper function to annotate Operands with a comment.
createMIROperandComment(const MachineInstr & MI,const MachineOperand & Op,unsigned OpIdx,const TargetRegisterInfo * TRI) const256281ad6265SDimitry Andric std::string RISCVInstrInfo::createMIROperandComment(
256381ad6265SDimitry Andric     const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx,
256481ad6265SDimitry Andric     const TargetRegisterInfo *TRI) const {
256581ad6265SDimitry Andric   // Print a generic comment for this operand if there is one.
256681ad6265SDimitry Andric   std::string GenericComment =
256781ad6265SDimitry Andric       TargetInstrInfo::createMIROperandComment(MI, Op, OpIdx, TRI);
256881ad6265SDimitry Andric   if (!GenericComment.empty())
256981ad6265SDimitry Andric     return GenericComment;
257081ad6265SDimitry Andric 
257181ad6265SDimitry Andric   // If not, we must have an immediate operand.
257281ad6265SDimitry Andric   if (!Op.isImm())
257381ad6265SDimitry Andric     return std::string();
257481ad6265SDimitry Andric 
257581ad6265SDimitry Andric   std::string Comment;
257681ad6265SDimitry Andric   raw_string_ostream OS(Comment);
257781ad6265SDimitry Andric 
257881ad6265SDimitry Andric   uint64_t TSFlags = MI.getDesc().TSFlags;
257981ad6265SDimitry Andric 
258081ad6265SDimitry Andric   // Print the full VType operand of vsetvli/vsetivli instructions, and the SEW
258181ad6265SDimitry Andric   // operand of vector codegen pseudos.
258281ad6265SDimitry Andric   if ((MI.getOpcode() == RISCV::VSETVLI || MI.getOpcode() == RISCV::VSETIVLI ||
258381ad6265SDimitry Andric        MI.getOpcode() == RISCV::PseudoVSETVLI ||
258481ad6265SDimitry Andric        MI.getOpcode() == RISCV::PseudoVSETIVLI ||
258581ad6265SDimitry Andric        MI.getOpcode() == RISCV::PseudoVSETVLIX0) &&
258681ad6265SDimitry Andric       OpIdx == 2) {
258781ad6265SDimitry Andric     unsigned Imm = MI.getOperand(OpIdx).getImm();
258881ad6265SDimitry Andric     RISCVVType::printVType(Imm, OS);
2589bdd1243dSDimitry Andric   } else if (RISCVII::hasSEWOp(TSFlags) &&
2590bdd1243dSDimitry Andric              OpIdx == RISCVII::getSEWOpNum(MI.getDesc())) {
259181ad6265SDimitry Andric     unsigned Log2SEW = MI.getOperand(OpIdx).getImm();
259281ad6265SDimitry Andric     unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
259381ad6265SDimitry Andric     assert(RISCVVType::isValidSEW(SEW) && "Unexpected SEW");
259481ad6265SDimitry Andric     OS << "e" << SEW;
2595bdd1243dSDimitry Andric   } else if (RISCVII::hasVecPolicyOp(TSFlags) &&
2596bdd1243dSDimitry Andric              OpIdx == RISCVII::getVecPolicyOpNum(MI.getDesc())) {
2597bdd1243dSDimitry Andric     unsigned Policy = MI.getOperand(OpIdx).getImm();
2598bdd1243dSDimitry Andric     assert(Policy <= (RISCVII::TAIL_AGNOSTIC | RISCVII::MASK_AGNOSTIC) &&
2599bdd1243dSDimitry Andric            "Invalid Policy Value");
2600bdd1243dSDimitry Andric     OS << (Policy & RISCVII::TAIL_AGNOSTIC ? "ta" : "tu") << ", "
2601bdd1243dSDimitry Andric        << (Policy & RISCVII::MASK_AGNOSTIC ? "ma" : "mu");
260281ad6265SDimitry Andric   }
260381ad6265SDimitry Andric 
260481ad6265SDimitry Andric   OS.flush();
260581ad6265SDimitry Andric   return Comment;
260681ad6265SDimitry Andric }
260781ad6265SDimitry Andric 
2608fe6060f1SDimitry Andric // clang-format off
2609fe6060f1SDimitry Andric #define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL)                                \
2610349cc55cSDimitry Andric   RISCV::PseudoV##OP##_##TYPE##_##LMUL
2611fe6060f1SDimitry Andric 
261204eeddc0SDimitry Andric #define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE)                                    \
261304eeddc0SDimitry Andric   CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1):                                       \
2614fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2):                                  \
2615fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4):                                  \
2616fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8)
2617fe6060f1SDimitry Andric 
261804eeddc0SDimitry Andric #define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE)                                   \
261904eeddc0SDimitry Andric   CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2):                                      \
262004eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE)
262104eeddc0SDimitry Andric 
262204eeddc0SDimitry Andric #define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE)                                   \
262304eeddc0SDimitry Andric   CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4):                                      \
262404eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE)
262504eeddc0SDimitry Andric 
262604eeddc0SDimitry Andric #define CASE_VFMA_OPCODE_LMULS(OP, TYPE)                                       \
262704eeddc0SDimitry Andric   CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF8):                                      \
262804eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE)
262904eeddc0SDimitry Andric 
2630fe6060f1SDimitry Andric #define CASE_VFMA_SPLATS(OP)                                                   \
26315f757f3fSDimitry Andric   CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16):                                      \
26325f757f3fSDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32):                                 \
26335f757f3fSDimitry Andric   case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64)
2634fe6060f1SDimitry Andric // clang-format on
2635fe6060f1SDimitry Andric 
findCommutedOpIndices(const MachineInstr & MI,unsigned & SrcOpIdx1,unsigned & SrcOpIdx2) const2636fe6060f1SDimitry Andric bool RISCVInstrInfo::findCommutedOpIndices(const MachineInstr &MI,
2637fe6060f1SDimitry Andric                                            unsigned &SrcOpIdx1,
2638fe6060f1SDimitry Andric                                            unsigned &SrcOpIdx2) const {
2639fe6060f1SDimitry Andric   const MCInstrDesc &Desc = MI.getDesc();
2640fe6060f1SDimitry Andric   if (!Desc.isCommutable())
2641fe6060f1SDimitry Andric     return false;
2642fe6060f1SDimitry Andric 
2643fe6060f1SDimitry Andric   switch (MI.getOpcode()) {
264406c3fb27SDimitry Andric   case RISCV::TH_MVEQZ:
264506c3fb27SDimitry Andric   case RISCV::TH_MVNEZ:
264606c3fb27SDimitry Andric     // We can't commute operands if operand 2 (i.e., rs1 in
264706c3fb27SDimitry Andric     // mveqz/mvnez rd,rs1,rs2) is the zero-register (as it is
264806c3fb27SDimitry Andric     // not valid as the in/out-operand 1).
264906c3fb27SDimitry Andric     if (MI.getOperand(2).getReg() == RISCV::X0)
265006c3fb27SDimitry Andric       return false;
265106c3fb27SDimitry Andric     // Operands 1 and 2 are commutable, if we switch the opcode.
265206c3fb27SDimitry Andric     return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
265306c3fb27SDimitry Andric   case RISCV::TH_MULA:
265406c3fb27SDimitry Andric   case RISCV::TH_MULAW:
265506c3fb27SDimitry Andric   case RISCV::TH_MULAH:
265606c3fb27SDimitry Andric   case RISCV::TH_MULS:
265706c3fb27SDimitry Andric   case RISCV::TH_MULSW:
265806c3fb27SDimitry Andric   case RISCV::TH_MULSH:
265906c3fb27SDimitry Andric     // Operands 2 and 3 are commutable.
266006c3fb27SDimitry Andric     return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
26611db9f3b2SDimitry Andric   case RISCV::PseudoCCMOVGPRNoX0:
2662bdd1243dSDimitry Andric   case RISCV::PseudoCCMOVGPR:
2663bdd1243dSDimitry Andric     // Operands 4 and 5 are commutable.
2664bdd1243dSDimitry Andric     return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 4, 5);
2665fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FMADD):
2666fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FMSUB):
2667fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FMACC):
2668fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FMSAC):
2669fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FNMADD):
2670fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FNMSUB):
2671fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FNMACC):
2672fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FNMSAC):
267304eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FMACC, VV):
267404eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FMSAC, VV):
267504eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FNMACC, VV):
267604eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FNMSAC, VV):
2677fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(MADD, VX):
2678fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(NMSUB, VX):
2679fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(MACC, VX):
2680fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(NMSAC, VX):
2681fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(MACC, VV):
2682fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(NMSAC, VV): {
2683349cc55cSDimitry Andric     // If the tail policy is undisturbed we can't commute.
2684349cc55cSDimitry Andric     assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags));
2685349cc55cSDimitry Andric     if ((MI.getOperand(MI.getNumExplicitOperands() - 1).getImm() & 1) == 0)
2686349cc55cSDimitry Andric       return false;
2687349cc55cSDimitry Andric 
2688fe6060f1SDimitry Andric     // For these instructions we can only swap operand 1 and operand 3 by
2689fe6060f1SDimitry Andric     // changing the opcode.
2690fe6060f1SDimitry Andric     unsigned CommutableOpIdx1 = 1;
2691fe6060f1SDimitry Andric     unsigned CommutableOpIdx2 = 3;
2692fe6060f1SDimitry Andric     if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
2693fe6060f1SDimitry Andric                               CommutableOpIdx2))
2694fe6060f1SDimitry Andric       return false;
2695fe6060f1SDimitry Andric     return true;
2696fe6060f1SDimitry Andric   }
269704eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FMADD, VV):
269804eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FMSUB, VV):
269904eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FNMADD, VV):
270004eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FNMSUB, VV):
2701fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(MADD, VV):
2702fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(NMSUB, VV): {
2703349cc55cSDimitry Andric     // If the tail policy is undisturbed we can't commute.
2704349cc55cSDimitry Andric     assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags));
2705349cc55cSDimitry Andric     if ((MI.getOperand(MI.getNumExplicitOperands() - 1).getImm() & 1) == 0)
2706349cc55cSDimitry Andric       return false;
2707349cc55cSDimitry Andric 
2708fe6060f1SDimitry Andric     // For these instructions we have more freedom. We can commute with the
2709fe6060f1SDimitry Andric     // other multiplicand or with the addend/subtrahend/minuend.
2710fe6060f1SDimitry Andric 
2711fe6060f1SDimitry Andric     // Any fixed operand must be from source 1, 2 or 3.
2712fe6060f1SDimitry Andric     if (SrcOpIdx1 != CommuteAnyOperandIndex && SrcOpIdx1 > 3)
2713fe6060f1SDimitry Andric       return false;
2714fe6060f1SDimitry Andric     if (SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx2 > 3)
2715fe6060f1SDimitry Andric       return false;
2716fe6060f1SDimitry Andric 
2717fe6060f1SDimitry Andric     // It both ops are fixed one must be the tied source.
2718fe6060f1SDimitry Andric     if (SrcOpIdx1 != CommuteAnyOperandIndex &&
2719fe6060f1SDimitry Andric         SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx1 != 1 && SrcOpIdx2 != 1)
2720fe6060f1SDimitry Andric       return false;
2721fe6060f1SDimitry Andric 
2722fe6060f1SDimitry Andric     // Look for two different register operands assumed to be commutable
2723fe6060f1SDimitry Andric     // regardless of the FMA opcode. The FMA opcode is adjusted later if
2724fe6060f1SDimitry Andric     // needed.
2725fe6060f1SDimitry Andric     if (SrcOpIdx1 == CommuteAnyOperandIndex ||
2726fe6060f1SDimitry Andric         SrcOpIdx2 == CommuteAnyOperandIndex) {
2727fe6060f1SDimitry Andric       // At least one of operands to be commuted is not specified and
2728fe6060f1SDimitry Andric       // this method is free to choose appropriate commutable operands.
2729fe6060f1SDimitry Andric       unsigned CommutableOpIdx1 = SrcOpIdx1;
2730fe6060f1SDimitry Andric       if (SrcOpIdx1 == SrcOpIdx2) {
2731fe6060f1SDimitry Andric         // Both of operands are not fixed. Set one of commutable
2732fe6060f1SDimitry Andric         // operands to the tied source.
2733fe6060f1SDimitry Andric         CommutableOpIdx1 = 1;
273469ade1e0SDimitry Andric       } else if (SrcOpIdx1 == CommuteAnyOperandIndex) {
2735fe6060f1SDimitry Andric         // Only one of the operands is not fixed.
2736fe6060f1SDimitry Andric         CommutableOpIdx1 = SrcOpIdx2;
2737fe6060f1SDimitry Andric       }
2738fe6060f1SDimitry Andric 
2739fe6060f1SDimitry Andric       // CommutableOpIdx1 is well defined now. Let's choose another commutable
2740fe6060f1SDimitry Andric       // operand and assign its index to CommutableOpIdx2.
2741fe6060f1SDimitry Andric       unsigned CommutableOpIdx2;
2742fe6060f1SDimitry Andric       if (CommutableOpIdx1 != 1) {
2743fe6060f1SDimitry Andric         // If we haven't already used the tied source, we must use it now.
2744fe6060f1SDimitry Andric         CommutableOpIdx2 = 1;
2745fe6060f1SDimitry Andric       } else {
2746fe6060f1SDimitry Andric         Register Op1Reg = MI.getOperand(CommutableOpIdx1).getReg();
2747fe6060f1SDimitry Andric 
2748fe6060f1SDimitry Andric         // The commuted operands should have different registers.
2749fe6060f1SDimitry Andric         // Otherwise, the commute transformation does not change anything and
2750fe6060f1SDimitry Andric         // is useless. We use this as a hint to make our decision.
2751fe6060f1SDimitry Andric         if (Op1Reg != MI.getOperand(2).getReg())
2752fe6060f1SDimitry Andric           CommutableOpIdx2 = 2;
2753fe6060f1SDimitry Andric         else
2754fe6060f1SDimitry Andric           CommutableOpIdx2 = 3;
2755fe6060f1SDimitry Andric       }
2756fe6060f1SDimitry Andric 
2757fe6060f1SDimitry Andric       // Assign the found pair of commutable indices to SrcOpIdx1 and
2758fe6060f1SDimitry Andric       // SrcOpIdx2 to return those values.
2759fe6060f1SDimitry Andric       if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
2760fe6060f1SDimitry Andric                                 CommutableOpIdx2))
2761fe6060f1SDimitry Andric         return false;
2762fe6060f1SDimitry Andric     }
2763fe6060f1SDimitry Andric 
2764fe6060f1SDimitry Andric     return true;
2765fe6060f1SDimitry Andric   }
2766fe6060f1SDimitry Andric   }
2767fe6060f1SDimitry Andric 
2768fe6060f1SDimitry Andric   return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2);
2769fe6060f1SDimitry Andric }
2770fe6060f1SDimitry Andric 
2771fe6060f1SDimitry Andric #define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL)               \
2772349cc55cSDimitry Andric   case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL:                                \
2773349cc55cSDimitry Andric     Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL;                             \
2774fe6060f1SDimitry Andric     break;
2775fe6060f1SDimitry Andric 
277604eeddc0SDimitry Andric #define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE)                   \
2777fe6060f1SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1)                       \
2778fe6060f1SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2)                       \
2779fe6060f1SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4)                       \
2780fe6060f1SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8)
2781fe6060f1SDimitry Andric 
278204eeddc0SDimitry Andric #define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE)                  \
278304eeddc0SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2)                      \
278404eeddc0SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE)
278504eeddc0SDimitry Andric 
278604eeddc0SDimitry Andric #define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE)                  \
278704eeddc0SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4)                      \
278804eeddc0SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE)
278904eeddc0SDimitry Andric 
279004eeddc0SDimitry Andric #define CASE_VFMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE)                      \
279104eeddc0SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8)                      \
279204eeddc0SDimitry Andric   CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE)
279304eeddc0SDimitry Andric 
2794fe6060f1SDimitry Andric #define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP)                           \
27955f757f3fSDimitry Andric   CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16)                      \
27965f757f3fSDimitry Andric   CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32)                      \
27975f757f3fSDimitry Andric   CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64)
2798fe6060f1SDimitry Andric 
commuteInstructionImpl(MachineInstr & MI,bool NewMI,unsigned OpIdx1,unsigned OpIdx2) const2799fe6060f1SDimitry Andric MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI,
2800fe6060f1SDimitry Andric                                                      bool NewMI,
2801fe6060f1SDimitry Andric                                                      unsigned OpIdx1,
2802fe6060f1SDimitry Andric                                                      unsigned OpIdx2) const {
2803fe6060f1SDimitry Andric   auto cloneIfNew = [NewMI](MachineInstr &MI) -> MachineInstr & {
2804fe6060f1SDimitry Andric     if (NewMI)
2805fe6060f1SDimitry Andric       return *MI.getParent()->getParent()->CloneMachineInstr(&MI);
2806fe6060f1SDimitry Andric     return MI;
2807fe6060f1SDimitry Andric   };
2808fe6060f1SDimitry Andric 
2809fe6060f1SDimitry Andric   switch (MI.getOpcode()) {
281006c3fb27SDimitry Andric   case RISCV::TH_MVEQZ:
281106c3fb27SDimitry Andric   case RISCV::TH_MVNEZ: {
281206c3fb27SDimitry Andric     auto &WorkingMI = cloneIfNew(MI);
281306c3fb27SDimitry Andric     WorkingMI.setDesc(get(MI.getOpcode() == RISCV::TH_MVEQZ ? RISCV::TH_MVNEZ
281406c3fb27SDimitry Andric                                                             : RISCV::TH_MVEQZ));
281506c3fb27SDimitry Andric     return TargetInstrInfo::commuteInstructionImpl(WorkingMI, false, OpIdx1,
281606c3fb27SDimitry Andric                                                    OpIdx2);
281706c3fb27SDimitry Andric   }
28181db9f3b2SDimitry Andric   case RISCV::PseudoCCMOVGPRNoX0:
2819bdd1243dSDimitry Andric   case RISCV::PseudoCCMOVGPR: {
2820bdd1243dSDimitry Andric     // CCMOV can be commuted by inverting the condition.
2821bdd1243dSDimitry Andric     auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
2822bdd1243dSDimitry Andric     CC = RISCVCC::getOppositeBranchCondition(CC);
2823bdd1243dSDimitry Andric     auto &WorkingMI = cloneIfNew(MI);
2824bdd1243dSDimitry Andric     WorkingMI.getOperand(3).setImm(CC);
2825bdd1243dSDimitry Andric     return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI*/ false,
2826bdd1243dSDimitry Andric                                                    OpIdx1, OpIdx2);
2827bdd1243dSDimitry Andric   }
2828fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FMACC):
2829fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FMADD):
2830fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FMSAC):
2831fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FMSUB):
2832fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FNMACC):
2833fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FNMADD):
2834fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FNMSAC):
2835fe6060f1SDimitry Andric   case CASE_VFMA_SPLATS(FNMSUB):
283604eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FMACC, VV):
283704eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FMSAC, VV):
283804eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FNMACC, VV):
283904eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FNMSAC, VV):
2840fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(MADD, VX):
2841fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(NMSUB, VX):
2842fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(MACC, VX):
2843fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(NMSAC, VX):
2844fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(MACC, VV):
2845fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(NMSAC, VV): {
2846fe6060f1SDimitry Andric     // It only make sense to toggle these between clobbering the
2847fe6060f1SDimitry Andric     // addend/subtrahend/minuend one of the multiplicands.
2848fe6060f1SDimitry Andric     assert((OpIdx1 == 1 || OpIdx2 == 1) && "Unexpected opcode index");
2849fe6060f1SDimitry Andric     assert((OpIdx1 == 3 || OpIdx2 == 3) && "Unexpected opcode index");
2850fe6060f1SDimitry Andric     unsigned Opc;
2851fe6060f1SDimitry Andric     switch (MI.getOpcode()) {
2852fe6060f1SDimitry Andric       default:
2853fe6060f1SDimitry Andric         llvm_unreachable("Unexpected opcode");
2854fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_SPLATS(FMACC, FMADD)
2855fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_SPLATS(FMADD, FMACC)
2856fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_SPLATS(FMSAC, FMSUB)
2857fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_SPLATS(FMSUB, FMSAC)
2858fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMACC, FNMADD)
2859fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMADD, FNMACC)
2860fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMSAC, FNMSUB)
2861fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMSUB, FNMSAC)
286204eeddc0SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMACC, FMADD, VV)
286304eeddc0SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMSAC, FMSUB, VV)
286404eeddc0SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMACC, FNMADD, VV)
286504eeddc0SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMSAC, FNMSUB, VV)
2866fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS(MACC, MADD, VX)
2867fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS(MADD, MACC, VX)
2868fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS(NMSAC, NMSUB, VX)
2869fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS(NMSUB, NMSAC, VX)
2870fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS(MACC, MADD, VV)
2871fe6060f1SDimitry Andric       CASE_VFMA_CHANGE_OPCODE_LMULS(NMSAC, NMSUB, VV)
2872fe6060f1SDimitry Andric     }
2873fe6060f1SDimitry Andric 
2874fe6060f1SDimitry Andric     auto &WorkingMI = cloneIfNew(MI);
2875fe6060f1SDimitry Andric     WorkingMI.setDesc(get(Opc));
2876fe6060f1SDimitry Andric     return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false,
2877fe6060f1SDimitry Andric                                                    OpIdx1, OpIdx2);
2878fe6060f1SDimitry Andric   }
287904eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FMADD, VV):
288004eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FMSUB, VV):
288104eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FNMADD, VV):
288204eeddc0SDimitry Andric   case CASE_VFMA_OPCODE_LMULS_MF4(FNMSUB, VV):
2883fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(MADD, VV):
2884fe6060f1SDimitry Andric   case CASE_VFMA_OPCODE_LMULS(NMSUB, VV): {
2885fe6060f1SDimitry Andric     assert((OpIdx1 == 1 || OpIdx2 == 1) && "Unexpected opcode index");
2886fe6060f1SDimitry Andric     // If one of the operands, is the addend we need to change opcode.
2887fe6060f1SDimitry Andric     // Otherwise we're just swapping 2 of the multiplicands.
2888fe6060f1SDimitry Andric     if (OpIdx1 == 3 || OpIdx2 == 3) {
2889fe6060f1SDimitry Andric       unsigned Opc;
2890fe6060f1SDimitry Andric       switch (MI.getOpcode()) {
2891fe6060f1SDimitry Andric         default:
2892fe6060f1SDimitry Andric           llvm_unreachable("Unexpected opcode");
289304eeddc0SDimitry Andric         CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMADD, FMACC, VV)
289404eeddc0SDimitry Andric         CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMSUB, FMSAC, VV)
289504eeddc0SDimitry Andric         CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMADD, FNMACC, VV)
289604eeddc0SDimitry Andric         CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMSUB, FNMSAC, VV)
2897fe6060f1SDimitry Andric         CASE_VFMA_CHANGE_OPCODE_LMULS(MADD, MACC, VV)
2898fe6060f1SDimitry Andric         CASE_VFMA_CHANGE_OPCODE_LMULS(NMSUB, NMSAC, VV)
2899fe6060f1SDimitry Andric       }
2900fe6060f1SDimitry Andric 
2901fe6060f1SDimitry Andric       auto &WorkingMI = cloneIfNew(MI);
2902fe6060f1SDimitry Andric       WorkingMI.setDesc(get(Opc));
2903fe6060f1SDimitry Andric       return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false,
2904fe6060f1SDimitry Andric                                                      OpIdx1, OpIdx2);
2905fe6060f1SDimitry Andric     }
2906fe6060f1SDimitry Andric     // Let the default code handle it.
2907fe6060f1SDimitry Andric     break;
2908fe6060f1SDimitry Andric   }
2909fe6060f1SDimitry Andric   }
2910fe6060f1SDimitry Andric 
2911fe6060f1SDimitry Andric   return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
2912fe6060f1SDimitry Andric }
2913fe6060f1SDimitry Andric 
2914fe6060f1SDimitry Andric #undef CASE_VFMA_CHANGE_OPCODE_SPLATS
2915fe6060f1SDimitry Andric #undef CASE_VFMA_CHANGE_OPCODE_LMULS
2916fe6060f1SDimitry Andric #undef CASE_VFMA_CHANGE_OPCODE_COMMON
2917fe6060f1SDimitry Andric #undef CASE_VFMA_SPLATS
2918fe6060f1SDimitry Andric #undef CASE_VFMA_OPCODE_LMULS
2919fe6060f1SDimitry Andric #undef CASE_VFMA_OPCODE_COMMON
2920fe6060f1SDimitry Andric 
2921fe6060f1SDimitry Andric // clang-format off
2922fe6060f1SDimitry Andric #define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL)                                    \
2923fe6060f1SDimitry Andric   RISCV::PseudoV##OP##_##LMUL##_TIED
2924fe6060f1SDimitry Andric 
292504eeddc0SDimitry Andric #define CASE_WIDEOP_OPCODE_LMULS_MF4(OP)                                       \
292604eeddc0SDimitry Andric   CASE_WIDEOP_OPCODE_COMMON(OP, MF4):                                          \
2927fe6060f1SDimitry Andric   case CASE_WIDEOP_OPCODE_COMMON(OP, MF2):                                     \
2928fe6060f1SDimitry Andric   case CASE_WIDEOP_OPCODE_COMMON(OP, M1):                                      \
2929fe6060f1SDimitry Andric   case CASE_WIDEOP_OPCODE_COMMON(OP, M2):                                      \
2930fe6060f1SDimitry Andric   case CASE_WIDEOP_OPCODE_COMMON(OP, M4)
293104eeddc0SDimitry Andric 
293204eeddc0SDimitry Andric #define CASE_WIDEOP_OPCODE_LMULS(OP)                                           \
293304eeddc0SDimitry Andric   CASE_WIDEOP_OPCODE_COMMON(OP, MF8):                                          \
293404eeddc0SDimitry Andric   case CASE_WIDEOP_OPCODE_LMULS_MF4(OP)
2935fe6060f1SDimitry Andric // clang-format on
2936fe6060f1SDimitry Andric 
2937fe6060f1SDimitry Andric #define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL)                             \
2938fe6060f1SDimitry Andric   case RISCV::PseudoV##OP##_##LMUL##_TIED:                                     \
2939fe6060f1SDimitry Andric     NewOpc = RISCV::PseudoV##OP##_##LMUL;                                      \
2940fe6060f1SDimitry Andric     break;
2941fe6060f1SDimitry Andric 
294204eeddc0SDimitry Andric #define CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP)                                 \
2943fe6060f1SDimitry Andric   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4)                                    \
2944fe6060f1SDimitry Andric   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2)                                    \
2945fe6060f1SDimitry Andric   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1)                                     \
2946fe6060f1SDimitry Andric   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2)                                     \
2947fe6060f1SDimitry Andric   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4)
2948fe6060f1SDimitry Andric 
294904eeddc0SDimitry Andric #define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP)                                    \
295004eeddc0SDimitry Andric   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8)                                    \
295104eeddc0SDimitry Andric   CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP)
295204eeddc0SDimitry Andric 
convertToThreeAddress(MachineInstr & MI,LiveVariables * LV,LiveIntervals * LIS) const2953349cc55cSDimitry Andric MachineInstr *RISCVInstrInfo::convertToThreeAddress(MachineInstr &MI,
2954349cc55cSDimitry Andric                                                     LiveVariables *LV,
2955349cc55cSDimitry Andric                                                     LiveIntervals *LIS) const {
295606c3fb27SDimitry Andric   MachineInstrBuilder MIB;
2957fe6060f1SDimitry Andric   switch (MI.getOpcode()) {
2958fe6060f1SDimitry Andric   default:
295906c3fb27SDimitry Andric     return nullptr;
296004eeddc0SDimitry Andric   case CASE_WIDEOP_OPCODE_LMULS_MF4(FWADD_WV):
296106c3fb27SDimitry Andric   case CASE_WIDEOP_OPCODE_LMULS_MF4(FWSUB_WV): {
296206c3fb27SDimitry Andric     assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags) &&
296306c3fb27SDimitry Andric            MI.getNumExplicitOperands() == 7 &&
296406c3fb27SDimitry Andric            "Expect 7 explicit operands rd, rs2, rs1, rm, vl, sew, policy");
296506c3fb27SDimitry Andric     // If the tail policy is undisturbed we can't convert.
296606c3fb27SDimitry Andric     if ((MI.getOperand(RISCVII::getVecPolicyOpNum(MI.getDesc())).getImm() &
296706c3fb27SDimitry Andric          1) == 0)
296806c3fb27SDimitry Andric       return nullptr;
296906c3fb27SDimitry Andric     // clang-format off
297006c3fb27SDimitry Andric     unsigned NewOpc;
297106c3fb27SDimitry Andric     switch (MI.getOpcode()) {
297206c3fb27SDimitry Andric     default:
297306c3fb27SDimitry Andric       llvm_unreachable("Unexpected opcode");
297406c3fb27SDimitry Andric     CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(FWADD_WV)
297506c3fb27SDimitry Andric     CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(FWSUB_WV)
297606c3fb27SDimitry Andric     }
297706c3fb27SDimitry Andric     // clang-format on
297806c3fb27SDimitry Andric 
297906c3fb27SDimitry Andric     MachineBasicBlock &MBB = *MI.getParent();
298006c3fb27SDimitry Andric     MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
298106c3fb27SDimitry Andric               .add(MI.getOperand(0))
298206c3fb27SDimitry Andric               .addReg(MI.getOperand(0).getReg(), RegState::Undef)
298306c3fb27SDimitry Andric               .add(MI.getOperand(1))
298406c3fb27SDimitry Andric               .add(MI.getOperand(2))
298506c3fb27SDimitry Andric               .add(MI.getOperand(3))
298606c3fb27SDimitry Andric               .add(MI.getOperand(4))
298706c3fb27SDimitry Andric               .add(MI.getOperand(5))
298806c3fb27SDimitry Andric               .add(MI.getOperand(6));
298906c3fb27SDimitry Andric     break;
299006c3fb27SDimitry Andric   }
2991fe6060f1SDimitry Andric   case CASE_WIDEOP_OPCODE_LMULS(WADD_WV):
2992fe6060f1SDimitry Andric   case CASE_WIDEOP_OPCODE_LMULS(WADDU_WV):
2993fe6060f1SDimitry Andric   case CASE_WIDEOP_OPCODE_LMULS(WSUB_WV):
2994fe6060f1SDimitry Andric   case CASE_WIDEOP_OPCODE_LMULS(WSUBU_WV): {
299581ad6265SDimitry Andric     // If the tail policy is undisturbed we can't convert.
299681ad6265SDimitry Andric     assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags) &&
299781ad6265SDimitry Andric            MI.getNumExplicitOperands() == 6);
299881ad6265SDimitry Andric     if ((MI.getOperand(5).getImm() & 1) == 0)
299981ad6265SDimitry Andric       return nullptr;
300081ad6265SDimitry Andric 
3001fe6060f1SDimitry Andric     // clang-format off
3002fe6060f1SDimitry Andric     unsigned NewOpc;
3003fe6060f1SDimitry Andric     switch (MI.getOpcode()) {
3004fe6060f1SDimitry Andric     default:
3005fe6060f1SDimitry Andric       llvm_unreachable("Unexpected opcode");
3006fe6060f1SDimitry Andric     CASE_WIDEOP_CHANGE_OPCODE_LMULS(WADD_WV)
3007fe6060f1SDimitry Andric     CASE_WIDEOP_CHANGE_OPCODE_LMULS(WADDU_WV)
3008fe6060f1SDimitry Andric     CASE_WIDEOP_CHANGE_OPCODE_LMULS(WSUB_WV)
3009fe6060f1SDimitry Andric     CASE_WIDEOP_CHANGE_OPCODE_LMULS(WSUBU_WV)
3010fe6060f1SDimitry Andric     }
3011fe6060f1SDimitry Andric     // clang-format on
3012fe6060f1SDimitry Andric 
3013349cc55cSDimitry Andric     MachineBasicBlock &MBB = *MI.getParent();
301406c3fb27SDimitry Andric     MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
3015fe6060f1SDimitry Andric               .add(MI.getOperand(0))
301606c3fb27SDimitry Andric               .addReg(MI.getOperand(0).getReg(), RegState::Undef)
3017fe6060f1SDimitry Andric               .add(MI.getOperand(1))
3018fe6060f1SDimitry Andric               .add(MI.getOperand(2))
3019fe6060f1SDimitry Andric               .add(MI.getOperand(3))
302006c3fb27SDimitry Andric               .add(MI.getOperand(4))
302106c3fb27SDimitry Andric               .add(MI.getOperand(5));
30225f757f3fSDimitry Andric     break;
302306c3fb27SDimitry Andric   }
302406c3fb27SDimitry Andric   }
3025fe6060f1SDimitry Andric   MIB.copyImplicitOps(MI);
3026fe6060f1SDimitry Andric 
3027fe6060f1SDimitry Andric   if (LV) {
3028fe6060f1SDimitry Andric     unsigned NumOps = MI.getNumOperands();
3029fe6060f1SDimitry Andric     for (unsigned I = 1; I < NumOps; ++I) {
3030fe6060f1SDimitry Andric       MachineOperand &Op = MI.getOperand(I);
3031fe6060f1SDimitry Andric       if (Op.isReg() && Op.isKill())
3032fe6060f1SDimitry Andric         LV->replaceKillInstruction(Op.getReg(), MI, *MIB);
3033fe6060f1SDimitry Andric     }
3034fe6060f1SDimitry Andric   }
3035fe6060f1SDimitry Andric 
3036349cc55cSDimitry Andric   if (LIS) {
3037349cc55cSDimitry Andric     SlotIndex Idx = LIS->ReplaceMachineInstrInMaps(MI, *MIB);
3038349cc55cSDimitry Andric 
3039349cc55cSDimitry Andric     if (MI.getOperand(0).isEarlyClobber()) {
3040349cc55cSDimitry Andric       // Use operand 1 was tied to early-clobber def operand 0, so its live
3041349cc55cSDimitry Andric       // interval could have ended at an early-clobber slot. Now they are not
3042349cc55cSDimitry Andric       // tied we need to update it to the normal register slot.
3043349cc55cSDimitry Andric       LiveInterval &LI = LIS->getInterval(MI.getOperand(1).getReg());
3044349cc55cSDimitry Andric       LiveRange::Segment *S = LI.getSegmentContaining(Idx);
3045349cc55cSDimitry Andric       if (S->end == Idx.getRegSlot(true))
3046349cc55cSDimitry Andric         S->end = Idx.getRegSlot();
3047349cc55cSDimitry Andric     }
3048349cc55cSDimitry Andric   }
3049349cc55cSDimitry Andric 
3050fe6060f1SDimitry Andric   return MIB;
3051fe6060f1SDimitry Andric }
3052fe6060f1SDimitry Andric 
3053fe6060f1SDimitry Andric #undef CASE_WIDEOP_CHANGE_OPCODE_LMULS
3054fe6060f1SDimitry Andric #undef CASE_WIDEOP_CHANGE_OPCODE_COMMON
3055fe6060f1SDimitry Andric #undef CASE_WIDEOP_OPCODE_LMULS
3056fe6060f1SDimitry Andric #undef CASE_WIDEOP_OPCODE_COMMON
3057fe6060f1SDimitry Andric 
getVLENFactoredAmount(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator II,const DebugLoc & DL,Register DestReg,int64_t Amount,MachineInstr::MIFlag Flag) const3058bdd1243dSDimitry Andric void RISCVInstrInfo::getVLENFactoredAmount(MachineFunction &MF,
3059fe6060f1SDimitry Andric                                            MachineBasicBlock &MBB,
3060fe6060f1SDimitry Andric                                            MachineBasicBlock::iterator II,
3061bdd1243dSDimitry Andric                                            const DebugLoc &DL, Register DestReg,
3062fe6060f1SDimitry Andric                                            int64_t Amount,
3063fe6060f1SDimitry Andric                                            MachineInstr::MIFlag Flag) const {
3064fe6060f1SDimitry Andric   assert(Amount > 0 && "There is no need to get VLEN scaled value.");
3065fe6060f1SDimitry Andric   assert(Amount % 8 == 0 &&
3066fe6060f1SDimitry Andric          "Reserve the stack by the multiple of one vector size.");
3067fe6060f1SDimitry Andric 
3068fe6060f1SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
3069fe6060f1SDimitry Andric   int64_t NumOfVReg = Amount / 8;
3070fe6060f1SDimitry Andric 
3071bdd1243dSDimitry Andric   BuildMI(MBB, II, DL, get(RISCV::PseudoReadVLENB), DestReg).setMIFlag(Flag);
3072fe6060f1SDimitry Andric   assert(isInt<32>(NumOfVReg) &&
3073fe6060f1SDimitry Andric          "Expect the number of vector registers within 32-bits.");
307406c3fb27SDimitry Andric   if (llvm::has_single_bit<uint32_t>(NumOfVReg)) {
3075fe6060f1SDimitry Andric     uint32_t ShiftAmount = Log2_32(NumOfVReg);
3076fe6060f1SDimitry Andric     if (ShiftAmount == 0)
3077bdd1243dSDimitry Andric       return;
3078bdd1243dSDimitry Andric     BuildMI(MBB, II, DL, get(RISCV::SLLI), DestReg)
3079bdd1243dSDimitry Andric         .addReg(DestReg, RegState::Kill)
3080fe6060f1SDimitry Andric         .addImm(ShiftAmount)
3081fe6060f1SDimitry Andric         .setMIFlag(Flag);
3082fcaf7f86SDimitry Andric   } else if (STI.hasStdExtZba() &&
3083fcaf7f86SDimitry Andric              ((NumOfVReg % 3 == 0 && isPowerOf2_64(NumOfVReg / 3)) ||
3084fcaf7f86SDimitry Andric               (NumOfVReg % 5 == 0 && isPowerOf2_64(NumOfVReg / 5)) ||
3085fcaf7f86SDimitry Andric               (NumOfVReg % 9 == 0 && isPowerOf2_64(NumOfVReg / 9)))) {
3086fcaf7f86SDimitry Andric     // We can use Zba SHXADD+SLLI instructions for multiply in some cases.
308781ad6265SDimitry Andric     unsigned Opc;
3088fcaf7f86SDimitry Andric     uint32_t ShiftAmount;
3089fcaf7f86SDimitry Andric     if (NumOfVReg % 9 == 0) {
3090fcaf7f86SDimitry Andric       Opc = RISCV::SH3ADD;
3091fcaf7f86SDimitry Andric       ShiftAmount = Log2_64(NumOfVReg / 9);
3092fcaf7f86SDimitry Andric     } else if (NumOfVReg % 5 == 0) {
3093fcaf7f86SDimitry Andric       Opc = RISCV::SH2ADD;
3094fcaf7f86SDimitry Andric       ShiftAmount = Log2_64(NumOfVReg / 5);
3095fcaf7f86SDimitry Andric     } else if (NumOfVReg % 3 == 0) {
3096fcaf7f86SDimitry Andric       Opc = RISCV::SH1ADD;
3097fcaf7f86SDimitry Andric       ShiftAmount = Log2_64(NumOfVReg / 3);
3098fcaf7f86SDimitry Andric     } else {
3099fcaf7f86SDimitry Andric       llvm_unreachable("Unexpected number of vregs");
310081ad6265SDimitry Andric     }
3101fcaf7f86SDimitry Andric     if (ShiftAmount)
3102bdd1243dSDimitry Andric       BuildMI(MBB, II, DL, get(RISCV::SLLI), DestReg)
3103bdd1243dSDimitry Andric           .addReg(DestReg, RegState::Kill)
3104fcaf7f86SDimitry Andric           .addImm(ShiftAmount)
3105fcaf7f86SDimitry Andric           .setMIFlag(Flag);
3106bdd1243dSDimitry Andric     BuildMI(MBB, II, DL, get(Opc), DestReg)
3107bdd1243dSDimitry Andric         .addReg(DestReg, RegState::Kill)
3108bdd1243dSDimitry Andric         .addReg(DestReg)
310981ad6265SDimitry Andric         .setMIFlag(Flag);
311006c3fb27SDimitry Andric   } else if (llvm::has_single_bit<uint32_t>(NumOfVReg - 1)) {
3111fe6060f1SDimitry Andric     Register ScaledRegister = MRI.createVirtualRegister(&RISCV::GPRRegClass);
3112fe6060f1SDimitry Andric     uint32_t ShiftAmount = Log2_32(NumOfVReg - 1);
311381ad6265SDimitry Andric     BuildMI(MBB, II, DL, get(RISCV::SLLI), ScaledRegister)
3114bdd1243dSDimitry Andric         .addReg(DestReg)
3115fe6060f1SDimitry Andric         .addImm(ShiftAmount)
3116fe6060f1SDimitry Andric         .setMIFlag(Flag);
3117bdd1243dSDimitry Andric     BuildMI(MBB, II, DL, get(RISCV::ADD), DestReg)
3118fe6060f1SDimitry Andric         .addReg(ScaledRegister, RegState::Kill)
3119bdd1243dSDimitry Andric         .addReg(DestReg, RegState::Kill)
3120fe6060f1SDimitry Andric         .setMIFlag(Flag);
312106c3fb27SDimitry Andric   } else if (llvm::has_single_bit<uint32_t>(NumOfVReg + 1)) {
3122fe6060f1SDimitry Andric     Register ScaledRegister = MRI.createVirtualRegister(&RISCV::GPRRegClass);
3123fe6060f1SDimitry Andric     uint32_t ShiftAmount = Log2_32(NumOfVReg + 1);
312481ad6265SDimitry Andric     BuildMI(MBB, II, DL, get(RISCV::SLLI), ScaledRegister)
3125bdd1243dSDimitry Andric         .addReg(DestReg)
3126fe6060f1SDimitry Andric         .addImm(ShiftAmount)
3127fe6060f1SDimitry Andric         .setMIFlag(Flag);
3128bdd1243dSDimitry Andric     BuildMI(MBB, II, DL, get(RISCV::SUB), DestReg)
3129fe6060f1SDimitry Andric         .addReg(ScaledRegister, RegState::Kill)
3130bdd1243dSDimitry Andric         .addReg(DestReg, RegState::Kill)
3131fe6060f1SDimitry Andric         .setMIFlag(Flag);
31327a6dacacSDimitry Andric   } else if (STI.hasStdExtM() || STI.hasStdExtZmmul()) {
3133fe6060f1SDimitry Andric     Register N = MRI.createVirtualRegister(&RISCV::GPRRegClass);
313481ad6265SDimitry Andric     movImm(MBB, II, DL, N, NumOfVReg, Flag);
3135bdd1243dSDimitry Andric     BuildMI(MBB, II, DL, get(RISCV::MUL), DestReg)
3136bdd1243dSDimitry Andric         .addReg(DestReg, RegState::Kill)
3137fe6060f1SDimitry Andric         .addReg(N, RegState::Kill)
3138fe6060f1SDimitry Andric         .setMIFlag(Flag);
31397a6dacacSDimitry Andric   } else {
31407a6dacacSDimitry Andric     Register Acc = MRI.createVirtualRegister(&RISCV::GPRRegClass);
31417a6dacacSDimitry Andric     BuildMI(MBB, II, DL, get(RISCV::ADDI), Acc)
31427a6dacacSDimitry Andric         .addReg(RISCV::X0)
31437a6dacacSDimitry Andric         .addImm(0)
31447a6dacacSDimitry Andric         .setMIFlag(Flag);
31457a6dacacSDimitry Andric     uint32_t PrevShiftAmount = 0;
31467a6dacacSDimitry Andric     for (uint32_t ShiftAmount = 0; NumOfVReg >> ShiftAmount; ShiftAmount++) {
31477a6dacacSDimitry Andric       if (NumOfVReg & (1LL << ShiftAmount)) {
31487a6dacacSDimitry Andric         if (ShiftAmount)
31497a6dacacSDimitry Andric           BuildMI(MBB, II, DL, get(RISCV::SLLI), DestReg)
31507a6dacacSDimitry Andric               .addReg(DestReg, RegState::Kill)
31517a6dacacSDimitry Andric               .addImm(ShiftAmount - PrevShiftAmount)
31527a6dacacSDimitry Andric               .setMIFlag(Flag);
31537a6dacacSDimitry Andric         if (NumOfVReg >> (ShiftAmount + 1))
31547a6dacacSDimitry Andric           BuildMI(MBB, II, DL, get(RISCV::ADD), Acc)
31557a6dacacSDimitry Andric               .addReg(Acc, RegState::Kill)
31567a6dacacSDimitry Andric               .addReg(DestReg)
31577a6dacacSDimitry Andric               .setMIFlag(Flag);
31587a6dacacSDimitry Andric         PrevShiftAmount = ShiftAmount;
31597a6dacacSDimitry Andric       }
31607a6dacacSDimitry Andric     }
31617a6dacacSDimitry Andric     BuildMI(MBB, II, DL, get(RISCV::ADD), DestReg)
31627a6dacacSDimitry Andric         .addReg(DestReg, RegState::Kill)
31637a6dacacSDimitry Andric         .addReg(Acc)
31647a6dacacSDimitry Andric         .setMIFlag(Flag);
3165fe6060f1SDimitry Andric   }
3166bdd1243dSDimitry Andric }
3167fe6060f1SDimitry Andric 
316806c3fb27SDimitry Andric ArrayRef<std::pair<MachineMemOperand::Flags, const char *>>
getSerializableMachineMemOperandTargetFlags() const316906c3fb27SDimitry Andric RISCVInstrInfo::getSerializableMachineMemOperandTargetFlags() const {
317006c3fb27SDimitry Andric   static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
317106c3fb27SDimitry Andric       {{MONontemporalBit0, "riscv-nontemporal-domain-bit-0"},
317206c3fb27SDimitry Andric        {MONontemporalBit1, "riscv-nontemporal-domain-bit-1"}};
317306c3fb27SDimitry Andric   return ArrayRef(TargetFlags);
3174fe6060f1SDimitry Andric }
3175fe6060f1SDimitry Andric 
3176fcaf7f86SDimitry Andric // Returns true if this is the sext.w pattern, addiw rd, rs1, 0.
isSEXT_W(const MachineInstr & MI)3177fcaf7f86SDimitry Andric bool RISCV::isSEXT_W(const MachineInstr &MI) {
3178fcaf7f86SDimitry Andric   return MI.getOpcode() == RISCV::ADDIW && MI.getOperand(1).isReg() &&
3179fcaf7f86SDimitry Andric          MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0;
3180fcaf7f86SDimitry Andric }
3181fcaf7f86SDimitry Andric 
3182fcaf7f86SDimitry Andric // Returns true if this is the zext.w pattern, adduw rd, rs1, x0.
isZEXT_W(const MachineInstr & MI)3183fcaf7f86SDimitry Andric bool RISCV::isZEXT_W(const MachineInstr &MI) {
3184fcaf7f86SDimitry Andric   return MI.getOpcode() == RISCV::ADD_UW && MI.getOperand(1).isReg() &&
3185fcaf7f86SDimitry Andric          MI.getOperand(2).isReg() && MI.getOperand(2).getReg() == RISCV::X0;
3186fcaf7f86SDimitry Andric }
3187fcaf7f86SDimitry Andric 
3188fcaf7f86SDimitry Andric // Returns true if this is the zext.b pattern, andi rd, rs1, 255.
isZEXT_B(const MachineInstr & MI)3189fcaf7f86SDimitry Andric bool RISCV::isZEXT_B(const MachineInstr &MI) {
3190fcaf7f86SDimitry Andric   return MI.getOpcode() == RISCV::ANDI && MI.getOperand(1).isReg() &&
3191fcaf7f86SDimitry Andric          MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 255;
3192fcaf7f86SDimitry Andric }
3193fcaf7f86SDimitry Andric 
isRVVWholeLoadStore(unsigned Opcode)3194fe6060f1SDimitry Andric static bool isRVVWholeLoadStore(unsigned Opcode) {
3195fe6060f1SDimitry Andric   switch (Opcode) {
3196fe6060f1SDimitry Andric   default:
3197fe6060f1SDimitry Andric     return false;
3198fe6060f1SDimitry Andric   case RISCV::VS1R_V:
3199fe6060f1SDimitry Andric   case RISCV::VS2R_V:
3200fe6060f1SDimitry Andric   case RISCV::VS4R_V:
3201fe6060f1SDimitry Andric   case RISCV::VS8R_V:
3202fe6060f1SDimitry Andric   case RISCV::VL1RE8_V:
3203fe6060f1SDimitry Andric   case RISCV::VL2RE8_V:
3204fe6060f1SDimitry Andric   case RISCV::VL4RE8_V:
3205fe6060f1SDimitry Andric   case RISCV::VL8RE8_V:
3206fe6060f1SDimitry Andric   case RISCV::VL1RE16_V:
3207fe6060f1SDimitry Andric   case RISCV::VL2RE16_V:
3208fe6060f1SDimitry Andric   case RISCV::VL4RE16_V:
3209fe6060f1SDimitry Andric   case RISCV::VL8RE16_V:
3210fe6060f1SDimitry Andric   case RISCV::VL1RE32_V:
3211fe6060f1SDimitry Andric   case RISCV::VL2RE32_V:
3212fe6060f1SDimitry Andric   case RISCV::VL4RE32_V:
3213fe6060f1SDimitry Andric   case RISCV::VL8RE32_V:
3214fe6060f1SDimitry Andric   case RISCV::VL1RE64_V:
3215fe6060f1SDimitry Andric   case RISCV::VL2RE64_V:
3216fe6060f1SDimitry Andric   case RISCV::VL4RE64_V:
3217fe6060f1SDimitry Andric   case RISCV::VL8RE64_V:
3218fe6060f1SDimitry Andric     return true;
3219fe6060f1SDimitry Andric   }
3220fe6060f1SDimitry Andric }
3221fe6060f1SDimitry Andric 
isRVVSpill(const MachineInstr & MI)322281ad6265SDimitry Andric bool RISCV::isRVVSpill(const MachineInstr &MI) {
3223fe6060f1SDimitry Andric   // RVV lacks any support for immediate addressing for stack addresses, so be
3224fe6060f1SDimitry Andric   // conservative.
3225fe6060f1SDimitry Andric   unsigned Opcode = MI.getOpcode();
3226fe6060f1SDimitry Andric   if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
3227fe6060f1SDimitry Andric       !isRVVWholeLoadStore(Opcode) && !isRVVSpillForZvlsseg(Opcode))
3228fe6060f1SDimitry Andric     return false;
322981ad6265SDimitry Andric   return true;
3230fe6060f1SDimitry Andric }
3231fe6060f1SDimitry Andric 
3232bdd1243dSDimitry Andric std::optional<std::pair<unsigned, unsigned>>
isRVVSpillForZvlsseg(unsigned Opcode)323381ad6265SDimitry Andric RISCV::isRVVSpillForZvlsseg(unsigned Opcode) {
3234fe6060f1SDimitry Andric   switch (Opcode) {
3235fe6060f1SDimitry Andric   default:
3236bdd1243dSDimitry Andric     return std::nullopt;
3237fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL2_M1:
3238fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD2_M1:
3239fe6060f1SDimitry Andric     return std::make_pair(2u, 1u);
3240fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL2_M2:
3241fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD2_M2:
3242fe6060f1SDimitry Andric     return std::make_pair(2u, 2u);
3243fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL2_M4:
3244fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD2_M4:
3245fe6060f1SDimitry Andric     return std::make_pair(2u, 4u);
3246fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL3_M1:
3247fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD3_M1:
3248fe6060f1SDimitry Andric     return std::make_pair(3u, 1u);
3249fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL3_M2:
3250fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD3_M2:
3251fe6060f1SDimitry Andric     return std::make_pair(3u, 2u);
3252fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL4_M1:
3253fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD4_M1:
3254fe6060f1SDimitry Andric     return std::make_pair(4u, 1u);
3255fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL4_M2:
3256fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD4_M2:
3257fe6060f1SDimitry Andric     return std::make_pair(4u, 2u);
3258fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL5_M1:
3259fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD5_M1:
3260fe6060f1SDimitry Andric     return std::make_pair(5u, 1u);
3261fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL6_M1:
3262fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD6_M1:
3263fe6060f1SDimitry Andric     return std::make_pair(6u, 1u);
3264fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL7_M1:
3265fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD7_M1:
3266fe6060f1SDimitry Andric     return std::make_pair(7u, 1u);
3267fe6060f1SDimitry Andric   case RISCV::PseudoVSPILL8_M1:
3268fe6060f1SDimitry Andric   case RISCV::PseudoVRELOAD8_M1:
3269fe6060f1SDimitry Andric     return std::make_pair(8u, 1u);
3270fe6060f1SDimitry Andric   }
3271fe6060f1SDimitry Andric }
327281ad6265SDimitry Andric 
isFaultFirstLoad(const MachineInstr & MI)327381ad6265SDimitry Andric bool RISCV::isFaultFirstLoad(const MachineInstr &MI) {
327481ad6265SDimitry Andric   return MI.getNumExplicitDefs() == 2 && MI.modifiesRegister(RISCV::VL) &&
327581ad6265SDimitry Andric          !MI.isInlineAsm();
327681ad6265SDimitry Andric }
3277bdd1243dSDimitry Andric 
hasEqualFRM(const MachineInstr & MI1,const MachineInstr & MI2)3278bdd1243dSDimitry Andric bool RISCV::hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2) {
3279bdd1243dSDimitry Andric   int16_t MI1FrmOpIdx =
3280bdd1243dSDimitry Andric       RISCV::getNamedOperandIdx(MI1.getOpcode(), RISCV::OpName::frm);
3281bdd1243dSDimitry Andric   int16_t MI2FrmOpIdx =
3282bdd1243dSDimitry Andric       RISCV::getNamedOperandIdx(MI2.getOpcode(), RISCV::OpName::frm);
3283bdd1243dSDimitry Andric   if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0)
3284bdd1243dSDimitry Andric     return false;
3285bdd1243dSDimitry Andric   MachineOperand FrmOp1 = MI1.getOperand(MI1FrmOpIdx);
3286bdd1243dSDimitry Andric   MachineOperand FrmOp2 = MI2.getOperand(MI2FrmOpIdx);
3287bdd1243dSDimitry Andric   return FrmOp1.getImm() == FrmOp2.getImm();
3288bdd1243dSDimitry Andric }
32895f757f3fSDimitry Andric 
32905f757f3fSDimitry Andric std::optional<unsigned>
getVectorLowDemandedScalarBits(uint16_t Opcode,unsigned Log2SEW)32915f757f3fSDimitry Andric RISCV::getVectorLowDemandedScalarBits(uint16_t Opcode, unsigned Log2SEW) {
32925f757f3fSDimitry Andric   // TODO: Handle Zvbb instructions
32935f757f3fSDimitry Andric   switch (Opcode) {
32945f757f3fSDimitry Andric   default:
32955f757f3fSDimitry Andric     return std::nullopt;
32965f757f3fSDimitry Andric 
32975f757f3fSDimitry Andric   // 11.6. Vector Single-Width Shift Instructions
32985f757f3fSDimitry Andric   case RISCV::VSLL_VX:
32995f757f3fSDimitry Andric   case RISCV::VSRL_VX:
33005f757f3fSDimitry Andric   case RISCV::VSRA_VX:
33015f757f3fSDimitry Andric   // 12.4. Vector Single-Width Scaling Shift Instructions
33025f757f3fSDimitry Andric   case RISCV::VSSRL_VX:
33035f757f3fSDimitry Andric   case RISCV::VSSRA_VX:
33045f757f3fSDimitry Andric     // Only the low lg2(SEW) bits of the shift-amount value are used.
33055f757f3fSDimitry Andric     return Log2SEW;
33065f757f3fSDimitry Andric 
33075f757f3fSDimitry Andric   // 11.7 Vector Narrowing Integer Right Shift Instructions
33085f757f3fSDimitry Andric   case RISCV::VNSRL_WX:
33095f757f3fSDimitry Andric   case RISCV::VNSRA_WX:
33105f757f3fSDimitry Andric   // 12.5. Vector Narrowing Fixed-Point Clip Instructions
33115f757f3fSDimitry Andric   case RISCV::VNCLIPU_WX:
33125f757f3fSDimitry Andric   case RISCV::VNCLIP_WX:
33135f757f3fSDimitry Andric     // Only the low lg2(2*SEW) bits of the shift-amount value are used.
33145f757f3fSDimitry Andric     return Log2SEW + 1;
33155f757f3fSDimitry Andric 
33165f757f3fSDimitry Andric   // 11.1. Vector Single-Width Integer Add and Subtract
33175f757f3fSDimitry Andric   case RISCV::VADD_VX:
33185f757f3fSDimitry Andric   case RISCV::VSUB_VX:
33195f757f3fSDimitry Andric   case RISCV::VRSUB_VX:
33205f757f3fSDimitry Andric   // 11.2. Vector Widening Integer Add/Subtract
33215f757f3fSDimitry Andric   case RISCV::VWADDU_VX:
33225f757f3fSDimitry Andric   case RISCV::VWSUBU_VX:
33235f757f3fSDimitry Andric   case RISCV::VWADD_VX:
33245f757f3fSDimitry Andric   case RISCV::VWSUB_VX:
33255f757f3fSDimitry Andric   case RISCV::VWADDU_WX:
33265f757f3fSDimitry Andric   case RISCV::VWSUBU_WX:
33275f757f3fSDimitry Andric   case RISCV::VWADD_WX:
33285f757f3fSDimitry Andric   case RISCV::VWSUB_WX:
33295f757f3fSDimitry Andric   // 11.4. Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
33305f757f3fSDimitry Andric   case RISCV::VADC_VXM:
33315f757f3fSDimitry Andric   case RISCV::VADC_VIM:
33325f757f3fSDimitry Andric   case RISCV::VMADC_VXM:
33335f757f3fSDimitry Andric   case RISCV::VMADC_VIM:
33345f757f3fSDimitry Andric   case RISCV::VMADC_VX:
33355f757f3fSDimitry Andric   case RISCV::VSBC_VXM:
33365f757f3fSDimitry Andric   case RISCV::VMSBC_VXM:
33375f757f3fSDimitry Andric   case RISCV::VMSBC_VX:
33385f757f3fSDimitry Andric   // 11.5 Vector Bitwise Logical Instructions
33395f757f3fSDimitry Andric   case RISCV::VAND_VX:
33405f757f3fSDimitry Andric   case RISCV::VOR_VX:
33415f757f3fSDimitry Andric   case RISCV::VXOR_VX:
33425f757f3fSDimitry Andric   // 11.8. Vector Integer Compare Instructions
33435f757f3fSDimitry Andric   case RISCV::VMSEQ_VX:
33445f757f3fSDimitry Andric   case RISCV::VMSNE_VX:
33455f757f3fSDimitry Andric   case RISCV::VMSLTU_VX:
33465f757f3fSDimitry Andric   case RISCV::VMSLT_VX:
33475f757f3fSDimitry Andric   case RISCV::VMSLEU_VX:
33485f757f3fSDimitry Andric   case RISCV::VMSLE_VX:
33495f757f3fSDimitry Andric   case RISCV::VMSGTU_VX:
33505f757f3fSDimitry Andric   case RISCV::VMSGT_VX:
33515f757f3fSDimitry Andric   // 11.9. Vector Integer Min/Max Instructions
33525f757f3fSDimitry Andric   case RISCV::VMINU_VX:
33535f757f3fSDimitry Andric   case RISCV::VMIN_VX:
33545f757f3fSDimitry Andric   case RISCV::VMAXU_VX:
33555f757f3fSDimitry Andric   case RISCV::VMAX_VX:
33565f757f3fSDimitry Andric   // 11.10. Vector Single-Width Integer Multiply Instructions
33575f757f3fSDimitry Andric   case RISCV::VMUL_VX:
33585f757f3fSDimitry Andric   case RISCV::VMULH_VX:
33595f757f3fSDimitry Andric   case RISCV::VMULHU_VX:
33605f757f3fSDimitry Andric   case RISCV::VMULHSU_VX:
33615f757f3fSDimitry Andric   // 11.11. Vector Integer Divide Instructions
33625f757f3fSDimitry Andric   case RISCV::VDIVU_VX:
33635f757f3fSDimitry Andric   case RISCV::VDIV_VX:
33645f757f3fSDimitry Andric   case RISCV::VREMU_VX:
33655f757f3fSDimitry Andric   case RISCV::VREM_VX:
33665f757f3fSDimitry Andric   // 11.12. Vector Widening Integer Multiply Instructions
33675f757f3fSDimitry Andric   case RISCV::VWMUL_VX:
33685f757f3fSDimitry Andric   case RISCV::VWMULU_VX:
33695f757f3fSDimitry Andric   case RISCV::VWMULSU_VX:
33705f757f3fSDimitry Andric   // 11.13. Vector Single-Width Integer Multiply-Add Instructions
33715f757f3fSDimitry Andric   case RISCV::VMACC_VX:
33725f757f3fSDimitry Andric   case RISCV::VNMSAC_VX:
33735f757f3fSDimitry Andric   case RISCV::VMADD_VX:
33745f757f3fSDimitry Andric   case RISCV::VNMSUB_VX:
33755f757f3fSDimitry Andric   // 11.14. Vector Widening Integer Multiply-Add Instructions
33765f757f3fSDimitry Andric   case RISCV::VWMACCU_VX:
33775f757f3fSDimitry Andric   case RISCV::VWMACC_VX:
33785f757f3fSDimitry Andric   case RISCV::VWMACCSU_VX:
33795f757f3fSDimitry Andric   case RISCV::VWMACCUS_VX:
33805f757f3fSDimitry Andric   // 11.15. Vector Integer Merge Instructions
33815f757f3fSDimitry Andric   case RISCV::VMERGE_VXM:
33825f757f3fSDimitry Andric   // 11.16. Vector Integer Move Instructions
33835f757f3fSDimitry Andric   case RISCV::VMV_V_X:
33845f757f3fSDimitry Andric   // 12.1. Vector Single-Width Saturating Add and Subtract
33855f757f3fSDimitry Andric   case RISCV::VSADDU_VX:
33865f757f3fSDimitry Andric   case RISCV::VSADD_VX:
33875f757f3fSDimitry Andric   case RISCV::VSSUBU_VX:
33885f757f3fSDimitry Andric   case RISCV::VSSUB_VX:
33895f757f3fSDimitry Andric   // 12.2. Vector Single-Width Averaging Add and Subtract
33905f757f3fSDimitry Andric   case RISCV::VAADDU_VX:
33915f757f3fSDimitry Andric   case RISCV::VAADD_VX:
33925f757f3fSDimitry Andric   case RISCV::VASUBU_VX:
33935f757f3fSDimitry Andric   case RISCV::VASUB_VX:
33945f757f3fSDimitry Andric   // 12.3. Vector Single-Width Fractional Multiply with Rounding and Saturation
33955f757f3fSDimitry Andric   case RISCV::VSMUL_VX:
33965f757f3fSDimitry Andric   // 16.1. Integer Scalar Move Instructions
33975f757f3fSDimitry Andric   case RISCV::VMV_S_X:
33985f757f3fSDimitry Andric     return 1U << Log2SEW;
33995f757f3fSDimitry Andric   }
34005f757f3fSDimitry Andric }
34015f757f3fSDimitry Andric 
getRVVMCOpcode(unsigned RVVPseudoOpcode)34025f757f3fSDimitry Andric unsigned RISCV::getRVVMCOpcode(unsigned RVVPseudoOpcode) {
34035f757f3fSDimitry Andric   const RISCVVPseudosTable::PseudoInfo *RVV =
34045f757f3fSDimitry Andric       RISCVVPseudosTable::getPseudoInfo(RVVPseudoOpcode);
34055f757f3fSDimitry Andric   if (!RVV)
34065f757f3fSDimitry Andric     return 0;
34075f757f3fSDimitry Andric   return RVV->BaseInstr;
34085f757f3fSDimitry Andric }
3409