//===- RISCVVectorPeephole.cpp - MI Vector Pseudo Peepholes ---------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This pass performs various vector pseudo peephole optimisations after // instruction selection. // // Currently it converts vmerge.vvm to vmv.v.v // PseudoVMERGE_VVM %false, %false, %true, %allonesmask, %vl, %sew // -> // PseudoVMV_V_V %false, %true, %vl, %sew // // And masked pseudos to unmasked pseudos // PseudoVADD_V_V_MASK %passthru, %a, %b, %allonesmask, %vl, sew, policy // -> // PseudoVADD_V_V %passthru %a, %b, %vl, sew, policy // // It also converts AVLs to VLMAX where possible // %vl = VLENB * something // PseudoVADD_V_V %passthru, %a, %b, %vl, sew, policy // -> // PseudoVADD_V_V %passthru, %a, %b, -1, sew, policy // //===----------------------------------------------------------------------===// #include "RISCV.h" #include "RISCVISelDAGToDAG.h" #include "RISCVSubtarget.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetRegisterInfo.h" usingnamespacellvm; #define DEBUG_TYPE … namespace { class RISCVVectorPeephole : public MachineFunctionPass { … }; } // namespace char RISCVVectorPeephole::ID = …; INITIALIZE_PASS(…) /// Given two VL operands, do we know that LHS <= RHS? static bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS) { … } /// Given \p User that has an input operand with EEW=SEW, which uses the dest /// operand of \p Src with an unknown EEW, return true if their EEWs match. bool RISCVVectorPeephole::hasSameEEW(const MachineInstr &User, const MachineInstr &Src) const { … } // Attempt to reduce the VL of an instruction whose sole use is feeding a // instruction with a narrower VL. This currently works backwards from the // user instruction (which might have a smaller VL). bool RISCVVectorPeephole::tryToReduceVL(MachineInstr &MI) const { … } /// Check if an operand is an immediate or a materialized ADDI $x0, imm. std::optional<unsigned> RISCVVectorPeephole::getConstant(const MachineOperand &VL) const { … } /// Convert AVLs that are known to be VLMAX to the VLMAX sentinel. bool RISCVVectorPeephole::convertToVLMAX(MachineInstr &MI) const { … } bool RISCVVectorPeephole::isAllOnesMask(const MachineInstr *MaskDef) const { … } /// Convert unit strided unmasked loads and stores to whole-register equivalents /// to avoid the dependency on $vl and $vtype. /// /// %x = PseudoVLE8_V_M1 %passthru, %ptr, %vlmax, policy /// PseudoVSE8_V_M1 %v, %ptr, %vlmax /// /// -> /// /// %x = VL1RE8_V %ptr /// VS1R_V %v, %ptr bool RISCVVectorPeephole::convertToWholeRegister(MachineInstr &MI) const { … } static unsigned getVMV_V_VOpcodeForVMERGE_VVM(const MachineInstr &MI) { … } /// Convert a PseudoVMERGE_VVM with an all ones mask to a PseudoVMV_V_V. /// /// %x = PseudoVMERGE_VVM %passthru, %false, %true, %allones, sew, vl /// -> /// %x = PseudoVMV_V_V %passthru, %true, vl, sew, tu_mu bool RISCVVectorPeephole::convertAllOnesVMergeToVMv(MachineInstr &MI) const { … } /// If a PseudoVMERGE_VVM's true operand is a masked pseudo and both have the /// same mask, and the masked pseudo's passthru is the same as the false /// operand, we can convert the PseudoVMERGE_VVM to a PseudoVMV_V_V. /// /// %true = PseudoVADD_VV_M1_MASK %false, %x, %y, %mask, vl1, sew, policy /// %x = PseudoVMERGE_VVM %passthru, %false, %true, %mask, vl2, sew /// -> /// %true = PseudoVADD_VV_M1_MASK %false, %x, %y, %mask, vl1, sew, policy /// %x = PseudoVMV_V_V %passthru, %true, vl2, sew, tu_mu bool RISCVVectorPeephole::convertSameMaskVMergeToVMv(MachineInstr &MI) { … } bool RISCVVectorPeephole::convertToUnmasked(MachineInstr &MI) const { … } /// Check if it's safe to move From down to To, checking that no physical /// registers are clobbered. static bool isSafeToMove(const MachineInstr &From, const MachineInstr &To) { … } /// Given A and B are in the same MBB, returns true if A comes before B. static bool dominates(MachineBasicBlock::const_iterator A, MachineBasicBlock::const_iterator B) { … } /// If the register in \p MO doesn't dominate \p Src, try to move \p Src so it /// does. Returns false if doesn't dominate and we can't move. \p MO must be in /// the same basic block as \Src. bool RISCVVectorPeephole::ensureDominates(const MachineOperand &MO, MachineInstr &Src) const { … } /// If a PseudoVMV_V_V's passthru is undef then we can replace it with its input bool RISCVVectorPeephole::foldUndefPassthruVMV_V_V(MachineInstr &MI) { … } /// If a PseudoVMV_V_V is the only user of its input, fold its passthru and VL /// into it. /// /// %x = PseudoVADD_V_V_M1 %passthru, %a, %b, %vl1, sew, policy /// %y = PseudoVMV_V_V_M1 %passthru, %x, %vl2, sew, policy /// (where %vl1 <= %vl2, see related tryToReduceVL) /// /// -> /// /// %y = PseudoVADD_V_V_M1 %passthru, %a, %b, vl1, sew, policy bool RISCVVectorPeephole::foldVMV_V_V(MachineInstr &MI) { … } bool RISCVVectorPeephole::runOnMachineFunction(MachineFunction &MF) { … } FunctionPass *llvm::createRISCVVectorPeepholePass() { … }