xref: /openbsd-src/gnu/llvm/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- RISCVInstrInfo.cpp - RISCV Instruction Information ------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file contains the RISCV implementation of the TargetInstrInfo class.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "RISCVInstrInfo.h"
1473471bf0Spatrick #include "MCTargetDesc/RISCVMatInt.h"
1509467b48Spatrick #include "RISCV.h"
1673471bf0Spatrick #include "RISCVMachineFunctionInfo.h"
1709467b48Spatrick #include "RISCVSubtarget.h"
1809467b48Spatrick #include "RISCVTargetMachine.h"
1909467b48Spatrick #include "llvm/ADT/STLExtras.h"
2009467b48Spatrick #include "llvm/ADT/SmallVector.h"
2173471bf0Spatrick #include "llvm/Analysis/MemoryLocation.h"
22*d415bd75Srobert #include "llvm/CodeGen/LiveIntervals.h"
2373471bf0Spatrick #include "llvm/CodeGen/LiveVariables.h"
24*d415bd75Srobert #include "llvm/CodeGen/MachineCombinerPattern.h"
2509467b48Spatrick #include "llvm/CodeGen/MachineFunctionPass.h"
2609467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
2709467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2809467b48Spatrick #include "llvm/CodeGen/RegisterScavenging.h"
29*d415bd75Srobert #include "llvm/IR/DebugInfoMetadata.h"
3073471bf0Spatrick #include "llvm/MC/MCInstBuilder.h"
31*d415bd75Srobert #include "llvm/MC/TargetRegistry.h"
3209467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3309467b48Spatrick 
3409467b48Spatrick using namespace llvm;
3509467b48Spatrick 
3609467b48Spatrick #define GEN_CHECK_COMPRESS_INSTR
3709467b48Spatrick #include "RISCVGenCompressInstEmitter.inc"
3809467b48Spatrick 
3909467b48Spatrick #define GET_INSTRINFO_CTOR_DTOR
40*d415bd75Srobert #define GET_INSTRINFO_NAMED_OPS
4109467b48Spatrick #include "RISCVGenInstrInfo.inc"
4209467b48Spatrick 
43*d415bd75Srobert static cl::opt<bool> PreferWholeRegisterMove(
44*d415bd75Srobert     "riscv-prefer-whole-register-move", cl::init(false), cl::Hidden,
45*d415bd75Srobert     cl::desc("Prefer whole register move for vector registers."));
46*d415bd75Srobert 
47*d415bd75Srobert namespace llvm::RISCVVPseudosTable {
4873471bf0Spatrick 
4973471bf0Spatrick using namespace RISCV;
5073471bf0Spatrick 
5173471bf0Spatrick #define GET_RISCVVPseudosTable_IMPL
5273471bf0Spatrick #include "RISCVGenSearchableTables.inc"
5373471bf0Spatrick 
54*d415bd75Srobert } // namespace llvm::RISCVVPseudosTable
5573471bf0Spatrick 
RISCVInstrInfo(RISCVSubtarget & STI)5609467b48Spatrick RISCVInstrInfo::RISCVInstrInfo(RISCVSubtarget &STI)
5709467b48Spatrick     : RISCVGenInstrInfo(RISCV::ADJCALLSTACKDOWN, RISCV::ADJCALLSTACKUP),
5809467b48Spatrick       STI(STI) {}
5909467b48Spatrick 
getNop() const6073471bf0Spatrick MCInst RISCVInstrInfo::getNop() const {
61*d415bd75Srobert   if (STI.hasStdExtCOrZca())
6273471bf0Spatrick     return MCInstBuilder(RISCV::C_NOP);
6373471bf0Spatrick   return MCInstBuilder(RISCV::ADDI)
6473471bf0Spatrick       .addReg(RISCV::X0)
6573471bf0Spatrick       .addReg(RISCV::X0)
6673471bf0Spatrick       .addImm(0);
6773471bf0Spatrick }
6873471bf0Spatrick 
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const6909467b48Spatrick unsigned RISCVInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
7009467b48Spatrick                                              int &FrameIndex) const {
7109467b48Spatrick   switch (MI.getOpcode()) {
7209467b48Spatrick   default:
7309467b48Spatrick     return 0;
7409467b48Spatrick   case RISCV::LB:
7509467b48Spatrick   case RISCV::LBU:
7609467b48Spatrick   case RISCV::LH:
7709467b48Spatrick   case RISCV::LHU:
7873471bf0Spatrick   case RISCV::FLH:
7909467b48Spatrick   case RISCV::LW:
8009467b48Spatrick   case RISCV::FLW:
8109467b48Spatrick   case RISCV::LWU:
8209467b48Spatrick   case RISCV::LD:
8309467b48Spatrick   case RISCV::FLD:
8409467b48Spatrick     break;
8509467b48Spatrick   }
8609467b48Spatrick 
8709467b48Spatrick   if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
8809467b48Spatrick       MI.getOperand(2).getImm() == 0) {
8909467b48Spatrick     FrameIndex = MI.getOperand(1).getIndex();
9009467b48Spatrick     return MI.getOperand(0).getReg();
9109467b48Spatrick   }
9209467b48Spatrick 
9309467b48Spatrick   return 0;
9409467b48Spatrick }
9509467b48Spatrick 
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const9609467b48Spatrick unsigned RISCVInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
9709467b48Spatrick                                             int &FrameIndex) const {
9809467b48Spatrick   switch (MI.getOpcode()) {
9909467b48Spatrick   default:
10009467b48Spatrick     return 0;
10109467b48Spatrick   case RISCV::SB:
10209467b48Spatrick   case RISCV::SH:
10309467b48Spatrick   case RISCV::SW:
10473471bf0Spatrick   case RISCV::FSH:
10509467b48Spatrick   case RISCV::FSW:
10609467b48Spatrick   case RISCV::SD:
10709467b48Spatrick   case RISCV::FSD:
10809467b48Spatrick     break;
10909467b48Spatrick   }
11009467b48Spatrick 
111097a140dSpatrick   if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
112097a140dSpatrick       MI.getOperand(2).getImm() == 0) {
113097a140dSpatrick     FrameIndex = MI.getOperand(1).getIndex();
114097a140dSpatrick     return MI.getOperand(0).getReg();
11509467b48Spatrick   }
11609467b48Spatrick 
11709467b48Spatrick   return 0;
11809467b48Spatrick }
11909467b48Spatrick 
forwardCopyWillClobberTuple(unsigned DstReg,unsigned SrcReg,unsigned NumRegs)12073471bf0Spatrick static bool forwardCopyWillClobberTuple(unsigned DstReg, unsigned SrcReg,
12173471bf0Spatrick                                         unsigned NumRegs) {
122*d415bd75Srobert   return DstReg > SrcReg && (DstReg - SrcReg) < NumRegs;
123*d415bd75Srobert }
124*d415bd75Srobert 
isConvertibleToVMV_V_V(const RISCVSubtarget & STI,const MachineBasicBlock & MBB,MachineBasicBlock::const_iterator MBBI,MachineBasicBlock::const_iterator & DefMBBI,RISCVII::VLMUL LMul)125*d415bd75Srobert static bool isConvertibleToVMV_V_V(const RISCVSubtarget &STI,
126*d415bd75Srobert                                    const MachineBasicBlock &MBB,
127*d415bd75Srobert                                    MachineBasicBlock::const_iterator MBBI,
128*d415bd75Srobert                                    MachineBasicBlock::const_iterator &DefMBBI,
129*d415bd75Srobert                                    RISCVII::VLMUL LMul) {
130*d415bd75Srobert   if (PreferWholeRegisterMove)
131*d415bd75Srobert     return false;
132*d415bd75Srobert 
133*d415bd75Srobert   assert(MBBI->getOpcode() == TargetOpcode::COPY &&
134*d415bd75Srobert          "Unexpected COPY instruction.");
135*d415bd75Srobert   Register SrcReg = MBBI->getOperand(1).getReg();
136*d415bd75Srobert   const TargetRegisterInfo *TRI = STI.getRegisterInfo();
137*d415bd75Srobert 
138*d415bd75Srobert   bool FoundDef = false;
139*d415bd75Srobert   bool FirstVSetVLI = false;
140*d415bd75Srobert   unsigned FirstSEW = 0;
141*d415bd75Srobert   while (MBBI != MBB.begin()) {
142*d415bd75Srobert     --MBBI;
143*d415bd75Srobert     if (MBBI->isMetaInstruction())
144*d415bd75Srobert       continue;
145*d415bd75Srobert 
146*d415bd75Srobert     if (MBBI->getOpcode() == RISCV::PseudoVSETVLI ||
147*d415bd75Srobert         MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 ||
148*d415bd75Srobert         MBBI->getOpcode() == RISCV::PseudoVSETIVLI) {
149*d415bd75Srobert       // There is a vsetvli between COPY and source define instruction.
150*d415bd75Srobert       // vy = def_vop ...  (producing instruction)
151*d415bd75Srobert       // ...
152*d415bd75Srobert       // vsetvli
153*d415bd75Srobert       // ...
154*d415bd75Srobert       // vx = COPY vy
155*d415bd75Srobert       if (!FoundDef) {
156*d415bd75Srobert         if (!FirstVSetVLI) {
157*d415bd75Srobert           FirstVSetVLI = true;
158*d415bd75Srobert           unsigned FirstVType = MBBI->getOperand(2).getImm();
159*d415bd75Srobert           RISCVII::VLMUL FirstLMul = RISCVVType::getVLMUL(FirstVType);
160*d415bd75Srobert           FirstSEW = RISCVVType::getSEW(FirstVType);
161*d415bd75Srobert           // The first encountered vsetvli must have the same lmul as the
162*d415bd75Srobert           // register class of COPY.
163*d415bd75Srobert           if (FirstLMul != LMul)
164*d415bd75Srobert             return false;
165*d415bd75Srobert         }
166*d415bd75Srobert         // Only permit `vsetvli x0, x0, vtype` between COPY and the source
167*d415bd75Srobert         // define instruction.
168*d415bd75Srobert         if (MBBI->getOperand(0).getReg() != RISCV::X0)
169*d415bd75Srobert           return false;
170*d415bd75Srobert         if (MBBI->getOperand(1).isImm())
171*d415bd75Srobert           return false;
172*d415bd75Srobert         if (MBBI->getOperand(1).getReg() != RISCV::X0)
173*d415bd75Srobert           return false;
174*d415bd75Srobert         continue;
175*d415bd75Srobert       }
176*d415bd75Srobert 
177*d415bd75Srobert       // MBBI is the first vsetvli before the producing instruction.
178*d415bd75Srobert       unsigned VType = MBBI->getOperand(2).getImm();
179*d415bd75Srobert       // If there is a vsetvli between COPY and the producing instruction.
180*d415bd75Srobert       if (FirstVSetVLI) {
181*d415bd75Srobert         // If SEW is different, return false.
182*d415bd75Srobert         if (RISCVVType::getSEW(VType) != FirstSEW)
183*d415bd75Srobert           return false;
184*d415bd75Srobert       }
185*d415bd75Srobert 
186*d415bd75Srobert       // If the vsetvli is tail undisturbed, keep the whole register move.
187*d415bd75Srobert       if (!RISCVVType::isTailAgnostic(VType))
188*d415bd75Srobert         return false;
189*d415bd75Srobert 
190*d415bd75Srobert       // The checking is conservative. We only have register classes for
191*d415bd75Srobert       // LMUL = 1/2/4/8. We should be able to convert vmv1r.v to vmv.v.v
192*d415bd75Srobert       // for fractional LMUL operations. However, we could not use the vsetvli
193*d415bd75Srobert       // lmul for widening operations. The result of widening operation is
194*d415bd75Srobert       // 2 x LMUL.
195*d415bd75Srobert       return LMul == RISCVVType::getVLMUL(VType);
196*d415bd75Srobert     } else if (MBBI->isInlineAsm() || MBBI->isCall()) {
197*d415bd75Srobert       return false;
198*d415bd75Srobert     } else if (MBBI->getNumDefs()) {
199*d415bd75Srobert       // Check all the instructions which will change VL.
200*d415bd75Srobert       // For example, vleff has implicit def VL.
201*d415bd75Srobert       if (MBBI->modifiesRegister(RISCV::VL))
202*d415bd75Srobert         return false;
203*d415bd75Srobert 
204*d415bd75Srobert       // Only converting whole register copies to vmv.v.v when the defining
205*d415bd75Srobert       // value appears in the explicit operands.
206*d415bd75Srobert       for (const MachineOperand &MO : MBBI->explicit_operands()) {
207*d415bd75Srobert         if (!MO.isReg() || !MO.isDef())
208*d415bd75Srobert           continue;
209*d415bd75Srobert         if (!FoundDef && TRI->isSubRegisterEq(MO.getReg(), SrcReg)) {
210*d415bd75Srobert           // We only permit the source of COPY has the same LMUL as the defined
211*d415bd75Srobert           // operand.
212*d415bd75Srobert           // There are cases we need to keep the whole register copy if the LMUL
213*d415bd75Srobert           // is different.
214*d415bd75Srobert           // For example,
215*d415bd75Srobert           // $x0 = PseudoVSETIVLI 4, 73   // vsetivli zero, 4, e16,m2,ta,m
216*d415bd75Srobert           // $v28m4 = PseudoVWADD_VV_M2 $v26m2, $v8m2
217*d415bd75Srobert           // # The COPY may be created by vlmul_trunc intrinsic.
218*d415bd75Srobert           // $v26m2 = COPY renamable $v28m2, implicit killed $v28m4
219*d415bd75Srobert           //
220*d415bd75Srobert           // After widening, the valid value will be 4 x e32 elements. If we
221*d415bd75Srobert           // convert the COPY to vmv.v.v, it will only copy 4 x e16 elements.
222*d415bd75Srobert           // FIXME: The COPY of subregister of Zvlsseg register will not be able
223*d415bd75Srobert           // to convert to vmv.v.[v|i] under the constraint.
224*d415bd75Srobert           if (MO.getReg() != SrcReg)
225*d415bd75Srobert             return false;
226*d415bd75Srobert 
227*d415bd75Srobert           // In widening reduction instructions with LMUL_1 input vector case,
228*d415bd75Srobert           // only checking the LMUL is insufficient due to reduction result is
229*d415bd75Srobert           // always LMUL_1.
230*d415bd75Srobert           // For example,
231*d415bd75Srobert           // $x11 = PseudoVSETIVLI 1, 64 // vsetivli a1, 1, e8, m1, ta, mu
232*d415bd75Srobert           // $v8m1 = PseudoVWREDSUM_VS_M1 $v26, $v27
233*d415bd75Srobert           // $v26 = COPY killed renamable $v8
234*d415bd75Srobert           // After widening, The valid value will be 1 x e16 elements. If we
235*d415bd75Srobert           // convert the COPY to vmv.v.v, it will only copy 1 x e8 elements.
236*d415bd75Srobert           uint64_t TSFlags = MBBI->getDesc().TSFlags;
237*d415bd75Srobert           if (RISCVII::isRVVWideningReduction(TSFlags))
238*d415bd75Srobert             return false;
239*d415bd75Srobert 
240*d415bd75Srobert           // If the producing instruction does not depend on vsetvli, do not
241*d415bd75Srobert           // convert COPY to vmv.v.v. For example, VL1R_V or PseudoVRELOAD.
242*d415bd75Srobert           if (!RISCVII::hasSEWOp(TSFlags) || !RISCVII::hasVLOp(TSFlags))
243*d415bd75Srobert             return false;
244*d415bd75Srobert 
245*d415bd75Srobert           // Found the definition.
246*d415bd75Srobert           FoundDef = true;
247*d415bd75Srobert           DefMBBI = MBBI;
248*d415bd75Srobert           break;
249*d415bd75Srobert         }
250*d415bd75Srobert       }
251*d415bd75Srobert     }
252*d415bd75Srobert   }
253*d415bd75Srobert 
254*d415bd75Srobert   return false;
25573471bf0Spatrick }
25673471bf0Spatrick 
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,MCRegister DstReg,MCRegister SrcReg,bool KillSrc) const25709467b48Spatrick void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
25809467b48Spatrick                                  MachineBasicBlock::iterator MBBI,
25909467b48Spatrick                                  const DebugLoc &DL, MCRegister DstReg,
26009467b48Spatrick                                  MCRegister SrcReg, bool KillSrc) const {
26109467b48Spatrick   if (RISCV::GPRRegClass.contains(DstReg, SrcReg)) {
26209467b48Spatrick     BuildMI(MBB, MBBI, DL, get(RISCV::ADDI), DstReg)
26309467b48Spatrick         .addReg(SrcReg, getKillRegState(KillSrc))
26409467b48Spatrick         .addImm(0);
26509467b48Spatrick     return;
26609467b48Spatrick   }
26709467b48Spatrick 
268*d415bd75Srobert   // Handle copy from csr
269*d415bd75Srobert   if (RISCV::VCSRRegClass.contains(SrcReg) &&
270*d415bd75Srobert       RISCV::GPRRegClass.contains(DstReg)) {
271*d415bd75Srobert     const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
272*d415bd75Srobert     BuildMI(MBB, MBBI, DL, get(RISCV::CSRRS), DstReg)
273*d415bd75Srobert       .addImm(RISCVSysReg::lookupSysRegByName(TRI.getName(SrcReg))->Encoding)
274*d415bd75Srobert       .addReg(RISCV::X0);
275*d415bd75Srobert     return;
276*d415bd75Srobert   }
277*d415bd75Srobert 
27873471bf0Spatrick   // FPR->FPR copies and VR->VR copies.
27909467b48Spatrick   unsigned Opc;
28073471bf0Spatrick   bool IsScalableVector = true;
28173471bf0Spatrick   unsigned NF = 1;
282*d415bd75Srobert   RISCVII::VLMUL LMul = RISCVII::LMUL_1;
28373471bf0Spatrick   unsigned SubRegIdx = RISCV::sub_vrm1_0;
28473471bf0Spatrick   if (RISCV::FPR16RegClass.contains(DstReg, SrcReg)) {
285*d415bd75Srobert     if (!STI.hasStdExtZfh() && STI.hasStdExtZfhmin()) {
286*d415bd75Srobert       // Zfhmin subset doesn't have FSGNJ_H, replaces FSGNJ_H with FSGNJ_S.
287*d415bd75Srobert       const TargetRegisterInfo *TRI = STI.getRegisterInfo();
288*d415bd75Srobert       DstReg = TRI->getMatchingSuperReg(DstReg, RISCV::sub_16,
289*d415bd75Srobert                                         &RISCV::FPR32RegClass);
290*d415bd75Srobert       SrcReg = TRI->getMatchingSuperReg(SrcReg, RISCV::sub_16,
291*d415bd75Srobert                                         &RISCV::FPR32RegClass);
292*d415bd75Srobert       Opc = RISCV::FSGNJ_S;
293*d415bd75Srobert     } else {
29473471bf0Spatrick       Opc = RISCV::FSGNJ_H;
295*d415bd75Srobert     }
29673471bf0Spatrick     IsScalableVector = false;
29773471bf0Spatrick   } else if (RISCV::FPR32RegClass.contains(DstReg, SrcReg)) {
29809467b48Spatrick     Opc = RISCV::FSGNJ_S;
29973471bf0Spatrick     IsScalableVector = false;
30073471bf0Spatrick   } else if (RISCV::FPR64RegClass.contains(DstReg, SrcReg)) {
30109467b48Spatrick     Opc = RISCV::FSGNJ_D;
30273471bf0Spatrick     IsScalableVector = false;
30373471bf0Spatrick   } else if (RISCV::VRRegClass.contains(DstReg, SrcReg)) {
304*d415bd75Srobert     Opc = RISCV::VMV1R_V;
305*d415bd75Srobert     LMul = RISCVII::LMUL_1;
30673471bf0Spatrick   } else if (RISCV::VRM2RegClass.contains(DstReg, SrcReg)) {
307*d415bd75Srobert     Opc = RISCV::VMV2R_V;
308*d415bd75Srobert     LMul = RISCVII::LMUL_2;
30973471bf0Spatrick   } else if (RISCV::VRM4RegClass.contains(DstReg, SrcReg)) {
310*d415bd75Srobert     Opc = RISCV::VMV4R_V;
311*d415bd75Srobert     LMul = RISCVII::LMUL_4;
31273471bf0Spatrick   } else if (RISCV::VRM8RegClass.contains(DstReg, SrcReg)) {
313*d415bd75Srobert     Opc = RISCV::VMV8R_V;
314*d415bd75Srobert     LMul = RISCVII::LMUL_8;
31573471bf0Spatrick   } else if (RISCV::VRN2M1RegClass.contains(DstReg, SrcReg)) {
316*d415bd75Srobert     Opc = RISCV::VMV1R_V;
31773471bf0Spatrick     SubRegIdx = RISCV::sub_vrm1_0;
31873471bf0Spatrick     NF = 2;
319*d415bd75Srobert     LMul = RISCVII::LMUL_1;
32073471bf0Spatrick   } else if (RISCV::VRN2M2RegClass.contains(DstReg, SrcReg)) {
321*d415bd75Srobert     Opc = RISCV::VMV2R_V;
32273471bf0Spatrick     SubRegIdx = RISCV::sub_vrm2_0;
32373471bf0Spatrick     NF = 2;
324*d415bd75Srobert     LMul = RISCVII::LMUL_2;
32573471bf0Spatrick   } else if (RISCV::VRN2M4RegClass.contains(DstReg, SrcReg)) {
326*d415bd75Srobert     Opc = RISCV::VMV4R_V;
32773471bf0Spatrick     SubRegIdx = RISCV::sub_vrm4_0;
32873471bf0Spatrick     NF = 2;
329*d415bd75Srobert     LMul = RISCVII::LMUL_4;
33073471bf0Spatrick   } else if (RISCV::VRN3M1RegClass.contains(DstReg, SrcReg)) {
331*d415bd75Srobert     Opc = RISCV::VMV1R_V;
33273471bf0Spatrick     SubRegIdx = RISCV::sub_vrm1_0;
33373471bf0Spatrick     NF = 3;
334*d415bd75Srobert     LMul = RISCVII::LMUL_1;
33573471bf0Spatrick   } else if (RISCV::VRN3M2RegClass.contains(DstReg, SrcReg)) {
336*d415bd75Srobert     Opc = RISCV::VMV2R_V;
33773471bf0Spatrick     SubRegIdx = RISCV::sub_vrm2_0;
33873471bf0Spatrick     NF = 3;
339*d415bd75Srobert     LMul = RISCVII::LMUL_2;
34073471bf0Spatrick   } else if (RISCV::VRN4M1RegClass.contains(DstReg, SrcReg)) {
341*d415bd75Srobert     Opc = RISCV::VMV1R_V;
34273471bf0Spatrick     SubRegIdx = RISCV::sub_vrm1_0;
34373471bf0Spatrick     NF = 4;
344*d415bd75Srobert     LMul = RISCVII::LMUL_1;
34573471bf0Spatrick   } else if (RISCV::VRN4M2RegClass.contains(DstReg, SrcReg)) {
346*d415bd75Srobert     Opc = RISCV::VMV2R_V;
34773471bf0Spatrick     SubRegIdx = RISCV::sub_vrm2_0;
34873471bf0Spatrick     NF = 4;
349*d415bd75Srobert     LMul = RISCVII::LMUL_2;
35073471bf0Spatrick   } else if (RISCV::VRN5M1RegClass.contains(DstReg, SrcReg)) {
351*d415bd75Srobert     Opc = RISCV::VMV1R_V;
35273471bf0Spatrick     SubRegIdx = RISCV::sub_vrm1_0;
35373471bf0Spatrick     NF = 5;
354*d415bd75Srobert     LMul = RISCVII::LMUL_1;
35573471bf0Spatrick   } else if (RISCV::VRN6M1RegClass.contains(DstReg, SrcReg)) {
356*d415bd75Srobert     Opc = RISCV::VMV1R_V;
35773471bf0Spatrick     SubRegIdx = RISCV::sub_vrm1_0;
35873471bf0Spatrick     NF = 6;
359*d415bd75Srobert     LMul = RISCVII::LMUL_1;
36073471bf0Spatrick   } else if (RISCV::VRN7M1RegClass.contains(DstReg, SrcReg)) {
361*d415bd75Srobert     Opc = RISCV::VMV1R_V;
36273471bf0Spatrick     SubRegIdx = RISCV::sub_vrm1_0;
36373471bf0Spatrick     NF = 7;
364*d415bd75Srobert     LMul = RISCVII::LMUL_1;
36573471bf0Spatrick   } else if (RISCV::VRN8M1RegClass.contains(DstReg, SrcReg)) {
366*d415bd75Srobert     Opc = RISCV::VMV1R_V;
36773471bf0Spatrick     SubRegIdx = RISCV::sub_vrm1_0;
36873471bf0Spatrick     NF = 8;
369*d415bd75Srobert     LMul = RISCVII::LMUL_1;
37073471bf0Spatrick   } else {
37109467b48Spatrick     llvm_unreachable("Impossible reg-to-reg copy");
37273471bf0Spatrick   }
37309467b48Spatrick 
37473471bf0Spatrick   if (IsScalableVector) {
375*d415bd75Srobert     bool UseVMV_V_V = false;
376*d415bd75Srobert     MachineBasicBlock::const_iterator DefMBBI;
377*d415bd75Srobert     unsigned VIOpc;
378*d415bd75Srobert     if (isConvertibleToVMV_V_V(STI, MBB, MBBI, DefMBBI, LMul)) {
379*d415bd75Srobert       UseVMV_V_V = true;
380*d415bd75Srobert       // We only need to handle LMUL = 1/2/4/8 here because we only define
381*d415bd75Srobert       // vector register classes for LMUL = 1/2/4/8.
382*d415bd75Srobert       switch (LMul) {
383*d415bd75Srobert       default:
384*d415bd75Srobert         llvm_unreachable("Impossible LMUL for vector register copy.");
385*d415bd75Srobert       case RISCVII::LMUL_1:
386*d415bd75Srobert         Opc = RISCV::PseudoVMV_V_V_M1;
387*d415bd75Srobert         VIOpc = RISCV::PseudoVMV_V_I_M1;
388*d415bd75Srobert         break;
389*d415bd75Srobert       case RISCVII::LMUL_2:
390*d415bd75Srobert         Opc = RISCV::PseudoVMV_V_V_M2;
391*d415bd75Srobert         VIOpc = RISCV::PseudoVMV_V_I_M2;
392*d415bd75Srobert         break;
393*d415bd75Srobert       case RISCVII::LMUL_4:
394*d415bd75Srobert         Opc = RISCV::PseudoVMV_V_V_M4;
395*d415bd75Srobert         VIOpc = RISCV::PseudoVMV_V_I_M4;
396*d415bd75Srobert         break;
397*d415bd75Srobert       case RISCVII::LMUL_8:
398*d415bd75Srobert         Opc = RISCV::PseudoVMV_V_V_M8;
399*d415bd75Srobert         VIOpc = RISCV::PseudoVMV_V_I_M8;
400*d415bd75Srobert         break;
401*d415bd75Srobert       }
402*d415bd75Srobert     }
403*d415bd75Srobert 
404*d415bd75Srobert     bool UseVMV_V_I = false;
405*d415bd75Srobert     if (UseVMV_V_V && (DefMBBI->getOpcode() == VIOpc)) {
406*d415bd75Srobert       UseVMV_V_I = true;
407*d415bd75Srobert       Opc = VIOpc;
408*d415bd75Srobert     }
409*d415bd75Srobert 
41073471bf0Spatrick     if (NF == 1) {
411*d415bd75Srobert       auto MIB = BuildMI(MBB, MBBI, DL, get(Opc), DstReg);
412*d415bd75Srobert       if (UseVMV_V_I)
413*d415bd75Srobert         MIB = MIB.add(DefMBBI->getOperand(1));
414*d415bd75Srobert       else
415*d415bd75Srobert         MIB = MIB.addReg(SrcReg, getKillRegState(KillSrc));
416*d415bd75Srobert       if (UseVMV_V_V) {
417*d415bd75Srobert         const MCInstrDesc &Desc = DefMBBI->getDesc();
418*d415bd75Srobert         MIB.add(DefMBBI->getOperand(RISCVII::getVLOpNum(Desc))); // AVL
419*d415bd75Srobert         MIB.add(DefMBBI->getOperand(RISCVII::getSEWOpNum(Desc))); // SEW
420*d415bd75Srobert         MIB.addReg(RISCV::VL, RegState::Implicit);
421*d415bd75Srobert         MIB.addReg(RISCV::VTYPE, RegState::Implicit);
422*d415bd75Srobert       }
42373471bf0Spatrick     } else {
42473471bf0Spatrick       const TargetRegisterInfo *TRI = STI.getRegisterInfo();
42573471bf0Spatrick 
42673471bf0Spatrick       int I = 0, End = NF, Incr = 1;
42773471bf0Spatrick       unsigned SrcEncoding = TRI->getEncodingValue(SrcReg);
42873471bf0Spatrick       unsigned DstEncoding = TRI->getEncodingValue(DstReg);
429*d415bd75Srobert       unsigned LMulVal;
430*d415bd75Srobert       bool Fractional;
431*d415bd75Srobert       std::tie(LMulVal, Fractional) = RISCVVType::decodeVLMUL(LMul);
432*d415bd75Srobert       assert(!Fractional && "It is impossible be fractional lmul here.");
433*d415bd75Srobert       if (forwardCopyWillClobberTuple(DstEncoding, SrcEncoding, NF * LMulVal)) {
43473471bf0Spatrick         I = NF - 1;
43573471bf0Spatrick         End = -1;
43673471bf0Spatrick         Incr = -1;
43773471bf0Spatrick       }
43873471bf0Spatrick 
43973471bf0Spatrick       for (; I != End; I += Incr) {
440*d415bd75Srobert         auto MIB = BuildMI(MBB, MBBI, DL, get(Opc),
441*d415bd75Srobert                            TRI->getSubReg(DstReg, SubRegIdx + I));
442*d415bd75Srobert         if (UseVMV_V_I)
443*d415bd75Srobert           MIB = MIB.add(DefMBBI->getOperand(1));
444*d415bd75Srobert         else
445*d415bd75Srobert           MIB = MIB.addReg(TRI->getSubReg(SrcReg, SubRegIdx + I),
44673471bf0Spatrick                            getKillRegState(KillSrc));
447*d415bd75Srobert         if (UseVMV_V_V) {
448*d415bd75Srobert           const MCInstrDesc &Desc = DefMBBI->getDesc();
449*d415bd75Srobert           MIB.add(DefMBBI->getOperand(RISCVII::getVLOpNum(Desc))); // AVL
450*d415bd75Srobert           MIB.add(DefMBBI->getOperand(RISCVII::getSEWOpNum(Desc))); // SEW
451*d415bd75Srobert           MIB.addReg(RISCV::VL, RegState::Implicit);
452*d415bd75Srobert           MIB.addReg(RISCV::VTYPE, RegState::Implicit);
453*d415bd75Srobert         }
45473471bf0Spatrick       }
45573471bf0Spatrick     }
45673471bf0Spatrick   } else {
45709467b48Spatrick     BuildMI(MBB, MBBI, DL, get(Opc), DstReg)
45809467b48Spatrick         .addReg(SrcReg, getKillRegState(KillSrc))
45909467b48Spatrick         .addReg(SrcReg, getKillRegState(KillSrc));
46009467b48Spatrick   }
46173471bf0Spatrick }
46209467b48Spatrick 
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register SrcReg,bool IsKill,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const46309467b48Spatrick void RISCVInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
46409467b48Spatrick                                          MachineBasicBlock::iterator I,
465097a140dSpatrick                                          Register SrcReg, bool IsKill, int FI,
46609467b48Spatrick                                          const TargetRegisterClass *RC,
467*d415bd75Srobert                                          const TargetRegisterInfo *TRI,
468*d415bd75Srobert                                          Register VReg) const {
46909467b48Spatrick   DebugLoc DL;
47009467b48Spatrick   if (I != MBB.end())
47109467b48Spatrick     DL = I->getDebugLoc();
47209467b48Spatrick 
47373471bf0Spatrick   MachineFunction *MF = MBB.getParent();
47473471bf0Spatrick   MachineFrameInfo &MFI = MF->getFrameInfo();
47509467b48Spatrick 
47673471bf0Spatrick   unsigned Opcode;
47773471bf0Spatrick   bool IsScalableVector = true;
47873471bf0Spatrick   if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
47909467b48Spatrick     Opcode = TRI->getRegSizeInBits(RISCV::GPRRegClass) == 32 ?
48009467b48Spatrick              RISCV::SW : RISCV::SD;
48173471bf0Spatrick     IsScalableVector = false;
48273471bf0Spatrick   } else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
48373471bf0Spatrick     Opcode = RISCV::FSH;
48473471bf0Spatrick     IsScalableVector = false;
48573471bf0Spatrick   } else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
48609467b48Spatrick     Opcode = RISCV::FSW;
48773471bf0Spatrick     IsScalableVector = false;
48873471bf0Spatrick   } else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
48909467b48Spatrick     Opcode = RISCV::FSD;
49073471bf0Spatrick     IsScalableVector = false;
49173471bf0Spatrick   } else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
492*d415bd75Srobert     Opcode = RISCV::VS1R_V;
49373471bf0Spatrick   } else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
494*d415bd75Srobert     Opcode = RISCV::VS2R_V;
49573471bf0Spatrick   } else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
496*d415bd75Srobert     Opcode = RISCV::VS4R_V;
49773471bf0Spatrick   } else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
498*d415bd75Srobert     Opcode = RISCV::VS8R_V;
49973471bf0Spatrick   } else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
50073471bf0Spatrick     Opcode = RISCV::PseudoVSPILL2_M1;
50173471bf0Spatrick   else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
50273471bf0Spatrick     Opcode = RISCV::PseudoVSPILL2_M2;
50373471bf0Spatrick   else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
50473471bf0Spatrick     Opcode = RISCV::PseudoVSPILL2_M4;
50573471bf0Spatrick   else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
50673471bf0Spatrick     Opcode = RISCV::PseudoVSPILL3_M1;
50773471bf0Spatrick   else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
50873471bf0Spatrick     Opcode = RISCV::PseudoVSPILL3_M2;
50973471bf0Spatrick   else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
51073471bf0Spatrick     Opcode = RISCV::PseudoVSPILL4_M1;
51173471bf0Spatrick   else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
51273471bf0Spatrick     Opcode = RISCV::PseudoVSPILL4_M2;
51373471bf0Spatrick   else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
51473471bf0Spatrick     Opcode = RISCV::PseudoVSPILL5_M1;
51573471bf0Spatrick   else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
51673471bf0Spatrick     Opcode = RISCV::PseudoVSPILL6_M1;
51773471bf0Spatrick   else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
51873471bf0Spatrick     Opcode = RISCV::PseudoVSPILL7_M1;
51973471bf0Spatrick   else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
52073471bf0Spatrick     Opcode = RISCV::PseudoVSPILL8_M1;
52109467b48Spatrick   else
52209467b48Spatrick     llvm_unreachable("Can't store this register to stack slot");
52309467b48Spatrick 
52473471bf0Spatrick   if (IsScalableVector) {
52573471bf0Spatrick     MachineMemOperand *MMO = MF->getMachineMemOperand(
52673471bf0Spatrick         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
52773471bf0Spatrick         MemoryLocation::UnknownSize, MFI.getObjectAlign(FI));
52873471bf0Spatrick 
52973471bf0Spatrick     MFI.setStackID(FI, TargetStackID::ScalableVector);
530*d415bd75Srobert     BuildMI(MBB, I, DL, get(Opcode))
53173471bf0Spatrick         .addReg(SrcReg, getKillRegState(IsKill))
53273471bf0Spatrick         .addFrameIndex(FI)
53373471bf0Spatrick         .addMemOperand(MMO);
53473471bf0Spatrick   } else {
53573471bf0Spatrick     MachineMemOperand *MMO = MF->getMachineMemOperand(
53673471bf0Spatrick         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
53773471bf0Spatrick         MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
53873471bf0Spatrick 
53909467b48Spatrick     BuildMI(MBB, I, DL, get(Opcode))
54009467b48Spatrick         .addReg(SrcReg, getKillRegState(IsKill))
54109467b48Spatrick         .addFrameIndex(FI)
54273471bf0Spatrick         .addImm(0)
54373471bf0Spatrick         .addMemOperand(MMO);
54473471bf0Spatrick   }
54509467b48Spatrick }
54609467b48Spatrick 
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,Register DstReg,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const54709467b48Spatrick void RISCVInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
54809467b48Spatrick                                           MachineBasicBlock::iterator I,
549097a140dSpatrick                                           Register DstReg, int FI,
55009467b48Spatrick                                           const TargetRegisterClass *RC,
551*d415bd75Srobert                                           const TargetRegisterInfo *TRI,
552*d415bd75Srobert                                           Register VReg) const {
55309467b48Spatrick   DebugLoc DL;
55409467b48Spatrick   if (I != MBB.end())
55509467b48Spatrick     DL = I->getDebugLoc();
55609467b48Spatrick 
55773471bf0Spatrick   MachineFunction *MF = MBB.getParent();
55873471bf0Spatrick   MachineFrameInfo &MFI = MF->getFrameInfo();
55909467b48Spatrick 
56073471bf0Spatrick   unsigned Opcode;
56173471bf0Spatrick   bool IsScalableVector = true;
56273471bf0Spatrick   if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
56309467b48Spatrick     Opcode = TRI->getRegSizeInBits(RISCV::GPRRegClass) == 32 ?
56409467b48Spatrick              RISCV::LW : RISCV::LD;
56573471bf0Spatrick     IsScalableVector = false;
56673471bf0Spatrick   } else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
56773471bf0Spatrick     Opcode = RISCV::FLH;
56873471bf0Spatrick     IsScalableVector = false;
56973471bf0Spatrick   } else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
57009467b48Spatrick     Opcode = RISCV::FLW;
57173471bf0Spatrick     IsScalableVector = false;
57273471bf0Spatrick   } else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
57309467b48Spatrick     Opcode = RISCV::FLD;
57473471bf0Spatrick     IsScalableVector = false;
57573471bf0Spatrick   } else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
576*d415bd75Srobert     Opcode = RISCV::VL1RE8_V;
57773471bf0Spatrick   } else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
578*d415bd75Srobert     Opcode = RISCV::VL2RE8_V;
57973471bf0Spatrick   } else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
580*d415bd75Srobert     Opcode = RISCV::VL4RE8_V;
58173471bf0Spatrick   } else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
582*d415bd75Srobert     Opcode = RISCV::VL8RE8_V;
58373471bf0Spatrick   } else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
58473471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD2_M1;
58573471bf0Spatrick   else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
58673471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD2_M2;
58773471bf0Spatrick   else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
58873471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD2_M4;
58973471bf0Spatrick   else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
59073471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD3_M1;
59173471bf0Spatrick   else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
59273471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD3_M2;
59373471bf0Spatrick   else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
59473471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD4_M1;
59573471bf0Spatrick   else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
59673471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD4_M2;
59773471bf0Spatrick   else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
59873471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD5_M1;
59973471bf0Spatrick   else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
60073471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD6_M1;
60173471bf0Spatrick   else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
60273471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD7_M1;
60373471bf0Spatrick   else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
60473471bf0Spatrick     Opcode = RISCV::PseudoVRELOAD8_M1;
60509467b48Spatrick   else
60609467b48Spatrick     llvm_unreachable("Can't load this register from stack slot");
60709467b48Spatrick 
60873471bf0Spatrick   if (IsScalableVector) {
60973471bf0Spatrick     MachineMemOperand *MMO = MF->getMachineMemOperand(
61073471bf0Spatrick         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
61173471bf0Spatrick         MemoryLocation::UnknownSize, MFI.getObjectAlign(FI));
61273471bf0Spatrick 
61373471bf0Spatrick     MFI.setStackID(FI, TargetStackID::ScalableVector);
614*d415bd75Srobert     BuildMI(MBB, I, DL, get(Opcode), DstReg)
61573471bf0Spatrick         .addFrameIndex(FI)
61673471bf0Spatrick         .addMemOperand(MMO);
61773471bf0Spatrick   } else {
61873471bf0Spatrick     MachineMemOperand *MMO = MF->getMachineMemOperand(
61973471bf0Spatrick         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
62073471bf0Spatrick         MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
62173471bf0Spatrick 
62273471bf0Spatrick     BuildMI(MBB, I, DL, get(Opcode), DstReg)
62373471bf0Spatrick         .addFrameIndex(FI)
62473471bf0Spatrick         .addImm(0)
62573471bf0Spatrick         .addMemOperand(MMO);
62673471bf0Spatrick   }
62709467b48Spatrick }
62809467b48Spatrick 
foldMemoryOperandImpl(MachineFunction & MF,MachineInstr & MI,ArrayRef<unsigned> Ops,MachineBasicBlock::iterator InsertPt,int FrameIndex,LiveIntervals * LIS,VirtRegMap * VRM) const629*d415bd75Srobert MachineInstr *RISCVInstrInfo::foldMemoryOperandImpl(
630*d415bd75Srobert     MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
631*d415bd75Srobert     MachineBasicBlock::iterator InsertPt, int FrameIndex, LiveIntervals *LIS,
632*d415bd75Srobert     VirtRegMap *VRM) const {
633*d415bd75Srobert   const MachineFrameInfo &MFI = MF.getFrameInfo();
634*d415bd75Srobert 
635*d415bd75Srobert   // The below optimizations narrow the load so they are only valid for little
636*d415bd75Srobert   // endian.
637*d415bd75Srobert   // TODO: Support big endian by adding an offset into the frame object?
638*d415bd75Srobert   if (MF.getDataLayout().isBigEndian())
639*d415bd75Srobert     return nullptr;
640*d415bd75Srobert 
641*d415bd75Srobert   // Fold load from stack followed by sext.w into lw.
642*d415bd75Srobert   // TODO: Fold with sext.b, sext.h, zext.b, zext.h, zext.w?
643*d415bd75Srobert   if (Ops.size() != 1 || Ops[0] != 1)
644*d415bd75Srobert    return nullptr;
645*d415bd75Srobert 
646*d415bd75Srobert   unsigned LoadOpc;
647*d415bd75Srobert   switch (MI.getOpcode()) {
648*d415bd75Srobert   default:
649*d415bd75Srobert     if (RISCV::isSEXT_W(MI)) {
650*d415bd75Srobert       LoadOpc = RISCV::LW;
651*d415bd75Srobert       break;
652*d415bd75Srobert     }
653*d415bd75Srobert     if (RISCV::isZEXT_W(MI)) {
654*d415bd75Srobert       LoadOpc = RISCV::LWU;
655*d415bd75Srobert       break;
656*d415bd75Srobert     }
657*d415bd75Srobert     if (RISCV::isZEXT_B(MI)) {
658*d415bd75Srobert       LoadOpc = RISCV::LBU;
659*d415bd75Srobert       break;
660*d415bd75Srobert     }
661*d415bd75Srobert     return nullptr;
662*d415bd75Srobert   case RISCV::SEXT_H:
663*d415bd75Srobert     LoadOpc = RISCV::LH;
664*d415bd75Srobert     break;
665*d415bd75Srobert   case RISCV::SEXT_B:
666*d415bd75Srobert     LoadOpc = RISCV::LB;
667*d415bd75Srobert     break;
668*d415bd75Srobert   case RISCV::ZEXT_H_RV32:
669*d415bd75Srobert   case RISCV::ZEXT_H_RV64:
670*d415bd75Srobert     LoadOpc = RISCV::LHU;
671*d415bd75Srobert     break;
672*d415bd75Srobert   }
673*d415bd75Srobert 
674*d415bd75Srobert   MachineMemOperand *MMO = MF.getMachineMemOperand(
675*d415bd75Srobert       MachinePointerInfo::getFixedStack(MF, FrameIndex),
676*d415bd75Srobert       MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
677*d415bd75Srobert       MFI.getObjectAlign(FrameIndex));
678*d415bd75Srobert 
679*d415bd75Srobert   Register DstReg = MI.getOperand(0).getReg();
680*d415bd75Srobert   return BuildMI(*MI.getParent(), InsertPt, MI.getDebugLoc(), get(LoadOpc),
681*d415bd75Srobert                  DstReg)
682*d415bd75Srobert       .addFrameIndex(FrameIndex)
683*d415bd75Srobert       .addImm(0)
684*d415bd75Srobert       .addMemOperand(MMO);
685*d415bd75Srobert }
686*d415bd75Srobert 
movImm(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,Register DstReg,uint64_t Val,MachineInstr::MIFlag Flag) const68709467b48Spatrick void RISCVInstrInfo::movImm(MachineBasicBlock &MBB,
68809467b48Spatrick                             MachineBasicBlock::iterator MBBI,
68909467b48Spatrick                             const DebugLoc &DL, Register DstReg, uint64_t Val,
69009467b48Spatrick                             MachineInstr::MIFlag Flag) const {
69109467b48Spatrick   Register SrcReg = RISCV::X0;
69209467b48Spatrick 
69373471bf0Spatrick   if (!STI.is64Bit() && !isInt<32>(Val))
69409467b48Spatrick     report_fatal_error("Should only materialize 32-bit constants for RV32");
69509467b48Spatrick 
69673471bf0Spatrick   RISCVMatInt::InstSeq Seq =
69773471bf0Spatrick       RISCVMatInt::generateInstSeq(Val, STI.getFeatureBits());
69873471bf0Spatrick   assert(!Seq.empty());
69909467b48Spatrick 
70009467b48Spatrick   for (RISCVMatInt::Inst &Inst : Seq) {
701*d415bd75Srobert     switch (Inst.getOpndKind()) {
702*d415bd75Srobert     case RISCVMatInt::Imm:
703*d415bd75Srobert       BuildMI(MBB, MBBI, DL, get(Inst.getOpcode()), DstReg)
704*d415bd75Srobert           .addImm(Inst.getImm())
70509467b48Spatrick           .setMIFlag(Flag);
706*d415bd75Srobert       break;
707*d415bd75Srobert     case RISCVMatInt::RegX0:
708*d415bd75Srobert       BuildMI(MBB, MBBI, DL, get(Inst.getOpcode()), DstReg)
70973471bf0Spatrick           .addReg(SrcReg, RegState::Kill)
71073471bf0Spatrick           .addReg(RISCV::X0)
71173471bf0Spatrick           .setMIFlag(Flag);
712*d415bd75Srobert       break;
713*d415bd75Srobert     case RISCVMatInt::RegReg:
714*d415bd75Srobert       BuildMI(MBB, MBBI, DL, get(Inst.getOpcode()), DstReg)
71509467b48Spatrick           .addReg(SrcReg, RegState::Kill)
716*d415bd75Srobert           .addReg(SrcReg, RegState::Kill)
71709467b48Spatrick           .setMIFlag(Flag);
718*d415bd75Srobert       break;
719*d415bd75Srobert     case RISCVMatInt::RegImm:
720*d415bd75Srobert       BuildMI(MBB, MBBI, DL, get(Inst.getOpcode()), DstReg)
721*d415bd75Srobert           .addReg(SrcReg, RegState::Kill)
722*d415bd75Srobert           .addImm(Inst.getImm())
723*d415bd75Srobert           .setMIFlag(Flag);
724*d415bd75Srobert       break;
72509467b48Spatrick     }
726*d415bd75Srobert 
72709467b48Spatrick     // Only the first instruction has X0 as its source.
728*d415bd75Srobert     SrcReg = DstReg;
729*d415bd75Srobert   }
730*d415bd75Srobert }
731*d415bd75Srobert 
getCondFromBranchOpc(unsigned Opc)732*d415bd75Srobert static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
733*d415bd75Srobert   switch (Opc) {
734*d415bd75Srobert   default:
735*d415bd75Srobert     return RISCVCC::COND_INVALID;
736*d415bd75Srobert   case RISCV::BEQ:
737*d415bd75Srobert     return RISCVCC::COND_EQ;
738*d415bd75Srobert   case RISCV::BNE:
739*d415bd75Srobert     return RISCVCC::COND_NE;
740*d415bd75Srobert   case RISCV::BLT:
741*d415bd75Srobert     return RISCVCC::COND_LT;
742*d415bd75Srobert   case RISCV::BGE:
743*d415bd75Srobert     return RISCVCC::COND_GE;
744*d415bd75Srobert   case RISCV::BLTU:
745*d415bd75Srobert     return RISCVCC::COND_LTU;
746*d415bd75Srobert   case RISCV::BGEU:
747*d415bd75Srobert     return RISCVCC::COND_GEU;
74809467b48Spatrick   }
74909467b48Spatrick }
75009467b48Spatrick 
75109467b48Spatrick // The contents of values added to Cond are not examined outside of
75209467b48Spatrick // RISCVInstrInfo, giving us flexibility in what to push to it. For RISCV, we
75309467b48Spatrick // push BranchOpcode, Reg1, Reg2.
parseCondBranch(MachineInstr & LastInst,MachineBasicBlock * & Target,SmallVectorImpl<MachineOperand> & Cond)75409467b48Spatrick static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
75509467b48Spatrick                             SmallVectorImpl<MachineOperand> &Cond) {
75609467b48Spatrick   // Block ends with fall-through condbranch.
75709467b48Spatrick   assert(LastInst.getDesc().isConditionalBranch() &&
75809467b48Spatrick          "Unknown conditional branch");
75909467b48Spatrick   Target = LastInst.getOperand(2).getMBB();
760*d415bd75Srobert   unsigned CC = getCondFromBranchOpc(LastInst.getOpcode());
761*d415bd75Srobert   Cond.push_back(MachineOperand::CreateImm(CC));
76209467b48Spatrick   Cond.push_back(LastInst.getOperand(0));
76309467b48Spatrick   Cond.push_back(LastInst.getOperand(1));
76409467b48Spatrick }
76509467b48Spatrick 
getBrCond(RISCVCC::CondCode CC) const766*d415bd75Srobert const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC) const {
767*d415bd75Srobert   switch (CC) {
768*d415bd75Srobert   default:
769*d415bd75Srobert     llvm_unreachable("Unknown condition code!");
770*d415bd75Srobert   case RISCVCC::COND_EQ:
771*d415bd75Srobert     return get(RISCV::BEQ);
772*d415bd75Srobert   case RISCVCC::COND_NE:
773*d415bd75Srobert     return get(RISCV::BNE);
774*d415bd75Srobert   case RISCVCC::COND_LT:
775*d415bd75Srobert     return get(RISCV::BLT);
776*d415bd75Srobert   case RISCVCC::COND_GE:
777*d415bd75Srobert     return get(RISCV::BGE);
778*d415bd75Srobert   case RISCVCC::COND_LTU:
779*d415bd75Srobert     return get(RISCV::BLTU);
780*d415bd75Srobert   case RISCVCC::COND_GEU:
781*d415bd75Srobert     return get(RISCV::BGEU);
782*d415bd75Srobert   }
783*d415bd75Srobert }
784*d415bd75Srobert 
getOppositeBranchCondition(RISCVCC::CondCode CC)785*d415bd75Srobert RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
786*d415bd75Srobert   switch (CC) {
78709467b48Spatrick   default:
78809467b48Spatrick     llvm_unreachable("Unrecognized conditional branch");
789*d415bd75Srobert   case RISCVCC::COND_EQ:
790*d415bd75Srobert     return RISCVCC::COND_NE;
791*d415bd75Srobert   case RISCVCC::COND_NE:
792*d415bd75Srobert     return RISCVCC::COND_EQ;
793*d415bd75Srobert   case RISCVCC::COND_LT:
794*d415bd75Srobert     return RISCVCC::COND_GE;
795*d415bd75Srobert   case RISCVCC::COND_GE:
796*d415bd75Srobert     return RISCVCC::COND_LT;
797*d415bd75Srobert   case RISCVCC::COND_LTU:
798*d415bd75Srobert     return RISCVCC::COND_GEU;
799*d415bd75Srobert   case RISCVCC::COND_GEU:
800*d415bd75Srobert     return RISCVCC::COND_LTU;
80109467b48Spatrick   }
80209467b48Spatrick }
80309467b48Spatrick 
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const80409467b48Spatrick bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
80509467b48Spatrick                                    MachineBasicBlock *&TBB,
80609467b48Spatrick                                    MachineBasicBlock *&FBB,
80709467b48Spatrick                                    SmallVectorImpl<MachineOperand> &Cond,
80809467b48Spatrick                                    bool AllowModify) const {
80909467b48Spatrick   TBB = FBB = nullptr;
81009467b48Spatrick   Cond.clear();
81109467b48Spatrick 
81209467b48Spatrick   // If the block has no terminators, it just falls into the block after it.
81309467b48Spatrick   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
81409467b48Spatrick   if (I == MBB.end() || !isUnpredicatedTerminator(*I))
81509467b48Spatrick     return false;
81609467b48Spatrick 
81709467b48Spatrick   // Count the number of terminators and find the first unconditional or
81809467b48Spatrick   // indirect branch.
81909467b48Spatrick   MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
82009467b48Spatrick   int NumTerminators = 0;
82109467b48Spatrick   for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
82209467b48Spatrick        J++) {
82309467b48Spatrick     NumTerminators++;
82409467b48Spatrick     if (J->getDesc().isUnconditionalBranch() ||
82509467b48Spatrick         J->getDesc().isIndirectBranch()) {
82609467b48Spatrick       FirstUncondOrIndirectBr = J.getReverse();
82709467b48Spatrick     }
82809467b48Spatrick   }
82909467b48Spatrick 
83009467b48Spatrick   // If AllowModify is true, we can erase any terminators after
83109467b48Spatrick   // FirstUncondOrIndirectBR.
83209467b48Spatrick   if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
83309467b48Spatrick     while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
83409467b48Spatrick       std::next(FirstUncondOrIndirectBr)->eraseFromParent();
83509467b48Spatrick       NumTerminators--;
83609467b48Spatrick     }
83709467b48Spatrick     I = FirstUncondOrIndirectBr;
83809467b48Spatrick   }
83909467b48Spatrick 
84009467b48Spatrick   // We can't handle blocks that end in an indirect branch.
84109467b48Spatrick   if (I->getDesc().isIndirectBranch())
84209467b48Spatrick     return true;
84309467b48Spatrick 
84409467b48Spatrick   // We can't handle blocks with more than 2 terminators.
84509467b48Spatrick   if (NumTerminators > 2)
84609467b48Spatrick     return true;
84709467b48Spatrick 
84809467b48Spatrick   // Handle a single unconditional branch.
84909467b48Spatrick   if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
850097a140dSpatrick     TBB = getBranchDestBlock(*I);
85109467b48Spatrick     return false;
85209467b48Spatrick   }
85309467b48Spatrick 
85409467b48Spatrick   // Handle a single conditional branch.
85509467b48Spatrick   if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
85609467b48Spatrick     parseCondBranch(*I, TBB, Cond);
85709467b48Spatrick     return false;
85809467b48Spatrick   }
85909467b48Spatrick 
86009467b48Spatrick   // Handle a conditional branch followed by an unconditional branch.
86109467b48Spatrick   if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
86209467b48Spatrick       I->getDesc().isUnconditionalBranch()) {
86309467b48Spatrick     parseCondBranch(*std::prev(I), TBB, Cond);
864097a140dSpatrick     FBB = getBranchDestBlock(*I);
86509467b48Spatrick     return false;
86609467b48Spatrick   }
86709467b48Spatrick 
86809467b48Spatrick   // Otherwise, we can't handle this.
86909467b48Spatrick   return true;
87009467b48Spatrick }
87109467b48Spatrick 
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const87209467b48Spatrick unsigned RISCVInstrInfo::removeBranch(MachineBasicBlock &MBB,
87309467b48Spatrick                                       int *BytesRemoved) const {
87409467b48Spatrick   if (BytesRemoved)
87509467b48Spatrick     *BytesRemoved = 0;
87609467b48Spatrick   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
87709467b48Spatrick   if (I == MBB.end())
87809467b48Spatrick     return 0;
87909467b48Spatrick 
88009467b48Spatrick   if (!I->getDesc().isUnconditionalBranch() &&
88109467b48Spatrick       !I->getDesc().isConditionalBranch())
88209467b48Spatrick     return 0;
88309467b48Spatrick 
88409467b48Spatrick   // Remove the branch.
88509467b48Spatrick   if (BytesRemoved)
88609467b48Spatrick     *BytesRemoved += getInstSizeInBytes(*I);
88709467b48Spatrick   I->eraseFromParent();
88809467b48Spatrick 
88909467b48Spatrick   I = MBB.end();
89009467b48Spatrick 
89109467b48Spatrick   if (I == MBB.begin())
89209467b48Spatrick     return 1;
89309467b48Spatrick   --I;
89409467b48Spatrick   if (!I->getDesc().isConditionalBranch())
89509467b48Spatrick     return 1;
89609467b48Spatrick 
89709467b48Spatrick   // Remove the branch.
89809467b48Spatrick   if (BytesRemoved)
89909467b48Spatrick     *BytesRemoved += getInstSizeInBytes(*I);
90009467b48Spatrick   I->eraseFromParent();
90109467b48Spatrick   return 2;
90209467b48Spatrick }
90309467b48Spatrick 
90409467b48Spatrick // Inserts a branch into the end of the specific MachineBasicBlock, returning
90509467b48Spatrick // the number of instructions inserted.
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const90609467b48Spatrick unsigned RISCVInstrInfo::insertBranch(
90709467b48Spatrick     MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
90809467b48Spatrick     ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
90909467b48Spatrick   if (BytesAdded)
91009467b48Spatrick     *BytesAdded = 0;
91109467b48Spatrick 
91209467b48Spatrick   // Shouldn't be a fall through.
913097a140dSpatrick   assert(TBB && "insertBranch must not be told to insert a fallthrough");
91409467b48Spatrick   assert((Cond.size() == 3 || Cond.size() == 0) &&
91509467b48Spatrick          "RISCV branch conditions have two components!");
91609467b48Spatrick 
91709467b48Spatrick   // Unconditional branch.
91809467b48Spatrick   if (Cond.empty()) {
91909467b48Spatrick     MachineInstr &MI = *BuildMI(&MBB, DL, get(RISCV::PseudoBR)).addMBB(TBB);
92009467b48Spatrick     if (BytesAdded)
92109467b48Spatrick       *BytesAdded += getInstSizeInBytes(MI);
92209467b48Spatrick     return 1;
92309467b48Spatrick   }
92409467b48Spatrick 
92509467b48Spatrick   // Either a one or two-way conditional branch.
926*d415bd75Srobert   auto CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
92709467b48Spatrick   MachineInstr &CondMI =
928*d415bd75Srobert       *BuildMI(&MBB, DL, getBrCond(CC)).add(Cond[1]).add(Cond[2]).addMBB(TBB);
92909467b48Spatrick   if (BytesAdded)
93009467b48Spatrick     *BytesAdded += getInstSizeInBytes(CondMI);
93109467b48Spatrick 
93209467b48Spatrick   // One-way conditional branch.
93309467b48Spatrick   if (!FBB)
93409467b48Spatrick     return 1;
93509467b48Spatrick 
93609467b48Spatrick   // Two-way conditional branch.
93709467b48Spatrick   MachineInstr &MI = *BuildMI(&MBB, DL, get(RISCV::PseudoBR)).addMBB(FBB);
93809467b48Spatrick   if (BytesAdded)
93909467b48Spatrick     *BytesAdded += getInstSizeInBytes(MI);
94009467b48Spatrick   return 2;
94109467b48Spatrick }
94209467b48Spatrick 
insertIndirectBranch(MachineBasicBlock & MBB,MachineBasicBlock & DestBB,MachineBasicBlock & RestoreBB,const DebugLoc & DL,int64_t BrOffset,RegScavenger * RS) const943*d415bd75Srobert void RISCVInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
94409467b48Spatrick                                           MachineBasicBlock &DestBB,
945*d415bd75Srobert                                           MachineBasicBlock &RestoreBB,
946*d415bd75Srobert                                           const DebugLoc &DL, int64_t BrOffset,
94709467b48Spatrick                                           RegScavenger *RS) const {
94809467b48Spatrick   assert(RS && "RegScavenger required for long branching");
94909467b48Spatrick   assert(MBB.empty() &&
95009467b48Spatrick          "new block should be inserted for expanding unconditional branch");
95109467b48Spatrick   assert(MBB.pred_size() == 1);
952*d415bd75Srobert   assert(RestoreBB.empty() &&
953*d415bd75Srobert          "restore block should be inserted for restoring clobbered registers");
95409467b48Spatrick 
95509467b48Spatrick   MachineFunction *MF = MBB.getParent();
95609467b48Spatrick   MachineRegisterInfo &MRI = MF->getRegInfo();
957*d415bd75Srobert   RISCVMachineFunctionInfo *RVFI = MF->getInfo<RISCVMachineFunctionInfo>();
958*d415bd75Srobert   const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
95909467b48Spatrick 
96009467b48Spatrick   if (!isInt<32>(BrOffset))
96109467b48Spatrick     report_fatal_error(
96209467b48Spatrick         "Branch offsets outside of the signed 32-bit range not supported");
96309467b48Spatrick 
96409467b48Spatrick   // FIXME: A virtual register must be used initially, as the register
96509467b48Spatrick   // scavenger won't work with empty blocks (SIInstrInfo::insertIndirectBranch
96609467b48Spatrick   // uses the same workaround).
96709467b48Spatrick   Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
96809467b48Spatrick   auto II = MBB.end();
969*d415bd75Srobert   // We may also update the jump target to RestoreBB later.
970097a140dSpatrick   MachineInstr &MI = *BuildMI(MBB, II, DL, get(RISCV::PseudoJump))
971097a140dSpatrick                           .addReg(ScratchReg, RegState::Define | RegState::Dead)
972097a140dSpatrick                           .addMBB(&DestBB, RISCVII::MO_CALL);
97309467b48Spatrick 
97409467b48Spatrick   RS->enterBasicBlockEnd(MBB);
975*d415bd75Srobert   Register TmpGPR =
976*d415bd75Srobert       RS->scavengeRegisterBackwards(RISCV::GPRRegClass, MI.getIterator(),
977*d415bd75Srobert                                     /*RestoreAfter=*/false, /*SpAdj=*/0,
978*d415bd75Srobert                                     /*AllowSpill=*/false);
979*d415bd75Srobert   if (TmpGPR != RISCV::NoRegister)
980*d415bd75Srobert     RS->setRegUsed(TmpGPR);
981*d415bd75Srobert   else {
982*d415bd75Srobert     // The case when there is no scavenged register needs special handling.
983*d415bd75Srobert 
984*d415bd75Srobert     // Pick s11 because it doesn't make a difference.
985*d415bd75Srobert     TmpGPR = RISCV::X27;
986*d415bd75Srobert 
987*d415bd75Srobert     int FrameIndex = RVFI->getBranchRelaxationScratchFrameIndex();
988*d415bd75Srobert     if (FrameIndex == -1)
989*d415bd75Srobert       report_fatal_error("underestimated function size");
990*d415bd75Srobert 
991*d415bd75Srobert     storeRegToStackSlot(MBB, MI, TmpGPR, /*IsKill=*/true, FrameIndex,
992*d415bd75Srobert                         &RISCV::GPRRegClass, TRI, Register());
993*d415bd75Srobert     TRI->eliminateFrameIndex(std::prev(MI.getIterator()),
994*d415bd75Srobert                              /*SpAdj=*/0, /*FIOperandNum=*/1);
995*d415bd75Srobert 
996*d415bd75Srobert     MI.getOperand(1).setMBB(&RestoreBB);
997*d415bd75Srobert 
998*d415bd75Srobert     loadRegFromStackSlot(RestoreBB, RestoreBB.end(), TmpGPR, FrameIndex,
999*d415bd75Srobert                          &RISCV::GPRRegClass, TRI, Register());
1000*d415bd75Srobert     TRI->eliminateFrameIndex(RestoreBB.back(),
1001*d415bd75Srobert                              /*SpAdj=*/0, /*FIOperandNum=*/1);
1002*d415bd75Srobert   }
1003*d415bd75Srobert 
1004*d415bd75Srobert   MRI.replaceRegWith(ScratchReg, TmpGPR);
100509467b48Spatrick   MRI.clearVirtRegs();
100609467b48Spatrick }
100709467b48Spatrick 
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const100809467b48Spatrick bool RISCVInstrInfo::reverseBranchCondition(
100909467b48Spatrick     SmallVectorImpl<MachineOperand> &Cond) const {
101009467b48Spatrick   assert((Cond.size() == 3) && "Invalid branch condition!");
1011*d415bd75Srobert   auto CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
1012*d415bd75Srobert   Cond[0].setImm(getOppositeBranchCondition(CC));
101309467b48Spatrick   return false;
101409467b48Spatrick }
101509467b48Spatrick 
101609467b48Spatrick MachineBasicBlock *
getBranchDestBlock(const MachineInstr & MI) const101709467b48Spatrick RISCVInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
101809467b48Spatrick   assert(MI.getDesc().isBranch() && "Unexpected opcode!");
101909467b48Spatrick   // The branch target is always the last operand.
102009467b48Spatrick   int NumOp = MI.getNumExplicitOperands();
102109467b48Spatrick   return MI.getOperand(NumOp - 1).getMBB();
102209467b48Spatrick }
102309467b48Spatrick 
isBranchOffsetInRange(unsigned BranchOp,int64_t BrOffset) const102409467b48Spatrick bool RISCVInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
102509467b48Spatrick                                            int64_t BrOffset) const {
1026097a140dSpatrick   unsigned XLen = STI.getXLen();
102709467b48Spatrick   // Ideally we could determine the supported branch offset from the
102809467b48Spatrick   // RISCVII::FormMask, but this can't be used for Pseudo instructions like
102909467b48Spatrick   // PseudoBR.
103009467b48Spatrick   switch (BranchOp) {
103109467b48Spatrick   default:
103209467b48Spatrick     llvm_unreachable("Unexpected opcode!");
103309467b48Spatrick   case RISCV::BEQ:
103409467b48Spatrick   case RISCV::BNE:
103509467b48Spatrick   case RISCV::BLT:
103609467b48Spatrick   case RISCV::BGE:
103709467b48Spatrick   case RISCV::BLTU:
103809467b48Spatrick   case RISCV::BGEU:
103909467b48Spatrick     return isIntN(13, BrOffset);
104009467b48Spatrick   case RISCV::JAL:
104109467b48Spatrick   case RISCV::PseudoBR:
104209467b48Spatrick     return isIntN(21, BrOffset);
1043097a140dSpatrick   case RISCV::PseudoJump:
1044097a140dSpatrick     return isIntN(32, SignExtend64(BrOffset + 0x800, XLen));
104509467b48Spatrick   }
104609467b48Spatrick }
104709467b48Spatrick 
1048*d415bd75Srobert // If the operation has a predicated pseudo instruction, return the pseudo
1049*d415bd75Srobert // instruction opcode. Otherwise, return RISCV::INSTRUCTION_LIST_END.
1050*d415bd75Srobert // TODO: Support more operations.
getPredicatedOpcode(unsigned Opcode)1051*d415bd75Srobert unsigned getPredicatedOpcode(unsigned Opcode) {
1052*d415bd75Srobert   switch (Opcode) {
1053*d415bd75Srobert   case RISCV::ADD:   return RISCV::PseudoCCADD;   break;
1054*d415bd75Srobert   case RISCV::SUB:   return RISCV::PseudoCCSUB;   break;
1055*d415bd75Srobert   case RISCV::AND:   return RISCV::PseudoCCAND;   break;
1056*d415bd75Srobert   case RISCV::OR:    return RISCV::PseudoCCOR;    break;
1057*d415bd75Srobert   case RISCV::XOR:   return RISCV::PseudoCCXOR;   break;
1058*d415bd75Srobert 
1059*d415bd75Srobert   case RISCV::ADDW:  return RISCV::PseudoCCADDW;  break;
1060*d415bd75Srobert   case RISCV::SUBW:  return RISCV::PseudoCCSUBW;  break;
1061*d415bd75Srobert   }
1062*d415bd75Srobert 
1063*d415bd75Srobert   return RISCV::INSTRUCTION_LIST_END;
1064*d415bd75Srobert }
1065*d415bd75Srobert 
1066*d415bd75Srobert /// Identify instructions that can be folded into a CCMOV instruction, and
1067*d415bd75Srobert /// return the defining instruction.
canFoldAsPredicatedOp(Register Reg,const MachineRegisterInfo & MRI,const TargetInstrInfo * TII)1068*d415bd75Srobert static MachineInstr *canFoldAsPredicatedOp(Register Reg,
1069*d415bd75Srobert                                            const MachineRegisterInfo &MRI,
1070*d415bd75Srobert                                            const TargetInstrInfo *TII) {
1071*d415bd75Srobert   if (!Reg.isVirtual())
1072*d415bd75Srobert     return nullptr;
1073*d415bd75Srobert   if (!MRI.hasOneNonDBGUse(Reg))
1074*d415bd75Srobert     return nullptr;
1075*d415bd75Srobert   MachineInstr *MI = MRI.getVRegDef(Reg);
1076*d415bd75Srobert   if (!MI)
1077*d415bd75Srobert     return nullptr;
1078*d415bd75Srobert   // Check if MI can be predicated and folded into the CCMOV.
1079*d415bd75Srobert   if (getPredicatedOpcode(MI->getOpcode()) == RISCV::INSTRUCTION_LIST_END)
1080*d415bd75Srobert     return nullptr;
1081*d415bd75Srobert   // Check if MI has any other defs or physreg uses.
1082*d415bd75Srobert   for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) {
1083*d415bd75Srobert     const MachineOperand &MO = MI->getOperand(i);
1084*d415bd75Srobert     // Reject frame index operands, PEI can't handle the predicated pseudos.
1085*d415bd75Srobert     if (MO.isFI() || MO.isCPI() || MO.isJTI())
1086*d415bd75Srobert       return nullptr;
1087*d415bd75Srobert     if (!MO.isReg())
1088*d415bd75Srobert       continue;
1089*d415bd75Srobert     // MI can't have any tied operands, that would conflict with predication.
1090*d415bd75Srobert     if (MO.isTied())
1091*d415bd75Srobert       return nullptr;
1092*d415bd75Srobert     if (MO.isDef())
1093*d415bd75Srobert       return nullptr;
1094*d415bd75Srobert     // Allow constant physregs.
1095*d415bd75Srobert     if (MO.getReg().isPhysical() && !MRI.isConstantPhysReg(MO.getReg()))
1096*d415bd75Srobert       return nullptr;
1097*d415bd75Srobert   }
1098*d415bd75Srobert   bool DontMoveAcrossStores = true;
1099*d415bd75Srobert   if (!MI->isSafeToMove(/* AliasAnalysis = */ nullptr, DontMoveAcrossStores))
1100*d415bd75Srobert     return nullptr;
1101*d415bd75Srobert   return MI;
1102*d415bd75Srobert }
1103*d415bd75Srobert 
analyzeSelect(const MachineInstr & MI,SmallVectorImpl<MachineOperand> & Cond,unsigned & TrueOp,unsigned & FalseOp,bool & Optimizable) const1104*d415bd75Srobert bool RISCVInstrInfo::analyzeSelect(const MachineInstr &MI,
1105*d415bd75Srobert                                    SmallVectorImpl<MachineOperand> &Cond,
1106*d415bd75Srobert                                    unsigned &TrueOp, unsigned &FalseOp,
1107*d415bd75Srobert                                    bool &Optimizable) const {
1108*d415bd75Srobert   assert(MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1109*d415bd75Srobert          "Unknown select instruction");
1110*d415bd75Srobert   // CCMOV operands:
1111*d415bd75Srobert   // 0: Def.
1112*d415bd75Srobert   // 1: LHS of compare.
1113*d415bd75Srobert   // 2: RHS of compare.
1114*d415bd75Srobert   // 3: Condition code.
1115*d415bd75Srobert   // 4: False use.
1116*d415bd75Srobert   // 5: True use.
1117*d415bd75Srobert   TrueOp = 5;
1118*d415bd75Srobert   FalseOp = 4;
1119*d415bd75Srobert   Cond.push_back(MI.getOperand(1));
1120*d415bd75Srobert   Cond.push_back(MI.getOperand(2));
1121*d415bd75Srobert   Cond.push_back(MI.getOperand(3));
1122*d415bd75Srobert   // We can only fold when we support short forward branch opt.
1123*d415bd75Srobert   Optimizable = STI.hasShortForwardBranchOpt();
1124*d415bd75Srobert   return false;
1125*d415bd75Srobert }
1126*d415bd75Srobert 
1127*d415bd75Srobert MachineInstr *
optimizeSelect(MachineInstr & MI,SmallPtrSetImpl<MachineInstr * > & SeenMIs,bool PreferFalse) const1128*d415bd75Srobert RISCVInstrInfo::optimizeSelect(MachineInstr &MI,
1129*d415bd75Srobert                                SmallPtrSetImpl<MachineInstr *> &SeenMIs,
1130*d415bd75Srobert                                bool PreferFalse) const {
1131*d415bd75Srobert   assert(MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1132*d415bd75Srobert          "Unknown select instruction");
1133*d415bd75Srobert   if (!STI.hasShortForwardBranchOpt())
1134*d415bd75Srobert     return nullptr;
1135*d415bd75Srobert 
1136*d415bd75Srobert   MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
1137*d415bd75Srobert   MachineInstr *DefMI =
1138*d415bd75Srobert       canFoldAsPredicatedOp(MI.getOperand(5).getReg(), MRI, this);
1139*d415bd75Srobert   bool Invert = !DefMI;
1140*d415bd75Srobert   if (!DefMI)
1141*d415bd75Srobert     DefMI = canFoldAsPredicatedOp(MI.getOperand(4).getReg(), MRI, this);
1142*d415bd75Srobert   if (!DefMI)
1143*d415bd75Srobert     return nullptr;
1144*d415bd75Srobert 
1145*d415bd75Srobert   // Find new register class to use.
1146*d415bd75Srobert   MachineOperand FalseReg = MI.getOperand(Invert ? 5 : 4);
1147*d415bd75Srobert   Register DestReg = MI.getOperand(0).getReg();
1148*d415bd75Srobert   const TargetRegisterClass *PreviousClass = MRI.getRegClass(FalseReg.getReg());
1149*d415bd75Srobert   if (!MRI.constrainRegClass(DestReg, PreviousClass))
1150*d415bd75Srobert     return nullptr;
1151*d415bd75Srobert 
1152*d415bd75Srobert   unsigned PredOpc = getPredicatedOpcode(DefMI->getOpcode());
1153*d415bd75Srobert   assert(PredOpc != RISCV::INSTRUCTION_LIST_END && "Unexpected opcode!");
1154*d415bd75Srobert 
1155*d415bd75Srobert   // Create a new predicated version of DefMI.
1156*d415bd75Srobert   MachineInstrBuilder NewMI =
1157*d415bd75Srobert       BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), get(PredOpc), DestReg);
1158*d415bd75Srobert 
1159*d415bd75Srobert   // Copy the condition portion.
1160*d415bd75Srobert   NewMI.add(MI.getOperand(1));
1161*d415bd75Srobert   NewMI.add(MI.getOperand(2));
1162*d415bd75Srobert 
1163*d415bd75Srobert   // Add condition code, inverting if necessary.
1164*d415bd75Srobert   auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
1165*d415bd75Srobert   if (Invert)
1166*d415bd75Srobert     CC = RISCVCC::getOppositeBranchCondition(CC);
1167*d415bd75Srobert   NewMI.addImm(CC);
1168*d415bd75Srobert 
1169*d415bd75Srobert   // Copy the false register.
1170*d415bd75Srobert   NewMI.add(FalseReg);
1171*d415bd75Srobert 
1172*d415bd75Srobert   // Copy all the DefMI operands.
1173*d415bd75Srobert   const MCInstrDesc &DefDesc = DefMI->getDesc();
1174*d415bd75Srobert   for (unsigned i = 1, e = DefDesc.getNumOperands(); i != e; ++i)
1175*d415bd75Srobert     NewMI.add(DefMI->getOperand(i));
1176*d415bd75Srobert 
1177*d415bd75Srobert   // Update SeenMIs set: register newly created MI and erase removed DefMI.
1178*d415bd75Srobert   SeenMIs.insert(NewMI);
1179*d415bd75Srobert   SeenMIs.erase(DefMI);
1180*d415bd75Srobert 
1181*d415bd75Srobert   // If MI is inside a loop, and DefMI is outside the loop, then kill flags on
1182*d415bd75Srobert   // DefMI would be invalid when tranferred inside the loop.  Checking for a
1183*d415bd75Srobert   // loop is expensive, but at least remove kill flags if they are in different
1184*d415bd75Srobert   // BBs.
1185*d415bd75Srobert   if (DefMI->getParent() != MI.getParent())
1186*d415bd75Srobert     NewMI->clearKillInfo();
1187*d415bd75Srobert 
1188*d415bd75Srobert   // The caller will erase MI, but not DefMI.
1189*d415bd75Srobert   DefMI->eraseFromParent();
1190*d415bd75Srobert   return NewMI;
1191*d415bd75Srobert }
1192*d415bd75Srobert 
getInstSizeInBytes(const MachineInstr & MI) const119309467b48Spatrick unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
1194*d415bd75Srobert   if (MI.isMetaInstruction())
1195*d415bd75Srobert     return 0;
1196*d415bd75Srobert 
119709467b48Spatrick   unsigned Opcode = MI.getOpcode();
119809467b48Spatrick 
1199*d415bd75Srobert   if (Opcode == TargetOpcode::INLINEASM ||
1200*d415bd75Srobert       Opcode == TargetOpcode::INLINEASM_BR) {
120109467b48Spatrick     const MachineFunction &MF = *MI.getParent()->getParent();
120209467b48Spatrick     const auto &TM = static_cast<const RISCVTargetMachine &>(MF.getTarget());
120309467b48Spatrick     return getInlineAsmLength(MI.getOperand(0).getSymbolName(),
120409467b48Spatrick                               *TM.getMCAsmInfo());
120509467b48Spatrick   }
1206*d415bd75Srobert 
1207*d415bd75Srobert   if (MI.getParent() && MI.getParent()->getParent()) {
1208*d415bd75Srobert     if (isCompressibleInst(MI, STI))
1209*d415bd75Srobert       return 2;
121073471bf0Spatrick   }
1211*d415bd75Srobert   return get(Opcode).getSize();
121209467b48Spatrick }
121309467b48Spatrick 
isAsCheapAsAMove(const MachineInstr & MI) const121409467b48Spatrick bool RISCVInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const {
121509467b48Spatrick   const unsigned Opcode = MI.getOpcode();
121609467b48Spatrick   switch (Opcode) {
121709467b48Spatrick   default:
121809467b48Spatrick     break;
121973471bf0Spatrick   case RISCV::FSGNJ_D:
122073471bf0Spatrick   case RISCV::FSGNJ_S:
1221*d415bd75Srobert   case RISCV::FSGNJ_H:
122273471bf0Spatrick     // The canonical floating-point move is fsgnj rd, rs, rs.
122373471bf0Spatrick     return MI.getOperand(1).isReg() && MI.getOperand(2).isReg() &&
122473471bf0Spatrick            MI.getOperand(1).getReg() == MI.getOperand(2).getReg();
122509467b48Spatrick   case RISCV::ADDI:
122609467b48Spatrick   case RISCV::ORI:
122709467b48Spatrick   case RISCV::XORI:
122873471bf0Spatrick     return (MI.getOperand(1).isReg() &&
122973471bf0Spatrick             MI.getOperand(1).getReg() == RISCV::X0) ||
123073471bf0Spatrick            (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0);
123109467b48Spatrick   }
123209467b48Spatrick   return MI.isAsCheapAsAMove();
123309467b48Spatrick }
123409467b48Spatrick 
1235*d415bd75Srobert std::optional<DestSourcePair>
isCopyInstrImpl(const MachineInstr & MI) const123673471bf0Spatrick RISCVInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
123773471bf0Spatrick   if (MI.isMoveReg())
123873471bf0Spatrick     return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
123973471bf0Spatrick   switch (MI.getOpcode()) {
124073471bf0Spatrick   default:
124173471bf0Spatrick     break;
124273471bf0Spatrick   case RISCV::ADDI:
124373471bf0Spatrick     // Operand 1 can be a frameindex but callers expect registers
124473471bf0Spatrick     if (MI.getOperand(1).isReg() && MI.getOperand(2).isImm() &&
124573471bf0Spatrick         MI.getOperand(2).getImm() == 0)
124673471bf0Spatrick       return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
124773471bf0Spatrick     break;
124873471bf0Spatrick   case RISCV::FSGNJ_D:
124973471bf0Spatrick   case RISCV::FSGNJ_S:
1250*d415bd75Srobert   case RISCV::FSGNJ_H:
125173471bf0Spatrick     // The canonical floating-point move is fsgnj rd, rs, rs.
125273471bf0Spatrick     if (MI.getOperand(1).isReg() && MI.getOperand(2).isReg() &&
125373471bf0Spatrick         MI.getOperand(1).getReg() == MI.getOperand(2).getReg())
125473471bf0Spatrick       return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
125573471bf0Spatrick     break;
125673471bf0Spatrick   }
1257*d415bd75Srobert   return std::nullopt;
1258*d415bd75Srobert }
1259*d415bd75Srobert 
setSpecialOperandAttr(MachineInstr & OldMI1,MachineInstr & OldMI2,MachineInstr & NewMI1,MachineInstr & NewMI2) const1260*d415bd75Srobert void RISCVInstrInfo::setSpecialOperandAttr(MachineInstr &OldMI1,
1261*d415bd75Srobert                                            MachineInstr &OldMI2,
1262*d415bd75Srobert                                            MachineInstr &NewMI1,
1263*d415bd75Srobert                                            MachineInstr &NewMI2) const {
1264*d415bd75Srobert   uint16_t IntersectedFlags = OldMI1.getFlags() & OldMI2.getFlags();
1265*d415bd75Srobert   NewMI1.setFlags(IntersectedFlags);
1266*d415bd75Srobert   NewMI2.setFlags(IntersectedFlags);
1267*d415bd75Srobert }
1268*d415bd75Srobert 
finalizeInsInstrs(MachineInstr & Root,MachineCombinerPattern & P,SmallVectorImpl<MachineInstr * > & InsInstrs) const1269*d415bd75Srobert void RISCVInstrInfo::finalizeInsInstrs(
1270*d415bd75Srobert     MachineInstr &Root, MachineCombinerPattern &P,
1271*d415bd75Srobert     SmallVectorImpl<MachineInstr *> &InsInstrs) const {
1272*d415bd75Srobert   int16_t FrmOpIdx =
1273*d415bd75Srobert       RISCV::getNamedOperandIdx(Root.getOpcode(), RISCV::OpName::frm);
1274*d415bd75Srobert   if (FrmOpIdx < 0) {
1275*d415bd75Srobert     assert(all_of(InsInstrs,
1276*d415bd75Srobert                   [](MachineInstr *MI) {
1277*d415bd75Srobert                     return RISCV::getNamedOperandIdx(MI->getOpcode(),
1278*d415bd75Srobert                                                      RISCV::OpName::frm) < 0;
1279*d415bd75Srobert                   }) &&
1280*d415bd75Srobert            "New instructions require FRM whereas the old one does not have it");
1281*d415bd75Srobert     return;
1282*d415bd75Srobert   }
1283*d415bd75Srobert 
1284*d415bd75Srobert   const MachineOperand &FRM = Root.getOperand(FrmOpIdx);
1285*d415bd75Srobert   MachineFunction &MF = *Root.getMF();
1286*d415bd75Srobert 
1287*d415bd75Srobert   for (auto *NewMI : InsInstrs) {
1288*d415bd75Srobert     assert(static_cast<unsigned>(RISCV::getNamedOperandIdx(
1289*d415bd75Srobert                NewMI->getOpcode(), RISCV::OpName::frm)) ==
1290*d415bd75Srobert                NewMI->getNumOperands() &&
1291*d415bd75Srobert            "Instruction has unexpected number of operands");
1292*d415bd75Srobert     MachineInstrBuilder MIB(MF, NewMI);
1293*d415bd75Srobert     MIB.add(FRM);
1294*d415bd75Srobert     if (FRM.getImm() == RISCVFPRndMode::DYN)
1295*d415bd75Srobert       MIB.addUse(RISCV::FRM, RegState::Implicit);
1296*d415bd75Srobert   }
1297*d415bd75Srobert }
1298*d415bd75Srobert 
isFADD(unsigned Opc)1299*d415bd75Srobert static bool isFADD(unsigned Opc) {
1300*d415bd75Srobert   switch (Opc) {
1301*d415bd75Srobert   default:
1302*d415bd75Srobert     return false;
1303*d415bd75Srobert   case RISCV::FADD_H:
1304*d415bd75Srobert   case RISCV::FADD_S:
1305*d415bd75Srobert   case RISCV::FADD_D:
1306*d415bd75Srobert     return true;
1307*d415bd75Srobert   }
1308*d415bd75Srobert }
1309*d415bd75Srobert 
isFSUB(unsigned Opc)1310*d415bd75Srobert static bool isFSUB(unsigned Opc) {
1311*d415bd75Srobert   switch (Opc) {
1312*d415bd75Srobert   default:
1313*d415bd75Srobert     return false;
1314*d415bd75Srobert   case RISCV::FSUB_H:
1315*d415bd75Srobert   case RISCV::FSUB_S:
1316*d415bd75Srobert   case RISCV::FSUB_D:
1317*d415bd75Srobert     return true;
1318*d415bd75Srobert   }
1319*d415bd75Srobert }
1320*d415bd75Srobert 
isFMUL(unsigned Opc)1321*d415bd75Srobert static bool isFMUL(unsigned Opc) {
1322*d415bd75Srobert   switch (Opc) {
1323*d415bd75Srobert   default:
1324*d415bd75Srobert     return false;
1325*d415bd75Srobert   case RISCV::FMUL_H:
1326*d415bd75Srobert   case RISCV::FMUL_S:
1327*d415bd75Srobert   case RISCV::FMUL_D:
1328*d415bd75Srobert     return true;
1329*d415bd75Srobert   }
1330*d415bd75Srobert }
1331*d415bd75Srobert 
hasReassociableSibling(const MachineInstr & Inst,bool & Commuted) const1332*d415bd75Srobert bool RISCVInstrInfo::hasReassociableSibling(const MachineInstr &Inst,
1333*d415bd75Srobert                                             bool &Commuted) const {
1334*d415bd75Srobert   if (!TargetInstrInfo::hasReassociableSibling(Inst, Commuted))
1335*d415bd75Srobert     return false;
1336*d415bd75Srobert 
1337*d415bd75Srobert   const MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
1338*d415bd75Srobert   unsigned OperandIdx = Commuted ? 2 : 1;
1339*d415bd75Srobert   const MachineInstr &Sibling =
1340*d415bd75Srobert       *MRI.getVRegDef(Inst.getOperand(OperandIdx).getReg());
1341*d415bd75Srobert 
1342*d415bd75Srobert   int16_t InstFrmOpIdx =
1343*d415bd75Srobert       RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::frm);
1344*d415bd75Srobert   int16_t SiblingFrmOpIdx =
1345*d415bd75Srobert       RISCV::getNamedOperandIdx(Sibling.getOpcode(), RISCV::OpName::frm);
1346*d415bd75Srobert 
1347*d415bd75Srobert   return (InstFrmOpIdx < 0 && SiblingFrmOpIdx < 0) ||
1348*d415bd75Srobert          RISCV::hasEqualFRM(Inst, Sibling);
1349*d415bd75Srobert }
1350*d415bd75Srobert 
isAssociativeAndCommutative(const MachineInstr & Inst,bool Invert) const1351*d415bd75Srobert bool RISCVInstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
1352*d415bd75Srobert                                                  bool Invert) const {
1353*d415bd75Srobert   unsigned Opc = Inst.getOpcode();
1354*d415bd75Srobert   if (Invert) {
1355*d415bd75Srobert     auto InverseOpcode = getInverseOpcode(Opc);
1356*d415bd75Srobert     if (!InverseOpcode)
1357*d415bd75Srobert       return false;
1358*d415bd75Srobert     Opc = *InverseOpcode;
1359*d415bd75Srobert   }
1360*d415bd75Srobert 
1361*d415bd75Srobert   if (isFADD(Opc) || isFMUL(Opc))
1362*d415bd75Srobert     return Inst.getFlag(MachineInstr::MIFlag::FmReassoc) &&
1363*d415bd75Srobert            Inst.getFlag(MachineInstr::MIFlag::FmNsz);
1364*d415bd75Srobert 
1365*d415bd75Srobert   switch (Opc) {
1366*d415bd75Srobert   default:
1367*d415bd75Srobert     return false;
1368*d415bd75Srobert   case RISCV::ADD:
1369*d415bd75Srobert   case RISCV::ADDW:
1370*d415bd75Srobert   case RISCV::AND:
1371*d415bd75Srobert   case RISCV::OR:
1372*d415bd75Srobert   case RISCV::XOR:
1373*d415bd75Srobert   // From RISC-V ISA spec, if both the high and low bits of the same product
1374*d415bd75Srobert   // are required, then the recommended code sequence is:
1375*d415bd75Srobert   //
1376*d415bd75Srobert   // MULH[[S]U] rdh, rs1, rs2
1377*d415bd75Srobert   // MUL        rdl, rs1, rs2
1378*d415bd75Srobert   // (source register specifiers must be in same order and rdh cannot be the
1379*d415bd75Srobert   //  same as rs1 or rs2)
1380*d415bd75Srobert   //
1381*d415bd75Srobert   // Microarchitectures can then fuse these into a single multiply operation
1382*d415bd75Srobert   // instead of performing two separate multiplies.
1383*d415bd75Srobert   // MachineCombiner may reassociate MUL operands and lose the fusion
1384*d415bd75Srobert   // opportunity.
1385*d415bd75Srobert   case RISCV::MUL:
1386*d415bd75Srobert   case RISCV::MULW:
1387*d415bd75Srobert   case RISCV::MIN:
1388*d415bd75Srobert   case RISCV::MINU:
1389*d415bd75Srobert   case RISCV::MAX:
1390*d415bd75Srobert   case RISCV::MAXU:
1391*d415bd75Srobert   case RISCV::FMIN_H:
1392*d415bd75Srobert   case RISCV::FMIN_S:
1393*d415bd75Srobert   case RISCV::FMIN_D:
1394*d415bd75Srobert   case RISCV::FMAX_H:
1395*d415bd75Srobert   case RISCV::FMAX_S:
1396*d415bd75Srobert   case RISCV::FMAX_D:
1397*d415bd75Srobert     return true;
1398*d415bd75Srobert   }
1399*d415bd75Srobert 
1400*d415bd75Srobert   return false;
1401*d415bd75Srobert }
1402*d415bd75Srobert 
1403*d415bd75Srobert std::optional<unsigned>
getInverseOpcode(unsigned Opcode) const1404*d415bd75Srobert RISCVInstrInfo::getInverseOpcode(unsigned Opcode) const {
1405*d415bd75Srobert   switch (Opcode) {
1406*d415bd75Srobert   default:
1407*d415bd75Srobert     return std::nullopt;
1408*d415bd75Srobert   case RISCV::FADD_H:
1409*d415bd75Srobert     return RISCV::FSUB_H;
1410*d415bd75Srobert   case RISCV::FADD_S:
1411*d415bd75Srobert     return RISCV::FSUB_S;
1412*d415bd75Srobert   case RISCV::FADD_D:
1413*d415bd75Srobert     return RISCV::FSUB_D;
1414*d415bd75Srobert   case RISCV::FSUB_H:
1415*d415bd75Srobert     return RISCV::FADD_H;
1416*d415bd75Srobert   case RISCV::FSUB_S:
1417*d415bd75Srobert     return RISCV::FADD_S;
1418*d415bd75Srobert   case RISCV::FSUB_D:
1419*d415bd75Srobert     return RISCV::FADD_D;
1420*d415bd75Srobert   case RISCV::ADD:
1421*d415bd75Srobert     return RISCV::SUB;
1422*d415bd75Srobert   case RISCV::SUB:
1423*d415bd75Srobert     return RISCV::ADD;
1424*d415bd75Srobert   case RISCV::ADDW:
1425*d415bd75Srobert     return RISCV::SUBW;
1426*d415bd75Srobert   case RISCV::SUBW:
1427*d415bd75Srobert     return RISCV::ADDW;
1428*d415bd75Srobert   }
1429*d415bd75Srobert }
1430*d415bd75Srobert 
canCombineFPFusedMultiply(const MachineInstr & Root,const MachineOperand & MO,bool DoRegPressureReduce)1431*d415bd75Srobert static bool canCombineFPFusedMultiply(const MachineInstr &Root,
1432*d415bd75Srobert                                       const MachineOperand &MO,
1433*d415bd75Srobert                                       bool DoRegPressureReduce) {
1434*d415bd75Srobert   if (!MO.isReg() || !MO.getReg().isVirtual())
1435*d415bd75Srobert     return false;
1436*d415bd75Srobert   const MachineRegisterInfo &MRI = Root.getMF()->getRegInfo();
1437*d415bd75Srobert   MachineInstr *MI = MRI.getVRegDef(MO.getReg());
1438*d415bd75Srobert   if (!MI || !isFMUL(MI->getOpcode()))
1439*d415bd75Srobert     return false;
1440*d415bd75Srobert 
1441*d415bd75Srobert   if (!Root.getFlag(MachineInstr::MIFlag::FmContract) ||
1442*d415bd75Srobert       !MI->getFlag(MachineInstr::MIFlag::FmContract))
1443*d415bd75Srobert     return false;
1444*d415bd75Srobert 
1445*d415bd75Srobert   // Try combining even if fmul has more than one use as it eliminates
1446*d415bd75Srobert   // dependency between fadd(fsub) and fmul. However, it can extend liveranges
1447*d415bd75Srobert   // for fmul operands, so reject the transformation in register pressure
1448*d415bd75Srobert   // reduction mode.
1449*d415bd75Srobert   if (DoRegPressureReduce && !MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
1450*d415bd75Srobert     return false;
1451*d415bd75Srobert 
1452*d415bd75Srobert   // Do not combine instructions from different basic blocks.
1453*d415bd75Srobert   if (Root.getParent() != MI->getParent())
1454*d415bd75Srobert     return false;
1455*d415bd75Srobert   return RISCV::hasEqualFRM(Root, *MI);
1456*d415bd75Srobert }
1457*d415bd75Srobert 
1458*d415bd75Srobert static bool
getFPFusedMultiplyPatterns(MachineInstr & Root,SmallVectorImpl<MachineCombinerPattern> & Patterns,bool DoRegPressureReduce)1459*d415bd75Srobert getFPFusedMultiplyPatterns(MachineInstr &Root,
1460*d415bd75Srobert                            SmallVectorImpl<MachineCombinerPattern> &Patterns,
1461*d415bd75Srobert                            bool DoRegPressureReduce) {
1462*d415bd75Srobert   unsigned Opc = Root.getOpcode();
1463*d415bd75Srobert   bool IsFAdd = isFADD(Opc);
1464*d415bd75Srobert   if (!IsFAdd && !isFSUB(Opc))
1465*d415bd75Srobert     return false;
1466*d415bd75Srobert   bool Added = false;
1467*d415bd75Srobert   if (canCombineFPFusedMultiply(Root, Root.getOperand(1),
1468*d415bd75Srobert                                 DoRegPressureReduce)) {
1469*d415bd75Srobert     Patterns.push_back(IsFAdd ? MachineCombinerPattern::FMADD_AX
1470*d415bd75Srobert                               : MachineCombinerPattern::FMSUB);
1471*d415bd75Srobert     Added = true;
1472*d415bd75Srobert   }
1473*d415bd75Srobert   if (canCombineFPFusedMultiply(Root, Root.getOperand(2),
1474*d415bd75Srobert                                 DoRegPressureReduce)) {
1475*d415bd75Srobert     Patterns.push_back(IsFAdd ? MachineCombinerPattern::FMADD_XA
1476*d415bd75Srobert                               : MachineCombinerPattern::FNMSUB);
1477*d415bd75Srobert     Added = true;
1478*d415bd75Srobert   }
1479*d415bd75Srobert   return Added;
1480*d415bd75Srobert }
1481*d415bd75Srobert 
getFPPatterns(MachineInstr & Root,SmallVectorImpl<MachineCombinerPattern> & Patterns,bool DoRegPressureReduce)1482*d415bd75Srobert static bool getFPPatterns(MachineInstr &Root,
1483*d415bd75Srobert                           SmallVectorImpl<MachineCombinerPattern> &Patterns,
1484*d415bd75Srobert                           bool DoRegPressureReduce) {
1485*d415bd75Srobert   return getFPFusedMultiplyPatterns(Root, Patterns, DoRegPressureReduce);
1486*d415bd75Srobert }
1487*d415bd75Srobert 
getMachineCombinerPatterns(MachineInstr & Root,SmallVectorImpl<MachineCombinerPattern> & Patterns,bool DoRegPressureReduce) const1488*d415bd75Srobert bool RISCVInstrInfo::getMachineCombinerPatterns(
1489*d415bd75Srobert     MachineInstr &Root, SmallVectorImpl<MachineCombinerPattern> &Patterns,
1490*d415bd75Srobert     bool DoRegPressureReduce) const {
1491*d415bd75Srobert 
1492*d415bd75Srobert   if (getFPPatterns(Root, Patterns, DoRegPressureReduce))
1493*d415bd75Srobert     return true;
1494*d415bd75Srobert 
1495*d415bd75Srobert   return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns,
1496*d415bd75Srobert                                                      DoRegPressureReduce);
1497*d415bd75Srobert }
1498*d415bd75Srobert 
getFPFusedMultiplyOpcode(unsigned RootOpc,MachineCombinerPattern Pattern)1499*d415bd75Srobert static unsigned getFPFusedMultiplyOpcode(unsigned RootOpc,
1500*d415bd75Srobert                                          MachineCombinerPattern Pattern) {
1501*d415bd75Srobert   switch (RootOpc) {
1502*d415bd75Srobert   default:
1503*d415bd75Srobert     llvm_unreachable("Unexpected opcode");
1504*d415bd75Srobert   case RISCV::FADD_H:
1505*d415bd75Srobert     return RISCV::FMADD_H;
1506*d415bd75Srobert   case RISCV::FADD_S:
1507*d415bd75Srobert     return RISCV::FMADD_S;
1508*d415bd75Srobert   case RISCV::FADD_D:
1509*d415bd75Srobert     return RISCV::FMADD_D;
1510*d415bd75Srobert   case RISCV::FSUB_H:
1511*d415bd75Srobert     return Pattern == MachineCombinerPattern::FMSUB ? RISCV::FMSUB_H
1512*d415bd75Srobert                                                     : RISCV::FNMSUB_H;
1513*d415bd75Srobert   case RISCV::FSUB_S:
1514*d415bd75Srobert     return Pattern == MachineCombinerPattern::FMSUB ? RISCV::FMSUB_S
1515*d415bd75Srobert                                                     : RISCV::FNMSUB_S;
1516*d415bd75Srobert   case RISCV::FSUB_D:
1517*d415bd75Srobert     return Pattern == MachineCombinerPattern::FMSUB ? RISCV::FMSUB_D
1518*d415bd75Srobert                                                     : RISCV::FNMSUB_D;
1519*d415bd75Srobert   }
1520*d415bd75Srobert }
1521*d415bd75Srobert 
getAddendOperandIdx(MachineCombinerPattern Pattern)1522*d415bd75Srobert static unsigned getAddendOperandIdx(MachineCombinerPattern Pattern) {
1523*d415bd75Srobert   switch (Pattern) {
1524*d415bd75Srobert   default:
1525*d415bd75Srobert     llvm_unreachable("Unexpected pattern");
1526*d415bd75Srobert   case MachineCombinerPattern::FMADD_AX:
1527*d415bd75Srobert   case MachineCombinerPattern::FMSUB:
1528*d415bd75Srobert     return 2;
1529*d415bd75Srobert   case MachineCombinerPattern::FMADD_XA:
1530*d415bd75Srobert   case MachineCombinerPattern::FNMSUB:
1531*d415bd75Srobert     return 1;
1532*d415bd75Srobert   }
1533*d415bd75Srobert }
1534*d415bd75Srobert 
combineFPFusedMultiply(MachineInstr & Root,MachineInstr & Prev,MachineCombinerPattern Pattern,SmallVectorImpl<MachineInstr * > & InsInstrs,SmallVectorImpl<MachineInstr * > & DelInstrs)1535*d415bd75Srobert static void combineFPFusedMultiply(MachineInstr &Root, MachineInstr &Prev,
1536*d415bd75Srobert                                    MachineCombinerPattern Pattern,
1537*d415bd75Srobert                                    SmallVectorImpl<MachineInstr *> &InsInstrs,
1538*d415bd75Srobert                                    SmallVectorImpl<MachineInstr *> &DelInstrs) {
1539*d415bd75Srobert   MachineFunction *MF = Root.getMF();
1540*d415bd75Srobert   MachineRegisterInfo &MRI = MF->getRegInfo();
1541*d415bd75Srobert   const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
1542*d415bd75Srobert 
1543*d415bd75Srobert   MachineOperand &Mul1 = Prev.getOperand(1);
1544*d415bd75Srobert   MachineOperand &Mul2 = Prev.getOperand(2);
1545*d415bd75Srobert   MachineOperand &Dst = Root.getOperand(0);
1546*d415bd75Srobert   MachineOperand &Addend = Root.getOperand(getAddendOperandIdx(Pattern));
1547*d415bd75Srobert 
1548*d415bd75Srobert   Register DstReg = Dst.getReg();
1549*d415bd75Srobert   unsigned FusedOpc = getFPFusedMultiplyOpcode(Root.getOpcode(), Pattern);
1550*d415bd75Srobert   auto IntersectedFlags = Root.getFlags() & Prev.getFlags();
1551*d415bd75Srobert   DebugLoc MergedLoc =
1552*d415bd75Srobert       DILocation::getMergedLocation(Root.getDebugLoc(), Prev.getDebugLoc());
1553*d415bd75Srobert 
1554*d415bd75Srobert   MachineInstrBuilder MIB =
1555*d415bd75Srobert       BuildMI(*MF, MergedLoc, TII->get(FusedOpc), DstReg)
1556*d415bd75Srobert           .addReg(Mul1.getReg(), getKillRegState(Mul1.isKill()))
1557*d415bd75Srobert           .addReg(Mul2.getReg(), getKillRegState(Mul2.isKill()))
1558*d415bd75Srobert           .addReg(Addend.getReg(), getKillRegState(Addend.isKill()))
1559*d415bd75Srobert           .setMIFlags(IntersectedFlags);
1560*d415bd75Srobert 
1561*d415bd75Srobert   // Mul operands are not killed anymore.
1562*d415bd75Srobert   Mul1.setIsKill(false);
1563*d415bd75Srobert   Mul2.setIsKill(false);
1564*d415bd75Srobert 
1565*d415bd75Srobert   InsInstrs.push_back(MIB);
1566*d415bd75Srobert   if (MRI.hasOneNonDBGUse(Prev.getOperand(0).getReg()))
1567*d415bd75Srobert     DelInstrs.push_back(&Prev);
1568*d415bd75Srobert   DelInstrs.push_back(&Root);
1569*d415bd75Srobert }
1570*d415bd75Srobert 
genAlternativeCodeSequence(MachineInstr & Root,MachineCombinerPattern Pattern,SmallVectorImpl<MachineInstr * > & InsInstrs,SmallVectorImpl<MachineInstr * > & DelInstrs,DenseMap<unsigned,unsigned> & InstrIdxForVirtReg) const1571*d415bd75Srobert void RISCVInstrInfo::genAlternativeCodeSequence(
1572*d415bd75Srobert     MachineInstr &Root, MachineCombinerPattern Pattern,
1573*d415bd75Srobert     SmallVectorImpl<MachineInstr *> &InsInstrs,
1574*d415bd75Srobert     SmallVectorImpl<MachineInstr *> &DelInstrs,
1575*d415bd75Srobert     DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const {
1576*d415bd75Srobert   MachineRegisterInfo &MRI = Root.getMF()->getRegInfo();
1577*d415bd75Srobert   switch (Pattern) {
1578*d415bd75Srobert   default:
1579*d415bd75Srobert     TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
1580*d415bd75Srobert                                                 DelInstrs, InstrIdxForVirtReg);
1581*d415bd75Srobert     return;
1582*d415bd75Srobert   case MachineCombinerPattern::FMADD_AX:
1583*d415bd75Srobert   case MachineCombinerPattern::FMSUB: {
1584*d415bd75Srobert     MachineInstr &Prev = *MRI.getVRegDef(Root.getOperand(1).getReg());
1585*d415bd75Srobert     combineFPFusedMultiply(Root, Prev, Pattern, InsInstrs, DelInstrs);
1586*d415bd75Srobert     return;
1587*d415bd75Srobert   }
1588*d415bd75Srobert   case MachineCombinerPattern::FMADD_XA:
1589*d415bd75Srobert   case MachineCombinerPattern::FNMSUB: {
1590*d415bd75Srobert     MachineInstr &Prev = *MRI.getVRegDef(Root.getOperand(2).getReg());
1591*d415bd75Srobert     combineFPFusedMultiply(Root, Prev, Pattern, InsInstrs, DelInstrs);
1592*d415bd75Srobert     return;
1593*d415bd75Srobert   }
1594*d415bd75Srobert   }
159573471bf0Spatrick }
159673471bf0Spatrick 
verifyInstruction(const MachineInstr & MI,StringRef & ErrInfo) const159709467b48Spatrick bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
159809467b48Spatrick                                        StringRef &ErrInfo) const {
1599*d415bd75Srobert   MCInstrDesc const &Desc = MI.getDesc();
160009467b48Spatrick 
160109467b48Spatrick   for (auto &OI : enumerate(Desc.operands())) {
160209467b48Spatrick     unsigned OpType = OI.value().OperandType;
160309467b48Spatrick     if (OpType >= RISCVOp::OPERAND_FIRST_RISCV_IMM &&
160409467b48Spatrick         OpType <= RISCVOp::OPERAND_LAST_RISCV_IMM) {
160509467b48Spatrick       const MachineOperand &MO = MI.getOperand(OI.index());
160609467b48Spatrick       if (MO.isImm()) {
160709467b48Spatrick         int64_t Imm = MO.getImm();
160809467b48Spatrick         bool Ok;
160909467b48Spatrick         switch (OpType) {
161009467b48Spatrick         default:
161109467b48Spatrick           llvm_unreachable("Unexpected operand type");
1612*d415bd75Srobert 
1613*d415bd75Srobert           // clang-format off
1614*d415bd75Srobert #define CASE_OPERAND_UIMM(NUM)                                                 \
1615*d415bd75Srobert   case RISCVOp::OPERAND_UIMM##NUM:                                             \
1616*d415bd75Srobert     Ok = isUInt<NUM>(Imm);                                                     \
161709467b48Spatrick     break;
1618*d415bd75Srobert         CASE_OPERAND_UIMM(2)
1619*d415bd75Srobert         CASE_OPERAND_UIMM(3)
1620*d415bd75Srobert         CASE_OPERAND_UIMM(4)
1621*d415bd75Srobert         CASE_OPERAND_UIMM(5)
1622*d415bd75Srobert         CASE_OPERAND_UIMM(7)
1623*d415bd75Srobert         case RISCVOp::OPERAND_UIMM7_LSB00:
1624*d415bd75Srobert           Ok = isShiftedUInt<5, 2>(Imm);
162509467b48Spatrick           break;
1626*d415bd75Srobert         case RISCVOp::OPERAND_UIMM8_LSB00:
1627*d415bd75Srobert           Ok = isShiftedUInt<6, 2>(Imm);
1628*d415bd75Srobert           break;
1629*d415bd75Srobert         case RISCVOp::OPERAND_UIMM8_LSB000:
1630*d415bd75Srobert           Ok = isShiftedUInt<5, 3>(Imm);
1631*d415bd75Srobert           break;
1632*d415bd75Srobert         CASE_OPERAND_UIMM(12)
1633*d415bd75Srobert         CASE_OPERAND_UIMM(20)
1634*d415bd75Srobert           // clang-format on
1635*d415bd75Srobert         case RISCVOp::OPERAND_SIMM10_LSB0000_NONZERO:
1636*d415bd75Srobert           Ok = isShiftedInt<6, 4>(Imm) && (Imm != 0);
1637*d415bd75Srobert           break;
1638*d415bd75Srobert         case RISCVOp::OPERAND_ZERO:
1639*d415bd75Srobert           Ok = Imm == 0;
1640*d415bd75Srobert           break;
1641*d415bd75Srobert         case RISCVOp::OPERAND_SIMM5:
1642*d415bd75Srobert           Ok = isInt<5>(Imm);
1643*d415bd75Srobert           break;
1644*d415bd75Srobert         case RISCVOp::OPERAND_SIMM5_PLUS1:
1645*d415bd75Srobert           Ok = (isInt<5>(Imm) && Imm != -16) || Imm == 16;
1646*d415bd75Srobert           break;
1647*d415bd75Srobert         case RISCVOp::OPERAND_SIMM6:
1648*d415bd75Srobert           Ok = isInt<6>(Imm);
1649*d415bd75Srobert           break;
1650*d415bd75Srobert         case RISCVOp::OPERAND_SIMM6_NONZERO:
1651*d415bd75Srobert           Ok = Imm != 0 && isInt<6>(Imm);
1652*d415bd75Srobert           break;
1653*d415bd75Srobert         case RISCVOp::OPERAND_VTYPEI10:
1654*d415bd75Srobert           Ok = isUInt<10>(Imm);
1655*d415bd75Srobert           break;
1656*d415bd75Srobert         case RISCVOp::OPERAND_VTYPEI11:
1657*d415bd75Srobert           Ok = isUInt<11>(Imm);
165809467b48Spatrick           break;
165909467b48Spatrick         case RISCVOp::OPERAND_SIMM12:
166009467b48Spatrick           Ok = isInt<12>(Imm);
166109467b48Spatrick           break;
1662*d415bd75Srobert         case RISCVOp::OPERAND_SIMM12_LSB00000:
1663*d415bd75Srobert           Ok = isShiftedInt<7, 5>(Imm);
166409467b48Spatrick           break;
166509467b48Spatrick         case RISCVOp::OPERAND_UIMMLOG2XLEN:
1666*d415bd75Srobert           Ok = STI.is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
1667*d415bd75Srobert           break;
1668*d415bd75Srobert         case RISCVOp::OPERAND_UIMMLOG2XLEN_NONZERO:
1669*d415bd75Srobert           Ok = STI.is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
1670*d415bd75Srobert           Ok = Ok && Imm != 0;
1671*d415bd75Srobert           break;
1672*d415bd75Srobert         case RISCVOp::OPERAND_UIMM_SHFL:
1673*d415bd75Srobert           Ok = STI.is64Bit() ? isUInt<5>(Imm) : isUInt<4>(Imm);
1674*d415bd75Srobert           break;
1675*d415bd75Srobert         case RISCVOp::OPERAND_RVKRNUM:
1676*d415bd75Srobert           Ok = Imm >= 0 && Imm <= 10;
167709467b48Spatrick           break;
167809467b48Spatrick         }
167909467b48Spatrick         if (!Ok) {
168009467b48Spatrick           ErrInfo = "Invalid immediate";
168109467b48Spatrick           return false;
168209467b48Spatrick         }
168309467b48Spatrick       }
168409467b48Spatrick     }
168509467b48Spatrick   }
168609467b48Spatrick 
1687*d415bd75Srobert   const uint64_t TSFlags = Desc.TSFlags;
1688*d415bd75Srobert   if (RISCVII::hasMergeOp(TSFlags)) {
1689*d415bd75Srobert     unsigned OpIdx = RISCVII::getMergeOpNum(Desc);
1690*d415bd75Srobert     if (MI.findTiedOperandIdx(0) != OpIdx) {
1691*d415bd75Srobert       ErrInfo = "Merge op improperly tied";
1692*d415bd75Srobert       return false;
1693*d415bd75Srobert     }
1694*d415bd75Srobert   }
1695*d415bd75Srobert   if (RISCVII::hasVLOp(TSFlags)) {
1696*d415bd75Srobert     const MachineOperand &Op = MI.getOperand(RISCVII::getVLOpNum(Desc));
1697*d415bd75Srobert     if (!Op.isImm() && !Op.isReg())  {
1698*d415bd75Srobert       ErrInfo = "Invalid operand type for VL operand";
1699*d415bd75Srobert       return false;
1700*d415bd75Srobert     }
1701*d415bd75Srobert     if (Op.isReg() && Op.getReg() != RISCV::NoRegister) {
1702*d415bd75Srobert       const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
1703*d415bd75Srobert       auto *RC = MRI.getRegClass(Op.getReg());
1704*d415bd75Srobert       if (!RISCV::GPRRegClass.hasSubClassEq(RC)) {
1705*d415bd75Srobert         ErrInfo = "Invalid register class for VL operand";
1706*d415bd75Srobert         return false;
1707*d415bd75Srobert       }
1708*d415bd75Srobert     }
1709*d415bd75Srobert     if (!RISCVII::hasSEWOp(TSFlags)) {
1710*d415bd75Srobert       ErrInfo = "VL operand w/o SEW operand?";
1711*d415bd75Srobert       return false;
1712*d415bd75Srobert     }
1713*d415bd75Srobert   }
1714*d415bd75Srobert   if (RISCVII::hasSEWOp(TSFlags)) {
1715*d415bd75Srobert     unsigned OpIdx = RISCVII::getSEWOpNum(Desc);
1716*d415bd75Srobert     uint64_t Log2SEW = MI.getOperand(OpIdx).getImm();
1717*d415bd75Srobert     if (Log2SEW > 31) {
1718*d415bd75Srobert       ErrInfo = "Unexpected SEW value";
1719*d415bd75Srobert       return false;
1720*d415bd75Srobert     }
1721*d415bd75Srobert     unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
1722*d415bd75Srobert     if (!RISCVVType::isValidSEW(SEW)) {
1723*d415bd75Srobert       ErrInfo = "Unexpected SEW value";
1724*d415bd75Srobert       return false;
1725*d415bd75Srobert     }
1726*d415bd75Srobert   }
1727*d415bd75Srobert   if (RISCVII::hasVecPolicyOp(TSFlags)) {
1728*d415bd75Srobert     unsigned OpIdx = RISCVII::getVecPolicyOpNum(Desc);
1729*d415bd75Srobert     uint64_t Policy = MI.getOperand(OpIdx).getImm();
1730*d415bd75Srobert     if (Policy > (RISCVII::TAIL_AGNOSTIC | RISCVII::MASK_AGNOSTIC)) {
1731*d415bd75Srobert       ErrInfo = "Invalid Policy Value";
1732*d415bd75Srobert       return false;
1733*d415bd75Srobert     }
1734*d415bd75Srobert     if (!RISCVII::hasVLOp(TSFlags)) {
1735*d415bd75Srobert       ErrInfo = "policy operand w/o VL operand?";
1736*d415bd75Srobert       return false;
1737*d415bd75Srobert     }
1738*d415bd75Srobert 
1739*d415bd75Srobert     // VecPolicy operands can only exist on instructions with passthru/merge
1740*d415bd75Srobert     // arguments. Note that not all arguments with passthru have vec policy
1741*d415bd75Srobert     // operands- some instructions have implicit policies.
1742*d415bd75Srobert     unsigned UseOpIdx;
1743*d415bd75Srobert     if (!MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
1744*d415bd75Srobert       ErrInfo = "policy operand w/o tied operand?";
1745*d415bd75Srobert       return false;
1746*d415bd75Srobert     }
1747*d415bd75Srobert   }
1748*d415bd75Srobert 
174909467b48Spatrick   return true;
175009467b48Spatrick }
175109467b48Spatrick 
175209467b48Spatrick // Return true if get the base operand, byte offset of an instruction and the
175309467b48Spatrick // memory width. Width is the size of memory that is being loaded/stored.
getMemOperandWithOffsetWidth(const MachineInstr & LdSt,const MachineOperand * & BaseReg,int64_t & Offset,unsigned & Width,const TargetRegisterInfo * TRI) const175409467b48Spatrick bool RISCVInstrInfo::getMemOperandWithOffsetWidth(
175509467b48Spatrick     const MachineInstr &LdSt, const MachineOperand *&BaseReg, int64_t &Offset,
175609467b48Spatrick     unsigned &Width, const TargetRegisterInfo *TRI) const {
175709467b48Spatrick   if (!LdSt.mayLoadOrStore())
175809467b48Spatrick     return false;
175909467b48Spatrick 
176009467b48Spatrick   // Here we assume the standard RISC-V ISA, which uses a base+offset
176109467b48Spatrick   // addressing mode. You'll need to relax these conditions to support custom
176209467b48Spatrick   // load/stores instructions.
176309467b48Spatrick   if (LdSt.getNumExplicitOperands() != 3)
176409467b48Spatrick     return false;
176509467b48Spatrick   if (!LdSt.getOperand(1).isReg() || !LdSt.getOperand(2).isImm())
176609467b48Spatrick     return false;
176709467b48Spatrick 
176809467b48Spatrick   if (!LdSt.hasOneMemOperand())
176909467b48Spatrick     return false;
177009467b48Spatrick 
177109467b48Spatrick   Width = (*LdSt.memoperands_begin())->getSize();
177209467b48Spatrick   BaseReg = &LdSt.getOperand(1);
177309467b48Spatrick   Offset = LdSt.getOperand(2).getImm();
177409467b48Spatrick   return true;
177509467b48Spatrick }
177609467b48Spatrick 
areMemAccessesTriviallyDisjoint(const MachineInstr & MIa,const MachineInstr & MIb) const177709467b48Spatrick bool RISCVInstrInfo::areMemAccessesTriviallyDisjoint(
177809467b48Spatrick     const MachineInstr &MIa, const MachineInstr &MIb) const {
177909467b48Spatrick   assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
178009467b48Spatrick   assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
178109467b48Spatrick 
178209467b48Spatrick   if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() ||
178309467b48Spatrick       MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
178409467b48Spatrick     return false;
178509467b48Spatrick 
178609467b48Spatrick   // Retrieve the base register, offset from the base register and width. Width
178709467b48Spatrick   // is the size of memory that is being loaded/stored (e.g. 1, 2, 4).  If
178809467b48Spatrick   // base registers are identical, and the offset of a lower memory access +
178909467b48Spatrick   // the width doesn't overlap the offset of a higher memory access,
179009467b48Spatrick   // then the memory accesses are different.
179109467b48Spatrick   const TargetRegisterInfo *TRI = STI.getRegisterInfo();
179209467b48Spatrick   const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
179309467b48Spatrick   int64_t OffsetA = 0, OffsetB = 0;
179409467b48Spatrick   unsigned int WidthA = 0, WidthB = 0;
179509467b48Spatrick   if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, WidthA, TRI) &&
179609467b48Spatrick       getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, WidthB, TRI)) {
179709467b48Spatrick     if (BaseOpA->isIdenticalTo(*BaseOpB)) {
179809467b48Spatrick       int LowOffset = std::min(OffsetA, OffsetB);
179909467b48Spatrick       int HighOffset = std::max(OffsetA, OffsetB);
180009467b48Spatrick       int LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
180109467b48Spatrick       if (LowOffset + LowWidth <= HighOffset)
180209467b48Spatrick         return true;
180309467b48Spatrick     }
180409467b48Spatrick   }
180509467b48Spatrick   return false;
180609467b48Spatrick }
180709467b48Spatrick 
180809467b48Spatrick std::pair<unsigned, unsigned>
decomposeMachineOperandsTargetFlags(unsigned TF) const180909467b48Spatrick RISCVInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
181009467b48Spatrick   const unsigned Mask = RISCVII::MO_DIRECT_FLAG_MASK;
181109467b48Spatrick   return std::make_pair(TF & Mask, TF & ~Mask);
181209467b48Spatrick }
181309467b48Spatrick 
181409467b48Spatrick ArrayRef<std::pair<unsigned, const char *>>
getSerializableDirectMachineOperandTargetFlags() const181509467b48Spatrick RISCVInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
181609467b48Spatrick   using namespace RISCVII;
181709467b48Spatrick   static const std::pair<unsigned, const char *> TargetFlags[] = {
181809467b48Spatrick       {MO_CALL, "riscv-call"},
181909467b48Spatrick       {MO_PLT, "riscv-plt"},
182009467b48Spatrick       {MO_LO, "riscv-lo"},
182109467b48Spatrick       {MO_HI, "riscv-hi"},
182209467b48Spatrick       {MO_PCREL_LO, "riscv-pcrel-lo"},
182309467b48Spatrick       {MO_PCREL_HI, "riscv-pcrel-hi"},
182409467b48Spatrick       {MO_GOT_HI, "riscv-got-hi"},
182509467b48Spatrick       {MO_TPREL_LO, "riscv-tprel-lo"},
182609467b48Spatrick       {MO_TPREL_HI, "riscv-tprel-hi"},
182709467b48Spatrick       {MO_TPREL_ADD, "riscv-tprel-add"},
182809467b48Spatrick       {MO_TLS_GOT_HI, "riscv-tls-got-hi"},
182909467b48Spatrick       {MO_TLS_GD_HI, "riscv-tls-gd-hi"}};
1830*d415bd75Srobert   return ArrayRef(TargetFlags);
183109467b48Spatrick }
isFunctionSafeToOutlineFrom(MachineFunction & MF,bool OutlineFromLinkOnceODRs) const183209467b48Spatrick bool RISCVInstrInfo::isFunctionSafeToOutlineFrom(
183309467b48Spatrick     MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {
183409467b48Spatrick   const Function &F = MF.getFunction();
183509467b48Spatrick 
183609467b48Spatrick   // Can F be deduplicated by the linker? If it can, don't outline from it.
183709467b48Spatrick   if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())
183809467b48Spatrick     return false;
183909467b48Spatrick 
184009467b48Spatrick   // Don't outline from functions with section markings; the program could
184109467b48Spatrick   // expect that all the code is in the named section.
184209467b48Spatrick   if (F.hasSection())
184309467b48Spatrick     return false;
184409467b48Spatrick 
184509467b48Spatrick   // It's safe to outline from MF.
184609467b48Spatrick   return true;
184709467b48Spatrick }
184809467b48Spatrick 
isMBBSafeToOutlineFrom(MachineBasicBlock & MBB,unsigned & Flags) const184909467b48Spatrick bool RISCVInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
185009467b48Spatrick                                             unsigned &Flags) const {
185109467b48Spatrick   // More accurate safety checking is done in getOutliningCandidateInfo.
1852*d415bd75Srobert   return TargetInstrInfo::isMBBSafeToOutlineFrom(MBB, Flags);
185309467b48Spatrick }
185409467b48Spatrick 
185509467b48Spatrick // Enum values indicating how an outlined call should be constructed.
185609467b48Spatrick enum MachineOutlinerConstructionID {
185709467b48Spatrick   MachineOutlinerDefault
185809467b48Spatrick };
185909467b48Spatrick 
shouldOutlineFromFunctionByDefault(MachineFunction & MF) const1860*d415bd75Srobert bool RISCVInstrInfo::shouldOutlineFromFunctionByDefault(
1861*d415bd75Srobert     MachineFunction &MF) const {
1862*d415bd75Srobert   return MF.getFunction().hasMinSize();
1863*d415bd75Srobert }
1864*d415bd75Srobert 
getOutliningCandidateInfo(std::vector<outliner::Candidate> & RepeatedSequenceLocs) const186509467b48Spatrick outliner::OutlinedFunction RISCVInstrInfo::getOutliningCandidateInfo(
186609467b48Spatrick     std::vector<outliner::Candidate> &RepeatedSequenceLocs) const {
186709467b48Spatrick 
186809467b48Spatrick   // First we need to filter out candidates where the X5 register (IE t0) can't
186909467b48Spatrick   // be used to setup the function call.
187009467b48Spatrick   auto CannotInsertCall = [](outliner::Candidate &C) {
187109467b48Spatrick     const TargetRegisterInfo *TRI = C.getMF()->getSubtarget().getRegisterInfo();
1872*d415bd75Srobert     return !C.isAvailableAcrossAndOutOfSeq(RISCV::X5, *TRI);
187309467b48Spatrick   };
187409467b48Spatrick 
187573471bf0Spatrick   llvm::erase_if(RepeatedSequenceLocs, CannotInsertCall);
187609467b48Spatrick 
187709467b48Spatrick   // If the sequence doesn't have enough candidates left, then we're done.
187809467b48Spatrick   if (RepeatedSequenceLocs.size() < 2)
187909467b48Spatrick     return outliner::OutlinedFunction();
188009467b48Spatrick 
188109467b48Spatrick   unsigned SequenceSize = 0;
188209467b48Spatrick 
188309467b48Spatrick   auto I = RepeatedSequenceLocs[0].front();
188409467b48Spatrick   auto E = std::next(RepeatedSequenceLocs[0].back());
188509467b48Spatrick   for (; I != E; ++I)
188609467b48Spatrick     SequenceSize += getInstSizeInBytes(*I);
188709467b48Spatrick 
188809467b48Spatrick   // call t0, function = 8 bytes.
188909467b48Spatrick   unsigned CallOverhead = 8;
189009467b48Spatrick   for (auto &C : RepeatedSequenceLocs)
189109467b48Spatrick     C.setCallInfo(MachineOutlinerDefault, CallOverhead);
189209467b48Spatrick 
189309467b48Spatrick   // jr t0 = 4 bytes, 2 bytes if compressed instructions are enabled.
189409467b48Spatrick   unsigned FrameOverhead = 4;
1895*d415bd75Srobert   if (RepeatedSequenceLocs[0]
1896*d415bd75Srobert           .getMF()
1897*d415bd75Srobert           ->getSubtarget<RISCVSubtarget>()
1898*d415bd75Srobert           .hasStdExtCOrZca())
189909467b48Spatrick     FrameOverhead = 2;
190009467b48Spatrick 
190109467b48Spatrick   return outliner::OutlinedFunction(RepeatedSequenceLocs, SequenceSize,
190209467b48Spatrick                                     FrameOverhead, MachineOutlinerDefault);
190309467b48Spatrick }
190409467b48Spatrick 
190509467b48Spatrick outliner::InstrType
getOutliningType(MachineBasicBlock::iterator & MBBI,unsigned Flags) const190609467b48Spatrick RISCVInstrInfo::getOutliningType(MachineBasicBlock::iterator &MBBI,
190709467b48Spatrick                                  unsigned Flags) const {
190809467b48Spatrick   MachineInstr &MI = *MBBI;
190909467b48Spatrick   MachineBasicBlock *MBB = MI.getParent();
191009467b48Spatrick   const TargetRegisterInfo *TRI =
191109467b48Spatrick       MBB->getParent()->getSubtarget().getRegisterInfo();
1912*d415bd75Srobert   const auto &F = MI.getMF()->getFunction();
191309467b48Spatrick 
191409467b48Spatrick   // Positions generally can't safely be outlined.
191509467b48Spatrick   if (MI.isPosition()) {
191609467b48Spatrick     // We can manually strip out CFI instructions later.
191709467b48Spatrick     if (MI.isCFIInstruction())
1918*d415bd75Srobert       // If current function has exception handling code, we can't outline &
1919*d415bd75Srobert       // strip these CFI instructions since it may break .eh_frame section
1920*d415bd75Srobert       // needed in unwinding.
1921*d415bd75Srobert       return F.needsUnwindTableEntry() ? outliner::InstrType::Illegal
1922*d415bd75Srobert                                        : outliner::InstrType::Invisible;
192309467b48Spatrick 
192409467b48Spatrick     return outliner::InstrType::Illegal;
192509467b48Spatrick   }
192609467b48Spatrick 
192709467b48Spatrick   // Don't trust the user to write safe inline assembly.
192809467b48Spatrick   if (MI.isInlineAsm())
192909467b48Spatrick     return outliner::InstrType::Illegal;
193009467b48Spatrick 
193109467b48Spatrick   // We can't outline branches to other basic blocks.
193209467b48Spatrick   if (MI.isTerminator() && !MBB->succ_empty())
193309467b48Spatrick     return outliner::InstrType::Illegal;
193409467b48Spatrick 
193509467b48Spatrick   // We need support for tail calls to outlined functions before return
193609467b48Spatrick   // statements can be allowed.
193709467b48Spatrick   if (MI.isReturn())
193809467b48Spatrick     return outliner::InstrType::Illegal;
193909467b48Spatrick 
194009467b48Spatrick   // Don't allow modifying the X5 register which we use for return addresses for
194109467b48Spatrick   // these outlined functions.
194209467b48Spatrick   if (MI.modifiesRegister(RISCV::X5, TRI) ||
194309467b48Spatrick       MI.getDesc().hasImplicitDefOfPhysReg(RISCV::X5))
194409467b48Spatrick     return outliner::InstrType::Illegal;
194509467b48Spatrick 
194609467b48Spatrick   // Make sure the operands don't reference something unsafe.
1947*d415bd75Srobert   for (const auto &MO : MI.operands()) {
1948*d415bd75Srobert     if (MO.isMBB() || MO.isBlockAddress() || MO.isCPI() || MO.isJTI())
194909467b48Spatrick       return outliner::InstrType::Illegal;
195009467b48Spatrick 
1951*d415bd75Srobert     // pcrel-hi and pcrel-lo can't put in separate sections, filter that out
1952*d415bd75Srobert     // if any possible.
1953*d415bd75Srobert     if (MO.getTargetFlags() == RISCVII::MO_PCREL_LO &&
1954*d415bd75Srobert         (MI.getMF()->getTarget().getFunctionSections() || F.hasComdat() ||
1955*d415bd75Srobert          F.hasSection()))
1956*d415bd75Srobert       return outliner::InstrType::Illegal;
1957*d415bd75Srobert   }
1958*d415bd75Srobert 
195909467b48Spatrick   // Don't allow instructions which won't be materialized to impact outlining
196009467b48Spatrick   // analysis.
196109467b48Spatrick   if (MI.isMetaInstruction())
196209467b48Spatrick     return outliner::InstrType::Invisible;
196309467b48Spatrick 
196409467b48Spatrick   return outliner::InstrType::Legal;
196509467b48Spatrick }
196609467b48Spatrick 
buildOutlinedFrame(MachineBasicBlock & MBB,MachineFunction & MF,const outliner::OutlinedFunction & OF) const196709467b48Spatrick void RISCVInstrInfo::buildOutlinedFrame(
196809467b48Spatrick     MachineBasicBlock &MBB, MachineFunction &MF,
196909467b48Spatrick     const outliner::OutlinedFunction &OF) const {
197009467b48Spatrick 
197109467b48Spatrick   // Strip out any CFI instructions
197209467b48Spatrick   bool Changed = true;
197309467b48Spatrick   while (Changed) {
197409467b48Spatrick     Changed = false;
197509467b48Spatrick     auto I = MBB.begin();
197609467b48Spatrick     auto E = MBB.end();
197709467b48Spatrick     for (; I != E; ++I) {
197809467b48Spatrick       if (I->isCFIInstruction()) {
197909467b48Spatrick         I->removeFromParent();
198009467b48Spatrick         Changed = true;
198109467b48Spatrick         break;
198209467b48Spatrick       }
198309467b48Spatrick     }
198409467b48Spatrick   }
198509467b48Spatrick 
1986097a140dSpatrick   MBB.addLiveIn(RISCV::X5);
1987097a140dSpatrick 
198809467b48Spatrick   // Add in a return instruction to the end of the outlined frame.
198909467b48Spatrick   MBB.insert(MBB.end(), BuildMI(MF, DebugLoc(), get(RISCV::JALR))
199009467b48Spatrick       .addReg(RISCV::X0, RegState::Define)
199109467b48Spatrick       .addReg(RISCV::X5)
199209467b48Spatrick       .addImm(0));
199309467b48Spatrick }
199409467b48Spatrick 
insertOutlinedCall(Module & M,MachineBasicBlock & MBB,MachineBasicBlock::iterator & It,MachineFunction & MF,outliner::Candidate & C) const199509467b48Spatrick MachineBasicBlock::iterator RISCVInstrInfo::insertOutlinedCall(
199609467b48Spatrick     Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It,
1997*d415bd75Srobert     MachineFunction &MF, outliner::Candidate &C) const {
199809467b48Spatrick 
199909467b48Spatrick   // Add in a call instruction to the outlined function at the given location.
200009467b48Spatrick   It = MBB.insert(It,
200109467b48Spatrick                   BuildMI(MF, DebugLoc(), get(RISCV::PseudoCALLReg), RISCV::X5)
200209467b48Spatrick                       .addGlobalAddress(M.getNamedValue(MF.getName()), 0,
200309467b48Spatrick                                         RISCVII::MO_CALL));
200409467b48Spatrick   return It;
200509467b48Spatrick }
200673471bf0Spatrick 
2007*d415bd75Srobert // MIR printer helper function to annotate Operands with a comment.
createMIROperandComment(const MachineInstr & MI,const MachineOperand & Op,unsigned OpIdx,const TargetRegisterInfo * TRI) const2008*d415bd75Srobert std::string RISCVInstrInfo::createMIROperandComment(
2009*d415bd75Srobert     const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx,
2010*d415bd75Srobert     const TargetRegisterInfo *TRI) const {
2011*d415bd75Srobert   // Print a generic comment for this operand if there is one.
2012*d415bd75Srobert   std::string GenericComment =
2013*d415bd75Srobert       TargetInstrInfo::createMIROperandComment(MI, Op, OpIdx, TRI);
2014*d415bd75Srobert   if (!GenericComment.empty())
2015*d415bd75Srobert     return GenericComment;
2016*d415bd75Srobert 
2017*d415bd75Srobert   // If not, we must have an immediate operand.
2018*d415bd75Srobert   if (!Op.isImm())
2019*d415bd75Srobert     return std::string();
2020*d415bd75Srobert 
2021*d415bd75Srobert   std::string Comment;
2022*d415bd75Srobert   raw_string_ostream OS(Comment);
2023*d415bd75Srobert 
2024*d415bd75Srobert   uint64_t TSFlags = MI.getDesc().TSFlags;
2025*d415bd75Srobert 
2026*d415bd75Srobert   // Print the full VType operand of vsetvli/vsetivli instructions, and the SEW
2027*d415bd75Srobert   // operand of vector codegen pseudos.
2028*d415bd75Srobert   if ((MI.getOpcode() == RISCV::VSETVLI || MI.getOpcode() == RISCV::VSETIVLI ||
2029*d415bd75Srobert        MI.getOpcode() == RISCV::PseudoVSETVLI ||
2030*d415bd75Srobert        MI.getOpcode() == RISCV::PseudoVSETIVLI ||
2031*d415bd75Srobert        MI.getOpcode() == RISCV::PseudoVSETVLIX0) &&
2032*d415bd75Srobert       OpIdx == 2) {
2033*d415bd75Srobert     unsigned Imm = MI.getOperand(OpIdx).getImm();
2034*d415bd75Srobert     RISCVVType::printVType(Imm, OS);
2035*d415bd75Srobert   } else if (RISCVII::hasSEWOp(TSFlags) &&
2036*d415bd75Srobert              OpIdx == RISCVII::getSEWOpNum(MI.getDesc())) {
2037*d415bd75Srobert     unsigned Log2SEW = MI.getOperand(OpIdx).getImm();
2038*d415bd75Srobert     unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
2039*d415bd75Srobert     assert(RISCVVType::isValidSEW(SEW) && "Unexpected SEW");
2040*d415bd75Srobert     OS << "e" << SEW;
2041*d415bd75Srobert   } else if (RISCVII::hasVecPolicyOp(TSFlags) &&
2042*d415bd75Srobert              OpIdx == RISCVII::getVecPolicyOpNum(MI.getDesc())) {
2043*d415bd75Srobert     unsigned Policy = MI.getOperand(OpIdx).getImm();
2044*d415bd75Srobert     assert(Policy <= (RISCVII::TAIL_AGNOSTIC | RISCVII::MASK_AGNOSTIC) &&
2045*d415bd75Srobert            "Invalid Policy Value");
2046*d415bd75Srobert     OS << (Policy & RISCVII::TAIL_AGNOSTIC ? "ta" : "tu") << ", "
2047*d415bd75Srobert        << (Policy & RISCVII::MASK_AGNOSTIC ? "ma" : "mu");
2048*d415bd75Srobert   }
2049*d415bd75Srobert 
2050*d415bd75Srobert   OS.flush();
2051*d415bd75Srobert   return Comment;
2052*d415bd75Srobert }
2053*d415bd75Srobert 
205473471bf0Spatrick // clang-format off
205573471bf0Spatrick #define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL)                                \
2056*d415bd75Srobert   RISCV::PseudoV##OP##_##TYPE##_##LMUL
205773471bf0Spatrick 
2058*d415bd75Srobert #define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE)                                    \
2059*d415bd75Srobert   CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1):                                       \
206073471bf0Spatrick   case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2):                                  \
206173471bf0Spatrick   case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4):                                  \
206273471bf0Spatrick   case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8)
206373471bf0Spatrick 
2064*d415bd75Srobert #define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE)                                   \
2065*d415bd75Srobert   CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2):                                      \
2066*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE)
2067*d415bd75Srobert 
2068*d415bd75Srobert #define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE)                                   \
2069*d415bd75Srobert   CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4):                                      \
2070*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE)
2071*d415bd75Srobert 
2072*d415bd75Srobert #define CASE_VFMA_OPCODE_LMULS(OP, TYPE)                                       \
2073*d415bd75Srobert   CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF8):                                      \
2074*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE)
2075*d415bd75Srobert 
207673471bf0Spatrick #define CASE_VFMA_SPLATS(OP)                                                   \
2077*d415bd75Srobert   CASE_VFMA_OPCODE_LMULS_MF4(OP, VF16):                                        \
2078*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF2(OP, VF32):                                   \
2079*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_M1(OP, VF64)
208073471bf0Spatrick // clang-format on
208173471bf0Spatrick 
findCommutedOpIndices(const MachineInstr & MI,unsigned & SrcOpIdx1,unsigned & SrcOpIdx2) const208273471bf0Spatrick bool RISCVInstrInfo::findCommutedOpIndices(const MachineInstr &MI,
208373471bf0Spatrick                                            unsigned &SrcOpIdx1,
208473471bf0Spatrick                                            unsigned &SrcOpIdx2) const {
208573471bf0Spatrick   const MCInstrDesc &Desc = MI.getDesc();
208673471bf0Spatrick   if (!Desc.isCommutable())
208773471bf0Spatrick     return false;
208873471bf0Spatrick 
208973471bf0Spatrick   switch (MI.getOpcode()) {
2090*d415bd75Srobert   case RISCV::PseudoCCMOVGPR:
2091*d415bd75Srobert     // Operands 4 and 5 are commutable.
2092*d415bd75Srobert     return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 4, 5);
209373471bf0Spatrick   case CASE_VFMA_SPLATS(FMADD):
209473471bf0Spatrick   case CASE_VFMA_SPLATS(FMSUB):
209573471bf0Spatrick   case CASE_VFMA_SPLATS(FMACC):
209673471bf0Spatrick   case CASE_VFMA_SPLATS(FMSAC):
209773471bf0Spatrick   case CASE_VFMA_SPLATS(FNMADD):
209873471bf0Spatrick   case CASE_VFMA_SPLATS(FNMSUB):
209973471bf0Spatrick   case CASE_VFMA_SPLATS(FNMACC):
210073471bf0Spatrick   case CASE_VFMA_SPLATS(FNMSAC):
2101*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FMACC, VV):
2102*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FMSAC, VV):
2103*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FNMACC, VV):
2104*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FNMSAC, VV):
210573471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(MADD, VX):
210673471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(NMSUB, VX):
210773471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(MACC, VX):
210873471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(NMSAC, VX):
210973471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(MACC, VV):
211073471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(NMSAC, VV): {
2111*d415bd75Srobert     // If the tail policy is undisturbed we can't commute.
2112*d415bd75Srobert     assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags));
2113*d415bd75Srobert     if ((MI.getOperand(MI.getNumExplicitOperands() - 1).getImm() & 1) == 0)
2114*d415bd75Srobert       return false;
2115*d415bd75Srobert 
211673471bf0Spatrick     // For these instructions we can only swap operand 1 and operand 3 by
211773471bf0Spatrick     // changing the opcode.
211873471bf0Spatrick     unsigned CommutableOpIdx1 = 1;
211973471bf0Spatrick     unsigned CommutableOpIdx2 = 3;
212073471bf0Spatrick     if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
212173471bf0Spatrick                               CommutableOpIdx2))
212273471bf0Spatrick       return false;
212373471bf0Spatrick     return true;
212473471bf0Spatrick   }
2125*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FMADD, VV):
2126*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FMSUB, VV):
2127*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FNMADD, VV):
2128*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FNMSUB, VV):
212973471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(MADD, VV):
213073471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(NMSUB, VV): {
2131*d415bd75Srobert     // If the tail policy is undisturbed we can't commute.
2132*d415bd75Srobert     assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags));
2133*d415bd75Srobert     if ((MI.getOperand(MI.getNumExplicitOperands() - 1).getImm() & 1) == 0)
2134*d415bd75Srobert       return false;
2135*d415bd75Srobert 
213673471bf0Spatrick     // For these instructions we have more freedom. We can commute with the
213773471bf0Spatrick     // other multiplicand or with the addend/subtrahend/minuend.
213873471bf0Spatrick 
213973471bf0Spatrick     // Any fixed operand must be from source 1, 2 or 3.
214073471bf0Spatrick     if (SrcOpIdx1 != CommuteAnyOperandIndex && SrcOpIdx1 > 3)
214173471bf0Spatrick       return false;
214273471bf0Spatrick     if (SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx2 > 3)
214373471bf0Spatrick       return false;
214473471bf0Spatrick 
214573471bf0Spatrick     // It both ops are fixed one must be the tied source.
214673471bf0Spatrick     if (SrcOpIdx1 != CommuteAnyOperandIndex &&
214773471bf0Spatrick         SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx1 != 1 && SrcOpIdx2 != 1)
214873471bf0Spatrick       return false;
214973471bf0Spatrick 
215073471bf0Spatrick     // Look for two different register operands assumed to be commutable
215173471bf0Spatrick     // regardless of the FMA opcode. The FMA opcode is adjusted later if
215273471bf0Spatrick     // needed.
215373471bf0Spatrick     if (SrcOpIdx1 == CommuteAnyOperandIndex ||
215473471bf0Spatrick         SrcOpIdx2 == CommuteAnyOperandIndex) {
215573471bf0Spatrick       // At least one of operands to be commuted is not specified and
215673471bf0Spatrick       // this method is free to choose appropriate commutable operands.
215773471bf0Spatrick       unsigned CommutableOpIdx1 = SrcOpIdx1;
215873471bf0Spatrick       if (SrcOpIdx1 == SrcOpIdx2) {
215973471bf0Spatrick         // Both of operands are not fixed. Set one of commutable
216073471bf0Spatrick         // operands to the tied source.
216173471bf0Spatrick         CommutableOpIdx1 = 1;
216273471bf0Spatrick       } else if (SrcOpIdx1 == CommuteAnyOperandIndex) {
216373471bf0Spatrick         // Only one of the operands is not fixed.
216473471bf0Spatrick         CommutableOpIdx1 = SrcOpIdx2;
216573471bf0Spatrick       }
216673471bf0Spatrick 
216773471bf0Spatrick       // CommutableOpIdx1 is well defined now. Let's choose another commutable
216873471bf0Spatrick       // operand and assign its index to CommutableOpIdx2.
216973471bf0Spatrick       unsigned CommutableOpIdx2;
217073471bf0Spatrick       if (CommutableOpIdx1 != 1) {
217173471bf0Spatrick         // If we haven't already used the tied source, we must use it now.
217273471bf0Spatrick         CommutableOpIdx2 = 1;
217373471bf0Spatrick       } else {
217473471bf0Spatrick         Register Op1Reg = MI.getOperand(CommutableOpIdx1).getReg();
217573471bf0Spatrick 
217673471bf0Spatrick         // The commuted operands should have different registers.
217773471bf0Spatrick         // Otherwise, the commute transformation does not change anything and
217873471bf0Spatrick         // is useless. We use this as a hint to make our decision.
217973471bf0Spatrick         if (Op1Reg != MI.getOperand(2).getReg())
218073471bf0Spatrick           CommutableOpIdx2 = 2;
218173471bf0Spatrick         else
218273471bf0Spatrick           CommutableOpIdx2 = 3;
218373471bf0Spatrick       }
218473471bf0Spatrick 
218573471bf0Spatrick       // Assign the found pair of commutable indices to SrcOpIdx1 and
218673471bf0Spatrick       // SrcOpIdx2 to return those values.
218773471bf0Spatrick       if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
218873471bf0Spatrick                                 CommutableOpIdx2))
218973471bf0Spatrick         return false;
219073471bf0Spatrick     }
219173471bf0Spatrick 
219273471bf0Spatrick     return true;
219373471bf0Spatrick   }
219473471bf0Spatrick   }
219573471bf0Spatrick 
219673471bf0Spatrick   return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2);
219773471bf0Spatrick }
219873471bf0Spatrick 
219973471bf0Spatrick #define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL)               \
2200*d415bd75Srobert   case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL:                                \
2201*d415bd75Srobert     Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL;                             \
220273471bf0Spatrick     break;
220373471bf0Spatrick 
2204*d415bd75Srobert #define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE)                   \
220573471bf0Spatrick   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1)                       \
220673471bf0Spatrick   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2)                       \
220773471bf0Spatrick   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4)                       \
220873471bf0Spatrick   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8)
220973471bf0Spatrick 
2210*d415bd75Srobert #define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE)                  \
2211*d415bd75Srobert   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2)                      \
2212*d415bd75Srobert   CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE)
2213*d415bd75Srobert 
2214*d415bd75Srobert #define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE)                  \
2215*d415bd75Srobert   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4)                      \
2216*d415bd75Srobert   CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE)
2217*d415bd75Srobert 
2218*d415bd75Srobert #define CASE_VFMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE)                      \
2219*d415bd75Srobert   CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8)                      \
2220*d415bd75Srobert   CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE)
2221*d415bd75Srobert 
222273471bf0Spatrick #define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP)                           \
2223*d415bd75Srobert   CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VF16)                        \
2224*d415bd75Srobert   CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VF32)                        \
2225*d415bd75Srobert   CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VF64)
222673471bf0Spatrick 
commuteInstructionImpl(MachineInstr & MI,bool NewMI,unsigned OpIdx1,unsigned OpIdx2) const222773471bf0Spatrick MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI,
222873471bf0Spatrick                                                      bool NewMI,
222973471bf0Spatrick                                                      unsigned OpIdx1,
223073471bf0Spatrick                                                      unsigned OpIdx2) const {
223173471bf0Spatrick   auto cloneIfNew = [NewMI](MachineInstr &MI) -> MachineInstr & {
223273471bf0Spatrick     if (NewMI)
223373471bf0Spatrick       return *MI.getParent()->getParent()->CloneMachineInstr(&MI);
223473471bf0Spatrick     return MI;
223573471bf0Spatrick   };
223673471bf0Spatrick 
223773471bf0Spatrick   switch (MI.getOpcode()) {
2238*d415bd75Srobert   case RISCV::PseudoCCMOVGPR: {
2239*d415bd75Srobert     // CCMOV can be commuted by inverting the condition.
2240*d415bd75Srobert     auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
2241*d415bd75Srobert     CC = RISCVCC::getOppositeBranchCondition(CC);
2242*d415bd75Srobert     auto &WorkingMI = cloneIfNew(MI);
2243*d415bd75Srobert     WorkingMI.getOperand(3).setImm(CC);
2244*d415bd75Srobert     return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI*/ false,
2245*d415bd75Srobert                                                    OpIdx1, OpIdx2);
2246*d415bd75Srobert   }
224773471bf0Spatrick   case CASE_VFMA_SPLATS(FMACC):
224873471bf0Spatrick   case CASE_VFMA_SPLATS(FMADD):
224973471bf0Spatrick   case CASE_VFMA_SPLATS(FMSAC):
225073471bf0Spatrick   case CASE_VFMA_SPLATS(FMSUB):
225173471bf0Spatrick   case CASE_VFMA_SPLATS(FNMACC):
225273471bf0Spatrick   case CASE_VFMA_SPLATS(FNMADD):
225373471bf0Spatrick   case CASE_VFMA_SPLATS(FNMSAC):
225473471bf0Spatrick   case CASE_VFMA_SPLATS(FNMSUB):
2255*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FMACC, VV):
2256*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FMSAC, VV):
2257*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FNMACC, VV):
2258*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FNMSAC, VV):
225973471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(MADD, VX):
226073471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(NMSUB, VX):
226173471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(MACC, VX):
226273471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(NMSAC, VX):
226373471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(MACC, VV):
226473471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(NMSAC, VV): {
226573471bf0Spatrick     // It only make sense to toggle these between clobbering the
226673471bf0Spatrick     // addend/subtrahend/minuend one of the multiplicands.
226773471bf0Spatrick     assert((OpIdx1 == 1 || OpIdx2 == 1) && "Unexpected opcode index");
226873471bf0Spatrick     assert((OpIdx1 == 3 || OpIdx2 == 3) && "Unexpected opcode index");
226973471bf0Spatrick     unsigned Opc;
227073471bf0Spatrick     switch (MI.getOpcode()) {
227173471bf0Spatrick       default:
227273471bf0Spatrick         llvm_unreachable("Unexpected opcode");
227373471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_SPLATS(FMACC, FMADD)
227473471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_SPLATS(FMADD, FMACC)
227573471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_SPLATS(FMSAC, FMSUB)
227673471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_SPLATS(FMSUB, FMSAC)
227773471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMACC, FNMADD)
227873471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMADD, FNMACC)
227973471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMSAC, FNMSUB)
228073471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMSUB, FNMSAC)
2281*d415bd75Srobert       CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMACC, FMADD, VV)
2282*d415bd75Srobert       CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMSAC, FMSUB, VV)
2283*d415bd75Srobert       CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMACC, FNMADD, VV)
2284*d415bd75Srobert       CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMSAC, FNMSUB, VV)
228573471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_LMULS(MACC, MADD, VX)
228673471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_LMULS(MADD, MACC, VX)
228773471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_LMULS(NMSAC, NMSUB, VX)
228873471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_LMULS(NMSUB, NMSAC, VX)
228973471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_LMULS(MACC, MADD, VV)
229073471bf0Spatrick       CASE_VFMA_CHANGE_OPCODE_LMULS(NMSAC, NMSUB, VV)
229173471bf0Spatrick     }
229273471bf0Spatrick 
229373471bf0Spatrick     auto &WorkingMI = cloneIfNew(MI);
229473471bf0Spatrick     WorkingMI.setDesc(get(Opc));
229573471bf0Spatrick     return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false,
229673471bf0Spatrick                                                    OpIdx1, OpIdx2);
229773471bf0Spatrick   }
2298*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FMADD, VV):
2299*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FMSUB, VV):
2300*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FNMADD, VV):
2301*d415bd75Srobert   case CASE_VFMA_OPCODE_LMULS_MF4(FNMSUB, VV):
230273471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(MADD, VV):
230373471bf0Spatrick   case CASE_VFMA_OPCODE_LMULS(NMSUB, VV): {
230473471bf0Spatrick     assert((OpIdx1 == 1 || OpIdx2 == 1) && "Unexpected opcode index");
230573471bf0Spatrick     // If one of the operands, is the addend we need to change opcode.
230673471bf0Spatrick     // Otherwise we're just swapping 2 of the multiplicands.
230773471bf0Spatrick     if (OpIdx1 == 3 || OpIdx2 == 3) {
230873471bf0Spatrick       unsigned Opc;
230973471bf0Spatrick       switch (MI.getOpcode()) {
231073471bf0Spatrick         default:
231173471bf0Spatrick           llvm_unreachable("Unexpected opcode");
2312*d415bd75Srobert         CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMADD, FMACC, VV)
2313*d415bd75Srobert         CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMSUB, FMSAC, VV)
2314*d415bd75Srobert         CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMADD, FNMACC, VV)
2315*d415bd75Srobert         CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMSUB, FNMSAC, VV)
231673471bf0Spatrick         CASE_VFMA_CHANGE_OPCODE_LMULS(MADD, MACC, VV)
231773471bf0Spatrick         CASE_VFMA_CHANGE_OPCODE_LMULS(NMSUB, NMSAC, VV)
231873471bf0Spatrick       }
231973471bf0Spatrick 
232073471bf0Spatrick       auto &WorkingMI = cloneIfNew(MI);
232173471bf0Spatrick       WorkingMI.setDesc(get(Opc));
232273471bf0Spatrick       return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false,
232373471bf0Spatrick                                                      OpIdx1, OpIdx2);
232473471bf0Spatrick     }
232573471bf0Spatrick     // Let the default code handle it.
232673471bf0Spatrick     break;
232773471bf0Spatrick   }
232873471bf0Spatrick   }
232973471bf0Spatrick 
233073471bf0Spatrick   return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
233173471bf0Spatrick }
233273471bf0Spatrick 
233373471bf0Spatrick #undef CASE_VFMA_CHANGE_OPCODE_SPLATS
233473471bf0Spatrick #undef CASE_VFMA_CHANGE_OPCODE_LMULS
233573471bf0Spatrick #undef CASE_VFMA_CHANGE_OPCODE_COMMON
233673471bf0Spatrick #undef CASE_VFMA_SPLATS
233773471bf0Spatrick #undef CASE_VFMA_OPCODE_LMULS
233873471bf0Spatrick #undef CASE_VFMA_OPCODE_COMMON
233973471bf0Spatrick 
234073471bf0Spatrick // clang-format off
234173471bf0Spatrick #define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL)                                    \
234273471bf0Spatrick   RISCV::PseudoV##OP##_##LMUL##_TIED
234373471bf0Spatrick 
2344*d415bd75Srobert #define CASE_WIDEOP_OPCODE_LMULS_MF4(OP)                                       \
2345*d415bd75Srobert   CASE_WIDEOP_OPCODE_COMMON(OP, MF4):                                          \
234673471bf0Spatrick   case CASE_WIDEOP_OPCODE_COMMON(OP, MF2):                                     \
234773471bf0Spatrick   case CASE_WIDEOP_OPCODE_COMMON(OP, M1):                                      \
234873471bf0Spatrick   case CASE_WIDEOP_OPCODE_COMMON(OP, M2):                                      \
234973471bf0Spatrick   case CASE_WIDEOP_OPCODE_COMMON(OP, M4)
2350*d415bd75Srobert 
2351*d415bd75Srobert #define CASE_WIDEOP_OPCODE_LMULS(OP)                                           \
2352*d415bd75Srobert   CASE_WIDEOP_OPCODE_COMMON(OP, MF8):                                          \
2353*d415bd75Srobert   case CASE_WIDEOP_OPCODE_LMULS_MF4(OP)
235473471bf0Spatrick // clang-format on
235573471bf0Spatrick 
235673471bf0Spatrick #define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL)                             \
235773471bf0Spatrick   case RISCV::PseudoV##OP##_##LMUL##_TIED:                                     \
235873471bf0Spatrick     NewOpc = RISCV::PseudoV##OP##_##LMUL;                                      \
235973471bf0Spatrick     break;
236073471bf0Spatrick 
2361*d415bd75Srobert #define CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP)                                 \
236273471bf0Spatrick   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4)                                    \
236373471bf0Spatrick   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2)                                    \
236473471bf0Spatrick   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1)                                     \
236573471bf0Spatrick   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2)                                     \
236673471bf0Spatrick   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4)
236773471bf0Spatrick 
2368*d415bd75Srobert #define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP)                                    \
2369*d415bd75Srobert   CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8)                                    \
2370*d415bd75Srobert   CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP)
2371*d415bd75Srobert 
convertToThreeAddress(MachineInstr & MI,LiveVariables * LV,LiveIntervals * LIS) const2372*d415bd75Srobert MachineInstr *RISCVInstrInfo::convertToThreeAddress(MachineInstr &MI,
2373*d415bd75Srobert                                                     LiveVariables *LV,
2374*d415bd75Srobert                                                     LiveIntervals *LIS) const {
237573471bf0Spatrick   switch (MI.getOpcode()) {
237673471bf0Spatrick   default:
237773471bf0Spatrick     break;
2378*d415bd75Srobert   case CASE_WIDEOP_OPCODE_LMULS_MF4(FWADD_WV):
2379*d415bd75Srobert   case CASE_WIDEOP_OPCODE_LMULS_MF4(FWSUB_WV):
238073471bf0Spatrick   case CASE_WIDEOP_OPCODE_LMULS(WADD_WV):
238173471bf0Spatrick   case CASE_WIDEOP_OPCODE_LMULS(WADDU_WV):
238273471bf0Spatrick   case CASE_WIDEOP_OPCODE_LMULS(WSUB_WV):
238373471bf0Spatrick   case CASE_WIDEOP_OPCODE_LMULS(WSUBU_WV): {
2384*d415bd75Srobert     // If the tail policy is undisturbed we can't convert.
2385*d415bd75Srobert     assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags) &&
2386*d415bd75Srobert            MI.getNumExplicitOperands() == 6);
2387*d415bd75Srobert     if ((MI.getOperand(5).getImm() & 1) == 0)
2388*d415bd75Srobert       return nullptr;
2389*d415bd75Srobert 
239073471bf0Spatrick     // clang-format off
239173471bf0Spatrick     unsigned NewOpc;
239273471bf0Spatrick     switch (MI.getOpcode()) {
239373471bf0Spatrick     default:
239473471bf0Spatrick       llvm_unreachable("Unexpected opcode");
2395*d415bd75Srobert     CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(FWADD_WV)
2396*d415bd75Srobert     CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(FWSUB_WV)
239773471bf0Spatrick     CASE_WIDEOP_CHANGE_OPCODE_LMULS(WADD_WV)
239873471bf0Spatrick     CASE_WIDEOP_CHANGE_OPCODE_LMULS(WADDU_WV)
239973471bf0Spatrick     CASE_WIDEOP_CHANGE_OPCODE_LMULS(WSUB_WV)
240073471bf0Spatrick     CASE_WIDEOP_CHANGE_OPCODE_LMULS(WSUBU_WV)
240173471bf0Spatrick     }
240273471bf0Spatrick     // clang-format on
240373471bf0Spatrick 
2404*d415bd75Srobert     MachineBasicBlock &MBB = *MI.getParent();
2405*d415bd75Srobert     MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
240673471bf0Spatrick                                   .add(MI.getOperand(0))
240773471bf0Spatrick                                   .add(MI.getOperand(1))
240873471bf0Spatrick                                   .add(MI.getOperand(2))
240973471bf0Spatrick                                   .add(MI.getOperand(3))
241073471bf0Spatrick                                   .add(MI.getOperand(4));
241173471bf0Spatrick     MIB.copyImplicitOps(MI);
241273471bf0Spatrick 
241373471bf0Spatrick     if (LV) {
241473471bf0Spatrick       unsigned NumOps = MI.getNumOperands();
241573471bf0Spatrick       for (unsigned I = 1; I < NumOps; ++I) {
241673471bf0Spatrick         MachineOperand &Op = MI.getOperand(I);
241773471bf0Spatrick         if (Op.isReg() && Op.isKill())
241873471bf0Spatrick           LV->replaceKillInstruction(Op.getReg(), MI, *MIB);
241973471bf0Spatrick       }
242073471bf0Spatrick     }
242173471bf0Spatrick 
2422*d415bd75Srobert     if (LIS) {
2423*d415bd75Srobert       SlotIndex Idx = LIS->ReplaceMachineInstrInMaps(MI, *MIB);
2424*d415bd75Srobert 
2425*d415bd75Srobert       if (MI.getOperand(0).isEarlyClobber()) {
2426*d415bd75Srobert         // Use operand 1 was tied to early-clobber def operand 0, so its live
2427*d415bd75Srobert         // interval could have ended at an early-clobber slot. Now they are not
2428*d415bd75Srobert         // tied we need to update it to the normal register slot.
2429*d415bd75Srobert         LiveInterval &LI = LIS->getInterval(MI.getOperand(1).getReg());
2430*d415bd75Srobert         LiveRange::Segment *S = LI.getSegmentContaining(Idx);
2431*d415bd75Srobert         if (S->end == Idx.getRegSlot(true))
2432*d415bd75Srobert           S->end = Idx.getRegSlot();
2433*d415bd75Srobert       }
2434*d415bd75Srobert     }
2435*d415bd75Srobert 
243673471bf0Spatrick     return MIB;
243773471bf0Spatrick   }
243873471bf0Spatrick   }
243973471bf0Spatrick 
244073471bf0Spatrick   return nullptr;
244173471bf0Spatrick }
244273471bf0Spatrick 
244373471bf0Spatrick #undef CASE_WIDEOP_CHANGE_OPCODE_LMULS
244473471bf0Spatrick #undef CASE_WIDEOP_CHANGE_OPCODE_COMMON
244573471bf0Spatrick #undef CASE_WIDEOP_OPCODE_LMULS
244673471bf0Spatrick #undef CASE_WIDEOP_OPCODE_COMMON
244773471bf0Spatrick 
getVLENFactoredAmount(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator II,const DebugLoc & DL,Register DestReg,int64_t Amount,MachineInstr::MIFlag Flag) const2448*d415bd75Srobert void RISCVInstrInfo::getVLENFactoredAmount(MachineFunction &MF,
244973471bf0Spatrick                                            MachineBasicBlock &MBB,
245073471bf0Spatrick                                            MachineBasicBlock::iterator II,
2451*d415bd75Srobert                                            const DebugLoc &DL, Register DestReg,
245273471bf0Spatrick                                            int64_t Amount,
245373471bf0Spatrick                                            MachineInstr::MIFlag Flag) const {
245473471bf0Spatrick   assert(Amount > 0 && "There is no need to get VLEN scaled value.");
245573471bf0Spatrick   assert(Amount % 8 == 0 &&
245673471bf0Spatrick          "Reserve the stack by the multiple of one vector size.");
245773471bf0Spatrick 
245873471bf0Spatrick   MachineRegisterInfo &MRI = MF.getRegInfo();
245973471bf0Spatrick   int64_t NumOfVReg = Amount / 8;
246073471bf0Spatrick 
2461*d415bd75Srobert   BuildMI(MBB, II, DL, get(RISCV::PseudoReadVLENB), DestReg).setMIFlag(Flag);
246273471bf0Spatrick   assert(isInt<32>(NumOfVReg) &&
246373471bf0Spatrick          "Expect the number of vector registers within 32-bits.");
246473471bf0Spatrick   if (isPowerOf2_32(NumOfVReg)) {
246573471bf0Spatrick     uint32_t ShiftAmount = Log2_32(NumOfVReg);
246673471bf0Spatrick     if (ShiftAmount == 0)
2467*d415bd75Srobert       return;
2468*d415bd75Srobert     BuildMI(MBB, II, DL, get(RISCV::SLLI), DestReg)
2469*d415bd75Srobert         .addReg(DestReg, RegState::Kill)
247073471bf0Spatrick         .addImm(ShiftAmount)
247173471bf0Spatrick         .setMIFlag(Flag);
2472*d415bd75Srobert   } else if (STI.hasStdExtZba() &&
2473*d415bd75Srobert              ((NumOfVReg % 3 == 0 && isPowerOf2_64(NumOfVReg / 3)) ||
2474*d415bd75Srobert               (NumOfVReg % 5 == 0 && isPowerOf2_64(NumOfVReg / 5)) ||
2475*d415bd75Srobert               (NumOfVReg % 9 == 0 && isPowerOf2_64(NumOfVReg / 9)))) {
2476*d415bd75Srobert     // We can use Zba SHXADD+SLLI instructions for multiply in some cases.
2477*d415bd75Srobert     unsigned Opc;
2478*d415bd75Srobert     uint32_t ShiftAmount;
2479*d415bd75Srobert     if (NumOfVReg % 9 == 0) {
2480*d415bd75Srobert       Opc = RISCV::SH3ADD;
2481*d415bd75Srobert       ShiftAmount = Log2_64(NumOfVReg / 9);
2482*d415bd75Srobert     } else if (NumOfVReg % 5 == 0) {
2483*d415bd75Srobert       Opc = RISCV::SH2ADD;
2484*d415bd75Srobert       ShiftAmount = Log2_64(NumOfVReg / 5);
2485*d415bd75Srobert     } else if (NumOfVReg % 3 == 0) {
2486*d415bd75Srobert       Opc = RISCV::SH1ADD;
2487*d415bd75Srobert       ShiftAmount = Log2_64(NumOfVReg / 3);
2488*d415bd75Srobert     } else {
2489*d415bd75Srobert       llvm_unreachable("Unexpected number of vregs");
2490*d415bd75Srobert     }
2491*d415bd75Srobert     if (ShiftAmount)
2492*d415bd75Srobert       BuildMI(MBB, II, DL, get(RISCV::SLLI), DestReg)
2493*d415bd75Srobert           .addReg(DestReg, RegState::Kill)
2494*d415bd75Srobert           .addImm(ShiftAmount)
2495*d415bd75Srobert           .setMIFlag(Flag);
2496*d415bd75Srobert     BuildMI(MBB, II, DL, get(Opc), DestReg)
2497*d415bd75Srobert         .addReg(DestReg, RegState::Kill)
2498*d415bd75Srobert         .addReg(DestReg)
2499*d415bd75Srobert         .setMIFlag(Flag);
250073471bf0Spatrick   } else if (isPowerOf2_32(NumOfVReg - 1)) {
250173471bf0Spatrick     Register ScaledRegister = MRI.createVirtualRegister(&RISCV::GPRRegClass);
250273471bf0Spatrick     uint32_t ShiftAmount = Log2_32(NumOfVReg - 1);
2503*d415bd75Srobert     BuildMI(MBB, II, DL, get(RISCV::SLLI), ScaledRegister)
2504*d415bd75Srobert         .addReg(DestReg)
250573471bf0Spatrick         .addImm(ShiftAmount)
250673471bf0Spatrick         .setMIFlag(Flag);
2507*d415bd75Srobert     BuildMI(MBB, II, DL, get(RISCV::ADD), DestReg)
250873471bf0Spatrick         .addReg(ScaledRegister, RegState::Kill)
2509*d415bd75Srobert         .addReg(DestReg, RegState::Kill)
251073471bf0Spatrick         .setMIFlag(Flag);
251173471bf0Spatrick   } else if (isPowerOf2_32(NumOfVReg + 1)) {
251273471bf0Spatrick     Register ScaledRegister = MRI.createVirtualRegister(&RISCV::GPRRegClass);
251373471bf0Spatrick     uint32_t ShiftAmount = Log2_32(NumOfVReg + 1);
2514*d415bd75Srobert     BuildMI(MBB, II, DL, get(RISCV::SLLI), ScaledRegister)
2515*d415bd75Srobert         .addReg(DestReg)
251673471bf0Spatrick         .addImm(ShiftAmount)
251773471bf0Spatrick         .setMIFlag(Flag);
2518*d415bd75Srobert     BuildMI(MBB, II, DL, get(RISCV::SUB), DestReg)
251973471bf0Spatrick         .addReg(ScaledRegister, RegState::Kill)
2520*d415bd75Srobert         .addReg(DestReg, RegState::Kill)
252173471bf0Spatrick         .setMIFlag(Flag);
252273471bf0Spatrick   } else {
252373471bf0Spatrick     Register N = MRI.createVirtualRegister(&RISCV::GPRRegClass);
2524*d415bd75Srobert     movImm(MBB, II, DL, N, NumOfVReg, Flag);
2525*d415bd75Srobert     if (!STI.hasStdExtM() && !STI.hasStdExtZmmul())
252673471bf0Spatrick       MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
252773471bf0Spatrick           MF.getFunction(),
2528*d415bd75Srobert           "M- or Zmmul-extension must be enabled to calculate the vscaled size/"
2529*d415bd75Srobert           "offset."});
2530*d415bd75Srobert     BuildMI(MBB, II, DL, get(RISCV::MUL), DestReg)
2531*d415bd75Srobert         .addReg(DestReg, RegState::Kill)
253273471bf0Spatrick         .addReg(N, RegState::Kill)
253373471bf0Spatrick         .setMIFlag(Flag);
253473471bf0Spatrick   }
2535*d415bd75Srobert }
253673471bf0Spatrick 
2537*d415bd75Srobert // Checks if all users only demand the lower \p OrigBits of the original
2538*d415bd75Srobert // instruction's result.
2539*d415bd75Srobert // TODO: handle multiple interdependent transformations
hasAllNBitUsers(const MachineInstr & OrigMI,const MachineRegisterInfo & MRI,unsigned OrigBits) const2540*d415bd75Srobert bool RISCVInstrInfo::hasAllNBitUsers(const MachineInstr &OrigMI,
2541*d415bd75Srobert                                      const MachineRegisterInfo &MRI,
2542*d415bd75Srobert                                      unsigned OrigBits) const {
2543*d415bd75Srobert 
2544*d415bd75Srobert   SmallSet<std::pair<const MachineInstr *, unsigned>, 4> Visited;
2545*d415bd75Srobert   SmallVector<std::pair<const MachineInstr *, unsigned>, 4> Worklist;
2546*d415bd75Srobert 
2547*d415bd75Srobert   Worklist.push_back(std::make_pair(&OrigMI, OrigBits));
2548*d415bd75Srobert 
2549*d415bd75Srobert   while (!Worklist.empty()) {
2550*d415bd75Srobert     auto P = Worklist.pop_back_val();
2551*d415bd75Srobert     const MachineInstr *MI = P.first;
2552*d415bd75Srobert     unsigned Bits = P.second;
2553*d415bd75Srobert 
2554*d415bd75Srobert     if (!Visited.insert(P).second)
2555*d415bd75Srobert       continue;
2556*d415bd75Srobert 
2557*d415bd75Srobert     // Only handle instructions with one def.
2558*d415bd75Srobert     if (MI->getNumExplicitDefs() != 1)
2559*d415bd75Srobert       return false;
2560*d415bd75Srobert 
2561*d415bd75Srobert     for (auto &UserOp : MRI.use_operands(MI->getOperand(0).getReg())) {
2562*d415bd75Srobert       const MachineInstr *UserMI = UserOp.getParent();
2563*d415bd75Srobert       unsigned OpIdx = UserMI->getOperandNo(&UserOp);
2564*d415bd75Srobert 
2565*d415bd75Srobert       switch (UserMI->getOpcode()) {
2566*d415bd75Srobert       default:
2567*d415bd75Srobert         return false;
2568*d415bd75Srobert 
2569*d415bd75Srobert       case RISCV::ADDIW:
2570*d415bd75Srobert       case RISCV::ADDW:
2571*d415bd75Srobert       case RISCV::DIVUW:
2572*d415bd75Srobert       case RISCV::DIVW:
2573*d415bd75Srobert       case RISCV::MULW:
2574*d415bd75Srobert       case RISCV::REMUW:
2575*d415bd75Srobert       case RISCV::REMW:
2576*d415bd75Srobert       case RISCV::SLLIW:
2577*d415bd75Srobert       case RISCV::SLLW:
2578*d415bd75Srobert       case RISCV::SRAIW:
2579*d415bd75Srobert       case RISCV::SRAW:
2580*d415bd75Srobert       case RISCV::SRLIW:
2581*d415bd75Srobert       case RISCV::SRLW:
2582*d415bd75Srobert       case RISCV::SUBW:
2583*d415bd75Srobert       case RISCV::ROLW:
2584*d415bd75Srobert       case RISCV::RORW:
2585*d415bd75Srobert       case RISCV::RORIW:
2586*d415bd75Srobert       case RISCV::CLZW:
2587*d415bd75Srobert       case RISCV::CTZW:
2588*d415bd75Srobert       case RISCV::CPOPW:
2589*d415bd75Srobert       case RISCV::SLLI_UW:
2590*d415bd75Srobert       case RISCV::FMV_W_X:
2591*d415bd75Srobert       case RISCV::FCVT_H_W:
2592*d415bd75Srobert       case RISCV::FCVT_H_WU:
2593*d415bd75Srobert       case RISCV::FCVT_S_W:
2594*d415bd75Srobert       case RISCV::FCVT_S_WU:
2595*d415bd75Srobert       case RISCV::FCVT_D_W:
2596*d415bd75Srobert       case RISCV::FCVT_D_WU:
2597*d415bd75Srobert         if (Bits >= 32)
2598*d415bd75Srobert           break;
2599*d415bd75Srobert         return false;
2600*d415bd75Srobert       case RISCV::SEXT_B:
2601*d415bd75Srobert       case RISCV::PACKH:
2602*d415bd75Srobert         if (Bits >= 8)
2603*d415bd75Srobert           break;
2604*d415bd75Srobert         return false;
2605*d415bd75Srobert       case RISCV::SEXT_H:
2606*d415bd75Srobert       case RISCV::FMV_H_X:
2607*d415bd75Srobert       case RISCV::ZEXT_H_RV32:
2608*d415bd75Srobert       case RISCV::ZEXT_H_RV64:
2609*d415bd75Srobert       case RISCV::PACKW:
2610*d415bd75Srobert         if (Bits >= 16)
2611*d415bd75Srobert           break;
2612*d415bd75Srobert         return false;
2613*d415bd75Srobert 
2614*d415bd75Srobert       case RISCV::PACK:
2615*d415bd75Srobert         if (Bits >= (STI.getXLen() / 2))
2616*d415bd75Srobert           break;
2617*d415bd75Srobert         return false;
2618*d415bd75Srobert 
2619*d415bd75Srobert       case RISCV::SRLI: {
2620*d415bd75Srobert         // If we are shifting right by less than Bits, and users don't demand
2621*d415bd75Srobert         // any bits that were shifted into [Bits-1:0], then we can consider this
2622*d415bd75Srobert         // as an N-Bit user.
2623*d415bd75Srobert         unsigned ShAmt = UserMI->getOperand(2).getImm();
2624*d415bd75Srobert         if (Bits > ShAmt) {
2625*d415bd75Srobert           Worklist.push_back(std::make_pair(UserMI, Bits - ShAmt));
2626*d415bd75Srobert           break;
2627*d415bd75Srobert         }
2628*d415bd75Srobert         return false;
2629*d415bd75Srobert       }
2630*d415bd75Srobert 
2631*d415bd75Srobert       // these overwrite higher input bits, otherwise the lower word of output
2632*d415bd75Srobert       // depends only on the lower word of input. So check their uses read W.
2633*d415bd75Srobert       case RISCV::SLLI:
2634*d415bd75Srobert         if (Bits >= (STI.getXLen() - UserMI->getOperand(2).getImm()))
2635*d415bd75Srobert           break;
2636*d415bd75Srobert         Worklist.push_back(std::make_pair(UserMI, Bits));
2637*d415bd75Srobert         break;
2638*d415bd75Srobert       case RISCV::ANDI: {
2639*d415bd75Srobert         uint64_t Imm = UserMI->getOperand(2).getImm();
2640*d415bd75Srobert         if (Bits >= (unsigned)llvm::bit_width(Imm))
2641*d415bd75Srobert           break;
2642*d415bd75Srobert         Worklist.push_back(std::make_pair(UserMI, Bits));
2643*d415bd75Srobert         break;
2644*d415bd75Srobert       }
2645*d415bd75Srobert       case RISCV::ORI: {
2646*d415bd75Srobert         uint64_t Imm = UserMI->getOperand(2).getImm();
2647*d415bd75Srobert         if (Bits >= (unsigned)llvm::bit_width<uint64_t>(~Imm))
2648*d415bd75Srobert           break;
2649*d415bd75Srobert         Worklist.push_back(std::make_pair(UserMI, Bits));
2650*d415bd75Srobert         break;
2651*d415bd75Srobert       }
2652*d415bd75Srobert 
2653*d415bd75Srobert       case RISCV::SLL:
2654*d415bd75Srobert       case RISCV::BSET:
2655*d415bd75Srobert       case RISCV::BCLR:
2656*d415bd75Srobert       case RISCV::BINV:
2657*d415bd75Srobert         // Operand 2 is the shift amount which uses log2(xlen) bits.
2658*d415bd75Srobert         if (OpIdx == 2) {
2659*d415bd75Srobert           if (Bits >= Log2_32(STI.getXLen()))
2660*d415bd75Srobert             break;
2661*d415bd75Srobert           return false;
2662*d415bd75Srobert         }
2663*d415bd75Srobert         Worklist.push_back(std::make_pair(UserMI, Bits));
2664*d415bd75Srobert         break;
2665*d415bd75Srobert 
2666*d415bd75Srobert       case RISCV::SRA:
2667*d415bd75Srobert       case RISCV::SRL:
2668*d415bd75Srobert       case RISCV::ROL:
2669*d415bd75Srobert       case RISCV::ROR:
2670*d415bd75Srobert         // Operand 2 is the shift amount which uses 6 bits.
2671*d415bd75Srobert         if (OpIdx == 2 && Bits >= Log2_32(STI.getXLen()))
2672*d415bd75Srobert           break;
2673*d415bd75Srobert         return false;
2674*d415bd75Srobert 
2675*d415bd75Srobert       case RISCV::ADD_UW:
2676*d415bd75Srobert       case RISCV::SH1ADD_UW:
2677*d415bd75Srobert       case RISCV::SH2ADD_UW:
2678*d415bd75Srobert       case RISCV::SH3ADD_UW:
2679*d415bd75Srobert         // Operand 1 is implicitly zero extended.
2680*d415bd75Srobert         if (OpIdx == 1 && Bits >= 32)
2681*d415bd75Srobert           break;
2682*d415bd75Srobert         Worklist.push_back(std::make_pair(UserMI, Bits));
2683*d415bd75Srobert         break;
2684*d415bd75Srobert 
2685*d415bd75Srobert       case RISCV::BEXTI:
2686*d415bd75Srobert         if (UserMI->getOperand(2).getImm() >= Bits)
2687*d415bd75Srobert           return false;
2688*d415bd75Srobert         break;
2689*d415bd75Srobert 
2690*d415bd75Srobert       case RISCV::SB:
2691*d415bd75Srobert         // The first argument is the value to store.
2692*d415bd75Srobert         if (OpIdx == 0 && Bits >= 8)
2693*d415bd75Srobert           break;
2694*d415bd75Srobert         return false;
2695*d415bd75Srobert       case RISCV::SH:
2696*d415bd75Srobert         // The first argument is the value to store.
2697*d415bd75Srobert         if (OpIdx == 0 && Bits >= 16)
2698*d415bd75Srobert           break;
2699*d415bd75Srobert         return false;
2700*d415bd75Srobert       case RISCV::SW:
2701*d415bd75Srobert         // The first argument is the value to store.
2702*d415bd75Srobert         if (OpIdx == 0 && Bits >= 32)
2703*d415bd75Srobert           break;
2704*d415bd75Srobert         return false;
2705*d415bd75Srobert 
2706*d415bd75Srobert       // For these, lower word of output in these operations, depends only on
2707*d415bd75Srobert       // the lower word of input. So, we check all uses only read lower word.
2708*d415bd75Srobert       case RISCV::COPY:
2709*d415bd75Srobert       case RISCV::PHI:
2710*d415bd75Srobert 
2711*d415bd75Srobert       case RISCV::ADD:
2712*d415bd75Srobert       case RISCV::ADDI:
2713*d415bd75Srobert       case RISCV::AND:
2714*d415bd75Srobert       case RISCV::MUL:
2715*d415bd75Srobert       case RISCV::OR:
2716*d415bd75Srobert       case RISCV::SUB:
2717*d415bd75Srobert       case RISCV::XOR:
2718*d415bd75Srobert       case RISCV::XORI:
2719*d415bd75Srobert 
2720*d415bd75Srobert       case RISCV::ANDN:
2721*d415bd75Srobert       case RISCV::BREV8:
2722*d415bd75Srobert       case RISCV::CLMUL:
2723*d415bd75Srobert       case RISCV::ORC_B:
2724*d415bd75Srobert       case RISCV::ORN:
2725*d415bd75Srobert       case RISCV::SH1ADD:
2726*d415bd75Srobert       case RISCV::SH2ADD:
2727*d415bd75Srobert       case RISCV::SH3ADD:
2728*d415bd75Srobert       case RISCV::XNOR:
2729*d415bd75Srobert       case RISCV::BSETI:
2730*d415bd75Srobert       case RISCV::BCLRI:
2731*d415bd75Srobert       case RISCV::BINVI:
2732*d415bd75Srobert         Worklist.push_back(std::make_pair(UserMI, Bits));
2733*d415bd75Srobert         break;
2734*d415bd75Srobert 
2735*d415bd75Srobert       case RISCV::PseudoCCMOVGPR:
2736*d415bd75Srobert         // Either operand 4 or operand 5 is returned by this instruction. If
2737*d415bd75Srobert         // only the lower word of the result is used, then only the lower word
2738*d415bd75Srobert         // of operand 4 and 5 is used.
2739*d415bd75Srobert         if (OpIdx != 4 && OpIdx != 5)
2740*d415bd75Srobert           return false;
2741*d415bd75Srobert         Worklist.push_back(std::make_pair(UserMI, Bits));
2742*d415bd75Srobert         break;
2743*d415bd75Srobert 
2744*d415bd75Srobert       case RISCV::VT_MASKC:
2745*d415bd75Srobert       case RISCV::VT_MASKCN:
2746*d415bd75Srobert         if (OpIdx != 1)
2747*d415bd75Srobert           return false;
2748*d415bd75Srobert         Worklist.push_back(std::make_pair(UserMI, Bits));
2749*d415bd75Srobert         break;
2750*d415bd75Srobert       }
2751*d415bd75Srobert     }
2752*d415bd75Srobert   }
2753*d415bd75Srobert 
2754*d415bd75Srobert   return true;
2755*d415bd75Srobert }
2756*d415bd75Srobert 
2757*d415bd75Srobert // Returns true if this is the sext.w pattern, addiw rd, rs1, 0.
isSEXT_W(const MachineInstr & MI)2758*d415bd75Srobert bool RISCV::isSEXT_W(const MachineInstr &MI) {
2759*d415bd75Srobert   return MI.getOpcode() == RISCV::ADDIW && MI.getOperand(1).isReg() &&
2760*d415bd75Srobert          MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0;
2761*d415bd75Srobert }
2762*d415bd75Srobert 
2763*d415bd75Srobert // Returns true if this is the zext.w pattern, adduw rd, rs1, x0.
isZEXT_W(const MachineInstr & MI)2764*d415bd75Srobert bool RISCV::isZEXT_W(const MachineInstr &MI) {
2765*d415bd75Srobert   return MI.getOpcode() == RISCV::ADD_UW && MI.getOperand(1).isReg() &&
2766*d415bd75Srobert          MI.getOperand(2).isReg() && MI.getOperand(2).getReg() == RISCV::X0;
2767*d415bd75Srobert }
2768*d415bd75Srobert 
2769*d415bd75Srobert // Returns true if this is the zext.b pattern, andi rd, rs1, 255.
isZEXT_B(const MachineInstr & MI)2770*d415bd75Srobert bool RISCV::isZEXT_B(const MachineInstr &MI) {
2771*d415bd75Srobert   return MI.getOpcode() == RISCV::ANDI && MI.getOperand(1).isReg() &&
2772*d415bd75Srobert          MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 255;
277373471bf0Spatrick }
277473471bf0Spatrick 
isRVVWholeLoadStore(unsigned Opcode)277573471bf0Spatrick static bool isRVVWholeLoadStore(unsigned Opcode) {
277673471bf0Spatrick   switch (Opcode) {
277773471bf0Spatrick   default:
277873471bf0Spatrick     return false;
277973471bf0Spatrick   case RISCV::VS1R_V:
278073471bf0Spatrick   case RISCV::VS2R_V:
278173471bf0Spatrick   case RISCV::VS4R_V:
278273471bf0Spatrick   case RISCV::VS8R_V:
278373471bf0Spatrick   case RISCV::VL1RE8_V:
278473471bf0Spatrick   case RISCV::VL2RE8_V:
278573471bf0Spatrick   case RISCV::VL4RE8_V:
278673471bf0Spatrick   case RISCV::VL8RE8_V:
278773471bf0Spatrick   case RISCV::VL1RE16_V:
278873471bf0Spatrick   case RISCV::VL2RE16_V:
278973471bf0Spatrick   case RISCV::VL4RE16_V:
279073471bf0Spatrick   case RISCV::VL8RE16_V:
279173471bf0Spatrick   case RISCV::VL1RE32_V:
279273471bf0Spatrick   case RISCV::VL2RE32_V:
279373471bf0Spatrick   case RISCV::VL4RE32_V:
279473471bf0Spatrick   case RISCV::VL8RE32_V:
279573471bf0Spatrick   case RISCV::VL1RE64_V:
279673471bf0Spatrick   case RISCV::VL2RE64_V:
279773471bf0Spatrick   case RISCV::VL4RE64_V:
279873471bf0Spatrick   case RISCV::VL8RE64_V:
279973471bf0Spatrick     return true;
280073471bf0Spatrick   }
280173471bf0Spatrick }
280273471bf0Spatrick 
isRVVSpill(const MachineInstr & MI)2803*d415bd75Srobert bool RISCV::isRVVSpill(const MachineInstr &MI) {
280473471bf0Spatrick   // RVV lacks any support for immediate addressing for stack addresses, so be
280573471bf0Spatrick   // conservative.
280673471bf0Spatrick   unsigned Opcode = MI.getOpcode();
280773471bf0Spatrick   if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
280873471bf0Spatrick       !isRVVWholeLoadStore(Opcode) && !isRVVSpillForZvlsseg(Opcode))
280973471bf0Spatrick     return false;
2810*d415bd75Srobert   return true;
281173471bf0Spatrick }
281273471bf0Spatrick 
2813*d415bd75Srobert std::optional<std::pair<unsigned, unsigned>>
isRVVSpillForZvlsseg(unsigned Opcode)2814*d415bd75Srobert RISCV::isRVVSpillForZvlsseg(unsigned Opcode) {
281573471bf0Spatrick   switch (Opcode) {
281673471bf0Spatrick   default:
2817*d415bd75Srobert     return std::nullopt;
281873471bf0Spatrick   case RISCV::PseudoVSPILL2_M1:
281973471bf0Spatrick   case RISCV::PseudoVRELOAD2_M1:
282073471bf0Spatrick     return std::make_pair(2u, 1u);
282173471bf0Spatrick   case RISCV::PseudoVSPILL2_M2:
282273471bf0Spatrick   case RISCV::PseudoVRELOAD2_M2:
282373471bf0Spatrick     return std::make_pair(2u, 2u);
282473471bf0Spatrick   case RISCV::PseudoVSPILL2_M4:
282573471bf0Spatrick   case RISCV::PseudoVRELOAD2_M4:
282673471bf0Spatrick     return std::make_pair(2u, 4u);
282773471bf0Spatrick   case RISCV::PseudoVSPILL3_M1:
282873471bf0Spatrick   case RISCV::PseudoVRELOAD3_M1:
282973471bf0Spatrick     return std::make_pair(3u, 1u);
283073471bf0Spatrick   case RISCV::PseudoVSPILL3_M2:
283173471bf0Spatrick   case RISCV::PseudoVRELOAD3_M2:
283273471bf0Spatrick     return std::make_pair(3u, 2u);
283373471bf0Spatrick   case RISCV::PseudoVSPILL4_M1:
283473471bf0Spatrick   case RISCV::PseudoVRELOAD4_M1:
283573471bf0Spatrick     return std::make_pair(4u, 1u);
283673471bf0Spatrick   case RISCV::PseudoVSPILL4_M2:
283773471bf0Spatrick   case RISCV::PseudoVRELOAD4_M2:
283873471bf0Spatrick     return std::make_pair(4u, 2u);
283973471bf0Spatrick   case RISCV::PseudoVSPILL5_M1:
284073471bf0Spatrick   case RISCV::PseudoVRELOAD5_M1:
284173471bf0Spatrick     return std::make_pair(5u, 1u);
284273471bf0Spatrick   case RISCV::PseudoVSPILL6_M1:
284373471bf0Spatrick   case RISCV::PseudoVRELOAD6_M1:
284473471bf0Spatrick     return std::make_pair(6u, 1u);
284573471bf0Spatrick   case RISCV::PseudoVSPILL7_M1:
284673471bf0Spatrick   case RISCV::PseudoVRELOAD7_M1:
284773471bf0Spatrick     return std::make_pair(7u, 1u);
284873471bf0Spatrick   case RISCV::PseudoVSPILL8_M1:
284973471bf0Spatrick   case RISCV::PseudoVRELOAD8_M1:
285073471bf0Spatrick     return std::make_pair(8u, 1u);
285173471bf0Spatrick   }
285273471bf0Spatrick }
2853*d415bd75Srobert 
isFaultFirstLoad(const MachineInstr & MI)2854*d415bd75Srobert bool RISCV::isFaultFirstLoad(const MachineInstr &MI) {
2855*d415bd75Srobert   return MI.getNumExplicitDefs() == 2 && MI.modifiesRegister(RISCV::VL) &&
2856*d415bd75Srobert          !MI.isInlineAsm();
2857*d415bd75Srobert }
2858*d415bd75Srobert 
hasEqualFRM(const MachineInstr & MI1,const MachineInstr & MI2)2859*d415bd75Srobert bool RISCV::hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2) {
2860*d415bd75Srobert   int16_t MI1FrmOpIdx =
2861*d415bd75Srobert       RISCV::getNamedOperandIdx(MI1.getOpcode(), RISCV::OpName::frm);
2862*d415bd75Srobert   int16_t MI2FrmOpIdx =
2863*d415bd75Srobert       RISCV::getNamedOperandIdx(MI2.getOpcode(), RISCV::OpName::frm);
2864*d415bd75Srobert   if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0)
2865*d415bd75Srobert     return false;
2866*d415bd75Srobert   MachineOperand FrmOp1 = MI1.getOperand(MI1FrmOpIdx);
2867*d415bd75Srobert   MachineOperand FrmOp2 = MI2.getOperand(MI2FrmOpIdx);
2868*d415bd75Srobert   return FrmOp1.getImm() == FrmOp2.getImm();
2869*d415bd75Srobert }
2870