40#define DEBUG_TYPE "riscv-vector-peephole"
56 MachineFunctionProperties::Property::IsSSA);
60 return "RISC-V Vector Peephole Optimization";
80char RISCVVectorPeephole::ID = 0;
140 Register SrcReg =
MI.getOperand(SrcIdx).getReg();
142 if (!
MRI->hasOneUse(SrcReg))
146 if (!Src || Src->hasUnmodeledSideEffects() ||
147 Src->getParent() !=
MI.getParent() || Src->getNumDefs() != 1 ||
158 if (ActiveElementsAffectResult || Src->mayRaiseFPException())
176std::optional<unsigned>
182 if (!Def ||
Def->getOpcode() != RISCV::ADDI ||
183 Def->getOperand(1).getReg() != RISCV::X0)
185 return Def->getOperand(2).getImm();
196 unsigned LMULFixed =
LMUL.second ? (8 /
LMUL.first) : 8 *
LMUL.first;
199 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
201 assert(8 * LMULFixed / SEW > 0);
206 VLen && AVL && (*VLen * LMULFixed) / SEW == *AVL * 8) {
222 if (
Def->getOpcode() == RISCV::SLLI) {
223 assert(
Def->getOperand(2).getImm() < 64);
224 ScaleFixed <<=
Def->getOperand(2).getImm();
225 Def =
MRI->getVRegDef(
Def->getOperand(1).getReg());
226 }
else if (
Def->getOpcode() == RISCV::SRLI) {
227 assert(
Def->getOperand(2).getImm() < 64);
228 ScaleFixed >>=
Def->getOperand(2).getImm();
229 Def =
MRI->getVRegDef(
Def->getOperand(1).getReg());
232 if (!Def ||
Def->getOpcode() != RISCV::PseudoReadVLENB)
242 if (ScaleFixed != 8 * LMULFixed / SEW)
250bool RISCVVectorPeephole::isAllOnesMask(
const MachineInstr *MaskDef)
const {
256 MaskDef =
MRI->getVRegDef(SrcReg);
264 case RISCV::PseudoVMSET_M_B1:
265 case RISCV::PseudoVMSET_M_B2:
266 case RISCV::PseudoVMSET_M_B4:
267 case RISCV::PseudoVMSET_M_B8:
268 case RISCV::PseudoVMSET_M_B16:
269 case RISCV::PseudoVMSET_M_B32:
270 case RISCV::PseudoVMSET_M_B64:
287bool RISCVVectorPeephole::convertToWholeRegister(
MachineInstr &
MI)
const {
288#define CASE_WHOLE_REGISTER_LMUL_SEW(lmul, sew) \
289 case RISCV::PseudoVLE##sew##_V_M##lmul: \
290 NewOpc = RISCV::VL##lmul##RE##sew##_V; \
292 case RISCV::PseudoVSE##sew##_V_M##lmul: \
293 NewOpc = RISCV::VS##lmul##R_V; \
295#define CASE_WHOLE_REGISTER_LMUL(lmul) \
296 CASE_WHOLE_REGISTER_LMUL_SEW(lmul, 8) \
297 CASE_WHOLE_REGISTER_LMUL_SEW(lmul, 16) \
298 CASE_WHOLE_REGISTER_LMUL_SEW(lmul, 32) \
299 CASE_WHOLE_REGISTER_LMUL_SEW(lmul, 64)
302 switch (
MI.getOpcode()) {
317 if (RISCVII::hasVecPolicyOp(
MI.getDesc().TSFlags))
318 MI.removeOperand(RISCVII::getVecPolicyOpNum(
MI.getDesc()));
319 MI.removeOperand(RISCVII::getSEWOpNum(
MI.getDesc()));
320 MI.removeOperand(RISCVII::getVLOpNum(
MI.getDesc()));
321 if (RISCVII::isFirstDefTiedToFirstUse(
MI.getDesc()))
331bool RISCVVectorPeephole::convertVMergeToVMv(
MachineInstr &
MI)
const {
332#define CASE_VMERGE_TO_VMV(lmul) \
333 case RISCV::PseudoVMERGE_VVM_##lmul: \
334 NewOpc = RISCV::PseudoVMV_V_V_##lmul; \
337 switch (
MI.getOpcode()) {
349 Register PassthruReg =
MI.getOperand(1).getReg();
350 Register FalseReg =
MI.getOperand(2).getReg();
352 if (PassthruReg != RISCV::NoRegister &&
353 TRI->lookThruCopyLike(PassthruReg,
MRI) !=
354 TRI->lookThruCopyLike(FalseReg,
MRI))
357 assert(
MI.getOperand(4).isReg() &&
MI.getOperand(4).getReg() == RISCV::V0);
358 if (!isAllOnesMask(V0Defs.lookup(&
MI)))
361 MI.setDesc(
TII->get(NewOpc));
363 MI.tieOperands(0, 1);
370 MRI->recomputeRegClass(
MI.getOperand(0).getReg());
371 MRI->recomputeRegClass(
MI.getOperand(1).getReg());
375bool RISCVVectorPeephole::convertToUnmasked(
MachineInstr &
MI)
const {
377 RISCV::getMaskedPseudoInfo(
MI.getOpcode());
381 if (!isAllOnesMask(V0Defs.lookup(&
MI)))
386 const unsigned Opc =
I->UnmaskedPseudo;
388 [[maybe_unused]]
const bool HasPolicyOp =
395 "Masked and unmasked pseudos are inconsistent");
396 assert(HasPolicyOp == HasPassthru &&
"Unexpected pseudo structure");
403 unsigned MaskOpIdx =
I->MaskOpIdx +
MI.getNumExplicitDefs();
404 MI.removeOperand(MaskOpIdx);
408 MRI->recomputeRegClass(
MI.getOperand(0).getReg());
409 unsigned PassthruOpIdx =
MI.getNumExplicitDefs();
411 if (
MI.getOperand(PassthruOpIdx).getReg() != RISCV::NoRegister)
412 MRI->recomputeRegClass(
MI.getOperand(PassthruOpIdx).getReg());
414 MI.removeOperand(PassthruOpIdx);
425 if (MO.getReg().isPhysical())
427 bool SawStore =
false;
430 if (
II->definesRegister(PhysReg,
nullptr))
432 if (
II->mayStore()) {
437 return From.isSafeToMove(SawStore);
456 if (!
MRI->hasOneUse(
MI.getOperand(2).getReg()))
460 if (!Src || Src->hasUnmodeledSideEffects() ||
461 Src->getParent() !=
MI.getParent() || Src->getNumDefs() != 1 ||
473 if (SrcPassthru.
getReg() != RISCV::NoRegister &&
481 if (!isVLKnownLE(SrcVL,
MI.getOperand(3)))
489 Src->moveBefore(&
MI);
495 if (Passthru.
getReg() != RISCV::NoRegister)
496 MRI->constrainRegClass(Passthru.
getReg(),
497 TII->getRegClass(Src->getDesc(), 1,
TRI,
498 *Src->getParent()->getParent()));
506 MRI->replaceRegWith(
MI.getOperand(0).getReg(), Src->getOperand(0).getReg());
507 MI.eraseFromParent();
519 if (!
ST->hasVInstructions())
522 TII =
ST->getInstrInfo();
524 TRI =
MRI->getTargetRegisterInfo();
526 bool Changed =
false;
538 if (
MI.readsRegister(RISCV::V0,
TRI))
539 V0Defs[&
MI] = CurrentV0Def;
541 if (
MI.definesRegister(RISCV::V0,
TRI))
548 Changed |= convertToVLMAX(
MI);
549 Changed |= tryToReduceVL(
MI);
550 Changed |= convertToUnmasked(
MI);
551 Changed |= convertToWholeRegister(
MI);
552 Changed |= convertVMergeToVMv(
MI);
553 Changed |= foldVMV_V_V(
MI);
561 return new RISCVVectorPeephole();
unsigned const MachineRegisterInfo * MRI
static uint64_t getConstant(const Value *IndexValue)
BlockVerifier::State From
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static unsigned getSEWLMULRatio(const MachineInstr &MI)
if(RHS.isImm() &&RHS.getImm()==RISCV::VLMaxSentinel) return true
#define CASE_WHOLE_REGISTER_LMUL(lmul)
const MachineOperand & RHS
#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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
FunctionPass class - This class is used to implement most global optimizations.
Describe properties that are true of each instruction in the target description file.
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.
MachineFunctionProperties & set(Property P)
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
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
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.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
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,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
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()
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
static unsigned getVecPolicyOpNum(const MCInstrDesc &Desc)
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
static unsigned getVLOpNum(const MCInstrDesc &Desc)
static VLMUL getLMul(uint64_t TSFlags)
static bool hasVLOp(uint64_t TSFlags)
static bool hasVecPolicyOp(uint64_t TSFlags)
static bool activeElementsAffectResult(uint64_t TSFlags)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
static bool hasSEWOp(uint64_t TSFlags)
static bool isFirstDefTiedToFirstUse(const MCInstrDesc &Desc)
std::pair< unsigned, bool > decodeVLMUL(RISCVII::VLMUL VLMUL)
unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul)
static bool isValidSEW(unsigned SEW)
unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode)
static constexpr int64_t VLMaxSentinel
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
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...
unsigned M1(unsigned Val)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
FunctionPass * createRISCVVectorPeepholePass()