Skip to content

[RISCV][GISEL] instruction-select for G_SPLAT_VECTOR #111193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3303,8 +3303,14 @@ bool IRTranslator::translateShuffleVector(const User &U,
// poison are treated as zeroinitializer here).
if (U.getOperand(0)->getType()->isScalableTy()) {
Register Val = getOrCreateVReg(*U.getOperand(0));
auto SplatVal = MIRBuilder.buildExtractVectorElementConstant(
MRI->getType(Val).getElementType(), Val, 0);
// We don't use buildExtractVectorElementConstant because it creates
// problems for CSE since the constant gets placed in a different basic
// block.
unsigned VecIdxWidth = TLI->getVectorIdxTy(*DL).getSizeInBits();
auto *IdxCI = ConstantInt::get(U.getContext(), APInt(VecIdxWidth, 0));
Register Idx = getOrCreateVReg(*IdxCI);
auto SplatVal = MIRBuilder.buildExtractVectorElement(
MRI->getType(Val).getElementType(), Val, Idx);
MIRBuilder.buildSplatVector(getOrCreateVReg(U), SplatVal);
return true;
}
Expand Down
49 changes: 49 additions & 0 deletions llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class RISCVInstructionSelector : public InstructionSelector {
// Returns true if the instruction was modified.
void preISelLower(MachineInstr &MI, MachineIRBuilder &MIB);

// An early selection function that runs before the selectImpl() call.
bool earlySelect(MachineInstr &I);

bool replacePtrWithInt(MachineOperand &Op, MachineIRBuilder &MIB);

// Custom selection methods
Expand Down Expand Up @@ -568,6 +571,9 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
return true;
}

if (earlySelect(MI))
return true;

if (selectImpl(MI, *CoverageInfo))
return true;

Expand Down Expand Up @@ -804,6 +810,49 @@ void RISCVInstructionSelector::preISelLower(MachineInstr &MI,
}
}

bool RISCVInstructionSelector::earlySelect(MachineInstr &MI) {
assert(MI.getParent() && "Instruction should be in a basic block!");
assert(MI.getParent()->getParent() && "Instruction should be in a function!");

MachineIRBuilder MIB(MI);

switch (MI.getOpcode()) {
default:
break;
case TargetOpcode::G_SPLAT_VECTOR: {
// Convert integer SPLAT_VECTOR to VMV_V_X_VL and floating-point
// SPLAT_VECTOR to VFMV_V_F_VL to reduce isel burden.
Register Scalar = MI.getOperand(1).getReg();
bool IsGPRSplat = isRegInGprb(Scalar);
const LLT sXLen = LLT::scalar(STI.getXLen());
assert((!IsGPRSplat ||
TypeSize::isKnownGE(MRI->getType(Scalar).getSizeInBits(),
sXLen.getSizeInBits())) &&
"Unexpected Scalar register Type or Size");

// We create a IMPLICIT_DEF and a G_CONSTANT when we encounter a
// G_SPLAT_VECTOR. We cannot select the G_CONSTANT until after the MI is
// lowered, since renderVLOp needs to see the G_CONSTANT.
// FIXME: It would be nice if the InstructionSelector selected these
// instructions without needing to call select on them explicitly,
// which would allow us to lower G_SPLAT_VECTOR in preISelLower and
// rely on select to do the selection instead of early selecting here.
unsigned Opc = IsGPRSplat ? RISCV::G_VMV_V_X_VL : RISCV::G_VFMV_V_F_VL;
LLT VecTy = MRI->getType(MI.getOperand(0).getReg());
auto Passthru = MIB.buildUndef(VecTy);
auto VLMax = MIB.buildConstant(sXLen, -1);
MRI->setRegBank(Passthru.getReg(0), RBI.getRegBank(RISCV::VRBRegBankID));
MRI->setRegBank(VLMax.getReg(0), RBI.getRegBank(RISCV::GPRBRegBankID));
auto Splat = MIB.buildInstr(Opc, {MI.getOperand(0).getReg()},
{Passthru, Scalar, VLMax});
MI.eraseFromParent();
if (selectImpl(*Splat, *CoverageInfo))
return select(*Passthru) && select(*VLMax);
}
}
return false;
}

void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
const MachineInstr &MI,
int OpIdx) const {
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrGISel.td
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ def G_VMSET_VL : RISCVGenericInstruction {
}
def : GINodeEquiv<G_VMSET_VL, riscv_vmset_vl>;

// Pseudo equivalent to a RISCVISD::VMV_V_X_VL
def G_VMV_V_X_VL : RISCVGenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type1:$src);
let hasSideEffects = false;
}
def : GINodeEquiv<G_VMV_V_X_VL, riscv_vmv_v_x_vl>;

// Pseudo equivalent to a RISCVISD::VFMV_V_F_VL
def G_VFMV_V_F_VL : RISCVGenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type1:$src);
let hasSideEffects = false;
}
def : GINodeEquiv<G_VFMV_V_F_VL, riscv_vfmv_v_f_vl>;

// Pseudo equivalent to a RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL. There is no
// record to mark as equivalent to using GINodeEquiv because it gets lowered
// before instruction selection.
Expand Down
Loading
Loading