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