1//===-------------- RISCVVLOptimizer.cpp - VL Optimizer -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===---------------------------------------------------------------------===//
8//
9// This pass reduces the VL where possible at the MI level, before VSETVLI
10// instructions are inserted.
11//
12// The purpose of this optimization is to make the VL argument, for instructions
13// that have a VL argument, as small as possible.
14//
15// This is split into a sparse dataflow analysis where we determine what VL is
16// demanded by each instruction first, and then afterwards try to reduce the VL
17// of each instruction if it demands less than its VL operand.
18//
19// The analysis is explained in more detail in the 2025 EuroLLVM Developers'
20// Meeting talk "Accidental Dataflow Analysis: Extending the RISC-V VL
21// Optimizer", which is available on YouTube at
22// https://www.youtube.com/watch?v=Mfb5fRSdJAc
23//
24// The slides for the talk are available at
25// https://llvm.org/devmtg/2025-04/slides/technical_talk/lau_accidental_dataflow.pdf
26//
27//===---------------------------------------------------------------------===//
28
29#include "RISCV.h"
30#include "RISCVSubtarget.h"
31#include "llvm/ADT/PostOrderIterator.h"
32#include "llvm/ADT/SetVector.h"
33#include "llvm/CodeGen/MachineDominators.h"
34#include "llvm/CodeGen/MachineFunctionPass.h"
35#include "llvm/CodeGen/RegisterClassInfo.h"
36#include "llvm/InitializePasses.h"
37
38using namespace llvm;
39
40#define DEBUG_TYPE "riscv-vl-optimizer"
41#define PASS_NAME "RISC-V VL Optimizer"
42
43namespace {
44
45/// Wrapper around MachineOperand that defaults to immediate 0.
46struct DemandedVL {
47 MachineOperand VL;
48 DemandedVL() : VL(MachineOperand::CreateImm(Val: 0)) {}
49 DemandedVL(MachineOperand VL) : VL(VL) {}
50 static DemandedVL vlmax() {
51 return DemandedVL(MachineOperand::CreateImm(Val: RISCV::VLMaxSentinel));
52 }
53 bool operator!=(const DemandedVL &Other) const {
54 return !VL.isIdenticalTo(Other: Other.VL);
55 }
56
57 DemandedVL max(const MachineRegisterInfo &MRI, const DemandedVL &X) const {
58 if (RISCV::isVLKnownLE(MRI, LHS: VL, RHS: X.VL))
59 return X;
60 if (RISCV::isVLKnownLE(MRI, LHS: X.VL, RHS: VL))
61 return *this;
62 return DemandedVL::vlmax();
63 }
64};
65
66class RISCVVLOptimizerImpl {
67 MachineRegisterInfo *MRI;
68 const MachineDominatorTree *MDT;
69 const TargetInstrInfo *TII;
70
71public:
72 RISCVVLOptimizerImpl(const MachineDominatorTree *MDT) : MDT(MDT) {}
73
74 bool run(MachineFunction &MF);
75
76private:
77 DemandedVL getMinimumVLForUser(const MachineInstr &UserMI,
78 unsigned OpIdx) const;
79 /// Returns true if the users of \p MI have compatible EEWs and SEWs.
80 bool checkUsers(const MachineInstr &MI) const;
81 bool tryReduceVL(MachineInstr &MI, MachineOperand VL) const;
82 bool isSupportedInstr(const MachineInstr &MI) const;
83 bool isCandidate(const MachineInstr &MI) const;
84 void transfer(const MachineInstr &MI);
85
86 /// For a given instruction, records what elements of it are demanded by
87 /// downstream users.
88 MapVector<const MachineInstr *, DemandedVL> DemandedVLs;
89 SetVector<const MachineInstr *> Worklist;
90
91 /// \returns all vector virtual registers that \p MI uses.
92 auto virtual_vec_uses(const MachineInstr &MI) const {
93 return make_filter_range(Range: MI.uses(), Pred: [this](const MachineOperand &MO) {
94 return MO.isReg() && MO.getReg().isVirtual() &&
95 RISCVRegisterInfo::isRVVRegClass(RC: MRI->getRegClass(Reg: MO.getReg()));
96 });
97 }
98};
99
100class RISCVVLOptimizerLegacy : public MachineFunctionPass {
101public:
102 static char ID;
103
104 RISCVVLOptimizerLegacy() : MachineFunctionPass(ID) {}
105
106 bool runOnMachineFunction(MachineFunction &MF) override;
107
108 void getAnalysisUsage(AnalysisUsage &AU) const override {
109 AU.setPreservesCFG();
110 AU.addRequired<MachineDominatorTreeWrapperPass>();
111 AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
112 MachineFunctionPass::getAnalysisUsage(AU);
113 }
114
115 StringRef getPassName() const override { return PASS_NAME; }
116};
117
118/// Represents the EMUL and EEW of a MachineOperand.
119struct OperandInfo {
120 // Represent as 1,2,4,8, ... and fractional indicator. This is because
121 // EMUL can take on values that don't map to RISCVVType::VLMUL values exactly.
122 // For example, a mask operand can have an EMUL less than MF8.
123 // If nullopt, then EMUL isn't used (i.e. only a single scalar is read).
124 std::optional<std::pair<unsigned, bool>> EMUL;
125
126 unsigned Log2EEW;
127
128 OperandInfo(RISCVVType::VLMUL EMUL, unsigned Log2EEW)
129 : EMUL(RISCVVType::decodeVLMUL(VLMul: EMUL)), Log2EEW(Log2EEW) {}
130
131 OperandInfo(std::pair<unsigned, bool> EMUL, unsigned Log2EEW)
132 : EMUL(EMUL), Log2EEW(Log2EEW) {}
133
134 OperandInfo(unsigned Log2EEW) : Log2EEW(Log2EEW) {}
135
136 OperandInfo() = delete;
137
138 /// Return true if the EMUL and EEW produced by \p Def is compatible with the
139 /// EMUL and EEW used by \p User.
140 static bool areCompatible(const OperandInfo &Def, const OperandInfo &User) {
141 if (Def.Log2EEW != User.Log2EEW)
142 return false;
143 if (User.EMUL && Def.EMUL != User.EMUL)
144 return false;
145 return true;
146 }
147
148 void print(raw_ostream &OS) const {
149 if (EMUL) {
150 OS << "EMUL: m";
151 if (EMUL->second)
152 OS << "f";
153 OS << EMUL->first;
154 } else
155 OS << "EMUL: none\n";
156 OS << ", EEW: " << (1 << Log2EEW);
157 }
158};
159
160} // end anonymous namespace
161
162char RISCVVLOptimizerLegacy::ID = 0;
163INITIALIZE_PASS_BEGIN(RISCVVLOptimizerLegacy, DEBUG_TYPE, PASS_NAME, false,
164 false)
165INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
166INITIALIZE_PASS_END(RISCVVLOptimizerLegacy, DEBUG_TYPE, PASS_NAME, false, false)
167
168FunctionPass *llvm::createRISCVVLOptimizerLegacyPass() {
169 return new RISCVVLOptimizerLegacy();
170}
171
172[[maybe_unused]]
173static raw_ostream &operator<<(raw_ostream &OS, const OperandInfo &OI) {
174 OI.print(OS);
175 return OS;
176}
177
178[[maybe_unused]]
179static raw_ostream &operator<<(raw_ostream &OS,
180 const std::optional<OperandInfo> &OI) {
181 if (OI)
182 OI->print(OS);
183 else
184 OS << "nullopt";
185 return OS;
186}
187
188/// Return EMUL = (EEW / SEW) * LMUL where EEW comes from Log2EEW and LMUL and
189/// SEW are from the TSFlags of MI.
190static std::pair<unsigned, bool>
191getEMULEqualsEEWDivSEWTimesLMUL(unsigned Log2EEW, const MachineInstr &MI) {
192 RISCVVType::VLMUL MIVLMUL = RISCVII::getLMul(TSFlags: MI.getDesc().TSFlags);
193 auto [MILMUL, MILMULIsFractional] = RISCVVType::decodeVLMUL(VLMul: MIVLMUL);
194 unsigned MILog2SEW =
195 MI.getOperand(i: RISCVII::getSEWOpNum(Desc: MI.getDesc())).getImm();
196
197 // Mask instructions will have 0 as the SEW operand. But the LMUL of these
198 // instructions is calculated is as if the SEW operand was 3 (e8).
199 if (MILog2SEW == 0)
200 MILog2SEW = 3;
201
202 unsigned MISEW = 1 << MILog2SEW;
203
204 unsigned EEW = 1 << Log2EEW;
205 // Calculate (EEW/SEW)*LMUL preserving fractions less than 1. Use GCD
206 // to put fraction in simplest form.
207 unsigned Num = EEW, Denom = MISEW;
208 int GCD = MILMULIsFractional ? std::gcd(m: Num, n: Denom * MILMUL)
209 : std::gcd(m: Num * MILMUL, n: Denom);
210 Num = MILMULIsFractional ? Num / GCD : Num * MILMUL / GCD;
211 Denom = MILMULIsFractional ? Denom * MILMUL / GCD : Denom / GCD;
212 return std::make_pair(x&: Num > Denom ? Num : Denom, y: Denom > Num);
213}
214
215static DemandedVL doubleVL(DemandedVL MinimumVL) {
216 if (!MinimumVL.VL.isImm())
217 return DemandedVL::vlmax();
218
219 int64_t VL = MinimumVL.VL.getImm();
220 if (!isUInt<4>(x: VL))
221 return DemandedVL::vlmax();
222 return MachineOperand::CreateImm(Val: VL * 2);
223}
224
225static DemandedVL halfVL(DemandedVL MinimumVL, bool Ceil = false) {
226 if (!MinimumVL.VL.isImm())
227 return DemandedVL::vlmax();
228
229 int64_t VL = MinimumVL.VL.getImm();
230 if (!isUInt<5>(x: VL))
231 return DemandedVL::vlmax();
232 return MachineOperand::CreateImm(Val: (VL + Ceil) / 2);
233}
234
235static std::pair<unsigned, bool> doubleEMUL(std::pair<unsigned, bool> EMUL) {
236 auto [Num, IsFractional] = EMUL;
237 if (IsFractional)
238 return std::make_pair(x: Num / 2, y: Num > 2);
239 return std::make_pair(x: Num * 2, y: false);
240}
241
242static std::pair<unsigned, bool> halfEMUL(std::pair<unsigned, bool> EMUL) {
243 auto [Num, IsFractional] = EMUL;
244 if (IsFractional || Num == 1)
245 return std::make_pair(x: Num * 2, y: true);
246 return std::make_pair(x: Num / 2, y: false);
247}
248
249/// Dest has EEW=SEW. Source EEW=SEW/Factor (i.e. F2 => EEW/2).
250/// SEW comes from TSFlags of MI.
251static unsigned getIntegerExtensionOperandEEW(unsigned Factor,
252 const MachineInstr &MI,
253 unsigned OpIdx) {
254 unsigned MILog2SEW =
255 MI.getOperand(i: RISCVII::getSEWOpNum(Desc: MI.getDesc())).getImm();
256
257 if (OpIdx == 0)
258 return MILog2SEW;
259
260 unsigned MISEW = 1 << MILog2SEW;
261 unsigned EEW = MISEW / Factor;
262 unsigned Log2EEW = Log2_32(Value: EEW);
263
264 return Log2EEW;
265}
266
267#define VSEG_CASES(Prefix, EEW) \
268 RISCV::Prefix##SEG2E##EEW##_V: \
269 case RISCV::Prefix##SEG3E##EEW##_V: \
270 case RISCV::Prefix##SEG4E##EEW##_V: \
271 case RISCV::Prefix##SEG5E##EEW##_V: \
272 case RISCV::Prefix##SEG6E##EEW##_V: \
273 case RISCV::Prefix##SEG7E##EEW##_V: \
274 case RISCV::Prefix##SEG8E##EEW##_V
275#define VSSEG_CASES(EEW) VSEG_CASES(VS, EEW)
276#define VSSSEG_CASES(EEW) VSEG_CASES(VSS, EEW)
277#define VSUXSEG_CASES(EEW) VSEG_CASES(VSUX, I##EEW)
278#define VSOXSEG_CASES(EEW) VSEG_CASES(VSOX, I##EEW)
279
280static std::optional<unsigned> getOperandLog2EEW(const MachineInstr &MI,
281 unsigned OpIdx) {
282 const MCInstrDesc &Desc = MI.getDesc();
283 const RISCVVPseudosTable::PseudoInfo *RVV =
284 RISCVVPseudosTable::getPseudoInfo(Pseudo: MI.getOpcode());
285 assert(RVV && "Could not find MI in PseudoTable");
286
287 // MI has a SEW associated with it. The RVV specification defines
288 // the EEW of each operand and definition in relation to MI.SEW.
289 unsigned MILog2SEW = MI.getOperand(i: RISCVII::getSEWOpNum(Desc)).getImm();
290
291 const bool HasPassthru = RISCVII::isFirstDefTiedToFirstUse(Desc);
292 const bool IsTied = RISCVII::isTiedPseudo(TSFlags: Desc.TSFlags);
293
294 bool IsMODef =
295 OpIdx == 0 || (HasPassthru && OpIdx == MI.getNumExplicitDefs());
296
297 // All mask operands have EEW=1
298 const MCOperandInfo &Info = Desc.operands()[OpIdx];
299 if (Info.OperandType == MCOI::OPERAND_REGISTER &&
300 Info.RegClass == RISCV::VMV0RegClassID)
301 return 0;
302
303 // switch against BaseInstr to reduce number of cases that need to be
304 // considered.
305 switch (RVV->BaseInstr) {
306
307 // 6. Configuration-Setting Instructions
308 // Configuration setting instructions do not read or write vector registers
309 case RISCV::VSETIVLI:
310 case RISCV::VSETVL:
311 case RISCV::VSETVLI:
312 llvm_unreachable("Configuration setting instructions do not read or write "
313 "vector registers");
314
315 // Vector Loads and Stores
316 // Vector Unit-Stride Instructions
317 // Vector Strided Instructions
318 /// Dest EEW encoded in the instruction
319 case RISCV::VLM_V:
320 case RISCV::VSM_V:
321 return 0;
322 case RISCV::VLE8_V:
323 case RISCV::VSE8_V:
324 case RISCV::VLSE8_V:
325 case RISCV::VSSE8_V:
326 case VSSEG_CASES(8):
327 case VSSSEG_CASES(8):
328 return 3;
329 case RISCV::VLE16_V:
330 case RISCV::VSE16_V:
331 case RISCV::VLSE16_V:
332 case RISCV::VSSE16_V:
333 case VSSEG_CASES(16):
334 case VSSSEG_CASES(16):
335 return 4;
336 case RISCV::VLE32_V:
337 case RISCV::VSE32_V:
338 case RISCV::VLSE32_V:
339 case RISCV::VSSE32_V:
340 case VSSEG_CASES(32):
341 case VSSSEG_CASES(32):
342 return 5;
343 case RISCV::VLE64_V:
344 case RISCV::VSE64_V:
345 case RISCV::VLSE64_V:
346 case RISCV::VSSE64_V:
347 case VSSEG_CASES(64):
348 case VSSSEG_CASES(64):
349 return 6;
350
351 // Vector Indexed Instructions
352 // vs(o|u)xei<eew>.v
353 // Dest/Data (operand 0) EEW=SEW. Source EEW=<eew>.
354 case RISCV::VLUXEI8_V:
355 case RISCV::VLOXEI8_V:
356 case RISCV::VSUXEI8_V:
357 case RISCV::VSOXEI8_V:
358 case VSUXSEG_CASES(8):
359 case VSOXSEG_CASES(8): {
360 if (OpIdx == 0)
361 return MILog2SEW;
362 return 3;
363 }
364 case RISCV::VLUXEI16_V:
365 case RISCV::VLOXEI16_V:
366 case RISCV::VSUXEI16_V:
367 case RISCV::VSOXEI16_V:
368 case VSUXSEG_CASES(16):
369 case VSOXSEG_CASES(16): {
370 if (OpIdx == 0)
371 return MILog2SEW;
372 return 4;
373 }
374 case RISCV::VLUXEI32_V:
375 case RISCV::VLOXEI32_V:
376 case RISCV::VSUXEI32_V:
377 case RISCV::VSOXEI32_V:
378 case VSUXSEG_CASES(32):
379 case VSOXSEG_CASES(32): {
380 if (OpIdx == 0)
381 return MILog2SEW;
382 return 5;
383 }
384 case RISCV::VLUXEI64_V:
385 case RISCV::VLOXEI64_V:
386 case RISCV::VSUXEI64_V:
387 case RISCV::VSOXEI64_V:
388 case VSUXSEG_CASES(64):
389 case VSOXSEG_CASES(64): {
390 if (OpIdx == 0)
391 return MILog2SEW;
392 return 6;
393 }
394
395 // Vector Integer Arithmetic Instructions
396 // Vector Single-Width Integer Add and Subtract
397 case RISCV::VADD_VI:
398 case RISCV::VADD_VV:
399 case RISCV::VADD_VX:
400 case RISCV::VSUB_VV:
401 case RISCV::VSUB_VX:
402 case RISCV::VRSUB_VI:
403 case RISCV::VRSUB_VX:
404 // Vector Bitwise Logical Instructions
405 // Vector Single-Width Shift Instructions
406 // EEW=SEW.
407 case RISCV::VAND_VI:
408 case RISCV::VAND_VV:
409 case RISCV::VAND_VX:
410 case RISCV::VOR_VI:
411 case RISCV::VOR_VV:
412 case RISCV::VOR_VX:
413 case RISCV::VXOR_VI:
414 case RISCV::VXOR_VV:
415 case RISCV::VXOR_VX:
416 case RISCV::VSLL_VI:
417 case RISCV::VSLL_VV:
418 case RISCV::VSLL_VX:
419 case RISCV::VSRL_VI:
420 case RISCV::VSRL_VV:
421 case RISCV::VSRL_VX:
422 case RISCV::VSRA_VI:
423 case RISCV::VSRA_VV:
424 case RISCV::VSRA_VX:
425 // Vector Integer Min/Max Instructions
426 // EEW=SEW.
427 case RISCV::VMINU_VV:
428 case RISCV::VMINU_VX:
429 case RISCV::VMIN_VV:
430 case RISCV::VMIN_VX:
431 case RISCV::VMAXU_VV:
432 case RISCV::VMAXU_VX:
433 case RISCV::VMAX_VV:
434 case RISCV::VMAX_VX:
435 // Vector Single-Width Integer Multiply Instructions
436 // Source and Dest EEW=SEW.
437 case RISCV::VMUL_VV:
438 case RISCV::VMUL_VX:
439 case RISCV::VMULH_VV:
440 case RISCV::VMULH_VX:
441 case RISCV::VMULHU_VV:
442 case RISCV::VMULHU_VX:
443 case RISCV::VMULHSU_VV:
444 case RISCV::VMULHSU_VX:
445 // Vector Integer Divide Instructions
446 // EEW=SEW.
447 case RISCV::VDIVU_VV:
448 case RISCV::VDIVU_VX:
449 case RISCV::VDIV_VV:
450 case RISCV::VDIV_VX:
451 case RISCV::VREMU_VV:
452 case RISCV::VREMU_VX:
453 case RISCV::VREM_VV:
454 case RISCV::VREM_VX:
455 // Vector Single-Width Integer Multiply-Add Instructions
456 // EEW=SEW.
457 case RISCV::VMACC_VV:
458 case RISCV::VMACC_VX:
459 case RISCV::VNMSAC_VV:
460 case RISCV::VNMSAC_VX:
461 case RISCV::VMADD_VV:
462 case RISCV::VMADD_VX:
463 case RISCV::VNMSUB_VV:
464 case RISCV::VNMSUB_VX:
465 // Vector Integer Merge Instructions
466 // Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
467 // EEW=SEW, except the mask operand has EEW=1. Mask operand is handled
468 // before this switch.
469 case RISCV::VMERGE_VIM:
470 case RISCV::VMERGE_VVM:
471 case RISCV::VMERGE_VXM:
472 case RISCV::VADC_VIM:
473 case RISCV::VADC_VVM:
474 case RISCV::VADC_VXM:
475 case RISCV::VSBC_VVM:
476 case RISCV::VSBC_VXM:
477 // Vector Integer Move Instructions
478 // Vector Fixed-Point Arithmetic Instructions
479 // Vector Single-Width Saturating Add and Subtract
480 // Vector Single-Width Averaging Add and Subtract
481 // EEW=SEW.
482 case RISCV::VMV_V_I:
483 case RISCV::VMV_V_V:
484 case RISCV::VMV_V_X:
485 case RISCV::VSADDU_VI:
486 case RISCV::VSADDU_VV:
487 case RISCV::VSADDU_VX:
488 case RISCV::VSADD_VI:
489 case RISCV::VSADD_VV:
490 case RISCV::VSADD_VX:
491 case RISCV::VSSUBU_VV:
492 case RISCV::VSSUBU_VX:
493 case RISCV::VSSUB_VV:
494 case RISCV::VSSUB_VX:
495 case RISCV::VAADDU_VV:
496 case RISCV::VAADDU_VX:
497 case RISCV::VAADD_VV:
498 case RISCV::VAADD_VX:
499 case RISCV::VASUBU_VV:
500 case RISCV::VASUBU_VX:
501 case RISCV::VASUB_VV:
502 case RISCV::VASUB_VX:
503 // Vector Single-Width Fractional Multiply with Rounding and Saturation
504 // EEW=SEW. The instruction produces 2*SEW product internally but
505 // saturates to fit into SEW bits.
506 case RISCV::VSMUL_VV:
507 case RISCV::VSMUL_VX:
508 // Vector Single-Width Scaling Shift Instructions
509 // EEW=SEW.
510 case RISCV::VSSRL_VI:
511 case RISCV::VSSRL_VV:
512 case RISCV::VSSRL_VX:
513 case RISCV::VSSRA_VI:
514 case RISCV::VSSRA_VV:
515 case RISCV::VSSRA_VX:
516 // Vector Permutation Instructions
517 // Integer Scalar Move Instructions
518 // Floating-Point Scalar Move Instructions
519 // EEW=SEW.
520 case RISCV::VMV_X_S:
521 case RISCV::VMV_S_X:
522 case RISCV::VFMV_F_S:
523 case RISCV::VFMV_S_F:
524 // Vector Slide Instructions
525 // EEW=SEW.
526 case RISCV::VSLIDEUP_VI:
527 case RISCV::VSLIDEUP_VX:
528 case RISCV::VSLIDEDOWN_VI:
529 case RISCV::VSLIDEDOWN_VX:
530 case RISCV::VSLIDE1UP_VX:
531 case RISCV::VFSLIDE1UP_VF:
532 case RISCV::VSLIDE1DOWN_VX:
533 case RISCV::VFSLIDE1DOWN_VF:
534 // Vector Register Gather Instructions
535 // EEW=SEW. For mask operand, EEW=1.
536 case RISCV::VRGATHER_VI:
537 case RISCV::VRGATHER_VV:
538 case RISCV::VRGATHER_VX:
539 // Vector Element Index Instruction
540 case RISCV::VID_V:
541 // Vector Single-Width Floating-Point Add/Subtract Instructions
542 case RISCV::VFADD_VF:
543 case RISCV::VFADD_VV:
544 case RISCV::VFSUB_VF:
545 case RISCV::VFSUB_VV:
546 case RISCV::VFRSUB_VF:
547 // Vector Single-Width Floating-Point Multiply/Divide Instructions
548 case RISCV::VFMUL_VF:
549 case RISCV::VFMUL_VV:
550 case RISCV::VFDIV_VF:
551 case RISCV::VFDIV_VV:
552 case RISCV::VFRDIV_VF:
553 // Vector Single-Width Floating-Point Fused Multiply-Add Instructions
554 case RISCV::VFMACC_VV:
555 case RISCV::VFMACC_VF:
556 case RISCV::VFNMACC_VV:
557 case RISCV::VFNMACC_VF:
558 case RISCV::VFMSAC_VV:
559 case RISCV::VFMSAC_VF:
560 case RISCV::VFNMSAC_VV:
561 case RISCV::VFNMSAC_VF:
562 case RISCV::VFMADD_VV:
563 case RISCV::VFMADD_VF:
564 case RISCV::VFNMADD_VV:
565 case RISCV::VFNMADD_VF:
566 case RISCV::VFMSUB_VV:
567 case RISCV::VFMSUB_VF:
568 case RISCV::VFNMSUB_VV:
569 case RISCV::VFNMSUB_VF:
570 // Vector Floating-Point Square-Root Instruction
571 case RISCV::VFSQRT_V:
572 // Vector Floating-Point Reciprocal Square-Root Estimate Instruction
573 case RISCV::VFRSQRT7_V:
574 // Vector Floating-Point Reciprocal Estimate Instruction
575 case RISCV::VFREC7_V:
576 // Vector Floating-Point MIN/MAX Instructions
577 case RISCV::VFMIN_VF:
578 case RISCV::VFMIN_VV:
579 case RISCV::VFMAX_VF:
580 case RISCV::VFMAX_VV:
581 // Vector Floating-Point Sign-Injection Instructions
582 case RISCV::VFSGNJ_VF:
583 case RISCV::VFSGNJ_VV:
584 case RISCV::VFSGNJN_VV:
585 case RISCV::VFSGNJN_VF:
586 case RISCV::VFSGNJX_VF:
587 case RISCV::VFSGNJX_VV:
588 // Vector Floating-Point Classify Instruction
589 case RISCV::VFCLASS_V:
590 // Vector Floating-Point Move Instruction
591 case RISCV::VFMV_V_F:
592 // Single-Width Floating-Point/Integer Type-Convert Instructions
593 case RISCV::VFCVT_XU_F_V:
594 case RISCV::VFCVT_X_F_V:
595 case RISCV::VFCVT_RTZ_XU_F_V:
596 case RISCV::VFCVT_RTZ_X_F_V:
597 case RISCV::VFCVT_F_XU_V:
598 case RISCV::VFCVT_F_X_V:
599 // Vector Floating-Point Merge Instruction
600 case RISCV::VFMERGE_VFM:
601 // Vector count population in mask vcpop.m
602 // vfirst find-first-set mask bit
603 case RISCV::VCPOP_M:
604 case RISCV::VFIRST_M:
605 // Vector Bit-manipulation Instructions (Zvbb)
606 // Vector And-Not
607 case RISCV::VANDN_VV:
608 case RISCV::VANDN_VX:
609 // Vector Reverse Bits in Elements
610 case RISCV::VBREV_V:
611 // Vector Reverse Bits in Bytes
612 case RISCV::VBREV8_V:
613 // Vector Reverse Bytes
614 case RISCV::VREV8_V:
615 // Vector Count Leading Zeros
616 case RISCV::VCLZ_V:
617 // Vector Count Trailing Zeros
618 case RISCV::VCTZ_V:
619 // Vector Population Count
620 case RISCV::VCPOP_V:
621 // Vector Rotate Left
622 case RISCV::VROL_VV:
623 case RISCV::VROL_VX:
624 // Vector Rotate Right
625 case RISCV::VROR_VI:
626 case RISCV::VROR_VV:
627 case RISCV::VROR_VX:
628 // Vector Carry-less Multiplication Instructions (Zvbc)
629 // Vector Carry-less Multiply
630 case RISCV::VCLMUL_VV:
631 case RISCV::VCLMUL_VX:
632 // Vector Carry-less Multiply Return High Half
633 case RISCV::VCLMULH_VV:
634 case RISCV::VCLMULH_VX:
635
636 // Zvabd
637 case RISCV::VABD_VV:
638 case RISCV::VABD_VX:
639 case RISCV::VABDU_VV:
640 case RISCV::VABDU_VX:
641
642 // Zvzip
643 case RISCV::VZIP_VV:
644 case RISCV::VUNZIPE_V:
645 case RISCV::VUNZIPO_V:
646 case RISCV::VPAIRE_VV:
647 case RISCV::VPAIRO_VV:
648 return MILog2SEW;
649
650 // Vector Widening Shift Left Logical (Zvbb)
651 case RISCV::VWSLL_VI:
652 case RISCV::VWSLL_VX:
653 case RISCV::VWSLL_VV:
654 // Vector Widening Integer Add/Subtract
655 // Def uses EEW=2*SEW . Operands use EEW=SEW.
656 case RISCV::VWADDU_VV:
657 case RISCV::VWADDU_VX:
658 case RISCV::VWSUBU_VV:
659 case RISCV::VWSUBU_VX:
660 case RISCV::VWADD_VV:
661 case RISCV::VWADD_VX:
662 case RISCV::VWSUB_VV:
663 case RISCV::VWSUB_VX:
664 // Vector Widening Integer Multiply Instructions
665 // Destination EEW=2*SEW. Source EEW=SEW.
666 case RISCV::VWMUL_VV:
667 case RISCV::VWMUL_VX:
668 case RISCV::VWMULSU_VV:
669 case RISCV::VWMULSU_VX:
670 case RISCV::VWMULU_VV:
671 case RISCV::VWMULU_VX:
672 // Vector Widening Integer Multiply-Add Instructions
673 // Destination EEW=2*SEW. Source EEW=SEW.
674 // A SEW-bit*SEW-bit multiply of the sources forms a 2*SEW-bit value, which
675 // is then added to the 2*SEW-bit Dest. These instructions never have a
676 // passthru operand.
677 case RISCV::VWMACCU_VV:
678 case RISCV::VWMACCU_VX:
679 case RISCV::VWMACC_VV:
680 case RISCV::VWMACC_VX:
681 case RISCV::VWMACCSU_VV:
682 case RISCV::VWMACCSU_VX:
683 case RISCV::VWMACCUS_VX:
684 // Vector Widening Floating-Point Fused Multiply-Add Instructions
685 case RISCV::VFWMACC_VF:
686 case RISCV::VFWMACC_VV:
687 case RISCV::VFWNMACC_VF:
688 case RISCV::VFWNMACC_VV:
689 case RISCV::VFWMSAC_VF:
690 case RISCV::VFWMSAC_VV:
691 case RISCV::VFWNMSAC_VF:
692 case RISCV::VFWNMSAC_VV:
693 case RISCV::VFWMACCBF16_VV:
694 case RISCV::VFWMACCBF16_VF:
695 // Vector Widening Floating-Point Add/Subtract Instructions
696 // Dest EEW=2*SEW. Source EEW=SEW.
697 case RISCV::VFWADD_VV:
698 case RISCV::VFWADD_VF:
699 case RISCV::VFWSUB_VV:
700 case RISCV::VFWSUB_VF:
701 // Vector Widening Floating-Point Multiply
702 case RISCV::VFWMUL_VF:
703 case RISCV::VFWMUL_VV:
704 // Widening Floating-Point/Integer Type-Convert Instructions
705 case RISCV::VFWCVT_XU_F_V:
706 case RISCV::VFWCVT_X_F_V:
707 case RISCV::VFWCVT_RTZ_XU_F_V:
708 case RISCV::VFWCVT_RTZ_X_F_V:
709 case RISCV::VFWCVT_F_XU_V:
710 case RISCV::VFWCVT_F_X_V:
711 case RISCV::VFWCVT_F_F_V:
712 case RISCV::VFWCVTBF16_F_F_V:
713 // Zvabd
714 case RISCV::VWABDA_VV:
715 case RISCV::VWABDA_VX:
716 case RISCV::VWABDAU_VV:
717 case RISCV::VWABDAU_VX:
718 return IsMODef ? MILog2SEW + 1 : MILog2SEW;
719
720 // Def and Op1 uses EEW=2*SEW. Op2 uses EEW=SEW.
721 case RISCV::VWADDU_WV:
722 case RISCV::VWADDU_WX:
723 case RISCV::VWSUBU_WV:
724 case RISCV::VWSUBU_WX:
725 case RISCV::VWADD_WV:
726 case RISCV::VWADD_WX:
727 case RISCV::VWSUB_WV:
728 case RISCV::VWSUB_WX:
729 // Vector Widening Floating-Point Add/Subtract Instructions
730 case RISCV::VFWADD_WF:
731 case RISCV::VFWADD_WV:
732 case RISCV::VFWSUB_WF:
733 case RISCV::VFWSUB_WV: {
734 bool IsOp1 = (HasPassthru && !IsTied) ? OpIdx == 2 : OpIdx == 1;
735 bool TwoTimes = IsMODef || IsOp1;
736 return TwoTimes ? MILog2SEW + 1 : MILog2SEW;
737 }
738
739 // Vector Integer Extension
740 case RISCV::VZEXT_VF2:
741 case RISCV::VSEXT_VF2:
742 return getIntegerExtensionOperandEEW(Factor: 2, MI, OpIdx);
743 case RISCV::VZEXT_VF4:
744 case RISCV::VSEXT_VF4:
745 return getIntegerExtensionOperandEEW(Factor: 4, MI, OpIdx);
746 case RISCV::VZEXT_VF8:
747 case RISCV::VSEXT_VF8:
748 return getIntegerExtensionOperandEEW(Factor: 8, MI, OpIdx);
749
750 // Vector Narrowing Integer Right Shift Instructions
751 // Destination EEW=SEW, Op 1 has EEW=2*SEW. Op2 has EEW=SEW
752 case RISCV::VNSRL_WX:
753 case RISCV::VNSRL_WI:
754 case RISCV::VNSRL_WV:
755 case RISCV::VNSRA_WI:
756 case RISCV::VNSRA_WV:
757 case RISCV::VNSRA_WX:
758 // Vector Narrowing Fixed-Point Clip Instructions
759 // Destination and Op1 EEW=SEW. Op2 EEW=2*SEW.
760 case RISCV::VNCLIPU_WI:
761 case RISCV::VNCLIPU_WV:
762 case RISCV::VNCLIPU_WX:
763 case RISCV::VNCLIP_WI:
764 case RISCV::VNCLIP_WV:
765 case RISCV::VNCLIP_WX:
766 // Narrowing Floating-Point/Integer Type-Convert Instructions
767 case RISCV::VFNCVT_XU_F_W:
768 case RISCV::VFNCVT_X_F_W:
769 case RISCV::VFNCVT_RTZ_XU_F_W:
770 case RISCV::VFNCVT_RTZ_X_F_W:
771 case RISCV::VFNCVT_F_XU_W:
772 case RISCV::VFNCVT_F_X_W:
773 case RISCV::VFNCVT_F_F_W:
774 case RISCV::VFNCVT_ROD_F_F_W:
775 case RISCV::VFNCVTBF16_F_F_W: {
776 assert(!IsTied);
777 bool IsOp1 = HasPassthru ? OpIdx == 2 : OpIdx == 1;
778 bool TwoTimes = IsOp1;
779 return TwoTimes ? MILog2SEW + 1 : MILog2SEW;
780 }
781
782 // Vector Mask Instructions
783 // Vector Mask-Register Logical Instructions
784 // vmsbf.m set-before-first mask bit
785 // vmsif.m set-including-first mask bit
786 // vmsof.m set-only-first mask bit
787 // EEW=1
788 // We handle the cases when operand is a v0 mask operand above the switch,
789 // but these instructions may use non-v0 mask operands and need to be handled
790 // specifically.
791 case RISCV::VMAND_MM:
792 case RISCV::VMNAND_MM:
793 case RISCV::VMANDN_MM:
794 case RISCV::VMXOR_MM:
795 case RISCV::VMOR_MM:
796 case RISCV::VMNOR_MM:
797 case RISCV::VMORN_MM:
798 case RISCV::VMXNOR_MM:
799 case RISCV::VMSBF_M:
800 case RISCV::VMSIF_M:
801 case RISCV::VMSOF_M: {
802 return MILog2SEW;
803 }
804
805 // Vector Compress Instruction
806 // EEW=SEW, except the mask operand has EEW=1. Mask operand is not handled
807 // before this switch.
808 case RISCV::VCOMPRESS_VM:
809 return OpIdx == 3 ? 0 : MILog2SEW;
810
811 // Vector Iota Instruction
812 // EEW=SEW, except the mask operand has EEW=1. Mask operand is not handled
813 // before this switch.
814 case RISCV::VIOTA_M: {
815 if (IsMODef || OpIdx == 1)
816 return MILog2SEW;
817 return 0;
818 }
819
820 // Vector Integer Compare Instructions
821 // Dest EEW=1. Source EEW=SEW.
822 case RISCV::VMSEQ_VI:
823 case RISCV::VMSEQ_VV:
824 case RISCV::VMSEQ_VX:
825 case RISCV::VMSNE_VI:
826 case RISCV::VMSNE_VV:
827 case RISCV::VMSNE_VX:
828 case RISCV::VMSLTU_VV:
829 case RISCV::VMSLTU_VX:
830 case RISCV::VMSLT_VV:
831 case RISCV::VMSLT_VX:
832 case RISCV::VMSLEU_VV:
833 case RISCV::VMSLEU_VI:
834 case RISCV::VMSLEU_VX:
835 case RISCV::VMSLE_VV:
836 case RISCV::VMSLE_VI:
837 case RISCV::VMSLE_VX:
838 case RISCV::VMSGTU_VI:
839 case RISCV::VMSGTU_VX:
840 case RISCV::VMSGT_VI:
841 case RISCV::VMSGT_VX:
842 // Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
843 // Dest EEW=1. Source EEW=SEW. Mask source operand handled above this switch.
844 case RISCV::VMADC_VIM:
845 case RISCV::VMADC_VVM:
846 case RISCV::VMADC_VXM:
847 case RISCV::VMSBC_VVM:
848 case RISCV::VMSBC_VXM:
849 // Dest EEW=1. Source EEW=SEW.
850 case RISCV::VMADC_VV:
851 case RISCV::VMADC_VI:
852 case RISCV::VMADC_VX:
853 case RISCV::VMSBC_VV:
854 case RISCV::VMSBC_VX:
855 // 13.13. Vector Floating-Point Compare Instructions
856 // Dest EEW=1. Source EEW=SEW
857 case RISCV::VMFEQ_VF:
858 case RISCV::VMFEQ_VV:
859 case RISCV::VMFNE_VF:
860 case RISCV::VMFNE_VV:
861 case RISCV::VMFLT_VF:
862 case RISCV::VMFLT_VV:
863 case RISCV::VMFLE_VF:
864 case RISCV::VMFLE_VV:
865 case RISCV::VMFGT_VF:
866 case RISCV::VMFGE_VF: {
867 if (IsMODef)
868 return 0;
869 return MILog2SEW;
870 }
871
872 // Vector Reduction Operations
873 // Vector Single-Width Integer Reduction Instructions
874 case RISCV::VREDAND_VS:
875 case RISCV::VREDMAX_VS:
876 case RISCV::VREDMAXU_VS:
877 case RISCV::VREDMIN_VS:
878 case RISCV::VREDMINU_VS:
879 case RISCV::VREDOR_VS:
880 case RISCV::VREDSUM_VS:
881 case RISCV::VREDXOR_VS:
882 // Vector Single-Width Floating-Point Reduction Instructions
883 case RISCV::VFREDMAX_VS:
884 case RISCV::VFREDMIN_VS:
885 case RISCV::VFREDOSUM_VS:
886 case RISCV::VFREDUSUM_VS: {
887 return MILog2SEW;
888 }
889
890 // Vector Widening Integer Reduction Instructions
891 // The Dest and VS1 read only element 0 for the vector register. Return
892 // 2*EEW for these. VS2 has EEW=SEW and EMUL=LMUL.
893 case RISCV::VWREDSUM_VS:
894 case RISCV::VWREDSUMU_VS:
895 // Vector Widening Floating-Point Reduction Instructions
896 case RISCV::VFWREDOSUM_VS:
897 case RISCV::VFWREDUSUM_VS: {
898 bool TwoTimes = IsMODef || OpIdx == 3;
899 return TwoTimes ? MILog2SEW + 1 : MILog2SEW;
900 }
901
902 // Vector Register Gather with 16-bit Index Elements Instruction
903 // Dest and source data EEW=SEW. Index vector EEW=16.
904 case RISCV::VRGATHEREI16_VV: {
905 if (OpIdx == 2)
906 return 4;
907 return MILog2SEW;
908 }
909
910 default:
911 return std::nullopt;
912 }
913}
914
915static std::optional<OperandInfo> getOperandInfo(const MachineInstr &MI,
916 unsigned OpIdx) {
917 const RISCVVPseudosTable::PseudoInfo *RVV =
918 RISCVVPseudosTable::getPseudoInfo(Pseudo: MI.getOpcode());
919 assert(RVV && "Could not find MI in PseudoTable");
920
921 std::optional<unsigned> Log2EEW = getOperandLog2EEW(MI, OpIdx);
922 if (!Log2EEW)
923 return std::nullopt;
924
925 switch (RVV->BaseInstr) {
926 // Vector Reduction Operations
927 // Vector Single-Width Integer Reduction Instructions
928 // Vector Widening Integer Reduction Instructions
929 // Vector Widening Floating-Point Reduction Instructions
930 // The Dest and VS1 only read element 0 of the vector register. Return just
931 // the EEW for these.
932 case RISCV::VREDAND_VS:
933 case RISCV::VREDMAX_VS:
934 case RISCV::VREDMAXU_VS:
935 case RISCV::VREDMIN_VS:
936 case RISCV::VREDMINU_VS:
937 case RISCV::VREDOR_VS:
938 case RISCV::VREDSUM_VS:
939 case RISCV::VREDXOR_VS:
940 case RISCV::VWREDSUM_VS:
941 case RISCV::VWREDSUMU_VS:
942 case RISCV::VFWREDOSUM_VS:
943 case RISCV::VFWREDUSUM_VS:
944 if (OpIdx != 2)
945 return OperandInfo(*Log2EEW);
946 break;
947
948 // Zvzip - vzip.vv interleaves two half-LMUL vectors into an LMUL result with
949 // the same SEW. The vtype LMUL describes the result, so only the two source
950 // operands have half the instruction's EMUL.
951 case RISCV::VZIP_VV: {
952 auto EMUL = getEMULEqualsEEWDivSEWTimesLMUL(Log2EEW: *Log2EEW, MI);
953 if (OpIdx == 2 || OpIdx == 3)
954 EMUL = halfEMUL(EMUL);
955 return OperandInfo(EMUL, *Log2EEW);
956 }
957 // Zvzip - vunzipe.v / vunzipo.v split a 2*LMUL vector into LMUL even/odd
958 // elements with the same SEW. The source (and passthru tied to dest which is
959 // also LMUL sized - so only the vs2 source) has 2 * EMUL.
960 case RISCV::VUNZIPE_V:
961 case RISCV::VUNZIPO_V: {
962 auto EMUL = getEMULEqualsEEWDivSEWTimesLMUL(Log2EEW: *Log2EEW, MI);
963 if (OpIdx == 2)
964 EMUL = doubleEMUL(EMUL);
965 return OperandInfo(EMUL, *Log2EEW);
966 }
967 };
968
969 // All others have EMUL=EEW/SEW*LMUL
970 return OperandInfo(getEMULEqualsEEWDivSEWTimesLMUL(Log2EEW: *Log2EEW, MI), *Log2EEW);
971}
972
973static bool isTupleInsertInstr(const MachineInstr &MI);
974
975/// Return true if we can reason about demanded VLs elementwise for \p MI.
976bool RISCVVLOptimizerImpl::isSupportedInstr(const MachineInstr &MI) const {
977 if (MI.isPHI() || MI.isFullCopy() || isTupleInsertInstr(MI))
978 return true;
979
980 unsigned RVVOpc = RISCV::getRVVMCOpcode(RVVPseudoOpcode: MI.getOpcode());
981 if (!RVVOpc)
982 return false;
983
984 assert(!(MI.getNumExplicitDefs() == 0 && !MI.mayStore() &&
985 !RISCVII::elementsDependOnVL(TII->get(RVVOpc).TSFlags)) &&
986 "No defs but elements don't depend on VL?");
987
988 // TODO: Reduce vl for vmv.s.x and vfmv.s.f. Currently this introduces more vl
989 // toggles, we need to extend PRE in RISCVInsertVSETVLI first.
990 if (RVVOpc == RISCV::VMV_S_X || RVVOpc == RISCV::VFMV_S_F)
991 return false;
992
993 if (RISCVII::elementsDependOnVL(TSFlags: TII->get(Opcode: RVVOpc).TSFlags))
994 return false;
995
996 if (MI.mayStore())
997 return false;
998
999 return true;
1000}
1001
1002/// Return true if operand \p OpIdx of \p MI is a vector operand but is used as
1003/// a scalar operand.
1004static bool isVectorOpUsedAsScalarOp(const MachineInstr &MI, unsigned OpIdx) {
1005 const RISCVVPseudosTable::PseudoInfo *RVV =
1006 RISCVVPseudosTable::getPseudoInfo(Pseudo: MI.getOpcode());
1007
1008 if (!RVV)
1009 return false;
1010
1011 switch (RVV->BaseInstr) {
1012 // Reductions only use vs1[0] of vs1
1013 case RISCV::VREDAND_VS:
1014 case RISCV::VREDMAX_VS:
1015 case RISCV::VREDMAXU_VS:
1016 case RISCV::VREDMIN_VS:
1017 case RISCV::VREDMINU_VS:
1018 case RISCV::VREDOR_VS:
1019 case RISCV::VREDSUM_VS:
1020 case RISCV::VREDXOR_VS:
1021 case RISCV::VWREDSUM_VS:
1022 case RISCV::VWREDSUMU_VS:
1023 case RISCV::VFREDMAX_VS:
1024 case RISCV::VFREDMIN_VS:
1025 case RISCV::VFREDOSUM_VS:
1026 case RISCV::VFREDUSUM_VS:
1027 case RISCV::VFWREDOSUM_VS:
1028 case RISCV::VFWREDUSUM_VS:
1029 return OpIdx == 3;
1030 case RISCV::VMV_X_S:
1031 case RISCV::VFMV_F_S:
1032 return OpIdx == 1;
1033 default:
1034 return false;
1035 }
1036}
1037
1038bool RISCVVLOptimizerImpl::isCandidate(const MachineInstr &MI) const {
1039 const MCInstrDesc &Desc = MI.getDesc();
1040 if (!RISCVII::hasVLOp(TSFlags: Desc.TSFlags) || !RISCVII::hasSEWOp(TSFlags: Desc.TSFlags))
1041 return false;
1042
1043 if (MI.getNumExplicitDefs() != 1)
1044 return false;
1045
1046 // Some instructions have implicit defs e.g. $vxsat. If they might be read
1047 // later then we can't reduce VL.
1048 if (!MI.allImplicitDefsAreDead()) {
1049 LLVM_DEBUG(dbgs() << "Not a candidate because has non-dead implicit def\n");
1050 return false;
1051 }
1052
1053 if (MI.mayRaiseFPException()) {
1054 LLVM_DEBUG(dbgs() << "Not a candidate because may raise FP exception\n");
1055 return false;
1056 }
1057
1058 for (const MachineMemOperand *MMO : MI.memoperands()) {
1059 if (MMO->isVolatile()) {
1060 LLVM_DEBUG(dbgs() << "Not a candidate because contains volatile MMO\n");
1061 return false;
1062 }
1063 }
1064
1065 if (!isSupportedInstr(MI)) {
1066 LLVM_DEBUG(dbgs() << "Not a candidate due to unsupported instruction: "
1067 << MI);
1068 return false;
1069 }
1070
1071 assert(!RISCVII::elementsDependOnVL(
1072 TII->get(RISCV::getRVVMCOpcode(MI.getOpcode())).TSFlags) &&
1073 "Instruction shouldn't be supported if elements depend on VL");
1074
1075 assert(RISCVRI::isVRegClass(
1076 MRI->getRegClass(MI.getOperand(0).getReg())->TSFlags) &&
1077 "All supported instructions produce a vector register result");
1078
1079 LLVM_DEBUG(dbgs() << "Found a candidate for VL reduction: " << MI << "\n");
1080 return true;
1081}
1082
1083/// Given a vslidedown.vx like:
1084///
1085/// %slideamt = ADDI %x, -1
1086/// %v = PseudoVSLIDEDOWN_VX %passthru, %src, %slideamt, avl=1
1087///
1088/// %v will only read the first %slideamt + 1 lanes of %src, which = %x.
1089/// This is a common case when lowering extractelement.
1090///
1091/// Note that if %x is 0, %slideamt will be all ones. In this case %src will be
1092/// completely slid down and none of its lanes will be read (since %slideamt is
1093/// greater than the largest VLMAX of 65536) so we can demand any minimum VL.
1094static std::optional<DemandedVL>
1095getMinimumVLForVSLIDEDOWN_VX(const MachineInstr &MI, unsigned OpIdx,
1096 const MachineRegisterInfo *MRI) {
1097 if (RISCV::getRVVMCOpcode(RVVPseudoOpcode: MI.getOpcode()) != RISCV::VSLIDEDOWN_VX)
1098 return std::nullopt;
1099 // We're looking at what lanes are used from the src operand.
1100 if (OpIdx != 2)
1101 return std::nullopt;
1102 // For now, the AVL must be 1.
1103 const MachineOperand &AVL = MI.getOperand(i: 4);
1104 if (!AVL.isImm() || AVL.getImm() != 1)
1105 return std::nullopt;
1106 // The slide amount must be %x - 1.
1107 const MachineOperand &SlideAmt = MI.getOperand(i: 3);
1108 if (!SlideAmt.getReg().isVirtual())
1109 return std::nullopt;
1110 MachineInstr *SlideAmtDef = MRI->getVRegDef(Reg: SlideAmt.getReg());
1111 if (!SlideAmtDef || SlideAmtDef->getOpcode() != RISCV::ADDI ||
1112 SlideAmtDef->getOperand(i: 2).getImm() != -AVL.getImm() ||
1113 !SlideAmtDef->getOperand(i: 1).getReg().isVirtual())
1114 return std::nullopt;
1115 return SlideAmtDef->getOperand(i: 1);
1116}
1117
1118DemandedVL RISCVVLOptimizerImpl::getMinimumVLForUser(const MachineInstr &UserMI,
1119 unsigned OpIdx) const {
1120 const MachineOperand &UserOp = UserMI.getOperand(i: OpIdx);
1121 const MCInstrDesc &Desc = UserMI.getDesc();
1122
1123 if (UserMI.isPHI() || UserMI.isFullCopy() || isTupleInsertInstr(MI: UserMI))
1124 return DemandedVLs.lookup(Key: &UserMI);
1125
1126 if (!RISCVII::hasVLOp(TSFlags: Desc.TSFlags) || !RISCVII::hasSEWOp(TSFlags: Desc.TSFlags)) {
1127 LLVM_DEBUG(dbgs() << " Abort due to lack of VL, assume that"
1128 " use VLMAX\n");
1129 return DemandedVL::vlmax();
1130 }
1131
1132 if (auto VL = getMinimumVLForVSLIDEDOWN_VX(MI: UserMI, OpIdx, MRI))
1133 return *VL;
1134
1135 unsigned RVVOpc = RISCV::getRVVMCOpcode(RVVPseudoOpcode: UserMI.getOpcode());
1136 bool IsVUNZIP = RVVOpc == RISCV::VUNZIPE_V || RVVOpc == RISCV::VUNZIPO_V;
1137 bool IsVZIP = RVVOpc == RISCV::VZIP_VV;
1138 if (!IsVUNZIP && RISCVII::readsPastVL(TSFlags: TII->get(Opcode: RVVOpc).TSFlags)) {
1139 LLVM_DEBUG(dbgs() << " Abort because used by unsafe instruction\n");
1140 return DemandedVL::vlmax();
1141 }
1142
1143 unsigned VLOpNum = RISCVII::getVLOpNum(Desc);
1144 const MachineOperand &VLOp = UserMI.getOperand(i: VLOpNum);
1145 // Looking for an immediate or a register VL that isn't X0.
1146 assert((!VLOp.isReg() || VLOp.getReg() != RISCV::X0) &&
1147 "Did not expect X0 VL");
1148
1149 // If the user is a passthru it will read the elements past VL, so
1150 // abort if any of the elements past VL are demanded.
1151 if (UserOp.isTied()) {
1152 assert(OpIdx == UserMI.getNumExplicitDefs() &&
1153 RISCVII::isFirstDefTiedToFirstUse(UserMI.getDesc()));
1154 if (!RISCV::isVLKnownLE(MRI: *MRI, LHS: DemandedVLs.lookup(Key: &UserMI).VL, RHS: VLOp)) {
1155 LLVM_DEBUG(dbgs() << " Abort because user is passthru in "
1156 "instruction with demanded tail\n");
1157 return DemandedVL::vlmax();
1158 }
1159 }
1160
1161 // Instructions like reductions may use a vector register as a scalar
1162 // register. In this case, we should treat it as only reading the first lane.
1163 if (isVectorOpUsedAsScalarOp(MI: UserMI, OpIdx)) {
1164 LLVM_DEBUG(dbgs() << " Used this operand as a scalar operand\n");
1165 return MachineOperand::CreateImm(Val: 1);
1166 }
1167
1168 // If we know the demanded VL of UserMI, then we can reduce the VL it
1169 // requires.
1170 DemandedVL MinimumVL = VLOp;
1171 if (RISCV::isVLKnownLE(MRI: *MRI, LHS: DemandedVLs.lookup(Key: &UserMI).VL, RHS: VLOp))
1172 MinimumVL = DemandedVLs.lookup(Key: &UserMI);
1173
1174 if (IsVUNZIP && OpIdx == 2)
1175 MinimumVL = doubleVL(MinimumVL);
1176 if (IsVZIP && (OpIdx == 2 || OpIdx == 3))
1177 MinimumVL = halfVL(MinimumVL, Ceil: OpIdx == 2);
1178
1179 return MinimumVL;
1180}
1181
1182/// Return true if MI is an instruction used for assembling registers
1183/// for segmented store instructions, namely, RISCVISD::TUPLE_INSERT.
1184/// Currently it's lowered to INSERT_SUBREG.
1185static bool isTupleInsertInstr(const MachineInstr &MI) {
1186 if (!MI.isInsertSubreg())
1187 return false;
1188
1189 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
1190 const TargetRegisterClass *DstRC = MRI.getRegClass(Reg: MI.getOperand(i: 0).getReg());
1191 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
1192 if (!RISCVRI::isVRegClass(TSFlags: DstRC->TSFlags))
1193 return false;
1194 unsigned NF = RISCVRI::getNF(TSFlags: DstRC->TSFlags);
1195 if (NF < 2)
1196 return false;
1197
1198 // Check whether INSERT_SUBREG has the correct subreg index for tuple inserts.
1199 auto VLMul = RISCVRI::getLMul(TSFlags: DstRC->TSFlags);
1200 unsigned SubRegIdx = MI.getOperand(i: 3).getImm();
1201 [[maybe_unused]] auto [LMul, IsFractional] = RISCVVType::decodeVLMUL(VLMul);
1202 assert(!IsFractional && "unexpected LMUL for tuple register classes");
1203 return TRI->getSubRegIdxSize(Idx: SubRegIdx) == RISCV::RVVBitsPerBlock * LMul;
1204}
1205
1206static bool isSegmentedStoreInstr(const MachineInstr &MI) {
1207 switch (RISCV::getRVVMCOpcode(RVVPseudoOpcode: MI.getOpcode())) {
1208 case VSSEG_CASES(8):
1209 case VSSSEG_CASES(8):
1210 case VSUXSEG_CASES(8):
1211 case VSOXSEG_CASES(8):
1212 case VSSEG_CASES(16):
1213 case VSSSEG_CASES(16):
1214 case VSUXSEG_CASES(16):
1215 case VSOXSEG_CASES(16):
1216 case VSSEG_CASES(32):
1217 case VSSSEG_CASES(32):
1218 case VSUXSEG_CASES(32):
1219 case VSOXSEG_CASES(32):
1220 case VSSEG_CASES(64):
1221 case VSSSEG_CASES(64):
1222 case VSUXSEG_CASES(64):
1223 case VSOXSEG_CASES(64):
1224 return true;
1225 default:
1226 return false;
1227 }
1228}
1229
1230bool RISCVVLOptimizerImpl::checkUsers(const MachineInstr &MI) const {
1231 if (MI.isPHI() || MI.isFullCopy() || isTupleInsertInstr(MI))
1232 return true;
1233
1234 SmallSetVector<MachineOperand *, 8> OpWorklist;
1235 SmallPtrSet<const MachineInstr *, 4> PHISeen;
1236 for (auto &UserOp : MRI->use_operands(Reg: MI.getOperand(i: 0).getReg()))
1237 OpWorklist.insert(X: &UserOp);
1238
1239 while (!OpWorklist.empty()) {
1240 MachineOperand &UserOp = *OpWorklist.pop_back_val();
1241 const MachineInstr &UserMI = *UserOp.getParent();
1242 LLVM_DEBUG(dbgs() << " Checking user: " << UserMI << "\n");
1243
1244 if (UserMI.isFullCopy() && UserMI.getOperand(i: 0).getReg().isVirtual()) {
1245 LLVM_DEBUG(dbgs() << " Peeking through uses of COPY\n");
1246 OpWorklist.insert_range(R: llvm::make_pointer_range(
1247 Range: MRI->use_operands(Reg: UserMI.getOperand(i: 0).getReg())));
1248 continue;
1249 }
1250
1251 if (isTupleInsertInstr(MI: UserMI)) {
1252 LLVM_DEBUG(dbgs().indent(4) << "Peeking through uses of INSERT_SUBREG\n");
1253 for (MachineOperand &UseOp :
1254 MRI->use_operands(Reg: UserMI.getOperand(i: 0).getReg())) {
1255 const MachineInstr &CandidateMI = *UseOp.getParent();
1256 // We should not propagate the VL if the user is not a segmented store
1257 // or another INSERT_SUBREG, since VL just works differently
1258 // between segmented operations (per-field) v.s. other RVV ops (on the
1259 // whole register group).
1260 if (!isTupleInsertInstr(MI: CandidateMI) &&
1261 !isSegmentedStoreInstr(MI: CandidateMI))
1262 return false;
1263 OpWorklist.insert(X: &UseOp);
1264 }
1265 continue;
1266 }
1267
1268 if (UserMI.isPHI()) {
1269 // Don't follow PHI cycles
1270 if (!PHISeen.insert(Ptr: &UserMI).second)
1271 continue;
1272 LLVM_DEBUG(dbgs() << " Peeking through uses of PHI\n");
1273 OpWorklist.insert_range(R: llvm::make_pointer_range(
1274 Range: MRI->use_operands(Reg: UserMI.getOperand(i: 0).getReg())));
1275 continue;
1276 }
1277
1278 if (!RISCVII::hasSEWOp(TSFlags: UserMI.getDesc().TSFlags)) {
1279 LLVM_DEBUG(dbgs() << " Abort due to lack of SEW operand\n");
1280 return false;
1281 }
1282
1283 std::optional<OperandInfo> ConsumerInfo =
1284 getOperandInfo(MI: UserMI, OpIdx: UserMI.getOperandNo(I: &UserOp));
1285 std::optional<OperandInfo> ProducerInfo = getOperandInfo(MI, OpIdx: 0);
1286 if (!ConsumerInfo || !ProducerInfo) {
1287 LLVM_DEBUG(dbgs() << " Abort due to unknown operand information.\n");
1288 LLVM_DEBUG(dbgs() << " ConsumerInfo is: " << ConsumerInfo << "\n");
1289 LLVM_DEBUG(dbgs() << " ProducerInfo is: " << ProducerInfo << "\n");
1290 return false;
1291 }
1292
1293 if (!OperandInfo::areCompatible(Def: *ProducerInfo, User: *ConsumerInfo)) {
1294 LLVM_DEBUG(
1295 dbgs()
1296 << " Abort due to incompatible information for EMUL or EEW.\n");
1297 LLVM_DEBUG(dbgs() << " ConsumerInfo is: " << ConsumerInfo << "\n");
1298 LLVM_DEBUG(dbgs() << " ProducerInfo is: " << ProducerInfo << "\n");
1299 return false;
1300 }
1301 }
1302
1303 return true;
1304}
1305
1306bool RISCVVLOptimizerImpl::tryReduceVL(MachineInstr &MI,
1307 MachineOperand CommonVL) const {
1308 LLVM_DEBUG(dbgs() << "Trying to reduce VL for " << MI);
1309
1310 unsigned VLOpNum = RISCVII::getVLOpNum(Desc: MI.getDesc());
1311 MachineOperand &VLOp = MI.getOperand(i: VLOpNum);
1312
1313 assert((CommonVL.isImm() || CommonVL.getReg().isVirtual()) &&
1314 "Expected VL to be an Imm or virtual Reg");
1315
1316 // If the VL is defined by a vleff that doesn't dominate MI, try using the
1317 // vleff's AVL. It will be greater than or equal to the output VL.
1318 if (CommonVL.isReg()) {
1319 const MachineInstr *VLMI = MRI->getVRegDef(Reg: CommonVL.getReg());
1320 if (VLMI && RISCVInstrInfo::isFaultOnlyFirstLoad(MI: *VLMI) &&
1321 !MDT->dominates(A: VLMI, B: &MI))
1322 CommonVL = VLMI->getOperand(i: RISCVII::getVLOpNum(Desc: VLMI->getDesc()));
1323 }
1324
1325 if (!RISCV::isVLKnownLE(MRI: *MRI, LHS: CommonVL, RHS: VLOp)) {
1326 LLVM_DEBUG(dbgs() << " Abort due to CommonVL not <= VLOp.\n");
1327 return false;
1328 }
1329
1330 if (CommonVL.isIdenticalTo(Other: VLOp)) {
1331 LLVM_DEBUG(
1332 dbgs() << " Abort due to CommonVL == VLOp, no point in reducing.\n");
1333 return false;
1334 }
1335
1336 if (CommonVL.isImm()) {
1337 LLVM_DEBUG(dbgs() << " Reduce VL from " << VLOp << " to "
1338 << CommonVL.getImm() << " for " << MI << "\n");
1339 VLOp.ChangeToImmediate(ImmVal: CommonVL.getImm());
1340 return true;
1341 }
1342 MachineInstr *VLMI = MRI->getVRegDef(Reg: CommonVL.getReg());
1343 if (!VLMI)
1344 return false;
1345
1346 auto VLDominates = [this, &VLMI](const MachineInstr &MI) {
1347 return MDT->dominates(A: VLMI, B: &MI);
1348 };
1349 if (!VLDominates(MI)) {
1350 assert(MI.getNumExplicitDefs() == 1);
1351 auto Uses = MRI->use_instructions(Reg: MI.getOperand(i: 0).getReg());
1352 auto UsesSameBB = make_filter_range(Range&: Uses, Pred: [&MI](const MachineInstr &Use) {
1353 return Use.getParent() == MI.getParent();
1354 });
1355 if (VLMI->getParent() == MI.getParent() &&
1356 all_of(Range&: UsesSameBB, P: VLDominates) &&
1357 RISCVInstrInfo::isSafeToMove(From: MI, To: std::next(x: VLMI->getIterator()))) {
1358 VLMI->getParent()->splice(Where: std::next(x: VLMI->getIterator()), Other: MI.getParent(),
1359 From: MI.getIterator());
1360 } else {
1361 LLVM_DEBUG(dbgs() << " Abort due to VL not dominating.\n");
1362 return false;
1363 }
1364 }
1365 LLVM_DEBUG(dbgs() << " Reduce VL from " << VLOp << " to "
1366 << printReg(CommonVL.getReg(), MRI->getTargetRegisterInfo())
1367 << " for " << MI << "\n");
1368
1369 // All our checks passed. We can reduce VL.
1370 VLOp.ChangeToRegister(Reg: CommonVL.getReg(), isDef: false);
1371 MRI->constrainRegClass(Reg: CommonVL.getReg(), RC: &RISCV::GPRNoX0RegClass);
1372 return true;
1373}
1374
1375static bool isPhysical(const MachineOperand &MO) {
1376 return MO.isReg() && MO.getReg().isPhysical();
1377}
1378
1379/// Look through \p MI's operands and propagate what it demands to its uses.
1380void RISCVVLOptimizerImpl::transfer(const MachineInstr &MI) {
1381 if (!isSupportedInstr(MI) || !checkUsers(MI) || any_of(Range: MI.defs(), P: isPhysical))
1382 DemandedVLs[&MI] = DemandedVL::vlmax();
1383
1384 for (const MachineOperand &MO : virtual_vec_uses(MI)) {
1385 const MachineInstr *Def = MRI->getVRegDef(Reg: MO.getReg());
1386 DemandedVL Prev = DemandedVLs[Def];
1387 DemandedVLs[Def] = DemandedVLs[Def].max(
1388 MRI: *MRI, X: getMinimumVLForUser(UserMI: MI, OpIdx: MI.getOperandNo(I: &MO)));
1389 if (DemandedVLs[Def] != Prev)
1390 Worklist.insert(X: Def);
1391 }
1392}
1393
1394bool RISCVVLOptimizerImpl::run(MachineFunction &MF) {
1395 MRI = &MF.getRegInfo();
1396
1397 const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
1398 if (!ST.hasVInstructions())
1399 return false;
1400
1401 TII = ST.getInstrInfo();
1402
1403 assert(DemandedVLs.empty());
1404
1405 // For each instruction that defines a vector, propagate the VL it
1406 // uses to its inputs.
1407 for (MachineBasicBlock *MBB : post_order(G: &MF)) {
1408 assert(MDT->isReachableFromEntry(MBB));
1409 for (MachineInstr &MI : reverse(C&: *MBB))
1410 if (!MI.isDebugInstr())
1411 Worklist.insert(X: &MI);
1412 }
1413
1414 while (!Worklist.empty()) {
1415 const MachineInstr *MI = Worklist.front();
1416 Worklist.remove(X: MI);
1417 transfer(MI: *MI);
1418 }
1419
1420 // Then go through and see if we can reduce the VL of any instructions to
1421 // only what's demanded.
1422 bool MadeChange = false;
1423 for (auto &[MI, VL] : DemandedVLs) {
1424 assert(MDT->isReachableFromEntry(MI->getParent()));
1425 if (!isCandidate(MI: *MI))
1426 continue;
1427 if (!tryReduceVL(MI&: *const_cast<MachineInstr *>(MI), CommonVL: VL.VL))
1428 continue;
1429 MadeChange = true;
1430 }
1431
1432 DemandedVLs.clear();
1433 return MadeChange;
1434}
1435
1436bool RISCVVLOptimizerLegacy::runOnMachineFunction(MachineFunction &MF) {
1437 if (skipFunction(F: MF.getFunction()))
1438 return false;
1439
1440 auto *MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1441 return RISCVVLOptimizerImpl(MDT).run(MF);
1442}
1443
1444PreservedAnalyses
1445RISCVVLOptimizerPass::run(MachineFunction &MF,
1446 MachineFunctionAnalysisManager &MFAM) {
1447 auto *MDT = &MFAM.getResult<MachineDominatorTreeAnalysis>(IR&: MF);
1448 bool Changed = RISCVVLOptimizerImpl(MDT).run(MF);
1449 if (!Changed)
1450 return PreservedAnalyses::all();
1451
1452 PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
1453 PA.preserveSet<CFGAnalyses>();
1454 PA.preserve<MachineRegisterClassAnalysis>();
1455 return PA;
1456}
1457