Skip to content

Commit 4768150

Browse files
[RISCV][GISEL] Legalize G_VSCALE
G_VSCALE should be lowered using VLENB.
1 parent 05dc5d9 commit 4768150

File tree

8 files changed

+528
-1
lines changed

8 files changed

+528
-1
lines changed

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,17 @@ class MachineIRBuilder {
11651165
/// \return a MachineInstrBuilder for the newly created instruction.
11661166
MachineInstrBuilder buildVScale(const DstOp &Res, const ConstantInt &MinElts);
11671167

1168+
/// Build and insert \p Res = G_VSCALE \p MinElts
1169+
///
1170+
/// G_VSCALE puts the value of the runtime vscale multiplied by \p MinElts
1171+
/// into \p Res.
1172+
///
1173+
/// \pre setBasicBlock or setMI must have been called.
1174+
/// \pre \p Res must be a generic virtual register with scalar type.
1175+
///
1176+
/// \return a MachineInstrBuilder for the newly created instruction.
1177+
MachineInstrBuilder buildVScale(const DstOp &Res, const APInt &MinElts);
1178+
11681179
/// Build and insert a G_INTRINSIC instruction.
11691180
///
11701181
/// There are four different opcodes based on combinations of whether the

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,36 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
16991699
case TargetOpcode::G_FLDEXP:
17001700
case TargetOpcode::G_STRICT_FLDEXP:
17011701
return narrowScalarFLDEXP(MI, TypeIdx, NarrowTy);
1702+
case TargetOpcode::G_VSCALE: {
1703+
LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1704+
const APInt &Val = MI.getOperand(1).getCImm()->getValue();
1705+
unsigned TotalSize = Ty.getSizeInBits();
1706+
unsigned NarrowSize = NarrowTy.getSizeInBits();
1707+
int NumParts = TotalSize / NarrowSize;
1708+
1709+
SmallVector<Register, 4> PartRegs;
1710+
for (int I = 0; I != NumParts; ++I) {
1711+
unsigned Offset = I * NarrowSize;
1712+
auto K =
1713+
MIRBuilder.buildVScale(NarrowTy, Val.lshr(Offset).trunc(NarrowSize));
1714+
PartRegs.push_back(K.getReg(0));
1715+
}
1716+
LLT LeftoverTy;
1717+
unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1718+
SmallVector<Register, 1> LeftoverRegs;
1719+
if (LeftoverBits != 0) {
1720+
LeftoverTy = LLT::scalar(LeftoverBits);
1721+
auto K = MIRBuilder.buildVScale(
1722+
LeftoverTy, Val.lshr(NumParts * NarrowSize).trunc(LeftoverBits));
1723+
LeftoverRegs.push_back(K.getReg(0));
1724+
}
1725+
1726+
insertParts(MI.getOperand(0).getReg(), Ty, NarrowTy, PartRegs, LeftoverTy,
1727+
LeftoverRegs);
1728+
1729+
MI.eraseFromParent();
1730+
return Legalized;
1731+
}
17021732
}
17031733
}
17041734

@@ -2966,7 +2996,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
29662996
case TargetOpcode::G_VECREDUCE_FMIN:
29672997
case TargetOpcode::G_VECREDUCE_FMAX:
29682998
case TargetOpcode::G_VECREDUCE_FMINIMUM:
2969-
case TargetOpcode::G_VECREDUCE_FMAXIMUM:
2999+
case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
29703000
if (TypeIdx != 0)
29713001
return UnableToLegalize;
29723002
Observer.changingInstr(MI);
@@ -2980,6 +3010,25 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
29803010
Observer.changedInstr(MI);
29813011
return Legalized;
29823012
}
3013+
case TargetOpcode::G_VSCALE: {
3014+
MachineOperand &SrcMO = MI.getOperand(1);
3015+
LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
3016+
unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3017+
MRI.getType(MI.getOperand(0).getReg()));
3018+
assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3019+
ExtOpc == TargetOpcode::G_ANYEXT) &&
3020+
"Illegal Extend");
3021+
const APInt &SrcVal = SrcMO.getCImm()->getValue();
3022+
const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3023+
? SrcVal.sext(WideTy.getSizeInBits())
3024+
: SrcVal.zext(WideTy.getSizeInBits());
3025+
Observer.changingInstr(MI);
3026+
SrcMO.setCImm(ConstantInt::get(Ctx, Val));
3027+
widenScalarDst(MI, WideTy);
3028+
Observer.changedInstr(MI);
3029+
return Legalized;
3030+
}
3031+
}
29833032
}
29843033

29853034
static void getUnmergePieces(SmallVectorImpl<Register> &Pieces,

llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,13 @@ MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
811811
return VScale;
812812
}
813813

