LLVM 22.0.0git
RISCVVectorPeephole.cpp
Go to the documentation of this file.
1//===- RISCVVectorPeephole.cpp - MI Vector Pseudo Peepholes ---------------===//
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 performs various vector pseudo peephole optimisations after
10// instruction selection.
11//
12// Currently it converts vmerge.vvm to vmv.v.v
13// PseudoVMERGE_VVM %false, %false, %true, %allonesmask, %vl, %sew
14// ->
15// PseudoVMV_V_V %false, %true, %vl, %sew
16//
17// And masked pseudos to unmasked pseudos
18// PseudoVADD_V_V_MASK %passthru, %a, %b, %allonesmask, %vl, sew, policy
19// ->
20// PseudoVADD_V_V %passthru %a, %b, %vl, sew, policy
21//
22// It also converts AVLs to VLMAX where possible
23// %vl = VLENB * something
24// PseudoVADD_V_V %passthru, %a, %b, %vl, sew, policy
25// ->
26// PseudoVADD_V_V %passthru, %a, %b, -1, sew, policy
27//
28//===----------------------------------------------------------------------===//
29
30#include "RISCV.h"
31#include "RISCVSubtarget.h"
36
37using namespace llvm;
38
39#define DEBUG_TYPE "riscv-vector-peephole"
40
41namespace {
42
43class RISCVVectorPeephole : public MachineFunctionPass {
44public:
45 static char ID;
46 const TargetInstrInfo *TII;
49 const RISCVSubtarget *ST;
50 RISCVVectorPeephole() : MachineFunctionPass(ID) {}
51
52 bool runOnMachineFunction(MachineFunction &MF) override;
54 return MachineFunctionProperties().setIsSSA();
55 }
56
57 StringRef getPassName() const override {
58 return "RISC-V Vector Peephole Optimization";
59 }
60
61private:
62 bool tryToReduceVL(MachineInstr &MI) const;
63 bool convertToVLMAX(MachineInstr &MI) const;
64 bool convertToWholeRegister(MachineInstr &MI) const;
65 bool convertToUnmasked(MachineInstr &MI) const;
66 bool convertAllOnesVMergeToVMv(MachineInstr &MI) const;
67 bool convertSameMaskVMergeToVMv(MachineInstr &MI);
68 bool foldUndefPassthruVMV_V_V(MachineInstr &MI);
69 bool foldVMV_V_V(MachineInstr &MI);
70 bool foldVMergeToMask(MachineInstr &MI) const;
71
72 bool hasSameEEW(const MachineInstr &User, const MachineInstr &Src) const;
73 bool isAllOnesMask(const MachineInstr *MaskDef) const;
74 std::optional<unsigned> getConstant(const MachineOperand &VL) const;
75 bool ensureDominates(const MachineOperand &Use, MachineInstr &Src) const;
76 bool isKnownSameDefs(Register A, Register B) const;
77};
78
79} // namespace
80
81char RISCVVectorPeephole::ID = 0;
82
83INITIALIZE_PASS(RISCVVectorPeephole, DEBUG_TYPE, "RISC-V Fold Masks", false,
84 false)
85
86/// Given \p User that has an input operand with EEW=SEW, which uses the dest
87/// operand of \p Src with an unknown EEW, return true if their EEWs match.
88bool RISCVVectorPeephole::hasSameEEW(const MachineInstr &User,
89 const MachineInstr &Src) const {
90 unsigned UserLog2SEW =
91 User.getOperand(RISCVII::getSEWOpNum(User.getDesc())).getImm();
92 unsigned SrcLog2SEW =
93 Src.getOperand(RISCVII::getSEWOpNum(Src.getDesc())).getImm();
94 unsigned SrcLog2EEW = RISCV::getDestLog2EEW(
95 TII->get(RISCV::getRVVMCOpcode(Src.getOpcode())), SrcLog2SEW);
96 return SrcLog2EEW == UserLog2SEW;
97}
98
99// Attempt to reduce the VL of an instruction whose sole use is feeding a
100// instruction with a narrower VL. This currently works backwards from the
101// user instruction (which might have a smaller VL).
102bool RISCVVectorPeephole::tryToReduceVL(MachineInstr &MI) const {
103 // Note that the goal here is a bit multifaceted.
104 // 1) For store's reducing the VL of the value being stored may help to
105 // reduce VL toggles. This is somewhat of an artifact of the fact we
106 // promote arithmetic instructions but VL predicate stores.
107 // 2) For vmv.v.v reducing VL eagerly on the source instruction allows us
108 // to share code with the foldVMV_V_V transform below.
109 //
110 // Note that to the best of our knowledge, reducing VL is generally not
111 // a significant win on real hardware unless we can also reduce LMUL which
112 // this code doesn't try to do.
113 //
114 // TODO: We can handle a bunch more instructions here, and probably
115 // recurse backwards through operands too.
116 SmallVector<unsigned, 2> SrcIndices = {0};
117 switch (RISCV::getRVVMCOpcode(MI.getOpcode())) {
118 default:
119 return false;
120 case RISCV::VSE8_V:
121 case RISCV::VSE16_V:
122 case RISCV::VSE32_V:
123 case RISCV::VSE64_V:
124 break;
125 case RISCV::VMV_V_V:
126 SrcIndices[0] = 2;
127 break;
128 case RISCV::VMERGE_VVM:
129 SrcIndices.assign({2, 3});
130 break;
131 case RISCV::VREDSUM_VS:
132 case RISCV::VREDMAXU_VS:
133 case RISCV::VREDMAX_VS:
134 case RISCV::VREDMINU_VS:
135 case RISCV::VREDMIN_VS:
136 case RISCV::VREDAND_VS:
137 case RISCV::VREDOR_VS:
138 case RISCV::VREDXOR_VS:
139 case RISCV::VWREDSUM_VS:
140 case RISCV::VWREDSUMU_VS:
141 case RISCV::VFREDUSUM_VS:
142 case RISCV::VFREDOSUM_VS:
143 case RISCV::VFREDMAX_VS:
144 case RISCV::VFREDMIN_VS:
145 case RISCV::VFWREDUSUM_VS:
146 case RISCV::VFWREDOSUM_VS:
147 SrcIndices[0] = 2;
148 break;
149 }
150
151 MachineOperand &VL = MI.getOperand(RISCVII::getVLOpNum(MI.getDesc()));
152 if (VL.isImm() && VL.getImm() == RISCV::VLMaxSentinel)
153 return false;
154
155 bool Changed = false;
156 for (unsigned SrcIdx : SrcIndices) {
157 Register SrcReg = MI.getOperand(SrcIdx).getReg();
158 // Note: one *use*, not one *user*.
159 if (!MRI->hasOneUse(SrcReg))
160 continue;
161
162 MachineInstr *Src = MRI->getVRegDef(SrcReg);
163 if (!Src || Src->hasUnmodeledSideEffects() ||
164 Src->getParent() != MI.getParent() || Src->getNumDefs() != 1 ||
165 !RISCVII::hasVLOp(Src->getDesc().TSFlags) ||
166 !RISCVII::hasSEWOp(Src->getDesc().TSFlags))
167 continue;
168
169 // Src's dest needs to have the same EEW as MI's input.
170 if (!hasSameEEW(MI, *Src))
171 continue;
172
173 bool ElementsDependOnVL = RISCVII::elementsDependOnVL(
174 TII->get(RISCV::getRVVMCOpcode(Src->getOpcode())).TSFlags);
175 if (ElementsDependOnVL || Src->mayRaiseFPException())
176 continue;
177
178 MachineOperand &SrcVL =
179 Src->getOperand(RISCVII::getVLOpNum(Src->getDesc()));
180 if (VL.isIdenticalTo(SrcVL) || !RISCV::isVLKnownLE(VL, SrcVL))
181 continue;
182
183 if (!ensureDominates(VL, *Src))
184 continue;
185
186 if (VL.isImm())
187 SrcVL.ChangeToImmediate(VL.getImm());
188 else if (VL.isReg())
189 SrcVL.ChangeToRegister(VL.getReg(), false);
190
191 Changed = true;
192 }
193
194 // TODO: For instructions with a passthru, we could clear the passthru
195 // and tail policy since we've just proven the tail is not demanded.
196 return Changed;
197}
198
199/// Check if an operand is an immediate or a materialized ADDI $x0, imm.
200std::optional<unsigned>
201RISCVVectorPeephole::getConstant(const MachineOperand &VL) const {
202 if (VL.isImm())
203 return VL.getImm();
204
205 MachineInstr *Def = MRI->getVRegDef(VL.getReg());
206 if (!Def || Def->getOpcode() != RISCV::ADDI ||
207 Def->getOperand(1).getReg() != RISCV::X0)
208 return std::nullopt;
209 return Def->getOperand(2).getImm();
210}
211
212/// Convert AVLs that are known to be VLMAX to the VLMAX sentinel.
213bool RISCVVectorPeephole::convertToVLMAX(MachineInstr &MI) const {
214 if (!RISCVII::hasVLOp(MI.getDesc().TSFlags) ||
215 !RISCVII::hasSEWOp(MI.getDesc().TSFlags))
216 return false;
217
218 auto LMUL = RISCVVType::decodeVLMUL(RISCVII::getLMul(MI.getDesc().TSFlags));
219 // Fixed-point value, denominator=8
220 unsigned LMULFixed = LMUL.second ? (8 / LMUL.first) : 8 * LMUL.first;
221 unsigned Log2SEW = MI.getOperand(RISCVII::getSEWOpNum(MI.getDesc())).getImm();
222 // A Log2SEW of 0 is an operation on mask registers only
223 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
224 assert(RISCVVType::isValidSEW(SEW) && "Unexpected SEW");
225 assert(8 * LMULFixed / SEW > 0);
226
227 // If the exact VLEN is known then we know VLMAX, check if the AVL == VLMAX.
228 MachineOperand &VL = MI.getOperand(RISCVII::getVLOpNum(MI.getDesc()));
229 if (auto VLen = ST->getRealVLen(), AVL = getConstant(VL);
230 VLen && AVL && (*VLen * LMULFixed) / SEW == *AVL * 8) {
232 return true;
233 }
234
235 // If an AVL is a VLENB that's possibly scaled to be equal to VLMAX, convert
236 // it to the VLMAX sentinel value.
237 if (!VL.isReg())
238 return false;
239 MachineInstr *Def = MRI->getVRegDef(VL.getReg());
240 if (!Def)
241 return false;
242
243 // Fixed-point value, denominator=8
244 uint64_t ScaleFixed = 8;
245 // Check if the VLENB was potentially scaled with slli/srli
246 if (Def->getOpcode() == RISCV::SLLI) {
247 assert(Def->getOperand(2).getImm() < 64);
248 ScaleFixed <<= Def->getOperand(2).getImm();
249 Def = MRI->getVRegDef(Def->getOperand(1).getReg());
250 } else if (Def->getOpcode() == RISCV::SRLI) {
251 assert(Def->getOperand(2).getImm() < 64);
252 ScaleFixed >>= Def->getOperand(2).getImm();
253 Def = MRI->getVRegDef(Def->getOperand(1).getReg());
254 }
255
256 if (!Def || Def->getOpcode() != RISCV::PseudoReadVLENB)
257 return false;
258
259 // AVL = (VLENB * Scale)
260 //
261 // VLMAX = (VLENB * 8 * LMUL) / SEW
262 //
263 // AVL == VLMAX
264 // -> VLENB * Scale == (VLENB * 8 * LMUL) / SEW
265 // -> Scale == (8 * LMUL) / SEW
266 if (ScaleFixed != 8 * LMULFixed / SEW)
267 return false;
268
270
271 return true;
272}
273
274bool RISCVVectorPeephole::isAllOnesMask(const MachineInstr *MaskDef) const {
275 while (MaskDef->isCopy() && MaskDef->getOperand(1).getReg().isVirtual())
276 MaskDef = MRI->getVRegDef(MaskDef->getOperand(1).getReg());
277
278 // TODO: Check that the VMSET is the expected bitwidth? The pseudo has
279 // undefined behaviour if it's the wrong bitwidth, so we could choose to
280 // assume that it's all-ones? Same applies to its VL.
281 switch (MaskDef->getOpcode()) {
282 case RISCV::PseudoVMSET_M_B1:
283 case RISCV::PseudoVMSET_M_B2:
284 case RISCV::PseudoVMSET_M_B4:
285 case RISCV::PseudoVMSET_M_B8:
286 case RISCV::PseudoVMSET_M_B16:
287 case RISCV::PseudoVMSET_M_B32:
288 case RISCV::PseudoVMSET_M_B64:
289 return true;
290 default:
291 return false;
292 }
293}
294
295/// Convert unit strided unmasked loads and stores to whole-register equivalents
296/// to avoid the dependency on $vl and $vtype.
297///
298/// %x = PseudoVLE8_V_M1 %passthru, %ptr, %vlmax, policy
299/// PseudoVSE8_V_M1 %v, %ptr, %vlmax
300///
301/// ->
302///
303/// %x = VL1RE8_V %ptr
304/// VS1R_V %v, %ptr
305bool RISCVVectorPeephole::convertToWholeRegister(MachineInstr &MI) const {
306#define CASE_WHOLE_REGISTER_LMUL_SEW(lmul, sew) \
307 case RISCV::PseudoVLE##sew##_V_M##lmul: \
308 NewOpc = RISCV::VL##lmul##RE##sew##_V; \
309 break; \
310 case RISCV::PseudoVSE##sew##_V_M##lmul: \
311 NewOpc = RISCV::VS##lmul##R_V; \
312 break;
313#define CASE_WHOLE_REGISTER_LMUL(lmul) \
314 CASE_WHOLE_REGISTER_LMUL_SEW(lmul, 8) \
315 CASE_WHOLE_REGISTER_LMUL_SEW(lmul, 16) \
316 CASE_WHOLE_REGISTER_LMUL_SEW(lmul, 32) \
317 CASE_WHOLE_REGISTER_LMUL_SEW(lmul, 64)
318
319 unsigned NewOpc;
320 switch (MI.getOpcode()) {
325 default:
326 return false;
327 }
328
329 MachineOperand &VLOp = MI.getOperand(RISCVII::getVLOpNum(MI.getDesc()));
330 if (!VLOp.isImm() || VLOp.getImm() != RISCV::VLMaxSentinel)
331 return false;
332
333 // Whole register instructions aren't pseudos so they don't have
334 // policy/SEW/AVL ops, and they don't have passthrus.
335 if (RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags))
336 MI.removeOperand(RISCVII::getVecPolicyOpNum(MI.getDesc()));
337 MI.removeOperand(RISCVII::getSEWOpNum(MI.getDesc()));
338 MI.removeOperand(RISCVII::getVLOpNum(MI.getDesc()));
339 if (RISCVII::isFirstDefTiedToFirstUse(MI.getDesc()))
340 MI.removeOperand(1);
341
342 MI.setDesc(TII->get(NewOpc));
343
344 return true;
345}
346
347static unsigned getVMV_V_VOpcodeForVMERGE_VVM(const MachineInstr &MI) {
348#define CASE_VMERGE_TO_VMV(lmul) \
349 case RISCV::PseudoVMERGE_VVM_##lmul: \
350 return RISCV::PseudoVMV_V_V_##lmul;
351 switch (MI.getOpcode()) {
352 default:
353 return 0;
361 }
362}
363
364/// Convert a PseudoVMERGE_VVM with an all ones mask to a PseudoVMV_V_V.
365///
366/// %x = PseudoVMERGE_VVM %passthru, %false, %true, %allones, sew, vl
367/// ->
368/// %x = PseudoVMV_V_V %passthru, %true, vl, sew, tu_mu
369bool RISCVVectorPeephole::convertAllOnesVMergeToVMv(MachineInstr &MI) const {
370 unsigned NewOpc = getVMV_V_VOpcodeForVMERGE_VVM(MI);
371 if (!NewOpc)
372 return false;
373 if (!isAllOnesMask(MRI->getVRegDef(MI.getOperand(4).getReg())))
374 return false;
375
376 MI.setDesc(TII->get(NewOpc));
377 MI.removeOperand(2); // False operand
378 MI.removeOperand(3); // Mask operand
379 MI.addOperand(
381
382 // vmv.v.v doesn't have a mask operand, so we may be able to inflate the
383 // register class for the destination and passthru operands e.g. VRNoV0 -> VR
384 MRI->recomputeRegClass(MI.getOperand(0).getReg());
385 if (MI.getOperand(1).getReg() != RISCV::NoRegister)
386 MRI->recomputeRegClass(MI.getOperand(1).getReg());
387 return true;
388}
389
390bool RISCVVectorPeephole::isKnownSameDefs(Register A, Register B) const {
391 if (A.isPhysical() || B.isPhysical())
392 return false;
393
394 auto LookThruVirtRegCopies = [this](Register Reg) {
395 while (MachineInstr *Def = MRI->getUniqueVRegDef(Reg)) {
396 if (!Def->isFullCopy())
397 break;
398 Register Src = Def->getOperand(1).getReg();
399 if (!Src.isVirtual())
400 break;
401 Reg = Src;
402 }
403 return Reg;
404 };
405
406 return LookThruVirtRegCopies(A) == LookThruVirtRegCopies(B);
407}
408
409/// If a PseudoVMERGE_VVM's true operand is a masked pseudo and both have the
410/// same mask, and the masked pseudo's passthru is the same as the false
411/// operand, we can convert the PseudoVMERGE_VVM to a PseudoVMV_V_V.
412///
413/// %true = PseudoVADD_VV_M1_MASK %false, %x, %y, %mask, vl1, sew, policy
414/// %x = PseudoVMERGE_VVM %passthru, %false, %true, %mask, vl2, sew
415/// ->
416/// %true = PseudoVADD_VV_M1_MASK %false, %x, %y, %mask, vl1, sew, policy
417/// %x = PseudoVMV_V_V %passthru, %true, vl2, sew, tu_mu
418bool RISCVVectorPeephole::convertSameMaskVMergeToVMv(MachineInstr &MI) {
419 unsigned NewOpc = getVMV_V_VOpcodeForVMERGE_VVM(MI);
420 if (!NewOpc)
421 return false;
422 MachineInstr *True = MRI->getVRegDef(MI.getOperand(3).getReg());
423
424 if (!True || True->getParent() != MI.getParent())
425 return false;
426
427 auto *TrueMaskedInfo = RISCV::getMaskedPseudoInfo(True->getOpcode());
428 if (!TrueMaskedInfo || !hasSameEEW(MI, *True))
429 return false;
430
431 const MachineOperand &TrueMask =
432 True->getOperand(TrueMaskedInfo->MaskOpIdx + True->getNumExplicitDefs());
433 const MachineOperand &MIMask = MI.getOperand(4);
434 if (!isKnownSameDefs(TrueMask.getReg(), MIMask.getReg()))
435 return false;
436
437 // Masked off lanes past TrueVL will come from False, and converting to vmv
438 // will lose these lanes unless MIVL <= TrueVL.
439 // TODO: We could relax this for False == Passthru and True policy == TU
440 const MachineOperand &MIVL = MI.getOperand(RISCVII::getVLOpNum(MI.getDesc()));
441 const MachineOperand &TrueVL =
442 True->getOperand(RISCVII::getVLOpNum(True->getDesc()));
443 if (!RISCV::isVLKnownLE(MIVL, TrueVL))
444 return false;
445
446 // True's passthru needs to be equivalent to False
447 Register TruePassthruReg = True->getOperand(1).getReg();
448 Register FalseReg = MI.getOperand(2).getReg();
449 if (TruePassthruReg != FalseReg) {
450 // If True's passthru is undef see if we can change it to False
451 if (TruePassthruReg != RISCV::NoRegister ||
452 !MRI->hasOneUse(MI.getOperand(3).getReg()) ||
453 !ensureDominates(MI.getOperand(2), *True))
454 return false;
455 True->getOperand(1).setReg(MI.getOperand(2).getReg());
456 // If True is masked then its passthru needs to be in VRNoV0.
457 MRI->constrainRegClass(True->getOperand(1).getReg(),
458 TII->getRegClass(True->getDesc(), 1, TRI,
459 *True->getParent()->getParent()));
460 }
461
462 MI.setDesc(TII->get(NewOpc));
463 MI.removeOperand(2); // False operand
464 MI.removeOperand(3); // Mask operand
465 MI.addOperand(
467
468 // vmv.v.v doesn't have a mask operand, so we may be able to inflate the
469 // register class for the destination and passthru operands e.g. VRNoV0 -> VR
470 MRI->recomputeRegClass(MI.getOperand(0).getReg());
471 if (MI.getOperand(1).getReg() != RISCV::NoRegister)
472 MRI->recomputeRegClass(MI.getOperand(1).getReg());
473 return true;
474}
475
476bool RISCVVectorPeephole::convertToUnmasked(MachineInstr &MI) const {
478 RISCV::getMaskedPseudoInfo(MI.getOpcode());
479 if (!I)
480 return false;
481
482 if (!isAllOnesMask(MRI->getVRegDef(
483 MI.getOperand(I->MaskOpIdx + MI.getNumExplicitDefs()).getReg())))
484 return false;
485
486 // There are two classes of pseudos in the table - compares and
487 // everything else. See the comment on RISCVMaskedPseudo for details.
488 const unsigned Opc = I->UnmaskedPseudo;
489 const MCInstrDesc &MCID = TII->get(Opc);
490 [[maybe_unused]] const bool HasPolicyOp =
492 const bool HasPassthru = RISCVII::isFirstDefTiedToFirstUse(MCID);
493 const MCInstrDesc &MaskedMCID = TII->get(MI.getOpcode());
496 "Unmasked pseudo has policy but masked pseudo doesn't?");
497 assert(HasPolicyOp == HasPassthru && "Unexpected pseudo structure");
498 assert(!(HasPassthru && !RISCVII::isFirstDefTiedToFirstUse(MaskedMCID)) &&
499 "Unmasked with passthru but masked with no passthru?");
500 (void)HasPolicyOp;
501
502 MI.setDesc(MCID);
503
504 // Drop the policy operand if unmasked doesn't need it.
505 if (RISCVII::hasVecPolicyOp(MaskedMCID.TSFlags) &&
507 MI.removeOperand(RISCVII::getVecPolicyOpNum(MaskedMCID));
508
509 // TODO: Increment all MaskOpIdxs in tablegen by num of explicit defs?
510 unsigned MaskOpIdx = I->MaskOpIdx + MI.getNumExplicitDefs();
511 MI.removeOperand(MaskOpIdx);
512
513 // The unmasked pseudo will no longer be constrained to the vrnov0 reg class,
514 // so try and relax it to vr.
515 MRI->recomputeRegClass(MI.getOperand(0).getReg());
516
517 // If the original masked pseudo had a passthru, relax it or remove it.
518 if (RISCVII::isFirstDefTiedToFirstUse(MaskedMCID)) {
519 unsigned PassthruOpIdx = MI.getNumExplicitDefs();
520 if (HasPassthru) {
521 if (MI.getOperand(PassthruOpIdx).getReg() != RISCV::NoRegister)
522 MRI->recomputeRegClass(MI.getOperand(PassthruOpIdx).getReg());
523 } else
524 MI.removeOperand(PassthruOpIdx);
525 }
526
527 return true;
528}
529
530/// Check if it's safe to move From down to To, checking that no physical
531/// registers are clobbered.
532static bool isSafeToMove(const MachineInstr &From, const MachineInstr &To) {
533 assert(From.getParent() == To.getParent());
534 SmallVector<Register> PhysUses, PhysDefs;
535 for (const MachineOperand &MO : From.all_uses())
536 if (MO.getReg().isPhysical())
537 PhysUses.push_back(MO.getReg());
538 for (const MachineOperand &MO : From.all_defs())
539 if (MO.getReg().isPhysical())
540 PhysDefs.push_back(MO.getReg());
541 bool SawStore = false;
542 for (auto II = std::next(From.getIterator()); II != To.getIterator(); II++) {
543 for (Register PhysReg : PhysUses)
544 if (II->definesRegister(PhysReg, nullptr))
545 return false;
546 for (Register PhysReg : PhysDefs)
547 if (II->definesRegister(PhysReg, nullptr) ||
548 II->readsRegister(PhysReg, nullptr))
549 return false;
550 if (II->mayStore()) {
551 SawStore = true;
552 break;
553 }
554 }
555 return From.isSafeToMove(SawStore);
556}
557
558/// Given A and B are in the same MBB, returns true if A comes before B.
561 assert(A->getParent() == B->getParent());
562 const MachineBasicBlock *MBB = A->getParent();
563 auto MBBEnd = MBB->end();
564 if (B == MBBEnd)
565 return true;
566
568 for (; &*I != A && &*I != B; ++I)
569 ;
570
571 return &*I == A;
572}
573
574/// If the register in \p MO doesn't dominate \p Src, try to move \p Src so it
575/// does. Returns false if doesn't dominate and we can't move. \p MO must be in
576/// the same basic block as \Src.
577bool RISCVVectorPeephole::ensureDominates(const MachineOperand &MO,
578 MachineInstr &Src) const {
579 assert(MO.getParent()->getParent() == Src.getParent());
580 if (!MO.isReg() || MO.getReg() == RISCV::NoRegister)
581 return true;
582
583 MachineInstr *Def = MRI->getVRegDef(MO.getReg());
584 if (Def->getParent() == Src.getParent() && !dominates(Def, Src)) {
585 if (!isSafeToMove(Src, *Def->getNextNode()))
586 return false;
587 Src.moveBefore(Def->getNextNode());
588 }
589
590 return true;
591}
592
593/// If a PseudoVMV_V_V's passthru is undef then we can replace it with its input
594bool RISCVVectorPeephole::foldUndefPassthruVMV_V_V(MachineInstr &MI) {
595 if (RISCV::getRVVMCOpcode(MI.getOpcode()) != RISCV::VMV_V_V)
596 return false;
597 if (MI.getOperand(1).getReg() != RISCV::NoRegister)
598 return false;
599
600 // If the input was a pseudo with a policy operand, we can give it a tail
601 // agnostic policy if MI's undef tail subsumes the input's.
602 MachineInstr *Src = MRI->getVRegDef(MI.getOperand(2).getReg());
603 if (Src && !Src->hasUnmodeledSideEffects() &&
604 MRI->hasOneUse(MI.getOperand(2).getReg()) &&
605 RISCVII::hasVLOp(Src->getDesc().TSFlags) &&
606 RISCVII::hasVecPolicyOp(Src->getDesc().TSFlags) && hasSameEEW(MI, *Src)) {
607 const MachineOperand &MIVL = MI.getOperand(3);
608 const MachineOperand &SrcVL =
609 Src->getOperand(RISCVII::getVLOpNum(Src->getDesc()));
610
611 MachineOperand &SrcPolicy =
612 Src->getOperand(RISCVII::getVecPolicyOpNum(Src->getDesc()));
613
614 if (RISCV::isVLKnownLE(MIVL, SrcVL))
615 SrcPolicy.setImm(SrcPolicy.getImm() | RISCVVType::TAIL_AGNOSTIC);
616 }
617
618 MRI->constrainRegClass(MI.getOperand(2).getReg(),
619 MRI->getRegClass(MI.getOperand(0).getReg()));
620 MRI->replaceRegWith(MI.getOperand(0).getReg(), MI.getOperand(2).getReg());
621 MRI->clearKillFlags(MI.getOperand(2).getReg());
622 MI.eraseFromParent();
623 return true;
624}
625
626/// If a PseudoVMV_V_V is the only user of its input, fold its passthru and VL
627/// into it.
628///
629/// %x = PseudoVADD_V_V_M1 %passthru, %a, %b, %vl1, sew, policy
630/// %y = PseudoVMV_V_V_M1 %passthru, %x, %vl2, sew, policy
631/// (where %vl1 <= %vl2, see related tryToReduceVL)
632///
633/// ->
634///
635/// %y = PseudoVADD_V_V_M1 %passthru, %a, %b, vl1, sew, policy
636bool RISCVVectorPeephole::foldVMV_V_V(MachineInstr &MI) {
637 if (RISCV::getRVVMCOpcode(MI.getOpcode()) != RISCV::VMV_V_V)
638 return false;
639
640 MachineOperand &Passthru = MI.getOperand(1);
641
642 if (!MRI->hasOneUse(MI.getOperand(2).getReg()))
643 return false;
644
645 MachineInstr *Src = MRI->getVRegDef(MI.getOperand(2).getReg());
646 if (!Src || Src->hasUnmodeledSideEffects() ||
647 Src->getParent() != MI.getParent() ||
648 !RISCVII::isFirstDefTiedToFirstUse(Src->getDesc()) ||
649 !RISCVII::hasVLOp(Src->getDesc().TSFlags))
650 return false;
651
652 // Src's dest needs to have the same EEW as MI's input.
653 if (!hasSameEEW(MI, *Src))
654 return false;
655
656 // Src needs to have the same passthru as VMV_V_V
657 MachineOperand &SrcPassthru = Src->getOperand(Src->getNumExplicitDefs());
658 if (SrcPassthru.getReg() != RISCV::NoRegister &&
659 SrcPassthru.getReg() != Passthru.getReg())
660 return false;
661
662 // Src VL will have already been reduced if legal (see tryToReduceVL),
663 // so we don't need to handle a smaller source VL here. However, the
664 // user's VL may be larger
665 MachineOperand &SrcVL = Src->getOperand(RISCVII::getVLOpNum(Src->getDesc()));
666 if (!RISCV::isVLKnownLE(SrcVL, MI.getOperand(3)))
667 return false;
668
669 // If the new passthru doesn't dominate Src, try to move Src so it does.
670 if (!ensureDominates(Passthru, *Src))
671 return false;
672
673 if (SrcPassthru.getReg() != Passthru.getReg()) {
674 SrcPassthru.setReg(Passthru.getReg());
675 // If Src is masked then its passthru needs to be in VRNoV0.
676 if (Passthru.getReg() != RISCV::NoRegister)
677 MRI->constrainRegClass(Passthru.getReg(),
678 TII->getRegClass(Src->getDesc(),
679 SrcPassthru.getOperandNo(), TRI,
680 *Src->getParent()->getParent()));
681 }
682
683 if (RISCVII::hasVecPolicyOp(Src->getDesc().TSFlags)) {
684 // If MI was tail agnostic and the VL didn't increase, preserve it.
686 if ((MI.getOperand(5).getImm() & RISCVVType::TAIL_AGNOSTIC) &&
687 RISCV::isVLKnownLE(MI.getOperand(3), SrcVL))
689 Src->getOperand(RISCVII::getVecPolicyOpNum(Src->getDesc())).setImm(Policy);
690 }
691
692 MRI->constrainRegClass(Src->getOperand(0).getReg(),
693 MRI->getRegClass(MI.getOperand(0).getReg()));
694 MRI->replaceRegWith(MI.getOperand(0).getReg(), Src->getOperand(0).getReg());
695 MI.eraseFromParent();
696
697 return true;
698}
699
700/// Try to fold away VMERGE_VVM instructions into their operands:
701///
702/// %true = PseudoVADD_VV ...
703/// %x = PseudoVMERGE_VVM_M1 %false, %false, %true, %mask
704/// ->
705/// %x = PseudoVADD_VV_M1_MASK %false, ..., %mask
706///
707/// We can only fold if vmerge's passthru operand, vmerge's false operand and
708/// %true's passthru operand (if it has one) are the same. This is because we
709/// have to consolidate them into one passthru operand in the result.
710///
711/// If %true is masked, then we can use its mask instead of vmerge's if vmerge's
712/// mask is all ones.
713///
714/// The resulting VL is the minimum of the two VLs.
715///
716/// The resulting policy is the effective policy the vmerge would have had,
717/// i.e. whether or not it's passthru operand was implicit-def.
718bool RISCVVectorPeephole::foldVMergeToMask(MachineInstr &MI) const {
719 if (RISCV::getRVVMCOpcode(MI.getOpcode()) != RISCV::VMERGE_VVM)
720 return false;
721
722 Register PassthruReg = MI.getOperand(1).getReg();
723 Register FalseReg = MI.getOperand(2).getReg();
724 Register TrueReg = MI.getOperand(3).getReg();
725 if (!TrueReg.isVirtual() || !MRI->hasOneUse(TrueReg))
726 return false;
727 MachineInstr &True = *MRI->getUniqueVRegDef(TrueReg);
728 if (True.getParent() != MI.getParent())
729 return false;
730 const MachineOperand &MaskOp = MI.getOperand(4);
731 MachineInstr *Mask = MRI->getUniqueVRegDef(MaskOp.getReg());
732 assert(Mask);
733
735 RISCV::lookupMaskedIntrinsicByUnmasked(True.getOpcode());
736 if (!Info)
737 return false;
738
739 // If the EEW of True is different from vmerge's SEW, then we can't fold.
740 if (!hasSameEEW(MI, True))
741 return false;
742
743 // We require that either passthru and false are the same, or that passthru
744 // is undefined.
745 if (PassthruReg && !isKnownSameDefs(PassthruReg, FalseReg))
746 return false;
747
748 // If True has a passthru operand then it needs to be the same as vmerge's
749 // False, since False will be used for the result's passthru operand.
750 Register TruePassthru = True.getOperand(True.getNumExplicitDefs()).getReg();
751 if (RISCVII::isFirstDefTiedToFirstUse(True.getDesc()) && TruePassthru &&
752 !isKnownSameDefs(TruePassthru, FalseReg))
753 return false;
754
755 // Make sure it doesn't raise any observable fp exceptions, since changing the
756 // active elements will affect how fflags is set.
757 if (True.hasUnmodeledSideEffects() || True.mayRaiseFPException())
758 return false;
759
760 const MachineOperand &VMergeVL =
761 MI.getOperand(RISCVII::getVLOpNum(MI.getDesc()));
762 const MachineOperand &TrueVL =
764
766 if (RISCV::isVLKnownLE(TrueVL, VMergeVL))
767 MinVL = TrueVL;
768 else if (RISCV::isVLKnownLE(VMergeVL, TrueVL))
769 MinVL = VMergeVL;
770 else
771 return false;
772
773 unsigned RVVTSFlags =
774 TII->get(RISCV::getRVVMCOpcode(True.getOpcode())).TSFlags;
775 if (RISCVII::elementsDependOnVL(RVVTSFlags) && !TrueVL.isIdenticalTo(MinVL))
776 return false;
777 if (RISCVII::elementsDependOnMask(RVVTSFlags) && !isAllOnesMask(Mask))
778 return false;
779
780 // Use a tumu policy, relaxing it to tail agnostic provided that the passthru
781 // operand is undefined.
782 //
783 // However, if the VL became smaller than what the vmerge had originally, then
784 // elements past VL that were previously in the vmerge's body will have moved
785 // to the tail. In that case we always need to use tail undisturbed to
786 // preserve them.
788 if (!PassthruReg && RISCV::isVLKnownLE(VMergeVL, MinVL))
790
792 "Foldable unmasked pseudo should have a policy op already");
793
794 // Make sure the mask dominates True, otherwise move down True so it does.
795 // VL will always dominate since if it's a register they need to be the same.
796 if (!ensureDominates(MaskOp, True))
797 return false;
798
799 True.setDesc(TII->get(Info->MaskedPseudo));
800
801 // Insert the mask operand.
802 // TODO: Increment MaskOpIdx by number of explicit defs?
803 True.insert(True.operands_begin() + Info->MaskOpIdx +
804 True.getNumExplicitDefs(),
805 MachineOperand::CreateReg(MaskOp.getReg(), false));
806
807 // Update the passthru, AVL and policy.
808 True.getOperand(True.getNumExplicitDefs()).setReg(FalseReg);
810 True.insert(True.operands_begin() + RISCVII::getVLOpNum(True.getDesc()),
811 MinVL);
813
814 MRI->replaceRegWith(True.getOperand(0).getReg(), MI.getOperand(0).getReg());
815 // Now that True is masked, constrain its operands from vr -> vrnov0.
816 for (MachineOperand &MO : True.explicit_operands()) {
817 if (!MO.isReg() || !MO.getReg().isVirtual())
818 continue;
819 MRI->constrainRegClass(
820 MO.getReg(), True.getRegClassConstraint(MO.getOperandNo(), TII, TRI));
821 }
822 MI.eraseFromParent();
823
824 return true;
825}
826
827bool RISCVVectorPeephole::runOnMachineFunction(MachineFunction &MF) {
828 if (skipFunction(MF.getFunction()))
829 return false;
830
831 // Skip if the vector extension is not enabled.
833 if (!ST->hasVInstructions())
834 return false;
835
836 TII = ST->getInstrInfo();
837 MRI = &MF.getRegInfo();
838 TRI = MRI->getTargetRegisterInfo();
839
840 bool Changed = false;
841
842 for (MachineBasicBlock &MBB : MF) {
844 Changed |= foldVMergeToMask(MI);
845
847 Changed |= convertToVLMAX(MI);
848 Changed |= tryToReduceVL(MI);
849 Changed |= convertToUnmasked(MI);
850 Changed |= convertToWholeRegister(MI);
851 Changed |= convertAllOnesVMergeToVMv(MI);
852 Changed |= convertSameMaskVMergeToVMv(MI);
853 if (foldUndefPassthruVMV_V_V(MI)) {
854 Changed |= true;
855 continue; // MI is erased
856 }
857 Changed |= foldVMV_V_V(MI);
858 }
859 }
860
861 return Changed;
862}
863
865 return new RISCVVectorPeephole();
866}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
MachineBasicBlock & MBB
static uint64_t getConstant(const Value *IndexValue)
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
Register const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
if(PassOpts->AAPipeline)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
#define CASE_WHOLE_REGISTER_LMUL(lmul)
#define CASE_VMERGE_TO_VMV(lmul)
static bool isSafeToMove(const MachineInstr &From, const MachineInstr &To)
Check if it's safe to move From down to To, checking that no physical registers are clobbered.
#define DEBUG_TYPE
static bool dominates(MachineBasicBlock::const_iterator A, MachineBasicBlock::const_iterator B)
Given A and B are in the same MBB, returns true if A comes before B.
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.
Definition: MCInstrDesc.h:199
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
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.
Definition: MachineInstr.h:72
mop_iterator operands_begin()
Definition: MachineInstr.h:687
bool mayRaiseFPException() const
Return true if this instruction could possibly raise a floating-point exception.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:587
bool isCopy() const
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:359
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:584
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
LLVM_ABI void insert(mop_iterator InsertBefore, ArrayRef< MachineOperand > Ops)
Inserts Ops BEFORE It. Can untie/retie tied operands.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI unsigned getNumExplicitDefs() const
Returns the number of non-implicit definitions.
mop_range explicit_operands()
Definition: MachineInstr.h:696
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:595
LLVM_ABI const TargetRegisterClass * getRegClassConstraint(unsigned OpIdx, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const
Compute the static register class constraint for operand OpIdx.
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.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
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 ...
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:85
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:74
void assign(size_type NumElts, ValueParamT Elt)
Definition: SmallVector.h:705
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A Use represents the edge between a Value definition and its users.
Definition: Use.h:35
Value * getOperand(unsigned i) const
Definition: User.h:232
self_iterator getIterator()
Definition: ilist_node.h:134
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:126
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
static unsigned getVecPolicyOpNum(const MCInstrDesc &Desc)
static RISCVVType::VLMUL getLMul(uint64_t TSFlags)
static unsigned getVLOpNum(const MCInstrDesc &Desc)
static bool hasVLOp(uint64_t TSFlags)
static bool elementsDependOnMask(uint64_t TSFlags)
static bool hasVecPolicyOp(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)
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static bool isValidSEW(unsigned SEW)
bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS)
Given two VL operands, do we know that LHS <= RHS?
unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode)
unsigned getDestLog2EEW(const MCInstrDesc &Desc, unsigned Log2SEW)
static constexpr int64_t VLMaxSentinel
Reg
All possible values of the reg field in the ModR/M byte.
NodeAddr< DefNode * > Def
Definition: RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:663
unsigned M1(unsigned Val)
Definition: VE.h:377
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:976
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
FunctionPass * createRISCVVectorPeepholePass()