xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
1fe6060f1SDimitry Andric //===- RISCVInsertVSETVLI.cpp - Insert VSETVLI instructions ---------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // This file implements a function pass that inserts VSETVLI instructions where
1081ad6265SDimitry Andric // needed and expands the vl outputs of VLEFF/VLSEGFF to PseudoReadVL
1181ad6265SDimitry Andric // instructions.
12fe6060f1SDimitry Andric //
13fe6060f1SDimitry Andric // This pass consists of 3 phases:
14fe6060f1SDimitry Andric //
15fe6060f1SDimitry Andric // Phase 1 collects how each basic block affects VL/VTYPE.
16fe6060f1SDimitry Andric //
17fe6060f1SDimitry Andric // Phase 2 uses the information from phase 1 to do a data flow analysis to
18fe6060f1SDimitry Andric // propagate the VL/VTYPE changes through the function. This gives us the
19fe6060f1SDimitry Andric // VL/VTYPE at the start of each basic block.
20fe6060f1SDimitry Andric //
21fe6060f1SDimitry Andric // Phase 3 inserts VSETVLI instructions in each basic block. Information from
22fe6060f1SDimitry Andric // phase 2 is used to prevent inserting a VSETVLI before the first vector
23fe6060f1SDimitry Andric // instruction in the block if possible.
24fe6060f1SDimitry Andric //
25fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
26fe6060f1SDimitry Andric 
27fe6060f1SDimitry Andric #include "RISCV.h"
28fe6060f1SDimitry Andric #include "RISCVSubtarget.h"
29*7a6dacacSDimitry Andric #include "llvm/ADT/Statistic.h"
30fe6060f1SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
31fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
32fe6060f1SDimitry Andric #include <queue>
33fe6060f1SDimitry Andric using namespace llvm;
34fe6060f1SDimitry Andric 
35fe6060f1SDimitry Andric #define DEBUG_TYPE "riscv-insert-vsetvli"
3606c3fb27SDimitry Andric #define RISCV_INSERT_VSETVLI_NAME "RISC-V Insert VSETVLI pass"
37fe6060f1SDimitry Andric 
38*7a6dacacSDimitry Andric STATISTIC(NumInsertedVSETVL, "Number of VSETVL inst inserted");
39*7a6dacacSDimitry Andric STATISTIC(NumRemovedVSETVL, "Number of VSETVL inst removed");
40*7a6dacacSDimitry Andric 
41fe6060f1SDimitry Andric static cl::opt<bool> DisableInsertVSETVLPHIOpt(
42fe6060f1SDimitry Andric     "riscv-disable-insert-vsetvl-phi-opt", cl::init(false), cl::Hidden,
43fe6060f1SDimitry Andric     cl::desc("Disable looking through phis when inserting vsetvlis."));
44fe6060f1SDimitry Andric 
4581ad6265SDimitry Andric static cl::opt<bool> UseStrictAsserts(
4681ad6265SDimitry Andric     "riscv-insert-vsetvl-strict-asserts", cl::init(true), cl::Hidden,
4781ad6265SDimitry Andric     cl::desc("Enable strict assertion checking for the dataflow algorithm"));
4881ad6265SDimitry Andric 
49fe6060f1SDimitry Andric namespace {
50fe6060f1SDimitry Andric 
5181ad6265SDimitry Andric static unsigned getVLOpNum(const MachineInstr &MI) {
5281ad6265SDimitry Andric   return RISCVII::getVLOpNum(MI.getDesc());
53fe6060f1SDimitry Andric }
54fe6060f1SDimitry Andric 
5581ad6265SDimitry Andric static unsigned getSEWOpNum(const MachineInstr &MI) {
5681ad6265SDimitry Andric   return RISCVII::getSEWOpNum(MI.getDesc());
57fe6060f1SDimitry Andric }
58fe6060f1SDimitry Andric 
59bdd1243dSDimitry Andric static bool isVectorConfigInstr(const MachineInstr &MI) {
60bdd1243dSDimitry Andric   return MI.getOpcode() == RISCV::PseudoVSETVLI ||
61bdd1243dSDimitry Andric          MI.getOpcode() == RISCV::PseudoVSETVLIX0 ||
62bdd1243dSDimitry Andric          MI.getOpcode() == RISCV::PseudoVSETIVLI;
63bdd1243dSDimitry Andric }
64bdd1243dSDimitry Andric 
65bdd1243dSDimitry Andric /// Return true if this is 'vsetvli x0, x0, vtype' which preserves
66bdd1243dSDimitry Andric /// VL and only sets VTYPE.
67bdd1243dSDimitry Andric static bool isVLPreservingConfig(const MachineInstr &MI) {
68bdd1243dSDimitry Andric   if (MI.getOpcode() != RISCV::PseudoVSETVLIX0)
69bdd1243dSDimitry Andric     return false;
70bdd1243dSDimitry Andric   assert(RISCV::X0 == MI.getOperand(1).getReg());
71bdd1243dSDimitry Andric   return RISCV::X0 == MI.getOperand(0).getReg();
72bdd1243dSDimitry Andric }
73bdd1243dSDimitry Andric 
745f757f3fSDimitry Andric static bool isFloatScalarMoveOrScalarSplatInstr(const MachineInstr &MI) {
755f757f3fSDimitry Andric   switch (RISCV::getRVVMCOpcode(MI.getOpcode())) {
765f757f3fSDimitry Andric   default:
775f757f3fSDimitry Andric     return false;
785f757f3fSDimitry Andric   case RISCV::VFMV_S_F:
795f757f3fSDimitry Andric   case RISCV::VFMV_V_F:
805f757f3fSDimitry Andric     return true;
815f757f3fSDimitry Andric   }
82bdd1243dSDimitry Andric }
83bdd1243dSDimitry Andric 
845f757f3fSDimitry Andric static bool isScalarExtractInstr(const MachineInstr &MI) {
855f757f3fSDimitry Andric   switch (RISCV::getRVVMCOpcode(MI.getOpcode())) {
865f757f3fSDimitry Andric   default:
875f757f3fSDimitry Andric     return false;
885f757f3fSDimitry Andric   case RISCV::VMV_X_S:
895f757f3fSDimitry Andric   case RISCV::VFMV_F_S:
905f757f3fSDimitry Andric     return true;
915f757f3fSDimitry Andric   }
925f757f3fSDimitry Andric }
935f757f3fSDimitry Andric 
945f757f3fSDimitry Andric static bool isScalarInsertInstr(const MachineInstr &MI) {
955f757f3fSDimitry Andric   switch (RISCV::getRVVMCOpcode(MI.getOpcode())) {
9604eeddc0SDimitry Andric   default:
9704eeddc0SDimitry Andric     return false;
98bdd1243dSDimitry Andric   case RISCV::VMV_S_X:
99bdd1243dSDimitry Andric   case RISCV::VFMV_S_F:
10004eeddc0SDimitry Andric     return true;
10104eeddc0SDimitry Andric   }
10204eeddc0SDimitry Andric }
10304eeddc0SDimitry Andric 
10406c3fb27SDimitry Andric static bool isScalarSplatInstr(const MachineInstr &MI) {
1055f757f3fSDimitry Andric   switch (RISCV::getRVVMCOpcode(MI.getOpcode())) {
10606c3fb27SDimitry Andric   default:
10706c3fb27SDimitry Andric     return false;
10806c3fb27SDimitry Andric   case RISCV::VMV_V_I:
10906c3fb27SDimitry Andric   case RISCV::VMV_V_X:
11006c3fb27SDimitry Andric   case RISCV::VFMV_V_F:
11106c3fb27SDimitry Andric     return true;
11206c3fb27SDimitry Andric   }
11306c3fb27SDimitry Andric }
11406c3fb27SDimitry Andric 
11506c3fb27SDimitry Andric static bool isVSlideInstr(const MachineInstr &MI) {
1165f757f3fSDimitry Andric   switch (RISCV::getRVVMCOpcode(MI.getOpcode())) {
11706c3fb27SDimitry Andric   default:
11806c3fb27SDimitry Andric     return false;
11906c3fb27SDimitry Andric   case RISCV::VSLIDEDOWN_VX:
12006c3fb27SDimitry Andric   case RISCV::VSLIDEDOWN_VI:
12106c3fb27SDimitry Andric   case RISCV::VSLIDEUP_VX:
12206c3fb27SDimitry Andric   case RISCV::VSLIDEUP_VI:
12306c3fb27SDimitry Andric     return true;
12406c3fb27SDimitry Andric   }
12506c3fb27SDimitry Andric }
12606c3fb27SDimitry Andric 
127bdd1243dSDimitry Andric /// Get the EEW for a load or store instruction.  Return std::nullopt if MI is
128bdd1243dSDimitry Andric /// not a load or store which ignores SEW.
129bdd1243dSDimitry Andric static std::optional<unsigned> getEEWForLoadStore(const MachineInstr &MI) {
1305f757f3fSDimitry Andric   switch (RISCV::getRVVMCOpcode(MI.getOpcode())) {
131349cc55cSDimitry Andric   default:
132bdd1243dSDimitry Andric     return std::nullopt;
133bdd1243dSDimitry Andric   case RISCV::VLE8_V:
134bdd1243dSDimitry Andric   case RISCV::VLSE8_V:
135bdd1243dSDimitry Andric   case RISCV::VSE8_V:
136bdd1243dSDimitry Andric   case RISCV::VSSE8_V:
13781ad6265SDimitry Andric     return 8;
138bdd1243dSDimitry Andric   case RISCV::VLE16_V:
139bdd1243dSDimitry Andric   case RISCV::VLSE16_V:
140bdd1243dSDimitry Andric   case RISCV::VSE16_V:
141bdd1243dSDimitry Andric   case RISCV::VSSE16_V:
14281ad6265SDimitry Andric     return 16;
143bdd1243dSDimitry Andric   case RISCV::VLE32_V:
144bdd1243dSDimitry Andric   case RISCV::VLSE32_V:
145bdd1243dSDimitry Andric   case RISCV::VSE32_V:
146bdd1243dSDimitry Andric   case RISCV::VSSE32_V:
14781ad6265SDimitry Andric     return 32;
148bdd1243dSDimitry Andric   case RISCV::VLE64_V:
149bdd1243dSDimitry Andric   case RISCV::VLSE64_V:
150bdd1243dSDimitry Andric   case RISCV::VSE64_V:
151bdd1243dSDimitry Andric   case RISCV::VSSE64_V:
15281ad6265SDimitry Andric     return 64;
15381ad6265SDimitry Andric   }
154349cc55cSDimitry Andric }
155349cc55cSDimitry Andric 
1565f757f3fSDimitry Andric static bool isNonZeroLoadImmediate(MachineInstr &MI) {
1575f757f3fSDimitry Andric   return MI.getOpcode() == RISCV::ADDI &&
1585f757f3fSDimitry Andric     MI.getOperand(1).isReg() && MI.getOperand(2).isImm() &&
1595f757f3fSDimitry Andric     MI.getOperand(1).getReg() == RISCV::X0 &&
1605f757f3fSDimitry Andric     MI.getOperand(2).getImm() != 0;
1615f757f3fSDimitry Andric }
1625f757f3fSDimitry Andric 
16381ad6265SDimitry Andric /// Return true if this is an operation on mask registers.  Note that
16481ad6265SDimitry Andric /// this includes both arithmetic/logical ops and load/store (vlm/vsm).
16581ad6265SDimitry Andric static bool isMaskRegOp(const MachineInstr &MI) {
166bdd1243dSDimitry Andric   if (!RISCVII::hasSEWOp(MI.getDesc().TSFlags))
167bdd1243dSDimitry Andric     return false;
16881ad6265SDimitry Andric   const unsigned Log2SEW = MI.getOperand(getSEWOpNum(MI)).getImm();
16981ad6265SDimitry Andric   // A Log2SEW of 0 is an operation on mask registers only.
17081ad6265SDimitry Andric   return Log2SEW == 0;
17181ad6265SDimitry Andric }
17281ad6265SDimitry Andric 
17306c3fb27SDimitry Andric /// Return true if the inactive elements in the result are entirely undefined.
17406c3fb27SDimitry Andric /// Note that this is different from "agnostic" as defined by the vector
17506c3fb27SDimitry Andric /// specification.  Agnostic requires each lane to either be undisturbed, or
17606c3fb27SDimitry Andric /// take the value -1; no other value is allowed.
17706c3fb27SDimitry Andric static bool hasUndefinedMergeOp(const MachineInstr &MI,
17806c3fb27SDimitry Andric                                 const MachineRegisterInfo &MRI) {
17906c3fb27SDimitry Andric 
18006c3fb27SDimitry Andric   unsigned UseOpIdx;
18106c3fb27SDimitry Andric   if (!MI.isRegTiedToUseOperand(0, &UseOpIdx))
18206c3fb27SDimitry Andric     // If there is no passthrough operand, then the pass through
18306c3fb27SDimitry Andric     // lanes are undefined.
18406c3fb27SDimitry Andric     return true;
18506c3fb27SDimitry Andric 
1865f757f3fSDimitry Andric   // If the tied operand is NoReg, an IMPLICIT_DEF, or a REG_SEQEUENCE whose
1875f757f3fSDimitry Andric   // operands are solely IMPLICIT_DEFS, then the pass through lanes are
1885f757f3fSDimitry Andric   // undefined.
18906c3fb27SDimitry Andric   const MachineOperand &UseMO = MI.getOperand(UseOpIdx);
1905f757f3fSDimitry Andric   if (UseMO.getReg() == RISCV::NoRegister)
1915f757f3fSDimitry Andric     return true;
1925f757f3fSDimitry Andric 
19306c3fb27SDimitry Andric   if (MachineInstr *UseMI = MRI.getVRegDef(UseMO.getReg())) {
19406c3fb27SDimitry Andric     if (UseMI->isImplicitDef())
19506c3fb27SDimitry Andric       return true;
19606c3fb27SDimitry Andric 
19706c3fb27SDimitry Andric     if (UseMI->isRegSequence()) {
19806c3fb27SDimitry Andric       for (unsigned i = 1, e = UseMI->getNumOperands(); i < e; i += 2) {
19906c3fb27SDimitry Andric         MachineInstr *SourceMI = MRI.getVRegDef(UseMI->getOperand(i).getReg());
20006c3fb27SDimitry Andric         if (!SourceMI || !SourceMI->isImplicitDef())
20106c3fb27SDimitry Andric           return false;
20206c3fb27SDimitry Andric       }
20306c3fb27SDimitry Andric       return true;
20406c3fb27SDimitry Andric     }
20506c3fb27SDimitry Andric   }
20606c3fb27SDimitry Andric   return false;
20706c3fb27SDimitry Andric }
20806c3fb27SDimitry Andric 
20981ad6265SDimitry Andric /// Which subfields of VL or VTYPE have values we need to preserve?
21081ad6265SDimitry Andric struct DemandedFields {
211bdd1243dSDimitry Andric   // Some unknown property of VL is used.  If demanded, must preserve entire
212bdd1243dSDimitry Andric   // value.
213bdd1243dSDimitry Andric   bool VLAny = false;
214bdd1243dSDimitry Andric   // Only zero vs non-zero is used. If demanded, can change non-zero values.
215bdd1243dSDimitry Andric   bool VLZeroness = false;
21606c3fb27SDimitry Andric   // What properties of SEW we need to preserve.
21706c3fb27SDimitry Andric   enum : uint8_t {
2185f757f3fSDimitry Andric     SEWEqual = 3,              // The exact value of SEW needs to be preserved.
2195f757f3fSDimitry Andric     SEWGreaterThanOrEqual = 2, // SEW can be changed as long as it's greater
22006c3fb27SDimitry Andric                                // than or equal to the original value.
2215f757f3fSDimitry Andric     SEWGreaterThanOrEqualAndLessThan64 =
2225f757f3fSDimitry Andric         1,      // SEW can be changed as long as it's greater
2235f757f3fSDimitry Andric                 // than or equal to the original value, but must be less
2245f757f3fSDimitry Andric                 // than 64.
22506c3fb27SDimitry Andric     SEWNone = 0 // We don't need to preserve SEW at all.
22606c3fb27SDimitry Andric   } SEW = SEWNone;
22781ad6265SDimitry Andric   bool LMUL = false;
22881ad6265SDimitry Andric   bool SEWLMULRatio = false;
22981ad6265SDimitry Andric   bool TailPolicy = false;
23081ad6265SDimitry Andric   bool MaskPolicy = false;
23181ad6265SDimitry Andric 
23281ad6265SDimitry Andric   // Return true if any part of VTYPE was used
233bdd1243dSDimitry Andric   bool usedVTYPE() const {
23481ad6265SDimitry Andric     return SEW || LMUL || SEWLMULRatio || TailPolicy || MaskPolicy;
23581ad6265SDimitry Andric   }
23681ad6265SDimitry Andric 
237bdd1243dSDimitry Andric   // Return true if any property of VL was used
238bdd1243dSDimitry Andric   bool usedVL() {
239bdd1243dSDimitry Andric     return VLAny || VLZeroness;
240bdd1243dSDimitry Andric   }
241bdd1243dSDimitry Andric 
24281ad6265SDimitry Andric   // Mark all VTYPE subfields and properties as demanded
24381ad6265SDimitry Andric   void demandVTYPE() {
24406c3fb27SDimitry Andric     SEW = SEWEqual;
24581ad6265SDimitry Andric     LMUL = true;
24681ad6265SDimitry Andric     SEWLMULRatio = true;
24781ad6265SDimitry Andric     TailPolicy = true;
24881ad6265SDimitry Andric     MaskPolicy = true;
24981ad6265SDimitry Andric   }
250bdd1243dSDimitry Andric 
251bdd1243dSDimitry Andric   // Mark all VL properties as demanded
252bdd1243dSDimitry Andric   void demandVL() {
253bdd1243dSDimitry Andric     VLAny = true;
254bdd1243dSDimitry Andric     VLZeroness = true;
255bdd1243dSDimitry Andric   }
256bdd1243dSDimitry Andric 
257bdd1243dSDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
258bdd1243dSDimitry Andric   /// Support for debugging, callable in GDB: V->dump()
259bdd1243dSDimitry Andric   LLVM_DUMP_METHOD void dump() const {
260bdd1243dSDimitry Andric     print(dbgs());
261bdd1243dSDimitry Andric     dbgs() << "\n";
262bdd1243dSDimitry Andric   }
263bdd1243dSDimitry Andric 
264bdd1243dSDimitry Andric   /// Implement operator<<.
265bdd1243dSDimitry Andric   void print(raw_ostream &OS) const {
266bdd1243dSDimitry Andric     OS << "{";
267bdd1243dSDimitry Andric     OS << "VLAny=" << VLAny << ", ";
268bdd1243dSDimitry Andric     OS << "VLZeroness=" << VLZeroness << ", ";
26906c3fb27SDimitry Andric     OS << "SEW=";
27006c3fb27SDimitry Andric     switch (SEW) {
27106c3fb27SDimitry Andric     case SEWEqual:
27206c3fb27SDimitry Andric       OS << "SEWEqual";
27306c3fb27SDimitry Andric       break;
27406c3fb27SDimitry Andric     case SEWGreaterThanOrEqual:
27506c3fb27SDimitry Andric       OS << "SEWGreaterThanOrEqual";
27606c3fb27SDimitry Andric       break;
2775f757f3fSDimitry Andric     case SEWGreaterThanOrEqualAndLessThan64:
2785f757f3fSDimitry Andric       OS << "SEWGreaterThanOrEqualAndLessThan64";
2795f757f3fSDimitry Andric       break;
28006c3fb27SDimitry Andric     case SEWNone:
28106c3fb27SDimitry Andric       OS << "SEWNone";
28206c3fb27SDimitry Andric       break;
28306c3fb27SDimitry Andric     };
28406c3fb27SDimitry Andric     OS << ", ";
285bdd1243dSDimitry Andric     OS << "LMUL=" << LMUL << ", ";
286bdd1243dSDimitry Andric     OS << "SEWLMULRatio=" << SEWLMULRatio << ", ";
287bdd1243dSDimitry Andric     OS << "TailPolicy=" << TailPolicy << ", ";
288bdd1243dSDimitry Andric     OS << "MaskPolicy=" << MaskPolicy;
289bdd1243dSDimitry Andric     OS << "}";
290bdd1243dSDimitry Andric   }
291bdd1243dSDimitry Andric #endif
29281ad6265SDimitry Andric };
29381ad6265SDimitry Andric 
294bdd1243dSDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
295bdd1243dSDimitry Andric LLVM_ATTRIBUTE_USED
296bdd1243dSDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const DemandedFields &DF) {
297bdd1243dSDimitry Andric   DF.print(OS);
298bdd1243dSDimitry Andric   return OS;
299bdd1243dSDimitry Andric }
300bdd1243dSDimitry Andric #endif
301bdd1243dSDimitry Andric 
30206c3fb27SDimitry Andric /// Return true if moving from CurVType to NewVType is
30306c3fb27SDimitry Andric /// indistinguishable from the perspective of an instruction (or set
30406c3fb27SDimitry Andric /// of instructions) which use only the Used subfields and properties.
30506c3fb27SDimitry Andric static bool areCompatibleVTYPEs(uint64_t CurVType, uint64_t NewVType,
30681ad6265SDimitry Andric                                 const DemandedFields &Used) {
3075f757f3fSDimitry Andric   switch (Used.SEW) {
3085f757f3fSDimitry Andric   case DemandedFields::SEWNone:
3095f757f3fSDimitry Andric     break;
3105f757f3fSDimitry Andric   case DemandedFields::SEWEqual:
3115f757f3fSDimitry Andric     if (RISCVVType::getSEW(CurVType) != RISCVVType::getSEW(NewVType))
31206c3fb27SDimitry Andric       return false;
3135f757f3fSDimitry Andric     break;
3145f757f3fSDimitry Andric   case DemandedFields::SEWGreaterThanOrEqual:
3155f757f3fSDimitry Andric     if (RISCVVType::getSEW(NewVType) < RISCVVType::getSEW(CurVType))
31681ad6265SDimitry Andric       return false;
3175f757f3fSDimitry Andric     break;
3185f757f3fSDimitry Andric   case DemandedFields::SEWGreaterThanOrEqualAndLessThan64:
3195f757f3fSDimitry Andric     if (RISCVVType::getSEW(NewVType) < RISCVVType::getSEW(CurVType) ||
3205f757f3fSDimitry Andric         RISCVVType::getSEW(NewVType) >= 64)
3215f757f3fSDimitry Andric       return false;
3225f757f3fSDimitry Andric     break;
3235f757f3fSDimitry Andric   }
32481ad6265SDimitry Andric 
32581ad6265SDimitry Andric   if (Used.LMUL &&
32606c3fb27SDimitry Andric       RISCVVType::getVLMUL(CurVType) != RISCVVType::getVLMUL(NewVType))
32781ad6265SDimitry Andric     return false;
32881ad6265SDimitry Andric 
32981ad6265SDimitry Andric   if (Used.SEWLMULRatio) {
33006c3fb27SDimitry Andric     auto Ratio1 = RISCVVType::getSEWLMULRatio(RISCVVType::getSEW(CurVType),
33106c3fb27SDimitry Andric                                               RISCVVType::getVLMUL(CurVType));
33206c3fb27SDimitry Andric     auto Ratio2 = RISCVVType::getSEWLMULRatio(RISCVVType::getSEW(NewVType),
33306c3fb27SDimitry Andric                                               RISCVVType::getVLMUL(NewVType));
33481ad6265SDimitry Andric     if (Ratio1 != Ratio2)
33581ad6265SDimitry Andric       return false;
33681ad6265SDimitry Andric   }
33781ad6265SDimitry Andric 
33806c3fb27SDimitry Andric   if (Used.TailPolicy && RISCVVType::isTailAgnostic(CurVType) !=
33906c3fb27SDimitry Andric                              RISCVVType::isTailAgnostic(NewVType))
34081ad6265SDimitry Andric     return false;
34106c3fb27SDimitry Andric   if (Used.MaskPolicy && RISCVVType::isMaskAgnostic(CurVType) !=
34206c3fb27SDimitry Andric                              RISCVVType::isMaskAgnostic(NewVType))
34381ad6265SDimitry Andric     return false;
34481ad6265SDimitry Andric   return true;
34581ad6265SDimitry Andric }
34681ad6265SDimitry Andric 
34781ad6265SDimitry Andric /// Return the fields and properties demanded by the provided instruction.
34806c3fb27SDimitry Andric DemandedFields getDemanded(const MachineInstr &MI,
3495f757f3fSDimitry Andric                            const MachineRegisterInfo *MRI,
3505f757f3fSDimitry Andric                            const RISCVSubtarget *ST) {
35181ad6265SDimitry Andric   // Warning: This function has to work on both the lowered (i.e. post
35281ad6265SDimitry Andric   // emitVSETVLIs) and pre-lowering forms.  The main implication of this is
35381ad6265SDimitry Andric   // that it can't use the value of a SEW, VL, or Policy operand as they might
35481ad6265SDimitry Andric   // be stale after lowering.
35581ad6265SDimitry Andric 
35681ad6265SDimitry Andric   // Most instructions don't use any of these subfeilds.
35781ad6265SDimitry Andric   DemandedFields Res;
35881ad6265SDimitry Andric   // Start conservative if registers are used
35981ad6265SDimitry Andric   if (MI.isCall() || MI.isInlineAsm() || MI.readsRegister(RISCV::VL))
36006c3fb27SDimitry Andric     Res.demandVL();
36181ad6265SDimitry Andric   if (MI.isCall() || MI.isInlineAsm() || MI.readsRegister(RISCV::VTYPE))
36281ad6265SDimitry Andric     Res.demandVTYPE();
36381ad6265SDimitry Andric   // Start conservative on the unlowered form too
36481ad6265SDimitry Andric   uint64_t TSFlags = MI.getDesc().TSFlags;
36581ad6265SDimitry Andric   if (RISCVII::hasSEWOp(TSFlags)) {
36681ad6265SDimitry Andric     Res.demandVTYPE();
36781ad6265SDimitry Andric     if (RISCVII::hasVLOp(TSFlags))
368bdd1243dSDimitry Andric       Res.demandVL();
369bdd1243dSDimitry Andric 
370bdd1243dSDimitry Andric     // Behavior is independent of mask policy.
371bdd1243dSDimitry Andric     if (!RISCVII::usesMaskPolicy(TSFlags))
372bdd1243dSDimitry Andric       Res.MaskPolicy = false;
37381ad6265SDimitry Andric   }
37481ad6265SDimitry Andric 
37581ad6265SDimitry Andric   // Loads and stores with implicit EEW do not demand SEW or LMUL directly.
37681ad6265SDimitry Andric   // They instead demand the ratio of the two which is used in computing
37781ad6265SDimitry Andric   // EMUL, but which allows us the flexibility to change SEW and LMUL
37881ad6265SDimitry Andric   // provided we don't change the ratio.
37981ad6265SDimitry Andric   // Note: We assume that the instructions initial SEW is the EEW encoded
38081ad6265SDimitry Andric   // in the opcode.  This is asserted when constructing the VSETVLIInfo.
38181ad6265SDimitry Andric   if (getEEWForLoadStore(MI)) {
38206c3fb27SDimitry Andric     Res.SEW = DemandedFields::SEWNone;
38381ad6265SDimitry Andric     Res.LMUL = false;
38481ad6265SDimitry Andric   }
38581ad6265SDimitry Andric 
38681ad6265SDimitry Andric   // Store instructions don't use the policy fields.
38781ad6265SDimitry Andric   if (RISCVII::hasSEWOp(TSFlags) && MI.getNumExplicitDefs() == 0) {
38881ad6265SDimitry Andric     Res.TailPolicy = false;
38981ad6265SDimitry Andric     Res.MaskPolicy = false;
39081ad6265SDimitry Andric   }
39181ad6265SDimitry Andric 
39281ad6265SDimitry Andric   // If this is a mask reg operation, it only cares about VLMAX.
39381ad6265SDimitry Andric   // TODO: Possible extensions to this logic
39481ad6265SDimitry Andric   // * Probably ok if available VLMax is larger than demanded
39581ad6265SDimitry Andric   // * The policy bits can probably be ignored..
39681ad6265SDimitry Andric   if (isMaskRegOp(MI)) {
39706c3fb27SDimitry Andric     Res.SEW = DemandedFields::SEWNone;
39881ad6265SDimitry Andric     Res.LMUL = false;
39981ad6265SDimitry Andric   }
40081ad6265SDimitry Andric 
401bdd1243dSDimitry Andric   // For vmv.s.x and vfmv.s.f, there are only two behaviors, VL = 0 and VL > 0.
4025f757f3fSDimitry Andric   if (isScalarInsertInstr(MI)) {
403bdd1243dSDimitry Andric     Res.LMUL = false;
404bdd1243dSDimitry Andric     Res.SEWLMULRatio = false;
405bdd1243dSDimitry Andric     Res.VLAny = false;
40606c3fb27SDimitry Andric     // For vmv.s.x and vfmv.s.f, if the merge operand is *undefined*, we don't
40706c3fb27SDimitry Andric     // need to preserve any other bits and are thus compatible with any larger,
40806c3fb27SDimitry Andric     // etype and can disregard policy bits.  Warning: It's tempting to try doing
40906c3fb27SDimitry Andric     // this for any tail agnostic operation, but we can't as TA requires
41006c3fb27SDimitry Andric     // tail lanes to either be the original value or -1.  We are writing
41106c3fb27SDimitry Andric     // unknown bits to the lanes here.
41206c3fb27SDimitry Andric     if (hasUndefinedMergeOp(MI, *MRI)) {
4135f757f3fSDimitry Andric       if (isFloatScalarMoveOrScalarSplatInstr(MI) && !ST->hasVInstructionsF64())
4145f757f3fSDimitry Andric         Res.SEW = DemandedFields::SEWGreaterThanOrEqualAndLessThan64;
4155f757f3fSDimitry Andric       else
41606c3fb27SDimitry Andric         Res.SEW = DemandedFields::SEWGreaterThanOrEqual;
41706c3fb27SDimitry Andric       Res.TailPolicy = false;
41806c3fb27SDimitry Andric     }
419bdd1243dSDimitry Andric   }
420bdd1243dSDimitry Andric 
4215f757f3fSDimitry Andric   // vmv.x.s, and vmv.f.s are unconditional and ignore everything except SEW.
4225f757f3fSDimitry Andric   if (isScalarExtractInstr(MI)) {
4235f757f3fSDimitry Andric     assert(!RISCVII::hasVLOp(TSFlags));
4245f757f3fSDimitry Andric     Res.LMUL = false;
4255f757f3fSDimitry Andric     Res.SEWLMULRatio = false;
4265f757f3fSDimitry Andric     Res.TailPolicy = false;
4275f757f3fSDimitry Andric     Res.MaskPolicy = false;
4285f757f3fSDimitry Andric   }
4295f757f3fSDimitry Andric 
43081ad6265SDimitry Andric   return Res;
43181ad6265SDimitry Andric }
43281ad6265SDimitry Andric 
43381ad6265SDimitry Andric /// Defines the abstract state with which the forward dataflow models the
43481ad6265SDimitry Andric /// values of the VL and VTYPE registers after insertion.
43581ad6265SDimitry Andric class VSETVLIInfo {
43681ad6265SDimitry Andric   union {
43781ad6265SDimitry Andric     Register AVLReg;
43881ad6265SDimitry Andric     unsigned AVLImm;
43981ad6265SDimitry Andric   };
44081ad6265SDimitry Andric 
44181ad6265SDimitry Andric   enum : uint8_t {
44281ad6265SDimitry Andric     Uninitialized,
44381ad6265SDimitry Andric     AVLIsReg,
44481ad6265SDimitry Andric     AVLIsImm,
44581ad6265SDimitry Andric     Unknown,
44681ad6265SDimitry Andric   } State = Uninitialized;
44781ad6265SDimitry Andric 
44881ad6265SDimitry Andric   // Fields from VTYPE.
44981ad6265SDimitry Andric   RISCVII::VLMUL VLMul = RISCVII::LMUL_1;
45081ad6265SDimitry Andric   uint8_t SEW = 0;
45181ad6265SDimitry Andric   uint8_t TailAgnostic : 1;
45281ad6265SDimitry Andric   uint8_t MaskAgnostic : 1;
45381ad6265SDimitry Andric   uint8_t SEWLMULRatioOnly : 1;
45481ad6265SDimitry Andric 
45581ad6265SDimitry Andric public:
45681ad6265SDimitry Andric   VSETVLIInfo()
45781ad6265SDimitry Andric       : AVLImm(0), TailAgnostic(false), MaskAgnostic(false),
45881ad6265SDimitry Andric         SEWLMULRatioOnly(false) {}
45981ad6265SDimitry Andric 
46081ad6265SDimitry Andric   static VSETVLIInfo getUnknown() {
46181ad6265SDimitry Andric     VSETVLIInfo Info;
46281ad6265SDimitry Andric     Info.setUnknown();
46381ad6265SDimitry Andric     return Info;
46481ad6265SDimitry Andric   }
46581ad6265SDimitry Andric 
46681ad6265SDimitry Andric   bool isValid() const { return State != Uninitialized; }
46781ad6265SDimitry Andric   void setUnknown() { State = Unknown; }
46881ad6265SDimitry Andric   bool isUnknown() const { return State == Unknown; }
46981ad6265SDimitry Andric 
47081ad6265SDimitry Andric   void setAVLReg(Register Reg) {
47181ad6265SDimitry Andric     AVLReg = Reg;
47281ad6265SDimitry Andric     State = AVLIsReg;
47381ad6265SDimitry Andric   }
47481ad6265SDimitry Andric 
47581ad6265SDimitry Andric   void setAVLImm(unsigned Imm) {
47681ad6265SDimitry Andric     AVLImm = Imm;
47781ad6265SDimitry Andric     State = AVLIsImm;
47881ad6265SDimitry Andric   }
47981ad6265SDimitry Andric 
48081ad6265SDimitry Andric   bool hasAVLImm() const { return State == AVLIsImm; }
48181ad6265SDimitry Andric   bool hasAVLReg() const { return State == AVLIsReg; }
48281ad6265SDimitry Andric   Register getAVLReg() const {
48381ad6265SDimitry Andric     assert(hasAVLReg());
48481ad6265SDimitry Andric     return AVLReg;
48581ad6265SDimitry Andric   }
48681ad6265SDimitry Andric   unsigned getAVLImm() const {
48781ad6265SDimitry Andric     assert(hasAVLImm());
48881ad6265SDimitry Andric     return AVLImm;
48981ad6265SDimitry Andric   }
49081ad6265SDimitry Andric 
4915f757f3fSDimitry Andric   void setAVL(VSETVLIInfo Info) {
4925f757f3fSDimitry Andric     assert(Info.isValid());
4935f757f3fSDimitry Andric     if (Info.isUnknown())
4945f757f3fSDimitry Andric       setUnknown();
4955f757f3fSDimitry Andric     else if (Info.hasAVLReg())
4965f757f3fSDimitry Andric       setAVLReg(Info.getAVLReg());
4975f757f3fSDimitry Andric     else {
4985f757f3fSDimitry Andric       assert(Info.hasAVLImm());
4995f757f3fSDimitry Andric       setAVLImm(Info.getAVLImm());
5005f757f3fSDimitry Andric     }
5015f757f3fSDimitry Andric   }
5025f757f3fSDimitry Andric 
50381ad6265SDimitry Andric   unsigned getSEW() const { return SEW; }
50481ad6265SDimitry Andric   RISCVII::VLMUL getVLMUL() const { return VLMul; }
5055f757f3fSDimitry Andric   bool getTailAgnostic() const { return TailAgnostic; }
5065f757f3fSDimitry Andric   bool getMaskAgnostic() const { return MaskAgnostic; }
50781ad6265SDimitry Andric 
50806c3fb27SDimitry Andric   bool hasNonZeroAVL(const MachineRegisterInfo &MRI) const {
50981ad6265SDimitry Andric     if (hasAVLImm())
51081ad6265SDimitry Andric       return getAVLImm() > 0;
51106c3fb27SDimitry Andric     if (hasAVLReg()) {
51206c3fb27SDimitry Andric       if (getAVLReg() == RISCV::X0)
51306c3fb27SDimitry Andric         return true;
51406c3fb27SDimitry Andric       if (MachineInstr *MI = MRI.getVRegDef(getAVLReg());
5155f757f3fSDimitry Andric           MI && isNonZeroLoadImmediate(*MI))
51606c3fb27SDimitry Andric         return true;
51706c3fb27SDimitry Andric       return false;
51806c3fb27SDimitry Andric     }
51981ad6265SDimitry Andric     return false;
52081ad6265SDimitry Andric   }
52181ad6265SDimitry Andric 
52206c3fb27SDimitry Andric   bool hasEquallyZeroAVL(const VSETVLIInfo &Other,
52306c3fb27SDimitry Andric                          const MachineRegisterInfo &MRI) const {
524bdd1243dSDimitry Andric     if (hasSameAVL(Other))
525bdd1243dSDimitry Andric       return true;
52606c3fb27SDimitry Andric     return (hasNonZeroAVL(MRI) && Other.hasNonZeroAVL(MRI));
527bdd1243dSDimitry Andric   }
528bdd1243dSDimitry Andric 
52981ad6265SDimitry Andric   bool hasSameAVL(const VSETVLIInfo &Other) const {
53081ad6265SDimitry Andric     if (hasAVLReg() && Other.hasAVLReg())
53181ad6265SDimitry Andric       return getAVLReg() == Other.getAVLReg();
53281ad6265SDimitry Andric 
53381ad6265SDimitry Andric     if (hasAVLImm() && Other.hasAVLImm())
53481ad6265SDimitry Andric       return getAVLImm() == Other.getAVLImm();
53581ad6265SDimitry Andric 
53681ad6265SDimitry Andric     return false;
53781ad6265SDimitry Andric   }
53881ad6265SDimitry Andric 
53981ad6265SDimitry Andric   void setVTYPE(unsigned VType) {
54081ad6265SDimitry Andric     assert(isValid() && !isUnknown() &&
54181ad6265SDimitry Andric            "Can't set VTYPE for uninitialized or unknown");
54281ad6265SDimitry Andric     VLMul = RISCVVType::getVLMUL(VType);
54381ad6265SDimitry Andric     SEW = RISCVVType::getSEW(VType);
54481ad6265SDimitry Andric     TailAgnostic = RISCVVType::isTailAgnostic(VType);
54581ad6265SDimitry Andric     MaskAgnostic = RISCVVType::isMaskAgnostic(VType);
54681ad6265SDimitry Andric   }
54781ad6265SDimitry Andric   void setVTYPE(RISCVII::VLMUL L, unsigned S, bool TA, bool MA) {
54881ad6265SDimitry Andric     assert(isValid() && !isUnknown() &&
54981ad6265SDimitry Andric            "Can't set VTYPE for uninitialized or unknown");
55081ad6265SDimitry Andric     VLMul = L;
55181ad6265SDimitry Andric     SEW = S;
55281ad6265SDimitry Andric     TailAgnostic = TA;
55381ad6265SDimitry Andric     MaskAgnostic = MA;
55481ad6265SDimitry Andric   }
55581ad6265SDimitry Andric 
5565f757f3fSDimitry Andric   void setVLMul(RISCVII::VLMUL VLMul) { this->VLMul = VLMul; }
5575f757f3fSDimitry Andric 
55881ad6265SDimitry Andric   unsigned encodeVTYPE() const {
55981ad6265SDimitry Andric     assert(isValid() && !isUnknown() && !SEWLMULRatioOnly &&
56081ad6265SDimitry Andric            "Can't encode VTYPE for uninitialized or unknown");
56181ad6265SDimitry Andric     return RISCVVType::encodeVTYPE(VLMul, SEW, TailAgnostic, MaskAgnostic);
56281ad6265SDimitry Andric   }
56381ad6265SDimitry Andric 
56481ad6265SDimitry Andric   bool hasSEWLMULRatioOnly() const { return SEWLMULRatioOnly; }
56581ad6265SDimitry Andric 
56681ad6265SDimitry Andric   bool hasSameVTYPE(const VSETVLIInfo &Other) const {
56781ad6265SDimitry Andric     assert(isValid() && Other.isValid() &&
56881ad6265SDimitry Andric            "Can't compare invalid VSETVLIInfos");
56981ad6265SDimitry Andric     assert(!isUnknown() && !Other.isUnknown() &&
57081ad6265SDimitry Andric            "Can't compare VTYPE in unknown state");
57181ad6265SDimitry Andric     assert(!SEWLMULRatioOnly && !Other.SEWLMULRatioOnly &&
57281ad6265SDimitry Andric            "Can't compare when only LMUL/SEW ratio is valid.");
57381ad6265SDimitry Andric     return std::tie(VLMul, SEW, TailAgnostic, MaskAgnostic) ==
57481ad6265SDimitry Andric            std::tie(Other.VLMul, Other.SEW, Other.TailAgnostic,
57581ad6265SDimitry Andric                     Other.MaskAgnostic);
57681ad6265SDimitry Andric   }
57781ad6265SDimitry Andric 
57881ad6265SDimitry Andric   unsigned getSEWLMULRatio() const {
57981ad6265SDimitry Andric     assert(isValid() && !isUnknown() &&
58081ad6265SDimitry Andric            "Can't use VTYPE for uninitialized or unknown");
581bdd1243dSDimitry Andric     return RISCVVType::getSEWLMULRatio(SEW, VLMul);
58281ad6265SDimitry Andric   }
58381ad6265SDimitry Andric 
58481ad6265SDimitry Andric   // Check if the VTYPE for these two VSETVLIInfos produce the same VLMAX.
58581ad6265SDimitry Andric   // Note that having the same VLMAX ensures that both share the same
58681ad6265SDimitry Andric   // function from AVL to VL; that is, they must produce the same VL value
58781ad6265SDimitry Andric   // for any given AVL value.
58881ad6265SDimitry Andric   bool hasSameVLMAX(const VSETVLIInfo &Other) const {
58981ad6265SDimitry Andric     assert(isValid() && Other.isValid() &&
59081ad6265SDimitry Andric            "Can't compare invalid VSETVLIInfos");
59181ad6265SDimitry Andric     assert(!isUnknown() && !Other.isUnknown() &&
59281ad6265SDimitry Andric            "Can't compare VTYPE in unknown state");
59381ad6265SDimitry Andric     return getSEWLMULRatio() == Other.getSEWLMULRatio();
59481ad6265SDimitry Andric   }
59581ad6265SDimitry Andric 
596bdd1243dSDimitry Andric   bool hasCompatibleVTYPE(const DemandedFields &Used,
59781ad6265SDimitry Andric                           const VSETVLIInfo &Require) const {
59806c3fb27SDimitry Andric     return areCompatibleVTYPEs(Require.encodeVTYPE(), encodeVTYPE(), Used);
59981ad6265SDimitry Andric   }
60081ad6265SDimitry Andric 
60181ad6265SDimitry Andric   // Determine whether the vector instructions requirements represented by
60281ad6265SDimitry Andric   // Require are compatible with the previous vsetvli instruction represented
60381ad6265SDimitry Andric   // by this.  MI is the instruction whose requirements we're considering.
60406c3fb27SDimitry Andric   bool isCompatible(const DemandedFields &Used, const VSETVLIInfo &Require,
60506c3fb27SDimitry Andric                     const MachineRegisterInfo &MRI) const {
60681ad6265SDimitry Andric     assert(isValid() && Require.isValid() &&
60781ad6265SDimitry Andric            "Can't compare invalid VSETVLIInfos");
60881ad6265SDimitry Andric     assert(!Require.SEWLMULRatioOnly &&
60981ad6265SDimitry Andric            "Expected a valid VTYPE for instruction!");
61081ad6265SDimitry Andric     // Nothing is compatible with Unknown.
61181ad6265SDimitry Andric     if (isUnknown() || Require.isUnknown())
61281ad6265SDimitry Andric       return false;
61381ad6265SDimitry Andric 
61481ad6265SDimitry Andric     // If only our VLMAX ratio is valid, then this isn't compatible.
61581ad6265SDimitry Andric     if (SEWLMULRatioOnly)
61681ad6265SDimitry Andric       return false;
61781ad6265SDimitry Andric 
618bdd1243dSDimitry Andric     if (Used.VLAny && !hasSameAVL(Require))
619bdd1243dSDimitry Andric       return false;
620bdd1243dSDimitry Andric 
62106c3fb27SDimitry Andric     if (Used.VLZeroness && !hasEquallyZeroAVL(Require, MRI))
622bdd1243dSDimitry Andric       return false;
623bdd1243dSDimitry Andric 
62406c3fb27SDimitry Andric     return hasCompatibleVTYPE(Used, Require);
62581ad6265SDimitry Andric   }
62681ad6265SDimitry Andric 
62781ad6265SDimitry Andric   bool operator==(const VSETVLIInfo &Other) const {
62881ad6265SDimitry Andric     // Uninitialized is only equal to another Uninitialized.
62981ad6265SDimitry Andric     if (!isValid())
63081ad6265SDimitry Andric       return !Other.isValid();
63181ad6265SDimitry Andric     if (!Other.isValid())
63281ad6265SDimitry Andric       return !isValid();
63381ad6265SDimitry Andric 
63481ad6265SDimitry Andric     // Unknown is only equal to another Unknown.
63581ad6265SDimitry Andric     if (isUnknown())
63681ad6265SDimitry Andric       return Other.isUnknown();
63781ad6265SDimitry Andric     if (Other.isUnknown())
63881ad6265SDimitry Andric       return isUnknown();
63981ad6265SDimitry Andric 
64081ad6265SDimitry Andric     if (!hasSameAVL(Other))
64181ad6265SDimitry Andric       return false;
64281ad6265SDimitry Andric 
64381ad6265SDimitry Andric     // If the SEWLMULRatioOnly bits are different, then they aren't equal.
64481ad6265SDimitry Andric     if (SEWLMULRatioOnly != Other.SEWLMULRatioOnly)
64581ad6265SDimitry Andric       return false;
64681ad6265SDimitry Andric 
64781ad6265SDimitry Andric     // If only the VLMAX is valid, check that it is the same.
64881ad6265SDimitry Andric     if (SEWLMULRatioOnly)
64981ad6265SDimitry Andric       return hasSameVLMAX(Other);
65081ad6265SDimitry Andric 
65181ad6265SDimitry Andric     // If the full VTYPE is valid, check that it is the same.
65281ad6265SDimitry Andric     return hasSameVTYPE(Other);
65381ad6265SDimitry Andric   }
65481ad6265SDimitry Andric 
65581ad6265SDimitry Andric   bool operator!=(const VSETVLIInfo &Other) const {
65681ad6265SDimitry Andric     return !(*this == Other);
65781ad6265SDimitry Andric   }
65881ad6265SDimitry Andric 
65981ad6265SDimitry Andric   // Calculate the VSETVLIInfo visible to a block assuming this and Other are
66081ad6265SDimitry Andric   // both predecessors.
66181ad6265SDimitry Andric   VSETVLIInfo intersect(const VSETVLIInfo &Other) const {
66281ad6265SDimitry Andric     // If the new value isn't valid, ignore it.
66381ad6265SDimitry Andric     if (!Other.isValid())
66481ad6265SDimitry Andric       return *this;
66581ad6265SDimitry Andric 
66681ad6265SDimitry Andric     // If this value isn't valid, this must be the first predecessor, use it.
66781ad6265SDimitry Andric     if (!isValid())
66881ad6265SDimitry Andric       return Other;
66981ad6265SDimitry Andric 
67081ad6265SDimitry Andric     // If either is unknown, the result is unknown.
67181ad6265SDimitry Andric     if (isUnknown() || Other.isUnknown())
67281ad6265SDimitry Andric       return VSETVLIInfo::getUnknown();
67381ad6265SDimitry Andric 
67481ad6265SDimitry Andric     // If we have an exact, match return this.
67581ad6265SDimitry Andric     if (*this == Other)
67681ad6265SDimitry Andric       return *this;
67781ad6265SDimitry Andric 
67881ad6265SDimitry Andric     // Not an exact match, but maybe the AVL and VLMAX are the same. If so,
67981ad6265SDimitry Andric     // return an SEW/LMUL ratio only value.
68081ad6265SDimitry Andric     if (hasSameAVL(Other) && hasSameVLMAX(Other)) {
68181ad6265SDimitry Andric       VSETVLIInfo MergeInfo = *this;
68281ad6265SDimitry Andric       MergeInfo.SEWLMULRatioOnly = true;
68381ad6265SDimitry Andric       return MergeInfo;
68481ad6265SDimitry Andric     }
68581ad6265SDimitry Andric 
68681ad6265SDimitry Andric     // Otherwise the result is unknown.
68781ad6265SDimitry Andric     return VSETVLIInfo::getUnknown();
68881ad6265SDimitry Andric   }
68981ad6265SDimitry Andric 
69081ad6265SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
69181ad6265SDimitry Andric   /// Support for debugging, callable in GDB: V->dump()
69281ad6265SDimitry Andric   LLVM_DUMP_METHOD void dump() const {
69381ad6265SDimitry Andric     print(dbgs());
69481ad6265SDimitry Andric     dbgs() << "\n";
69581ad6265SDimitry Andric   }
69681ad6265SDimitry Andric 
69781ad6265SDimitry Andric   /// Implement operator<<.
69881ad6265SDimitry Andric   /// @{
69981ad6265SDimitry Andric   void print(raw_ostream &OS) const {
70081ad6265SDimitry Andric     OS << "{";
70181ad6265SDimitry Andric     if (!isValid())
70281ad6265SDimitry Andric       OS << "Uninitialized";
70381ad6265SDimitry Andric     if (isUnknown())
70481ad6265SDimitry Andric       OS << "unknown";
70581ad6265SDimitry Andric     if (hasAVLReg())
70681ad6265SDimitry Andric       OS << "AVLReg=" << (unsigned)AVLReg;
70781ad6265SDimitry Andric     if (hasAVLImm())
70881ad6265SDimitry Andric       OS << "AVLImm=" << (unsigned)AVLImm;
70981ad6265SDimitry Andric     OS << ", "
71081ad6265SDimitry Andric        << "VLMul=" << (unsigned)VLMul << ", "
71181ad6265SDimitry Andric        << "SEW=" << (unsigned)SEW << ", "
71281ad6265SDimitry Andric        << "TailAgnostic=" << (bool)TailAgnostic << ", "
71381ad6265SDimitry Andric        << "MaskAgnostic=" << (bool)MaskAgnostic << ", "
71481ad6265SDimitry Andric        << "SEWLMULRatioOnly=" << (bool)SEWLMULRatioOnly << "}";
71581ad6265SDimitry Andric   }
71681ad6265SDimitry Andric #endif
71781ad6265SDimitry Andric };
71881ad6265SDimitry Andric 
71981ad6265SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
72081ad6265SDimitry Andric LLVM_ATTRIBUTE_USED
72181ad6265SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const VSETVLIInfo &V) {
72281ad6265SDimitry Andric   V.print(OS);
72381ad6265SDimitry Andric   return OS;
72481ad6265SDimitry Andric }
72581ad6265SDimitry Andric #endif
72681ad6265SDimitry Andric 
72781ad6265SDimitry Andric struct BlockData {
72881ad6265SDimitry Andric   // The VSETVLIInfo that represents the VL/VTYPE settings on exit from this
72981ad6265SDimitry Andric   // block. Calculated in Phase 2.
73081ad6265SDimitry Andric   VSETVLIInfo Exit;
73181ad6265SDimitry Andric 
73281ad6265SDimitry Andric   // The VSETVLIInfo that represents the VL/VTYPE settings from all predecessor
73381ad6265SDimitry Andric   // blocks. Calculated in Phase 2, and used by Phase 3.
73481ad6265SDimitry Andric   VSETVLIInfo Pred;
73581ad6265SDimitry Andric 
73681ad6265SDimitry Andric   // Keeps track of whether the block is already in the queue.
73781ad6265SDimitry Andric   bool InQueue = false;
73881ad6265SDimitry Andric 
73981ad6265SDimitry Andric   BlockData() = default;
74081ad6265SDimitry Andric };
74181ad6265SDimitry Andric 
74281ad6265SDimitry Andric class RISCVInsertVSETVLI : public MachineFunctionPass {
7435f757f3fSDimitry Andric   const RISCVSubtarget *ST;
74481ad6265SDimitry Andric   const TargetInstrInfo *TII;
74581ad6265SDimitry Andric   MachineRegisterInfo *MRI;
74681ad6265SDimitry Andric 
74781ad6265SDimitry Andric   std::vector<BlockData> BlockInfo;
74881ad6265SDimitry Andric   std::queue<const MachineBasicBlock *> WorkList;
74981ad6265SDimitry Andric 
75081ad6265SDimitry Andric public:
75181ad6265SDimitry Andric   static char ID;
75281ad6265SDimitry Andric 
7535f757f3fSDimitry Andric   RISCVInsertVSETVLI() : MachineFunctionPass(ID) {}
75481ad6265SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
75581ad6265SDimitry Andric 
75681ad6265SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
75781ad6265SDimitry Andric     AU.setPreservesCFG();
75881ad6265SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
75981ad6265SDimitry Andric   }
76081ad6265SDimitry Andric 
76181ad6265SDimitry Andric   StringRef getPassName() const override { return RISCV_INSERT_VSETVLI_NAME; }
76281ad6265SDimitry Andric 
76381ad6265SDimitry Andric private:
76481ad6265SDimitry Andric   bool needVSETVLI(const MachineInstr &MI, const VSETVLIInfo &Require,
76581ad6265SDimitry Andric                    const VSETVLIInfo &CurInfo) const;
76681ad6265SDimitry Andric   bool needVSETVLIPHI(const VSETVLIInfo &Require,
76781ad6265SDimitry Andric                       const MachineBasicBlock &MBB) const;
76881ad6265SDimitry Andric   void insertVSETVLI(MachineBasicBlock &MBB, MachineInstr &MI,
76981ad6265SDimitry Andric                      const VSETVLIInfo &Info, const VSETVLIInfo &PrevInfo);
77081ad6265SDimitry Andric   void insertVSETVLI(MachineBasicBlock &MBB,
77181ad6265SDimitry Andric                      MachineBasicBlock::iterator InsertPt, DebugLoc DL,
77281ad6265SDimitry Andric                      const VSETVLIInfo &Info, const VSETVLIInfo &PrevInfo);
77381ad6265SDimitry Andric 
7745f757f3fSDimitry Andric   void transferBefore(VSETVLIInfo &Info, const MachineInstr &MI) const;
7755f757f3fSDimitry Andric   void transferAfter(VSETVLIInfo &Info, const MachineInstr &MI) const;
7765f757f3fSDimitry Andric   bool computeVLVTYPEChanges(const MachineBasicBlock &MBB,
7775f757f3fSDimitry Andric                              VSETVLIInfo &Info) const;
77881ad6265SDimitry Andric   void computeIncomingVLVTYPE(const MachineBasicBlock &MBB);
77981ad6265SDimitry Andric   void emitVSETVLIs(MachineBasicBlock &MBB);
78081ad6265SDimitry Andric   void doLocalPostpass(MachineBasicBlock &MBB);
78181ad6265SDimitry Andric   void doPRE(MachineBasicBlock &MBB);
78281ad6265SDimitry Andric   void insertReadVL(MachineBasicBlock &MBB);
78381ad6265SDimitry Andric };
78481ad6265SDimitry Andric 
78581ad6265SDimitry Andric } // end anonymous namespace
78681ad6265SDimitry Andric 
78781ad6265SDimitry Andric char RISCVInsertVSETVLI::ID = 0;
78881ad6265SDimitry Andric 
78981ad6265SDimitry Andric INITIALIZE_PASS(RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME,
79081ad6265SDimitry Andric                 false, false)
79181ad6265SDimitry Andric 
7925f757f3fSDimitry Andric // Return a VSETVLIInfo representing the changes made by this VSETVLI or
7935f757f3fSDimitry Andric // VSETIVLI instruction.
7945f757f3fSDimitry Andric static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
7955f757f3fSDimitry Andric   VSETVLIInfo NewInfo;
7965f757f3fSDimitry Andric   if (MI.getOpcode() == RISCV::PseudoVSETIVLI) {
7975f757f3fSDimitry Andric     NewInfo.setAVLImm(MI.getOperand(1).getImm());
7985f757f3fSDimitry Andric   } else {
7995f757f3fSDimitry Andric     assert(MI.getOpcode() == RISCV::PseudoVSETVLI ||
8005f757f3fSDimitry Andric            MI.getOpcode() == RISCV::PseudoVSETVLIX0);
8015f757f3fSDimitry Andric     Register AVLReg = MI.getOperand(1).getReg();
8025f757f3fSDimitry Andric     assert((AVLReg != RISCV::X0 || MI.getOperand(0).getReg() != RISCV::X0) &&
8035f757f3fSDimitry Andric            "Can't handle X0, X0 vsetvli yet");
8045f757f3fSDimitry Andric     NewInfo.setAVLReg(AVLReg);
8055f757f3fSDimitry Andric   }
8065f757f3fSDimitry Andric   NewInfo.setVTYPE(MI.getOperand(2).getImm());
8075f757f3fSDimitry Andric 
8085f757f3fSDimitry Andric   return NewInfo;
8095f757f3fSDimitry Andric }
8105f757f3fSDimitry Andric 
811*7a6dacacSDimitry Andric static unsigned computeVLMAX(unsigned VLEN, unsigned SEW,
812*7a6dacacSDimitry Andric                              RISCVII::VLMUL VLMul) {
813*7a6dacacSDimitry Andric   auto [LMul, Fractional] = RISCVVType::decodeVLMUL(VLMul);
814*7a6dacacSDimitry Andric   if (Fractional)
815*7a6dacacSDimitry Andric     VLEN = VLEN / LMul;
816*7a6dacacSDimitry Andric   else
817*7a6dacacSDimitry Andric     VLEN = VLEN * LMul;
818*7a6dacacSDimitry Andric   return VLEN/SEW;
819*7a6dacacSDimitry Andric }
820*7a6dacacSDimitry Andric 
82181ad6265SDimitry Andric static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags,
822*7a6dacacSDimitry Andric                                        const RISCVSubtarget &ST,
82381ad6265SDimitry Andric                                        const MachineRegisterInfo *MRI) {
82481ad6265SDimitry Andric   VSETVLIInfo InstrInfo;
82581ad6265SDimitry Andric 
82606c3fb27SDimitry Andric   bool TailAgnostic = true;
82706c3fb27SDimitry Andric   bool MaskAgnostic = true;
82806c3fb27SDimitry Andric   if (!hasUndefinedMergeOp(MI, *MRI)) {
829bdd1243dSDimitry Andric     // Start with undisturbed.
830bdd1243dSDimitry Andric     TailAgnostic = false;
831bdd1243dSDimitry Andric     MaskAgnostic = false;
832bdd1243dSDimitry Andric 
833bdd1243dSDimitry Andric     // If there is a policy operand, use it.
83481ad6265SDimitry Andric     if (RISCVII::hasVecPolicyOp(TSFlags)) {
83581ad6265SDimitry Andric       const MachineOperand &Op = MI.getOperand(MI.getNumExplicitOperands() - 1);
83681ad6265SDimitry Andric       uint64_t Policy = Op.getImm();
83781ad6265SDimitry Andric       assert(Policy <= (RISCVII::TAIL_AGNOSTIC | RISCVII::MASK_AGNOSTIC) &&
83881ad6265SDimitry Andric              "Invalid Policy Value");
83981ad6265SDimitry Andric       TailAgnostic = Policy & RISCVII::TAIL_AGNOSTIC;
84081ad6265SDimitry Andric       MaskAgnostic = Policy & RISCVII::MASK_AGNOSTIC;
841bdd1243dSDimitry Andric     }
842bdd1243dSDimitry Andric 
84381ad6265SDimitry Andric     // Some pseudo instructions force a tail agnostic policy despite having a
84481ad6265SDimitry Andric     // tied def.
84581ad6265SDimitry Andric     if (RISCVII::doesForceTailAgnostic(TSFlags))
84681ad6265SDimitry Andric       TailAgnostic = true;
847bdd1243dSDimitry Andric 
848bdd1243dSDimitry Andric     if (!RISCVII::usesMaskPolicy(TSFlags))
849bdd1243dSDimitry Andric       MaskAgnostic = true;
85081ad6265SDimitry Andric   }
85181ad6265SDimitry Andric 
85281ad6265SDimitry Andric   RISCVII::VLMUL VLMul = RISCVII::getLMul(TSFlags);
85381ad6265SDimitry Andric 
85481ad6265SDimitry Andric   unsigned Log2SEW = MI.getOperand(getSEWOpNum(MI)).getImm();
85581ad6265SDimitry Andric   // A Log2SEW of 0 is an operation on mask registers only.
85681ad6265SDimitry Andric   unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
85781ad6265SDimitry Andric   assert(RISCVVType::isValidSEW(SEW) && "Unexpected SEW");
85881ad6265SDimitry Andric 
85981ad6265SDimitry Andric   if (RISCVII::hasVLOp(TSFlags)) {
86081ad6265SDimitry Andric     const MachineOperand &VLOp = MI.getOperand(getVLOpNum(MI));
86181ad6265SDimitry Andric     if (VLOp.isImm()) {
86281ad6265SDimitry Andric       int64_t Imm = VLOp.getImm();
86381ad6265SDimitry Andric       // Conver the VLMax sentintel to X0 register.
864*7a6dacacSDimitry Andric       if (Imm == RISCV::VLMaxSentinel) {
865*7a6dacacSDimitry Andric         // If we know the exact VLEN, see if we can use the constant encoding
866*7a6dacacSDimitry Andric         // for the VLMAX instead.  This reduces register pressure slightly.
867*7a6dacacSDimitry Andric         const unsigned VLMAX = computeVLMAX(ST.getRealMaxVLen(), SEW, VLMul);
868*7a6dacacSDimitry Andric         if (ST.getRealMinVLen() == ST.getRealMaxVLen() && VLMAX <= 31)
869*7a6dacacSDimitry Andric           InstrInfo.setAVLImm(VLMAX);
870*7a6dacacSDimitry Andric         else
87181ad6265SDimitry Andric           InstrInfo.setAVLReg(RISCV::X0);
872*7a6dacacSDimitry Andric       }
87381ad6265SDimitry Andric       else
87481ad6265SDimitry Andric         InstrInfo.setAVLImm(Imm);
87581ad6265SDimitry Andric     } else {
87681ad6265SDimitry Andric       InstrInfo.setAVLReg(VLOp.getReg());
87781ad6265SDimitry Andric     }
87881ad6265SDimitry Andric   } else {
8795f757f3fSDimitry Andric     assert(isScalarExtractInstr(MI));
88081ad6265SDimitry Andric     InstrInfo.setAVLReg(RISCV::NoRegister);
88181ad6265SDimitry Andric   }
88281ad6265SDimitry Andric #ifndef NDEBUG
883bdd1243dSDimitry Andric   if (std::optional<unsigned> EEW = getEEWForLoadStore(MI)) {
88481ad6265SDimitry Andric     assert(SEW == EEW && "Initial SEW doesn't match expected EEW");
88581ad6265SDimitry Andric   }
88681ad6265SDimitry Andric #endif
88781ad6265SDimitry Andric   InstrInfo.setVTYPE(VLMul, SEW, TailAgnostic, MaskAgnostic);
88881ad6265SDimitry Andric 
8895f757f3fSDimitry Andric   // If AVL is defined by a vsetvli with the same VLMAX, we can replace the
8905f757f3fSDimitry Andric   // AVL operand with the AVL of the defining vsetvli.  We avoid general
8915f757f3fSDimitry Andric   // register AVLs to avoid extending live ranges without being sure we can
8925f757f3fSDimitry Andric   // kill the original source reg entirely.
8935f757f3fSDimitry Andric   if (InstrInfo.hasAVLReg() && InstrInfo.getAVLReg().isVirtual()) {
8945f757f3fSDimitry Andric     MachineInstr *DefMI = MRI->getVRegDef(InstrInfo.getAVLReg());
8955f757f3fSDimitry Andric     if (DefMI && isVectorConfigInstr(*DefMI)) {
8965f757f3fSDimitry Andric       VSETVLIInfo DefInstrInfo = getInfoForVSETVLI(*DefMI);
8975f757f3fSDimitry Andric       if (DefInstrInfo.hasSameVLMAX(InstrInfo) &&
8985f757f3fSDimitry Andric           (DefInstrInfo.hasAVLImm() || DefInstrInfo.getAVLReg() == RISCV::X0)) {
8995f757f3fSDimitry Andric         InstrInfo.setAVL(DefInstrInfo);
9005f757f3fSDimitry Andric       }
9015f757f3fSDimitry Andric     }
9025f757f3fSDimitry Andric   }
9035f757f3fSDimitry Andric 
90481ad6265SDimitry Andric   return InstrInfo;
90581ad6265SDimitry Andric }
90681ad6265SDimitry Andric 
90781ad6265SDimitry Andric void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB, MachineInstr &MI,
90881ad6265SDimitry Andric                                        const VSETVLIInfo &Info,
90981ad6265SDimitry Andric                                        const VSETVLIInfo &PrevInfo) {
91081ad6265SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
91181ad6265SDimitry Andric   insertVSETVLI(MBB, MachineBasicBlock::iterator(&MI), DL, Info, PrevInfo);
91281ad6265SDimitry Andric }
91381ad6265SDimitry Andric 
91481ad6265SDimitry Andric void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB,
91581ad6265SDimitry Andric                      MachineBasicBlock::iterator InsertPt, DebugLoc DL,
91681ad6265SDimitry Andric                      const VSETVLIInfo &Info, const VSETVLIInfo &PrevInfo) {
91781ad6265SDimitry Andric 
918*7a6dacacSDimitry Andric   ++NumInsertedVSETVL;
91906c3fb27SDimitry Andric   if (PrevInfo.isValid() && !PrevInfo.isUnknown()) {
92081ad6265SDimitry Andric     // Use X0, X0 form if the AVL is the same and the SEW+LMUL gives the same
92181ad6265SDimitry Andric     // VLMAX.
92206c3fb27SDimitry Andric     if (Info.hasSameAVL(PrevInfo) && Info.hasSameVLMAX(PrevInfo)) {
92381ad6265SDimitry Andric       BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0))
92481ad6265SDimitry Andric           .addReg(RISCV::X0, RegState::Define | RegState::Dead)
92581ad6265SDimitry Andric           .addReg(RISCV::X0, RegState::Kill)
92681ad6265SDimitry Andric           .addImm(Info.encodeVTYPE())
92781ad6265SDimitry Andric           .addReg(RISCV::VL, RegState::Implicit);
92881ad6265SDimitry Andric       return;
92981ad6265SDimitry Andric     }
93081ad6265SDimitry Andric 
93106c3fb27SDimitry Andric     // If our AVL is a virtual register, it might be defined by a VSET(I)VLI. If
93206c3fb27SDimitry Andric     // it has the same VLMAX we want and the last VL/VTYPE we observed is the
93306c3fb27SDimitry Andric     // same, we can use the X0, X0 form.
93406c3fb27SDimitry Andric     if (Info.hasSameVLMAX(PrevInfo) && Info.hasAVLReg() &&
93506c3fb27SDimitry Andric         Info.getAVLReg().isVirtual()) {
93606c3fb27SDimitry Andric       if (MachineInstr *DefMI = MRI->getVRegDef(Info.getAVLReg())) {
93706c3fb27SDimitry Andric         if (isVectorConfigInstr(*DefMI)) {
93806c3fb27SDimitry Andric           VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI);
93906c3fb27SDimitry Andric           if (DefInfo.hasSameAVL(PrevInfo) && DefInfo.hasSameVLMAX(PrevInfo)) {
94006c3fb27SDimitry Andric             BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0))
94106c3fb27SDimitry Andric                 .addReg(RISCV::X0, RegState::Define | RegState::Dead)
94206c3fb27SDimitry Andric                 .addReg(RISCV::X0, RegState::Kill)
94306c3fb27SDimitry Andric                 .addImm(Info.encodeVTYPE())
94406c3fb27SDimitry Andric                 .addReg(RISCV::VL, RegState::Implicit);
94506c3fb27SDimitry Andric             return;
94606c3fb27SDimitry Andric           }
94706c3fb27SDimitry Andric         }
94806c3fb27SDimitry Andric       }
94906c3fb27SDimitry Andric     }
95006c3fb27SDimitry Andric   }
95106c3fb27SDimitry Andric 
95281ad6265SDimitry Andric   if (Info.hasAVLImm()) {
95381ad6265SDimitry Andric     BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETIVLI))
95481ad6265SDimitry Andric         .addReg(RISCV::X0, RegState::Define | RegState::Dead)
95581ad6265SDimitry Andric         .addImm(Info.getAVLImm())
95681ad6265SDimitry Andric         .addImm(Info.encodeVTYPE());
95781ad6265SDimitry Andric     return;
95881ad6265SDimitry Andric   }
95981ad6265SDimitry Andric 
96081ad6265SDimitry Andric   Register AVLReg = Info.getAVLReg();
96181ad6265SDimitry Andric   if (AVLReg == RISCV::NoRegister) {
96281ad6265SDimitry Andric     // We can only use x0, x0 if there's no chance of the vtype change causing
96381ad6265SDimitry Andric     // the previous vl to become invalid.
96481ad6265SDimitry Andric     if (PrevInfo.isValid() && !PrevInfo.isUnknown() &&
96581ad6265SDimitry Andric         Info.hasSameVLMAX(PrevInfo)) {
96681ad6265SDimitry Andric       BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0))
96781ad6265SDimitry Andric           .addReg(RISCV::X0, RegState::Define | RegState::Dead)
96881ad6265SDimitry Andric           .addReg(RISCV::X0, RegState::Kill)
96981ad6265SDimitry Andric           .addImm(Info.encodeVTYPE())
97081ad6265SDimitry Andric           .addReg(RISCV::VL, RegState::Implicit);
97181ad6265SDimitry Andric       return;
97281ad6265SDimitry Andric     }
9735f757f3fSDimitry Andric     // Otherwise use an AVL of 1 to avoid depending on previous vl.
97481ad6265SDimitry Andric     BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETIVLI))
97581ad6265SDimitry Andric         .addReg(RISCV::X0, RegState::Define | RegState::Dead)
9765f757f3fSDimitry Andric         .addImm(1)
97781ad6265SDimitry Andric         .addImm(Info.encodeVTYPE());
97881ad6265SDimitry Andric     return;
97981ad6265SDimitry Andric   }
98081ad6265SDimitry Andric 
98181ad6265SDimitry Andric   if (AVLReg.isVirtual())
98281ad6265SDimitry Andric     MRI->constrainRegClass(AVLReg, &RISCV::GPRNoX0RegClass);
98381ad6265SDimitry Andric 
98481ad6265SDimitry Andric   // Use X0 as the DestReg unless AVLReg is X0. We also need to change the
98581ad6265SDimitry Andric   // opcode if the AVLReg is X0 as they have different register classes for
98681ad6265SDimitry Andric   // the AVL operand.
98781ad6265SDimitry Andric   Register DestReg = RISCV::X0;
98881ad6265SDimitry Andric   unsigned Opcode = RISCV::PseudoVSETVLI;
98981ad6265SDimitry Andric   if (AVLReg == RISCV::X0) {
99081ad6265SDimitry Andric     DestReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
99181ad6265SDimitry Andric     Opcode = RISCV::PseudoVSETVLIX0;
99281ad6265SDimitry Andric   }
99381ad6265SDimitry Andric   BuildMI(MBB, InsertPt, DL, TII->get(Opcode))
99481ad6265SDimitry Andric       .addReg(DestReg, RegState::Define | RegState::Dead)
99581ad6265SDimitry Andric       .addReg(AVLReg)
99681ad6265SDimitry Andric       .addImm(Info.encodeVTYPE());
99781ad6265SDimitry Andric }
99881ad6265SDimitry Andric 
99906c3fb27SDimitry Andric static bool isLMUL1OrSmaller(RISCVII::VLMUL LMUL) {
100006c3fb27SDimitry Andric   auto [LMul, Fractional] = RISCVVType::decodeVLMUL(LMUL);
100106c3fb27SDimitry Andric   return Fractional || LMul == 1;
100281ad6265SDimitry Andric }
100381ad6265SDimitry Andric 
100481ad6265SDimitry Andric /// Return true if a VSETVLI is required to transition from CurInfo to Require
100581ad6265SDimitry Andric /// before MI.
100681ad6265SDimitry Andric bool RISCVInsertVSETVLI::needVSETVLI(const MachineInstr &MI,
100781ad6265SDimitry Andric                                      const VSETVLIInfo &Require,
100881ad6265SDimitry Andric                                      const VSETVLIInfo &CurInfo) const {
1009*7a6dacacSDimitry Andric   assert(Require == computeInfoForInstr(MI, MI.getDesc().TSFlags, *ST, MRI));
101081ad6265SDimitry Andric 
101181ad6265SDimitry Andric   if (!CurInfo.isValid() || CurInfo.isUnknown() || CurInfo.hasSEWLMULRatioOnly())
101281ad6265SDimitry Andric     return true;
101381ad6265SDimitry Andric 
10145f757f3fSDimitry Andric   DemandedFields Used = getDemanded(MI, MRI, ST);
1015bdd1243dSDimitry Andric 
101606c3fb27SDimitry Andric   // A slidedown/slideup with an *undefined* merge op can freely clobber
101706c3fb27SDimitry Andric   // elements not copied from the source vector (e.g. masked off, tail, or
101806c3fb27SDimitry Andric   // slideup's prefix). Notes:
101906c3fb27SDimitry Andric   // * We can't modify SEW here since the slide amount is in units of SEW.
102006c3fb27SDimitry Andric   // * VL=1 is special only because we have existing support for zero vs
102106c3fb27SDimitry Andric   //   non-zero VL.  We could generalize this if we had a VL > C predicate.
102206c3fb27SDimitry Andric   // * The LMUL1 restriction is for machines whose latency may depend on VL.
102306c3fb27SDimitry Andric   // * As above, this is only legal for tail "undefined" not "agnostic".
102406c3fb27SDimitry Andric   if (isVSlideInstr(MI) && Require.hasAVLImm() && Require.getAVLImm() == 1 &&
102506c3fb27SDimitry Andric       isLMUL1OrSmaller(CurInfo.getVLMUL()) && hasUndefinedMergeOp(MI, *MRI)) {
102606c3fb27SDimitry Andric     Used.VLAny = false;
102706c3fb27SDimitry Andric     Used.VLZeroness = true;
102806c3fb27SDimitry Andric     Used.LMUL = false;
1029bdd1243dSDimitry Andric     Used.TailPolicy = false;
103081ad6265SDimitry Andric   }
103106c3fb27SDimitry Andric 
103206c3fb27SDimitry Andric   // A tail undefined vmv.v.i/x or vfmv.v.f with VL=1 can be treated in the same
103306c3fb27SDimitry Andric   // semantically as vmv.s.x.  This is particularly useful since we don't have an
103406c3fb27SDimitry Andric   // immediate form of vmv.s.x, and thus frequently use vmv.v.i in it's place.
103506c3fb27SDimitry Andric   // Since a splat is non-constant time in LMUL, we do need to be careful to not
103606c3fb27SDimitry Andric   // increase the number of active vector registers (unlike for vmv.s.x.)
103706c3fb27SDimitry Andric   if (isScalarSplatInstr(MI) && Require.hasAVLImm() && Require.getAVLImm() == 1 &&
103806c3fb27SDimitry Andric       isLMUL1OrSmaller(CurInfo.getVLMUL()) && hasUndefinedMergeOp(MI, *MRI)) {
103906c3fb27SDimitry Andric     Used.LMUL = false;
104006c3fb27SDimitry Andric     Used.SEWLMULRatio = false;
104106c3fb27SDimitry Andric     Used.VLAny = false;
10425f757f3fSDimitry Andric     if (isFloatScalarMoveOrScalarSplatInstr(MI) && !ST->hasVInstructionsF64())
10435f757f3fSDimitry Andric       Used.SEW = DemandedFields::SEWGreaterThanOrEqualAndLessThan64;
10445f757f3fSDimitry Andric     else
104506c3fb27SDimitry Andric       Used.SEW = DemandedFields::SEWGreaterThanOrEqual;
104606c3fb27SDimitry Andric     Used.TailPolicy = false;
1047bdd1243dSDimitry Andric   }
1048bdd1243dSDimitry Andric 
104906c3fb27SDimitry Andric   if (CurInfo.isCompatible(Used, Require, *MRI))
1050bdd1243dSDimitry Andric     return false;
105181ad6265SDimitry Andric 
105281ad6265SDimitry Andric   // We didn't find a compatible value. If our AVL is a virtual register,
105381ad6265SDimitry Andric   // it might be defined by a VSET(I)VLI. If it has the same VLMAX we need
105481ad6265SDimitry Andric   // and the last VL/VTYPE we observed is the same, we don't need a
105581ad6265SDimitry Andric   // VSETVLI here.
105681ad6265SDimitry Andric   if (Require.hasAVLReg() && Require.getAVLReg().isVirtual() &&
1057bdd1243dSDimitry Andric       CurInfo.hasCompatibleVTYPE(Used, Require)) {
105881ad6265SDimitry Andric     if (MachineInstr *DefMI = MRI->getVRegDef(Require.getAVLReg())) {
105981ad6265SDimitry Andric       if (isVectorConfigInstr(*DefMI)) {
106081ad6265SDimitry Andric         VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI);
106181ad6265SDimitry Andric         if (DefInfo.hasSameAVL(CurInfo) && DefInfo.hasSameVLMAX(CurInfo))
106281ad6265SDimitry Andric           return false;
106381ad6265SDimitry Andric       }
106481ad6265SDimitry Andric     }
106581ad6265SDimitry Andric   }
106681ad6265SDimitry Andric 
106781ad6265SDimitry Andric   return true;
106881ad6265SDimitry Andric }
106981ad6265SDimitry Andric 
10705f757f3fSDimitry Andric // If we don't use LMUL or the SEW/LMUL ratio, then adjust LMUL so that we
10715f757f3fSDimitry Andric // maintain the SEW/LMUL ratio. This allows us to eliminate VL toggles in more
10725f757f3fSDimitry Andric // places.
10735f757f3fSDimitry Andric static VSETVLIInfo adjustIncoming(VSETVLIInfo PrevInfo, VSETVLIInfo NewInfo,
10745f757f3fSDimitry Andric                                   DemandedFields &Demanded) {
10755f757f3fSDimitry Andric   VSETVLIInfo Info = NewInfo;
10765f757f3fSDimitry Andric 
10775f757f3fSDimitry Andric   if (!Demanded.LMUL && !Demanded.SEWLMULRatio && PrevInfo.isValid() &&
10785f757f3fSDimitry Andric       !PrevInfo.isUnknown()) {
10795f757f3fSDimitry Andric     if (auto NewVLMul = RISCVVType::getSameRatioLMUL(
10805f757f3fSDimitry Andric             PrevInfo.getSEW(), PrevInfo.getVLMUL(), Info.getSEW()))
10815f757f3fSDimitry Andric       Info.setVLMul(*NewVLMul);
10825f757f3fSDimitry Andric     Demanded.LMUL = true;
10835f757f3fSDimitry Andric   }
10845f757f3fSDimitry Andric 
10855f757f3fSDimitry Andric   return Info;
10865f757f3fSDimitry Andric }
10875f757f3fSDimitry Andric 
10885f757f3fSDimitry Andric // Given an incoming state reaching MI, minimally modifies that state so that it
10895f757f3fSDimitry Andric // is compatible with MI. The resulting state is guaranteed to be semantically
10905f757f3fSDimitry Andric // legal for MI, but may not be the state requested by MI.
10915f757f3fSDimitry Andric void RISCVInsertVSETVLI::transferBefore(VSETVLIInfo &Info,
10925f757f3fSDimitry Andric                                         const MachineInstr &MI) const {
109381ad6265SDimitry Andric   uint64_t TSFlags = MI.getDesc().TSFlags;
109481ad6265SDimitry Andric   if (!RISCVII::hasSEWOp(TSFlags))
109581ad6265SDimitry Andric     return;
109681ad6265SDimitry Andric 
1097*7a6dacacSDimitry Andric   const VSETVLIInfo NewInfo = computeInfoForInstr(MI, TSFlags, *ST, MRI);
10985f757f3fSDimitry Andric   assert(NewInfo.isValid() && !NewInfo.isUnknown());
109981ad6265SDimitry Andric   if (Info.isValid() && !needVSETVLI(MI, NewInfo, Info))
110081ad6265SDimitry Andric     return;
110181ad6265SDimitry Andric 
110281ad6265SDimitry Andric   const VSETVLIInfo PrevInfo = Info;
11035f757f3fSDimitry Andric   if (!Info.isValid() || Info.isUnknown())
110481ad6265SDimitry Andric     Info = NewInfo;
110581ad6265SDimitry Andric 
11065f757f3fSDimitry Andric   DemandedFields Demanded = getDemanded(MI, MRI, ST);
11075f757f3fSDimitry Andric   const VSETVLIInfo IncomingInfo = adjustIncoming(PrevInfo, NewInfo, Demanded);
110881ad6265SDimitry Andric 
11095f757f3fSDimitry Andric   // If MI only demands that VL has the same zeroness, we only need to set the
11105f757f3fSDimitry Andric   // AVL if the zeroness differs.  This removes a vsetvli entirely if the types
11115f757f3fSDimitry Andric   // match or allows use of cheaper avl preserving variant if VLMAX doesn't
11125f757f3fSDimitry Andric   // change. If VLMAX might change, we couldn't use the 'vsetvli x0, x0, vtype"
11135f757f3fSDimitry Andric   // variant, so we avoid the transform to prevent extending live range of an
11145f757f3fSDimitry Andric   // avl register operand.
111581ad6265SDimitry Andric   // TODO: We can probably relax this for immediates.
11165f757f3fSDimitry Andric   bool EquallyZero = IncomingInfo.hasEquallyZeroAVL(PrevInfo, *MRI) &&
11175f757f3fSDimitry Andric                      IncomingInfo.hasSameVLMAX(PrevInfo);
11185f757f3fSDimitry Andric   if (Demanded.VLAny || (Demanded.VLZeroness && !EquallyZero))
11195f757f3fSDimitry Andric     Info.setAVL(IncomingInfo);
112081ad6265SDimitry Andric 
11215f757f3fSDimitry Andric   Info.setVTYPE(
11225f757f3fSDimitry Andric       ((Demanded.LMUL || Demanded.SEWLMULRatio) ? IncomingInfo : Info)
11235f757f3fSDimitry Andric           .getVLMUL(),
11245f757f3fSDimitry Andric       ((Demanded.SEW || Demanded.SEWLMULRatio) ? IncomingInfo : Info).getSEW(),
11255f757f3fSDimitry Andric       // Prefer tail/mask agnostic since it can be relaxed to undisturbed later
11265f757f3fSDimitry Andric       // if needed.
11275f757f3fSDimitry Andric       (Demanded.TailPolicy ? IncomingInfo : Info).getTailAgnostic() ||
11285f757f3fSDimitry Andric           IncomingInfo.getTailAgnostic(),
11295f757f3fSDimitry Andric       (Demanded.MaskPolicy ? IncomingInfo : Info).getMaskAgnostic() ||
11305f757f3fSDimitry Andric           IncomingInfo.getMaskAgnostic());
113181ad6265SDimitry Andric 
11325f757f3fSDimitry Andric   // If we only knew the sew/lmul ratio previously, replace the VTYPE but keep
11335f757f3fSDimitry Andric   // the AVL.
11345f757f3fSDimitry Andric   if (Info.hasSEWLMULRatioOnly()) {
11355f757f3fSDimitry Andric     VSETVLIInfo RatiolessInfo = IncomingInfo;
11365f757f3fSDimitry Andric     RatiolessInfo.setAVL(Info);
11375f757f3fSDimitry Andric     Info = RatiolessInfo;
113881ad6265SDimitry Andric   }
113981ad6265SDimitry Andric }
114081ad6265SDimitry Andric 
114181ad6265SDimitry Andric // Given a state with which we evaluated MI (see transferBefore above for why
114281ad6265SDimitry Andric // this might be different that the state MI requested), modify the state to
114381ad6265SDimitry Andric // reflect the changes MI might make.
11445f757f3fSDimitry Andric void RISCVInsertVSETVLI::transferAfter(VSETVLIInfo &Info,
11455f757f3fSDimitry Andric                                        const MachineInstr &MI) const {
114681ad6265SDimitry Andric   if (isVectorConfigInstr(MI)) {
114781ad6265SDimitry Andric     Info = getInfoForVSETVLI(MI);
114881ad6265SDimitry Andric     return;
114981ad6265SDimitry Andric   }
115081ad6265SDimitry Andric 
115181ad6265SDimitry Andric   if (RISCV::isFaultFirstLoad(MI)) {
115281ad6265SDimitry Andric     // Update AVL to vl-output of the fault first load.
115381ad6265SDimitry Andric     Info.setAVLReg(MI.getOperand(1).getReg());
115481ad6265SDimitry Andric     return;
115581ad6265SDimitry Andric   }
115681ad6265SDimitry Andric 
115781ad6265SDimitry Andric   // If this is something that updates VL/VTYPE that we don't know about, set
115881ad6265SDimitry Andric   // the state to unknown.
115981ad6265SDimitry Andric   if (MI.isCall() || MI.isInlineAsm() || MI.modifiesRegister(RISCV::VL) ||
116081ad6265SDimitry Andric       MI.modifiesRegister(RISCV::VTYPE))
116181ad6265SDimitry Andric     Info = VSETVLIInfo::getUnknown();
1162349cc55cSDimitry Andric }
1163349cc55cSDimitry Andric 
11645f757f3fSDimitry Andric bool RISCVInsertVSETVLI::computeVLVTYPEChanges(const MachineBasicBlock &MBB,
11655f757f3fSDimitry Andric                                                VSETVLIInfo &Info) const {
1166fe6060f1SDimitry Andric   bool HadVectorOp = false;
1167fe6060f1SDimitry Andric 
11685f757f3fSDimitry Andric   Info = BlockInfo[MBB.getNumber()].Pred;
1169fe6060f1SDimitry Andric   for (const MachineInstr &MI : MBB) {
11705f757f3fSDimitry Andric     transferBefore(Info, MI);
1171fe6060f1SDimitry Andric 
117281ad6265SDimitry Andric     if (isVectorConfigInstr(MI) || RISCVII::hasSEWOp(MI.getDesc().TSFlags))
1173fe6060f1SDimitry Andric       HadVectorOp = true;
1174fe6060f1SDimitry Andric 
11755f757f3fSDimitry Andric     transferAfter(Info, MI);
1176fe6060f1SDimitry Andric   }
1177fe6060f1SDimitry Andric 
1178fe6060f1SDimitry Andric   return HadVectorOp;
1179fe6060f1SDimitry Andric }
1180fe6060f1SDimitry Andric 
1181fe6060f1SDimitry Andric void RISCVInsertVSETVLI::computeIncomingVLVTYPE(const MachineBasicBlock &MBB) {
118281ad6265SDimitry Andric 
1183fe6060f1SDimitry Andric   BlockData &BBInfo = BlockInfo[MBB.getNumber()];
1184fe6060f1SDimitry Andric 
1185fe6060f1SDimitry Andric   BBInfo.InQueue = false;
1186fe6060f1SDimitry Andric 
1187bdd1243dSDimitry Andric   // Start with the previous entry so that we keep the most conservative state
1188bdd1243dSDimitry Andric   // we have ever found.
1189bdd1243dSDimitry Andric   VSETVLIInfo InInfo = BBInfo.Pred;
1190fe6060f1SDimitry Andric   if (MBB.pred_empty()) {
1191fe6060f1SDimitry Andric     // There are no predecessors, so use the default starting status.
1192fe6060f1SDimitry Andric     InInfo.setUnknown();
1193fe6060f1SDimitry Andric   } else {
1194fe6060f1SDimitry Andric     for (MachineBasicBlock *P : MBB.predecessors())
1195fe6060f1SDimitry Andric       InInfo = InInfo.intersect(BlockInfo[P->getNumber()].Exit);
1196fe6060f1SDimitry Andric   }
1197fe6060f1SDimitry Andric 
1198fe6060f1SDimitry Andric   // If we don't have any valid predecessor value, wait until we do.
1199fe6060f1SDimitry Andric   if (!InInfo.isValid())
1200fe6060f1SDimitry Andric     return;
1201fe6060f1SDimitry Andric 
120281ad6265SDimitry Andric   // If no change, no need to rerun block
120381ad6265SDimitry Andric   if (InInfo == BBInfo.Pred)
120481ad6265SDimitry Andric     return;
1205fe6060f1SDimitry Andric 
120681ad6265SDimitry Andric   BBInfo.Pred = InInfo;
120781ad6265SDimitry Andric   LLVM_DEBUG(dbgs() << "Entry state of " << printMBBReference(MBB)
120881ad6265SDimitry Andric                     << " changed to " << BBInfo.Pred << "\n");
120981ad6265SDimitry Andric 
121081ad6265SDimitry Andric   // Note: It's tempting to cache the state changes here, but due to the
121181ad6265SDimitry Andric   // compatibility checks performed a blocks output state can change based on
121281ad6265SDimitry Andric   // the input state.  To cache, we'd have to add logic for finding
121381ad6265SDimitry Andric   // never-compatible state changes.
12145f757f3fSDimitry Andric   VSETVLIInfo TmpStatus;
12155f757f3fSDimitry Andric   computeVLVTYPEChanges(MBB, TmpStatus);
1216fe6060f1SDimitry Andric 
1217fe6060f1SDimitry Andric   // If the new exit value matches the old exit value, we don't need to revisit
1218fe6060f1SDimitry Andric   // any blocks.
1219fe6060f1SDimitry Andric   if (BBInfo.Exit == TmpStatus)
1220fe6060f1SDimitry Andric     return;
1221fe6060f1SDimitry Andric 
1222fe6060f1SDimitry Andric   BBInfo.Exit = TmpStatus;
122381ad6265SDimitry Andric   LLVM_DEBUG(dbgs() << "Exit state of " << printMBBReference(MBB)
122481ad6265SDimitry Andric                     << " changed to " << BBInfo.Exit << "\n");
1225fe6060f1SDimitry Andric 
1226fe6060f1SDimitry Andric   // Add the successors to the work list so we can propagate the changed exit
1227fe6060f1SDimitry Andric   // status.
1228fe6060f1SDimitry Andric   for (MachineBasicBlock *S : MBB.successors())
1229bdd1243dSDimitry Andric     if (!BlockInfo[S->getNumber()].InQueue) {
1230bdd1243dSDimitry Andric       BlockInfo[S->getNumber()].InQueue = true;
1231fe6060f1SDimitry Andric       WorkList.push(S);
1232fe6060f1SDimitry Andric     }
1233bdd1243dSDimitry Andric }
1234fe6060f1SDimitry Andric 
1235fe6060f1SDimitry Andric // If we weren't able to prove a vsetvli was directly unneeded, it might still
123681ad6265SDimitry Andric // be unneeded if the AVL is a phi node where all incoming values are VL
1237fe6060f1SDimitry Andric // outputs from the last VSETVLI in their respective basic blocks.
1238fe6060f1SDimitry Andric bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo &Require,
123981ad6265SDimitry Andric                                         const MachineBasicBlock &MBB) const {
1240fe6060f1SDimitry Andric   if (DisableInsertVSETVLPHIOpt)
1241fe6060f1SDimitry Andric     return true;
1242fe6060f1SDimitry Andric 
1243fe6060f1SDimitry Andric   if (!Require.hasAVLReg())
1244fe6060f1SDimitry Andric     return true;
1245fe6060f1SDimitry Andric 
1246fe6060f1SDimitry Andric   Register AVLReg = Require.getAVLReg();
1247fe6060f1SDimitry Andric   if (!AVLReg.isVirtual())
1248fe6060f1SDimitry Andric     return true;
1249fe6060f1SDimitry Andric 
1250fe6060f1SDimitry Andric   // We need the AVL to be produce by a PHI node in this basic block.
1251fe6060f1SDimitry Andric   MachineInstr *PHI = MRI->getVRegDef(AVLReg);
1252fe6060f1SDimitry Andric   if (!PHI || PHI->getOpcode() != RISCV::PHI || PHI->getParent() != &MBB)
1253fe6060f1SDimitry Andric     return true;
1254fe6060f1SDimitry Andric 
1255fe6060f1SDimitry Andric   for (unsigned PHIOp = 1, NumOps = PHI->getNumOperands(); PHIOp != NumOps;
1256fe6060f1SDimitry Andric        PHIOp += 2) {
1257fe6060f1SDimitry Andric     Register InReg = PHI->getOperand(PHIOp).getReg();
1258fe6060f1SDimitry Andric     MachineBasicBlock *PBB = PHI->getOperand(PHIOp + 1).getMBB();
1259fe6060f1SDimitry Andric     const BlockData &PBBInfo = BlockInfo[PBB->getNumber()];
1260fe6060f1SDimitry Andric     // If the exit from the predecessor has the VTYPE we are looking for
1261fe6060f1SDimitry Andric     // we might be able to avoid a VSETVLI.
126281ad6265SDimitry Andric     if (PBBInfo.Exit.isUnknown() || !PBBInfo.Exit.hasSameVTYPE(Require))
1263fe6060f1SDimitry Andric       return true;
1264fe6060f1SDimitry Andric 
1265fe6060f1SDimitry Andric     // We need the PHI input to the be the output of a VSET(I)VLI.
1266fe6060f1SDimitry Andric     MachineInstr *DefMI = MRI->getVRegDef(InReg);
126781ad6265SDimitry Andric     if (!DefMI || !isVectorConfigInstr(*DefMI))
1268fe6060f1SDimitry Andric       return true;
1269fe6060f1SDimitry Andric 
1270fe6060f1SDimitry Andric     // We found a VSET(I)VLI make sure it matches the output of the
1271fe6060f1SDimitry Andric     // predecessor block.
1272fe6060f1SDimitry Andric     VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI);
1273fe6060f1SDimitry Andric     if (!DefInfo.hasSameAVL(PBBInfo.Exit) ||
1274fe6060f1SDimitry Andric         !DefInfo.hasSameVTYPE(PBBInfo.Exit))
1275fe6060f1SDimitry Andric       return true;
1276fe6060f1SDimitry Andric   }
1277fe6060f1SDimitry Andric 
1278fe6060f1SDimitry Andric   // If all the incoming values to the PHI checked out, we don't need
1279fe6060f1SDimitry Andric   // to insert a VSETVLI.
1280fe6060f1SDimitry Andric   return false;
1281fe6060f1SDimitry Andric }
1282fe6060f1SDimitry Andric 
1283fe6060f1SDimitry Andric void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) {
128481ad6265SDimitry Andric   VSETVLIInfo CurInfo = BlockInfo[MBB.getNumber()].Pred;
128581ad6265SDimitry Andric   // Track whether the prefix of the block we've scanned is transparent
128681ad6265SDimitry Andric   // (meaning has not yet changed the abstract state).
128781ad6265SDimitry Andric   bool PrefixTransparent = true;
1288fe6060f1SDimitry Andric   for (MachineInstr &MI : MBB) {
128981ad6265SDimitry Andric     const VSETVLIInfo PrevInfo = CurInfo;
129081ad6265SDimitry Andric     transferBefore(CurInfo, MI);
129181ad6265SDimitry Andric 
1292fe6060f1SDimitry Andric     // If this is an explicit VSETVLI or VSETIVLI, update our state.
129381ad6265SDimitry Andric     if (isVectorConfigInstr(MI)) {
1294fe6060f1SDimitry Andric       // Conservatively, mark the VL and VTYPE as live.
1295fe6060f1SDimitry Andric       assert(MI.getOperand(3).getReg() == RISCV::VL &&
1296fe6060f1SDimitry Andric              MI.getOperand(4).getReg() == RISCV::VTYPE &&
1297fe6060f1SDimitry Andric              "Unexpected operands where VL and VTYPE should be");
1298fe6060f1SDimitry Andric       MI.getOperand(3).setIsDead(false);
1299fe6060f1SDimitry Andric       MI.getOperand(4).setIsDead(false);
130081ad6265SDimitry Andric       PrefixTransparent = false;
1301fe6060f1SDimitry Andric     }
1302fe6060f1SDimitry Andric 
1303fe6060f1SDimitry Andric     uint64_t TSFlags = MI.getDesc().TSFlags;
1304fe6060f1SDimitry Andric     if (RISCVII::hasSEWOp(TSFlags)) {
130581ad6265SDimitry Andric       if (PrevInfo != CurInfo) {
130681ad6265SDimitry Andric         // If this is the first implicit state change, and the state change
130781ad6265SDimitry Andric         // requested can be proven to produce the same register contents, we
130881ad6265SDimitry Andric         // can skip emitting the actual state change and continue as if we
130981ad6265SDimitry Andric         // had since we know the GPR result of the implicit state change
131081ad6265SDimitry Andric         // wouldn't be used and VL/VTYPE registers are correct.  Note that
131181ad6265SDimitry Andric         // we *do* need to model the state as if it changed as while the
131281ad6265SDimitry Andric         // register contents are unchanged, the abstract model can change.
131381ad6265SDimitry Andric         if (!PrefixTransparent || needVSETVLIPHI(CurInfo, MBB))
131481ad6265SDimitry Andric           insertVSETVLI(MBB, MI, CurInfo, PrevInfo);
131581ad6265SDimitry Andric         PrefixTransparent = false;
131681ad6265SDimitry Andric       }
131781ad6265SDimitry Andric 
1318fe6060f1SDimitry Andric       if (RISCVII::hasVLOp(TSFlags)) {
131981ad6265SDimitry Andric         MachineOperand &VLOp = MI.getOperand(getVLOpNum(MI));
1320fe6060f1SDimitry Andric         if (VLOp.isReg()) {
13215f757f3fSDimitry Andric           Register Reg = VLOp.getReg();
13225f757f3fSDimitry Andric           MachineInstr *VLOpDef = MRI->getVRegDef(Reg);
13235f757f3fSDimitry Andric 
1324fe6060f1SDimitry Andric           // Erase the AVL operand from the instruction.
1325fe6060f1SDimitry Andric           VLOp.setReg(RISCV::NoRegister);
1326fe6060f1SDimitry Andric           VLOp.setIsKill(false);
13275f757f3fSDimitry Andric 
13285f757f3fSDimitry Andric           // If the AVL was an immediate > 31, then it would have been emitted
13295f757f3fSDimitry Andric           // as an ADDI. However, the ADDI might not have been used in the
13305f757f3fSDimitry Andric           // vsetvli, or a vsetvli might not have been emitted, so it may be
13315f757f3fSDimitry Andric           // dead now.
13325f757f3fSDimitry Andric           if (VLOpDef && TII->isAddImmediate(*VLOpDef, Reg) &&
13335f757f3fSDimitry Andric               MRI->use_nodbg_empty(Reg))
13345f757f3fSDimitry Andric             VLOpDef->eraseFromParent();
1335fe6060f1SDimitry Andric         }
1336fe6060f1SDimitry Andric         MI.addOperand(MachineOperand::CreateReg(RISCV::VL, /*isDef*/ false,
1337fe6060f1SDimitry Andric                                                 /*isImp*/ true));
1338fe6060f1SDimitry Andric       }
1339fe6060f1SDimitry Andric       MI.addOperand(MachineOperand::CreateReg(RISCV::VTYPE, /*isDef*/ false,
1340fe6060f1SDimitry Andric                                               /*isImp*/ true));
1341fe6060f1SDimitry Andric     }
1342fe6060f1SDimitry Andric 
1343fe6060f1SDimitry Andric     if (MI.isCall() || MI.isInlineAsm() || MI.modifiesRegister(RISCV::VL) ||
134481ad6265SDimitry Andric         MI.modifiesRegister(RISCV::VTYPE))
134581ad6265SDimitry Andric       PrefixTransparent = false;
134681ad6265SDimitry Andric 
134781ad6265SDimitry Andric     transferAfter(CurInfo, MI);
1348fe6060f1SDimitry Andric   }
1349d56accc7SDimitry Andric 
1350d56accc7SDimitry Andric   // If we reach the end of the block and our current info doesn't match the
1351d56accc7SDimitry Andric   // expected info, insert a vsetvli to correct.
135281ad6265SDimitry Andric   if (!UseStrictAsserts) {
1353d56accc7SDimitry Andric     const VSETVLIInfo &ExitInfo = BlockInfo[MBB.getNumber()].Exit;
1354d56accc7SDimitry Andric     if (CurInfo.isValid() && ExitInfo.isValid() && !ExitInfo.isUnknown() &&
1355d56accc7SDimitry Andric         CurInfo != ExitInfo) {
135681ad6265SDimitry Andric       // Note there's an implicit assumption here that terminators never use
135781ad6265SDimitry Andric       // or modify VL or VTYPE.  Also, fallthrough will return end().
135881ad6265SDimitry Andric       auto InsertPt = MBB.getFirstInstrTerminator();
135981ad6265SDimitry Andric       insertVSETVLI(MBB, InsertPt, MBB.findDebugLoc(InsertPt), ExitInfo,
136081ad6265SDimitry Andric                     CurInfo);
1361d56accc7SDimitry Andric       CurInfo = ExitInfo;
1362d56accc7SDimitry Andric     }
1363d56accc7SDimitry Andric   }
136481ad6265SDimitry Andric 
136581ad6265SDimitry Andric   if (UseStrictAsserts && CurInfo.isValid()) {
136681ad6265SDimitry Andric     const auto &Info = BlockInfo[MBB.getNumber()];
136781ad6265SDimitry Andric     if (CurInfo != Info.Exit) {
136881ad6265SDimitry Andric       LLVM_DEBUG(dbgs() << "in block " << printMBBReference(MBB) << "\n");
136981ad6265SDimitry Andric       LLVM_DEBUG(dbgs() << "  begin        state: " << Info.Pred << "\n");
137081ad6265SDimitry Andric       LLVM_DEBUG(dbgs() << "  expected end state: " << Info.Exit << "\n");
137181ad6265SDimitry Andric       LLVM_DEBUG(dbgs() << "  actual   end state: " << CurInfo << "\n");
137281ad6265SDimitry Andric     }
137381ad6265SDimitry Andric     assert(CurInfo == Info.Exit &&
137481ad6265SDimitry Andric            "InsertVSETVLI dataflow invariant violated");
137581ad6265SDimitry Andric   }
137681ad6265SDimitry Andric }
137781ad6265SDimitry Andric 
137881ad6265SDimitry Andric /// Perform simple partial redundancy elimination of the VSETVLI instructions
137981ad6265SDimitry Andric /// we're about to insert by looking for cases where we can PRE from the
138081ad6265SDimitry Andric /// beginning of one block to the end of one of its predecessors.  Specifically,
138181ad6265SDimitry Andric /// this is geared to catch the common case of a fixed length vsetvl in a single
138281ad6265SDimitry Andric /// block loop when it could execute once in the preheader instead.
138381ad6265SDimitry Andric void RISCVInsertVSETVLI::doPRE(MachineBasicBlock &MBB) {
138481ad6265SDimitry Andric   if (!BlockInfo[MBB.getNumber()].Pred.isUnknown())
138581ad6265SDimitry Andric     return;
138681ad6265SDimitry Andric 
138781ad6265SDimitry Andric   MachineBasicBlock *UnavailablePred = nullptr;
138881ad6265SDimitry Andric   VSETVLIInfo AvailableInfo;
138981ad6265SDimitry Andric   for (MachineBasicBlock *P : MBB.predecessors()) {
139081ad6265SDimitry Andric     const VSETVLIInfo &PredInfo = BlockInfo[P->getNumber()].Exit;
139181ad6265SDimitry Andric     if (PredInfo.isUnknown()) {
139281ad6265SDimitry Andric       if (UnavailablePred)
139381ad6265SDimitry Andric         return;
139481ad6265SDimitry Andric       UnavailablePred = P;
139581ad6265SDimitry Andric     } else if (!AvailableInfo.isValid()) {
139681ad6265SDimitry Andric       AvailableInfo = PredInfo;
139781ad6265SDimitry Andric     } else if (AvailableInfo != PredInfo) {
139881ad6265SDimitry Andric       return;
139981ad6265SDimitry Andric     }
140081ad6265SDimitry Andric   }
140181ad6265SDimitry Andric 
140281ad6265SDimitry Andric   // Unreachable, single pred, or full redundancy. Note that FRE is handled by
140381ad6265SDimitry Andric   // phase 3.
140481ad6265SDimitry Andric   if (!UnavailablePred || !AvailableInfo.isValid())
140581ad6265SDimitry Andric     return;
140681ad6265SDimitry Andric 
14071db9f3b2SDimitry Andric   // If we don't know the exact VTYPE, we can't copy the vsetvli to the exit of
14081db9f3b2SDimitry Andric   // the unavailable pred.
14091db9f3b2SDimitry Andric   if (AvailableInfo.hasSEWLMULRatioOnly())
14101db9f3b2SDimitry Andric     return;
14111db9f3b2SDimitry Andric 
141281ad6265SDimitry Andric   // Critical edge - TODO: consider splitting?
141381ad6265SDimitry Andric   if (UnavailablePred->succ_size() != 1)
141481ad6265SDimitry Andric     return;
141581ad6265SDimitry Andric 
14165f757f3fSDimitry Andric   // If the AVL value is a register (other than our VLMAX sentinel),
14175f757f3fSDimitry Andric   // we need to prove the value is available at the point we're going
14185f757f3fSDimitry Andric   // to insert the vsetvli at.
14195f757f3fSDimitry Andric   if (AvailableInfo.hasAVLReg() && RISCV::X0 != AvailableInfo.getAVLReg()) {
14205f757f3fSDimitry Andric     MachineInstr *AVLDefMI = MRI->getVRegDef(AvailableInfo.getAVLReg());
14215f757f3fSDimitry Andric     if (!AVLDefMI)
142281ad6265SDimitry Andric       return;
14235f757f3fSDimitry Andric     // This is an inline dominance check which covers the case of
14245f757f3fSDimitry Andric     // UnavailablePred being the preheader of a loop.
14255f757f3fSDimitry Andric     if (AVLDefMI->getParent() != UnavailablePred)
14265f757f3fSDimitry Andric       return;
14275f757f3fSDimitry Andric     for (auto &TermMI : UnavailablePred->terminators())
14285f757f3fSDimitry Andric       if (&TermMI == AVLDefMI)
14295f757f3fSDimitry Andric         return;
14305f757f3fSDimitry Andric   }
143181ad6265SDimitry Andric 
143206c3fb27SDimitry Andric   // Model the effect of changing the input state of the block MBB to
143306c3fb27SDimitry Andric   // AvailableInfo.  We're looking for two issues here; one legality,
143406c3fb27SDimitry Andric   // one profitability.
143506c3fb27SDimitry Andric   // 1) If the block doesn't use some of the fields from VL or VTYPE, we
143606c3fb27SDimitry Andric   //    may hit the end of the block with a different end state.  We can
143706c3fb27SDimitry Andric   //    not make this change without reflowing later blocks as well.
143806c3fb27SDimitry Andric   // 2) If we don't actually remove a transition, inserting a vsetvli
143906c3fb27SDimitry Andric   //    into the predecessor block would be correct, but unprofitable.
144006c3fb27SDimitry Andric   VSETVLIInfo OldInfo = BlockInfo[MBB.getNumber()].Pred;
144106c3fb27SDimitry Andric   VSETVLIInfo CurInfo = AvailableInfo;
144206c3fb27SDimitry Andric   int TransitionsRemoved = 0;
144306c3fb27SDimitry Andric   for (const MachineInstr &MI : MBB) {
144406c3fb27SDimitry Andric     const VSETVLIInfo LastInfo = CurInfo;
144506c3fb27SDimitry Andric     const VSETVLIInfo LastOldInfo = OldInfo;
144606c3fb27SDimitry Andric     transferBefore(CurInfo, MI);
144706c3fb27SDimitry Andric     transferBefore(OldInfo, MI);
144806c3fb27SDimitry Andric     if (CurInfo == LastInfo)
144906c3fb27SDimitry Andric       TransitionsRemoved++;
145006c3fb27SDimitry Andric     if (LastOldInfo == OldInfo)
145106c3fb27SDimitry Andric       TransitionsRemoved--;
145206c3fb27SDimitry Andric     transferAfter(CurInfo, MI);
145306c3fb27SDimitry Andric     transferAfter(OldInfo, MI);
145406c3fb27SDimitry Andric     if (CurInfo == OldInfo)
145506c3fb27SDimitry Andric       // Convergence.  All transitions after this must match by construction.
145681ad6265SDimitry Andric       break;
145781ad6265SDimitry Andric   }
145806c3fb27SDimitry Andric   if (CurInfo != OldInfo || TransitionsRemoved <= 0)
145906c3fb27SDimitry Andric     // Issues 1 and 2 above
146081ad6265SDimitry Andric     return;
146181ad6265SDimitry Andric 
146281ad6265SDimitry Andric   // Finally, update both data flow state and insert the actual vsetvli.
146381ad6265SDimitry Andric   // Doing both keeps the code in sync with the dataflow results, which
146481ad6265SDimitry Andric   // is critical for correctness of phase 3.
146506c3fb27SDimitry Andric   auto OldExit = BlockInfo[UnavailablePred->getNumber()].Exit;
146681ad6265SDimitry Andric   LLVM_DEBUG(dbgs() << "PRE VSETVLI from " << MBB.getName() << " to "
146781ad6265SDimitry Andric                     << UnavailablePred->getName() << " with state "
146881ad6265SDimitry Andric                     << AvailableInfo << "\n");
146981ad6265SDimitry Andric   BlockInfo[UnavailablePred->getNumber()].Exit = AvailableInfo;
147081ad6265SDimitry Andric   BlockInfo[MBB.getNumber()].Pred = AvailableInfo;
147181ad6265SDimitry Andric 
147281ad6265SDimitry Andric   // Note there's an implicit assumption here that terminators never use
147381ad6265SDimitry Andric   // or modify VL or VTYPE.  Also, fallthrough will return end().
147481ad6265SDimitry Andric   auto InsertPt = UnavailablePred->getFirstInstrTerminator();
147581ad6265SDimitry Andric   insertVSETVLI(*UnavailablePred, InsertPt,
147681ad6265SDimitry Andric                 UnavailablePred->findDebugLoc(InsertPt),
147706c3fb27SDimitry Andric                 AvailableInfo, OldExit);
147881ad6265SDimitry Andric }
147981ad6265SDimitry Andric 
148081ad6265SDimitry Andric static void doUnion(DemandedFields &A, DemandedFields B) {
1481bdd1243dSDimitry Andric   A.VLAny |= B.VLAny;
1482bdd1243dSDimitry Andric   A.VLZeroness |= B.VLZeroness;
148306c3fb27SDimitry Andric   A.SEW = std::max(A.SEW, B.SEW);
148481ad6265SDimitry Andric   A.LMUL |= B.LMUL;
148581ad6265SDimitry Andric   A.SEWLMULRatio |= B.SEWLMULRatio;
148681ad6265SDimitry Andric   A.TailPolicy |= B.TailPolicy;
148781ad6265SDimitry Andric   A.MaskPolicy |= B.MaskPolicy;
148881ad6265SDimitry Andric }
148981ad6265SDimitry Andric 
1490bdd1243dSDimitry Andric // Return true if we can mutate PrevMI to match MI without changing any the
1491bdd1243dSDimitry Andric // fields which would be observed.
149281ad6265SDimitry Andric static bool canMutatePriorConfig(const MachineInstr &PrevMI,
149381ad6265SDimitry Andric                                  const MachineInstr &MI,
14945f757f3fSDimitry Andric                                  const DemandedFields &Used,
14955f757f3fSDimitry Andric                                  const MachineRegisterInfo &MRI) {
1496bdd1243dSDimitry Andric   // If the VL values aren't equal, return false if either a) the former is
1497bdd1243dSDimitry Andric   // demanded, or b) we can't rewrite the former to be the later for
1498bdd1243dSDimitry Andric   // implementation reasons.
1499bdd1243dSDimitry Andric   if (!isVLPreservingConfig(MI)) {
1500bdd1243dSDimitry Andric     if (Used.VLAny)
150181ad6265SDimitry Andric       return false;
150281ad6265SDimitry Andric 
15035f757f3fSDimitry Andric     if (Used.VLZeroness) {
15045f757f3fSDimitry Andric       if (isVLPreservingConfig(PrevMI))
1505bdd1243dSDimitry Andric         return false;
1506297eecfbSDimitry Andric       if (!getInfoForVSETVLI(PrevMI).hasEquallyZeroAVL(getInfoForVSETVLI(MI),
1507297eecfbSDimitry Andric                                                        MRI))
15085f757f3fSDimitry Andric         return false;
15095f757f3fSDimitry Andric     }
1510bdd1243dSDimitry Andric 
1511297eecfbSDimitry Andric     auto &AVL = MI.getOperand(1);
1512297eecfbSDimitry Andric     auto &PrevAVL = PrevMI.getOperand(1);
1513297eecfbSDimitry Andric     assert(MRI.isSSA());
1514297eecfbSDimitry Andric 
1515297eecfbSDimitry Andric     // If the AVL is a register, we need to make sure MI's AVL dominates PrevMI.
1516297eecfbSDimitry Andric     // For now just check that PrevMI uses the same virtual register.
1517297eecfbSDimitry Andric     if (AVL.isReg() && AVL.getReg() != RISCV::X0) {
1518297eecfbSDimitry Andric       if (AVL.getReg().isPhysical())
1519bdd1243dSDimitry Andric         return false;
1520297eecfbSDimitry Andric       if (!PrevAVL.isReg() || PrevAVL.getReg() != AVL.getReg())
1521297eecfbSDimitry Andric         return false;
1522297eecfbSDimitry Andric     }
1523bdd1243dSDimitry Andric   }
1524bdd1243dSDimitry Andric 
152581ad6265SDimitry Andric   if (!PrevMI.getOperand(2).isImm() || !MI.getOperand(2).isImm())
152681ad6265SDimitry Andric     return false;
152781ad6265SDimitry Andric 
152881ad6265SDimitry Andric   auto PriorVType = PrevMI.getOperand(2).getImm();
152981ad6265SDimitry Andric   auto VType = MI.getOperand(2).getImm();
153081ad6265SDimitry Andric   return areCompatibleVTYPEs(PriorVType, VType, Used);
153181ad6265SDimitry Andric }
153281ad6265SDimitry Andric 
153381ad6265SDimitry Andric void RISCVInsertVSETVLI::doLocalPostpass(MachineBasicBlock &MBB) {
1534bdd1243dSDimitry Andric   MachineInstr *NextMI = nullptr;
1535bdd1243dSDimitry Andric   // We can have arbitrary code in successors, so VL and VTYPE
1536bdd1243dSDimitry Andric   // must be considered demanded.
153781ad6265SDimitry Andric   DemandedFields Used;
1538bdd1243dSDimitry Andric   Used.demandVL();
1539bdd1243dSDimitry Andric   Used.demandVTYPE();
154081ad6265SDimitry Andric   SmallVector<MachineInstr*> ToDelete;
1541bdd1243dSDimitry Andric   for (MachineInstr &MI : make_range(MBB.rbegin(), MBB.rend())) {
1542bdd1243dSDimitry Andric 
1543bdd1243dSDimitry Andric     if (!isVectorConfigInstr(MI)) {
15445f757f3fSDimitry Andric       doUnion(Used, getDemanded(MI, MRI, ST));
154581ad6265SDimitry Andric       continue;
154681ad6265SDimitry Andric     }
1547bdd1243dSDimitry Andric 
154881ad6265SDimitry Andric     Register VRegDef = MI.getOperand(0).getReg();
154981ad6265SDimitry Andric     if (VRegDef != RISCV::X0 &&
155081ad6265SDimitry Andric         !(VRegDef.isVirtual() && MRI->use_nodbg_empty(VRegDef)))
1551bdd1243dSDimitry Andric       Used.demandVL();
1552bdd1243dSDimitry Andric 
1553bdd1243dSDimitry Andric     if (NextMI) {
1554bdd1243dSDimitry Andric       if (!Used.usedVL() && !Used.usedVTYPE()) {
1555bdd1243dSDimitry Andric         ToDelete.push_back(&MI);
1556bdd1243dSDimitry Andric         // Leave NextMI unchanged
1557bdd1243dSDimitry Andric         continue;
15585f757f3fSDimitry Andric       } else if (canMutatePriorConfig(MI, *NextMI, Used, *MRI)) {
1559bdd1243dSDimitry Andric         if (!isVLPreservingConfig(*NextMI)) {
15605f757f3fSDimitry Andric           MI.getOperand(0).setReg(NextMI->getOperand(0).getReg());
15615f757f3fSDimitry Andric           MI.getOperand(0).setIsDead(false);
15625f757f3fSDimitry Andric           Register OldVLReg;
15635f757f3fSDimitry Andric           if (MI.getOperand(1).isReg())
15645f757f3fSDimitry Andric             OldVLReg = MI.getOperand(1).getReg();
1565bdd1243dSDimitry Andric           if (NextMI->getOperand(1).isImm())
1566bdd1243dSDimitry Andric             MI.getOperand(1).ChangeToImmediate(NextMI->getOperand(1).getImm());
1567bdd1243dSDimitry Andric           else
1568bdd1243dSDimitry Andric             MI.getOperand(1).ChangeToRegister(NextMI->getOperand(1).getReg(), false);
15695f757f3fSDimitry Andric           if (OldVLReg) {
15705f757f3fSDimitry Andric             MachineInstr *VLOpDef = MRI->getUniqueVRegDef(OldVLReg);
15715f757f3fSDimitry Andric             if (VLOpDef && TII->isAddImmediate(*VLOpDef, OldVLReg) &&
15725f757f3fSDimitry Andric                 MRI->use_nodbg_empty(OldVLReg))
15735f757f3fSDimitry Andric               VLOpDef->eraseFromParent();
15745f757f3fSDimitry Andric           }
1575bdd1243dSDimitry Andric           MI.setDesc(NextMI->getDesc());
1576bdd1243dSDimitry Andric         }
1577bdd1243dSDimitry Andric         MI.getOperand(2).setImm(NextMI->getOperand(2).getImm());
1578bdd1243dSDimitry Andric         ToDelete.push_back(NextMI);
1579bdd1243dSDimitry Andric         // fallthrough
1580bdd1243dSDimitry Andric       }
1581bdd1243dSDimitry Andric     }
1582bdd1243dSDimitry Andric     NextMI = &MI;
15835f757f3fSDimitry Andric     Used = getDemanded(MI, MRI, ST);
158481ad6265SDimitry Andric   }
158581ad6265SDimitry Andric 
1586*7a6dacacSDimitry Andric   NumRemovedVSETVL += ToDelete.size();
158781ad6265SDimitry Andric   for (auto *MI : ToDelete)
158881ad6265SDimitry Andric     MI->eraseFromParent();
158981ad6265SDimitry Andric }
159081ad6265SDimitry Andric 
159181ad6265SDimitry Andric void RISCVInsertVSETVLI::insertReadVL(MachineBasicBlock &MBB) {
159281ad6265SDimitry Andric   for (auto I = MBB.begin(), E = MBB.end(); I != E;) {
159381ad6265SDimitry Andric     MachineInstr &MI = *I++;
159481ad6265SDimitry Andric     if (RISCV::isFaultFirstLoad(MI)) {
159581ad6265SDimitry Andric       Register VLOutput = MI.getOperand(1).getReg();
159681ad6265SDimitry Andric       if (!MRI->use_nodbg_empty(VLOutput))
159781ad6265SDimitry Andric         BuildMI(MBB, I, MI.getDebugLoc(), TII->get(RISCV::PseudoReadVL),
159881ad6265SDimitry Andric                 VLOutput);
159981ad6265SDimitry Andric       // We don't use the vl output of the VLEFF/VLSEGFF anymore.
160081ad6265SDimitry Andric       MI.getOperand(1).setReg(RISCV::X0);
160181ad6265SDimitry Andric     }
1602fe6060f1SDimitry Andric   }
1603fe6060f1SDimitry Andric }
1604fe6060f1SDimitry Andric 
1605fe6060f1SDimitry Andric bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
1606fe6060f1SDimitry Andric   // Skip if the vector extension is not enabled.
16075f757f3fSDimitry Andric   ST = &MF.getSubtarget<RISCVSubtarget>();
16085f757f3fSDimitry Andric   if (!ST->hasVInstructions())
1609fe6060f1SDimitry Andric     return false;
1610fe6060f1SDimitry Andric 
161181ad6265SDimitry Andric   LLVM_DEBUG(dbgs() << "Entering InsertVSETVLI for " << MF.getName() << "\n");
161281ad6265SDimitry Andric 
16135f757f3fSDimitry Andric   TII = ST->getInstrInfo();
1614fe6060f1SDimitry Andric   MRI = &MF.getRegInfo();
1615fe6060f1SDimitry Andric 
1616fe6060f1SDimitry Andric   assert(BlockInfo.empty() && "Expect empty block infos");
1617fe6060f1SDimitry Andric   BlockInfo.resize(MF.getNumBlockIDs());
1618fe6060f1SDimitry Andric 
1619fe6060f1SDimitry Andric   bool HaveVectorOp = false;
1620fe6060f1SDimitry Andric 
1621fe6060f1SDimitry Andric   // Phase 1 - determine how VL/VTYPE are affected by the each block.
162281ad6265SDimitry Andric   for (const MachineBasicBlock &MBB : MF) {
16235f757f3fSDimitry Andric     VSETVLIInfo TmpStatus;
16245f757f3fSDimitry Andric     HaveVectorOp |= computeVLVTYPEChanges(MBB, TmpStatus);
162581ad6265SDimitry Andric     // Initial exit state is whatever change we found in the block.
162681ad6265SDimitry Andric     BlockData &BBInfo = BlockInfo[MBB.getNumber()];
16275f757f3fSDimitry Andric     BBInfo.Exit = TmpStatus;
162881ad6265SDimitry Andric     LLVM_DEBUG(dbgs() << "Initial exit state of " << printMBBReference(MBB)
162981ad6265SDimitry Andric                       << " is " << BBInfo.Exit << "\n");
163081ad6265SDimitry Andric 
163181ad6265SDimitry Andric   }
1632fe6060f1SDimitry Andric 
1633fe6060f1SDimitry Andric   // If we didn't find any instructions that need VSETVLI, we're done.
163481ad6265SDimitry Andric   if (!HaveVectorOp) {
163581ad6265SDimitry Andric     BlockInfo.clear();
163681ad6265SDimitry Andric     return false;
163781ad6265SDimitry Andric   }
163881ad6265SDimitry Andric 
1639fe6060f1SDimitry Andric   // Phase 2 - determine the exit VL/VTYPE from each block. We add all
1640fe6060f1SDimitry Andric   // blocks to the list here, but will also add any that need to be revisited
1641fe6060f1SDimitry Andric   // during Phase 2 processing.
1642fe6060f1SDimitry Andric   for (const MachineBasicBlock &MBB : MF) {
1643fe6060f1SDimitry Andric     WorkList.push(&MBB);
1644fe6060f1SDimitry Andric     BlockInfo[MBB.getNumber()].InQueue = true;
1645fe6060f1SDimitry Andric   }
1646fe6060f1SDimitry Andric   while (!WorkList.empty()) {
1647fe6060f1SDimitry Andric     const MachineBasicBlock &MBB = *WorkList.front();
1648fe6060f1SDimitry Andric     WorkList.pop();
1649fe6060f1SDimitry Andric     computeIncomingVLVTYPE(MBB);
1650fe6060f1SDimitry Andric   }
1651fe6060f1SDimitry Andric 
165281ad6265SDimitry Andric   // Perform partial redundancy elimination of vsetvli transitions.
165381ad6265SDimitry Andric   for (MachineBasicBlock &MBB : MF)
165481ad6265SDimitry Andric     doPRE(MBB);
165581ad6265SDimitry Andric 
1656fe6060f1SDimitry Andric   // Phase 3 - add any vsetvli instructions needed in the block. Use the
1657fe6060f1SDimitry Andric   // Phase 2 information to avoid adding vsetvlis before the first vector
1658fe6060f1SDimitry Andric   // instruction in the block if the VL/VTYPE is satisfied by its
1659fe6060f1SDimitry Andric   // predecessors.
1660fe6060f1SDimitry Andric   for (MachineBasicBlock &MBB : MF)
1661fe6060f1SDimitry Andric     emitVSETVLIs(MBB);
166281ad6265SDimitry Andric 
166381ad6265SDimitry Andric   // Now that all vsetvlis are explicit, go through and do block local
166481ad6265SDimitry Andric   // DSE and peephole based demanded fields based transforms.  Note that
166581ad6265SDimitry Andric   // this *must* be done outside the main dataflow so long as we allow
166681ad6265SDimitry Andric   // any cross block analysis within the dataflow.  We can't have both
166781ad6265SDimitry Andric   // demanded fields based mutation and non-local analysis in the
166881ad6265SDimitry Andric   // dataflow at the same time without introducing inconsistencies.
166981ad6265SDimitry Andric   for (MachineBasicBlock &MBB : MF)
167081ad6265SDimitry Andric     doLocalPostpass(MBB);
167181ad6265SDimitry Andric 
167281ad6265SDimitry Andric   // Insert PseudoReadVL after VLEFF/VLSEGFF and replace it with the vl output
167381ad6265SDimitry Andric   // of VLEFF/VLSEGFF.
167481ad6265SDimitry Andric   for (MachineBasicBlock &MBB : MF)
167581ad6265SDimitry Andric     insertReadVL(MBB);
1676fe6060f1SDimitry Andric 
167781ad6265SDimitry Andric   BlockInfo.clear();
1678fe6060f1SDimitry Andric   return HaveVectorOp;
1679fe6060f1SDimitry Andric }
1680fe6060f1SDimitry Andric 
1681fe6060f1SDimitry Andric /// Returns an instance of the Insert VSETVLI pass.
1682fe6060f1SDimitry Andric FunctionPass *llvm::createRISCVInsertVSETVLIPass() {
1683fe6060f1SDimitry Andric   return new RISCVInsertVSETVLI();
1684fe6060f1SDimitry Andric }
1685