814+
MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
815+
const APInt &MinElts) {
816+
ConstantInt *CI =
817+
ConstantInt::get(getMF().getFunction().getContext(), MinElts);
818+
return buildVScale(Res, *CI);
819+
}
820+
814821
static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) {
815822
if (HasSideEffects && IsConvergent)
816823
return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS;

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,10 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
406406
.clampScalar(0, s32, sXLen)
407407
.lowerForCartesianProduct({s32, sXLen, p0}, {p0});
408408

409+
getActionDefinitionsBuilder(G_VSCALE)
410+
.clampScalar(0, sXLen, sXLen)
411+
.customFor({sXLen});
412+
409413
getLegacyLegalizerInfo().computeTables();
410414
}
411415

@@ -527,6 +531,48 @@ bool RISCVLegalizerInfo::shouldBeInConstantPool(APInt APImm,
527531
return !(!SeqLo.empty() && (SeqLo.size() + 2) <= STI.getMaxBuildIntsCost());
528532
}
529533

534+
bool RISCVLegalizerInfo::legalizeVScale(MachineInstr &MI,
535+
MachineIRBuilder &MIB) const {
536+
const LLT XLenTy(STI.getXLenVT());
537+
Register Dst = MI.getOperand(0).getReg();
538+
539+
// We define our scalable vector types for lmul=1 to use a 64 bit known
540+
// minimum size. e.g. <vscale x 2 x i32>. VLENB is in bytes so we calculate
541+
// vscale as VLENB / 8.
542+
static_assert(RISCV::RVVBitsPerBlock == 64, "Unexpected bits per block!");
543+
if (STI.getRealMinVLen() < RISCV::RVVBitsPerBlock)
544+
// Support for VLEN==32 is incomplete.
545+
return false;
546+
547+
// We assume VLENB is a multiple of 8. We manually choose the best shift
548+
// here because SimplifyDemandedBits isn't always able to simplify it.
549+
uint64_t Val = MI.getOperand(1).getCImm()->getZExtValue();
550+
if (isPowerOf2_64(Val)) {
551+
uint64_t Log2 = Log2_64(Val);
552+
if (Log2 < 3) {
553+
auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
554+
MIB.buildLShr(Dst, VLENB, MIB.buildConstant(XLenTy, 3 - Log2));
555+
} else if (Log2 > 3) {
556+
auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
557+
MIB.buildShl(Dst, VLENB, MIB.buildConstant(XLenTy, Log2 - 3));
558+
} else {
559+
MIB.buildInstr(RISCV::G_READ_VLENB, {Dst}, {});
560+
}
561+
} else if ((Val % 8) == 0) {
562+
// If the multiplier is a multiple of 8, scale it down to avoid needing
563+
// to shift the VLENB value.
564+
auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
565+
MIB.buildMul(Dst, VLENB, MIB.buildConstant(XLenTy, Val / 8));
566+
} else {
567+
auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
568+
auto VScale = MIB.buildLShr(XLenTy, VLENB, MIB.buildConstant(XLenTy, 3));
569+
MIB.buildMul(Dst, VScale, MIB.buildConstant(XLenTy, Val));
570+
}
571+
572+
MI.eraseFromParent();
573+
return true;
574+
}
575+
530576
bool RISCVLegalizerInfo::legalizeCustom(
531577
LegalizerHelper &Helper, MachineInstr &MI,
532578
LostDebugLocObserver &LocObserver) const {
@@ -584,6 +630,8 @@ bool RISCVLegalizerInfo::legalizeCustom(
584630
}
585631
case TargetOpcode::G_VASTART:
586632
return legalizeVAStart(MI, MIRBuilder);
633+
case TargetOpcode::G_VSCALE:
634+
return legalizeVScale(MI, MIRBuilder);
587635
}
588636

589637
llvm_unreachable("expected switch to return");

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class RISCVLegalizerInfo : public LegalizerInfo {
4242
GISelChangeObserver &Observer) const;
4343

4444
bool legalizeVAStart(MachineInstr &MI, MachineIRBuilder &MIRBuilder) const;
45+
bool legalizeVScale(MachineInstr &MI, MachineIRBuilder &MIB) const;
4546
};
4647
} // end namespace llvm
4748
#endif

llvm/lib/Target/RISCV/RISCVInstrGISel.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,11 @@ def G_FCLASS : RISCVGenericInstruction {
2424
let hasSideEffects = false;
2525
}
2626
def : GINodeEquiv<G_FCLASS, riscv_fclass>;
27+
28+
// Pseudo equivalent to a RISCVISD::READ_VLENB.
29+
def G_READ_VLENB : RISCVGenericInstruction {
30+
let OutOperandList = (outs type0:$dst);
31+
let InOperandList = (ins);
32+
let hasSideEffects = false;
33+
}
34+
def : GINodeEquiv<G_READ_VLENB, riscv_read_vlenb>;

0 commit comments

Comments
 (0)