llvm-project/llvm/lib/Target/RISCV/RISCVVectorMaskDAGMutation.cpp
Liao Chunyu 52a9c493e6
Reland "[RISCV] AddEdge between mask producer and user of V0 (#146855)" (#148566)
The defmask vector cannot contain instructions that use V0. 

for `MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/mesh.cpp`
Save `%173:vrm2nov0 = PseudoVMERGE_VVM_M2 undef %173:vrm2nov0(tied-def
0), %116:vrm2, %173:vrm2nov0, killed $v0, -1, 5 `to def mask caused crash.
2025-07-18 10:56:07 +08:00

111 lines
3.8 KiB
C++

//===- RISCVVectorMaskDAGMutation.cpp - RISC-V Vector Mask DAGMutation ----===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// A schedule mutation that adds an artificial dependency between masks producer
// instructions and masked instructions, so that we can reduce the live range
// overlaps of mask registers.
//
// If there are multiple masks producers followed by multiple masked
// instructions, then at each masked instructions add dependency edges between
// every producer and masked instruction.
//
// The reason why we need to do this:
// 1. When tracking register pressure, we don't track physical registers.
// 2. We have a RegisterClass for mask register (which is `VMV0`), but we don't
// use it by the time we reach scheduling. Instead, we use physical
// register V0 directly and insert a `$v0 = COPY ...` before the use.
// 3. For mask producers, we are using VR RegisterClass (we can allocate V0-V31
// to it). So if V0 is not available, there are still 31 available registers
// out there.
//
// This means that the RegPressureTracker can't track the pressure of mask
// registers correctly.
//
// This schedule mutation is a workaround to fix this issue.
//
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/RISCVBaseInfo.h"
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "RISCVTargetMachine.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
#include "llvm/CodeGen/ScheduleDAGMutation.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
#define DEBUG_TYPE "machine-scheduler"
namespace llvm {
static bool isCopyToV0(const MachineInstr &MI) {
return MI.isFullCopy() && MI.getOperand(0).getReg() == RISCV::V0 &&
MI.getOperand(1).getReg().isVirtual();
}
static bool isSoleUseCopyToV0(SUnit &SU) {
if (SU.Succs.size() != 1)
return false;
SDep &Dep = SU.Succs[0];
// Ignore dependencies other than data or strong ordering.
if (Dep.isWeak())
return false;
SUnit &DepSU = *Dep.getSUnit();
if (DepSU.isBoundaryNode())
return false;
return isCopyToV0(*DepSU.getInstr());
}
class RISCVVectorMaskDAGMutation : public ScheduleDAGMutation {
private:
const TargetRegisterInfo *TRI;
public:
RISCVVectorMaskDAGMutation(const TargetRegisterInfo *TRI) : TRI(TRI) {}
void apply(ScheduleDAGInstrs *DAG) override {
SUnit *NearestUseV0SU = nullptr;
SmallVector<SUnit *, 2> DefMask;
for (SUnit &SU : DAG->SUnits) {
const MachineInstr *MI = SU.getInstr();
bool UseV0 = MI->findRegisterUseOperand(RISCV::V0, TRI);
if (isSoleUseCopyToV0(SU) && !UseV0)
DefMask.push_back(&SU);
if (UseV0) {
NearestUseV0SU = &SU;
// Copy may not be a real use, so skip it here.
if (DefMask.size() > 1 && !MI->isCopy()) {
for (SUnit *Def : DefMask)
if (DAG->canAddEdge(Def, &SU))
DAG->addEdge(Def, SDep(&SU, SDep::Artificial));
}
if (!DefMask.empty())
DefMask.erase(DefMask.begin());
}
if (NearestUseV0SU && NearestUseV0SU != &SU && isSoleUseCopyToV0(SU) &&
// For LMUL=8 cases, there will be more possibilities to spill.
// FIXME: We should use RegPressureTracker to do fine-grained
// controls.
RISCVII::getLMul(MI->getDesc().TSFlags) != RISCVVType::LMUL_8)
DAG->addEdge(&SU, SDep(NearestUseV0SU, SDep::Artificial));
}
}
};
std::unique_ptr<ScheduleDAGMutation>
createRISCVVectorMaskDAGMutation(const TargetRegisterInfo *TRI) {
return std::make_unique<RISCVVectorMaskDAGMutation>(TRI);
}
} // namespace llvm