Skip to content

Commit dfa1d9b

Browse files
authored
[AMDGPU][NFC] Have helpers to deal with encoding fields. (#82772)
These are hoped to provide more convenient and less error prone facilities to encode and decode fields than manually defined constants and functions.
1 parent 24e7be4 commit dfa1d9b

10 files changed

+74
-89
lines changed

llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4824,9 +4824,8 @@ bool AMDGPULegalizerInfo::legalizeFDIV16(MachineInstr &MI,
48244824
return true;
48254825
}
48264826

4827-
static const unsigned SPDenormModeBitField =
4828-
AMDGPU::Hwreg::ID_MODE | (4 << AMDGPU::Hwreg::OFFSET_SHIFT_) |
4829-
(1 << AMDGPU::Hwreg::WIDTH_M1_SHIFT_);
4827+
static constexpr unsigned SPDenormModeBitField =
4828+
AMDGPU::Hwreg::HwregEncoding::encode(AMDGPU::Hwreg::ID_MODE, 4, 2);
48304829

48314830
// Enable or disable FP32 denorm mode. When 'Enable' is true, emit instructions
48324831
// to enable denorm mode. When 'Enable' is false, disable denorm mode.

llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7272,11 +7272,11 @@ ParseStatus AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
72727272

72737273
if (trySkipId("hwreg", AsmToken::LParen)) {
72747274
OperandInfoTy HwReg(OPR_ID_UNKNOWN);
7275-
OperandInfoTy Offset(OFFSET_DEFAULT_);
7276-
OperandInfoTy Width(WIDTH_DEFAULT_);
7275+
OperandInfoTy Offset(HwregOffset::Default);
7276+
OperandInfoTy Width(HwregSize::Default);
72777277
if (parseHwregBody(HwReg, Offset, Width) &&
72787278
validateHwreg(HwReg, Offset, Width)) {
7279-
ImmVal = encodeHwreg(HwReg.Id, Offset.Id, Width.Id);
7279+
ImmVal = HwregEncoding::encode(HwReg.Id, Offset.Id, Width.Id);
72807280
} else {
72817281
return ParseStatus::Failure;
72827282
}

llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ static bool isLdsDma(const MachineInstr &MI) {
177177
static unsigned getHWReg(const SIInstrInfo *TII, const MachineInstr &RegInstr) {
178178
const MachineOperand *RegOp = TII->getNamedOperand(RegInstr,
179179
AMDGPU::OpName::simm16);
180-
return RegOp->getImm() & AMDGPU::Hwreg::ID_MASK_;
180+
return std::get<0>(AMDGPU::Hwreg::HwregEncoding::decode(RegOp->getImm()));
181181
}
182182

183183
ScheduleHazardRecognizer::HazardType

llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,13 +1778,9 @@ void AMDGPUInstPrinter::printSDelayALU(const MCInst *MI, unsigned OpNo,
17781778

17791779
void AMDGPUInstPrinter::printHwreg(const MCInst *MI, unsigned OpNo,
17801780
const MCSubtargetInfo &STI, raw_ostream &O) {
1781-
unsigned Id;
1782-
unsigned Offset;
1783-
unsigned Width;
1784-
17851781
using namespace llvm::AMDGPU::Hwreg;
17861782
unsigned Val = MI->getOperand(OpNo).getImm();
1787-
decodeHwreg(Val, Id, Offset, Width);
1783+
auto [Id, Offset, Width] = HwregEncoding::decode(Val);
17881784
StringRef HwRegName = getHwreg(Id, STI);
17891785

17901786
O << "hwreg(";
@@ -1793,9 +1789,8 @@ void AMDGPUInstPrinter::printHwreg(const MCInst *MI, unsigned OpNo,
17931789
} else {
17941790
O << Id;
17951791
}
1796-
if (Width != WIDTH_DEFAULT_ || Offset != OFFSET_DEFAULT_) {
1792+
if (Width != HwregSize::Default || Offset != HwregOffset::Default)
17971793
O << ", " << Offset << ", " << Width;
1798-
}
17991794
O << ')';
18001795
}
18011796

llvm/lib/Target/AMDGPU/SIDefines.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -549,33 +549,12 @@ enum Id { // HwRegCode, (6) [5:0]
549549
ID_SQ_PERF_SNAPSHOT_DATA1 = 22,
550550
ID_SQ_PERF_SNAPSHOT_PC_LO = 23,
551551
ID_SQ_PERF_SNAPSHOT_PC_HI = 24,
552-
553-
ID_SHIFT_ = 0,
554-
ID_WIDTH_ = 6,
555-
ID_MASK_ = (((1 << ID_WIDTH_) - 1) << ID_SHIFT_)
556552
};
557553

558554
enum Offset : unsigned { // Offset, (5) [10:6]
559-
OFFSET_DEFAULT_ = 0,
560-
OFFSET_SHIFT_ = 6,
561-
OFFSET_WIDTH_ = 5,
562-
OFFSET_MASK_ = (((1 << OFFSET_WIDTH_) - 1) << OFFSET_SHIFT_),
563-
564555
OFFSET_MEM_VIOL = 8,
565556
};
566557

567-
enum WidthMinusOne : unsigned { // WidthMinusOne, (5) [15:11]
568-
WIDTH_M1_DEFAULT_ = 31,
569-
WIDTH_M1_SHIFT_ = 11,
570-
WIDTH_M1_WIDTH_ = 5,
571-
WIDTH_M1_MASK_ = (((1 << WIDTH_M1_WIDTH_) - 1) << WIDTH_M1_SHIFT_),
572-
};
573-
574-
// Some values from WidthMinusOne mapped into Width domain.
575-
enum Width : unsigned {
576-
WIDTH_DEFAULT_ = WIDTH_M1_DEFAULT_ + 1,
577-
};
578-
579558
enum ModeRegisterMasks : uint32_t {
580559
FP_ROUND_MASK = 0xf << 0, // Bits 0..3
581560
FP_DENORM_MASK = 0xf << 4, // Bits 4..7

llvm/lib/Target/AMDGPU/SIFrameLowering.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -478,14 +478,13 @@ void SIFrameLowering::emitEntryFunctionFlatScratchInit(
478478
.addImm(0);
479479
Addc->getOperand(3).setIsDead(); // Mark SCC as dead.
480480

481-
BuildMI(MBB, I, DL, TII->get(AMDGPU::S_SETREG_B32)).
482-
addReg(FlatScrInitLo).
483-
addImm(int16_t(AMDGPU::Hwreg::ID_FLAT_SCR_LO |
484-
(31 << AMDGPU::Hwreg::WIDTH_M1_SHIFT_)));
485-
BuildMI(MBB, I, DL, TII->get(AMDGPU::S_SETREG_B32)).
486-
addReg(FlatScrInitHi).
487-
addImm(int16_t(AMDGPU::Hwreg::ID_FLAT_SCR_HI |
488-
(31 << AMDGPU::Hwreg::WIDTH_M1_SHIFT_)));
481+
using namespace AMDGPU::Hwreg;
482+
BuildMI(MBB, I, DL, TII->get(AMDGPU::S_SETREG_B32))
483+
.addReg(FlatScrInitLo)
484+
.addImm(int16_t(HwregEncoding::encode(ID_FLAT_SCR_LO, 0, 32)));
485+
BuildMI(MBB, I, DL, TII->get(AMDGPU::S_SETREG_B32))
486+
.addReg(FlatScrInitHi)
487+
.addImm(int16_t(HwregEncoding::encode(ID_FLAT_SCR_HI, 0, 32)));
489488
return;
490489
}
491490

llvm/lib/Target/AMDGPU/SIISelLowering.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3960,7 +3960,7 @@ SDValue SITargetLowering::lowerGET_ROUNDING(SDValue Op,
39603960
assert(Op.getValueType() == MVT::i32);
39613961

39623962
uint32_t BothRoundHwReg =
3963-
AMDGPU::Hwreg::encodeHwreg(AMDGPU::Hwreg::ID_MODE, 0, 4);
3963+
AMDGPU::Hwreg::HwregEncoding::encode(AMDGPU::Hwreg::ID_MODE, 0, 4);
39643964
SDValue GetRoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
39653965

39663966
SDValue IntrinID =
@@ -4195,8 +4195,8 @@ SITargetLowering::emitGWSMemViolTestLoop(MachineInstr &MI,
41954195

41964196
MachineBasicBlock::iterator I = LoopBB->end();
41974197

4198-
const unsigned EncodedReg = AMDGPU::Hwreg::encodeHwreg(
4199-
AMDGPU::Hwreg::ID_TRAPSTS, AMDGPU::Hwreg::OFFSET_MEM_VIOL, 1);
4198+
const unsigned EncodedReg = AMDGPU::Hwreg::HwregEncoding::encode(
4199+
AMDGPU::Hwreg::ID_TRAPSTS, AMDGPU::Hwreg::OFFSET_MEM_VIOL, 1);
42004200

42014201
// Clear TRAP_STS.MEM_VIOL
42024202
BuildMI(*LoopBB, LoopBB->begin(), DL, TII->get(AMDGPU::S_SETREG_IMM32_B32))
@@ -4999,18 +4999,16 @@ MachineBasicBlock *SITargetLowering::EmitInstrWithCustomInserter(
49994999
// Otherwise there was overflow and the result is hi2:0. In both cases the
50005000
// result should represent the actual time at some point during the sequence
50015001
// of three getregs.
5002+
using namespace AMDGPU::Hwreg;
50025003
Register RegHi1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
50035004
BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi1)
5004-
.addImm(AMDGPU::Hwreg::encodeHwreg(AMDGPU::Hwreg::ID_SHADER_CYCLES_HI,
5005-
0, 32));
5005+
.addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
50065006
Register RegLo1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
50075007
BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegLo1)
5008-
.addImm(
5009-
AMDGPU::Hwreg::encodeHwreg(AMDGPU::Hwreg::ID_SHADER_CYCLES, 0, 32));
5008+
.addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
50105009
Register RegHi2 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
50115010
BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi2)
5012-
.addImm(AMDGPU::Hwreg::encodeHwreg(AMDGPU::Hwreg::ID_SHADER_CYCLES_HI,
5013-
0, 32));
5011+
.addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
50145012
BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CMP_EQ_U32))
50155013
.addReg(RegHi1)
50165014
.addReg(RegHi2);
@@ -5207,8 +5205,8 @@ MachineBasicBlock *SITargetLowering::EmitInstrWithCustomInserter(
52075205
// FIXME: This could be predicates on the immediate, but tablegen doesn't
52085206
// allow you to have a no side effect instruction in the output of a
52095207
// sideeffecting pattern.
5210-
unsigned ID, Offset, Width;
5211-
AMDGPU::Hwreg::decodeHwreg(MI.getOperand(1).getImm(), ID, Offset, Width);
5208+
auto [ID, Offset, Width] =
5209+
AMDGPU::Hwreg::HwregEncoding::decode(MI.getOperand(1).getImm());
52125210
if (ID != AMDGPU::Hwreg::ID_MODE)
52135211
return BB;
52145212

@@ -10495,9 +10493,8 @@ SDValue SITargetLowering::LowerFDIV32(SDValue Op, SelectionDAG &DAG) const {
1049510493
SDValue NegDivScale0 = DAG.getNode(ISD::FNEG, SL, MVT::f32,
1049610494
DenominatorScaled, Flags);
1049710495

10498-
const unsigned Denorm32Reg = AMDGPU::Hwreg::ID_MODE |
10499-
(4 << AMDGPU::Hwreg::OFFSET_SHIFT_) |
10500-
(1 << AMDGPU::Hwreg::WIDTH_M1_SHIFT_);
10496+
using namespace AMDGPU::Hwreg;
10497+
const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
1050110498
const SDValue BitField = DAG.getTargetConstant(Denorm32Reg, SL, MVT::i32);
1050210499

1050310500
const MachineFunction &MF = DAG.getMachineFunction();

llvm/lib/Target/AMDGPU/SIModeRegister.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,10 @@ void SIModeRegister::insertSetreg(MachineBasicBlock &MBB, MachineInstr *MI,
225225
unsigned Offset = llvm::countr_zero<unsigned>(InstrMode.Mask);
226226
unsigned Width = llvm::countr_one<unsigned>(InstrMode.Mask >> Offset);
227227
unsigned Value = (InstrMode.Mode >> Offset) & ((1 << Width) - 1);
228+
using namespace AMDGPU::Hwreg;
228229
BuildMI(MBB, MI, nullptr, TII->get(AMDGPU::S_SETREG_IMM32_B32))
229230
.addImm(Value)
230-
.addImm(((Width - 1) << AMDGPU::Hwreg::WIDTH_M1_SHIFT_) |
231-
(Offset << AMDGPU::Hwreg::OFFSET_SHIFT_) |
232-
(AMDGPU::Hwreg::ID_MODE << AMDGPU::Hwreg::ID_SHIFT_));
231+
.addImm(HwregEncoding::encode(ID_MODE, Offset, Width));
233232
++NumSetregInserted;
234233
Changed = true;
235234
InstrMode.Mask &= ~(((1 << Width) - 1) << Offset);
@@ -276,15 +275,11 @@ void SIModeRegister::processBlockPhase1(MachineBasicBlock &MBB,
276275
// as we assume it has been inserted by a higher authority (this is
277276
// likely to be a very rare occurrence).
278277
unsigned Dst = TII->getNamedOperand(MI, AMDGPU::OpName::simm16)->getImm();
279-
if (((Dst & AMDGPU::Hwreg::ID_MASK_) >> AMDGPU::Hwreg::ID_SHIFT_) !=
280-
AMDGPU::Hwreg::ID_MODE)
278+
using namespace AMDGPU::Hwreg;
279+
auto [Id, Offset, Width] = HwregEncoding::decode(Dst);
280+
if (Id != ID_MODE)
281281
continue;
282282

283-
unsigned Width = ((Dst & AMDGPU::Hwreg::WIDTH_M1_MASK_) >>
284-
AMDGPU::Hwreg::WIDTH_M1_SHIFT_) +
285-
1;
286-
unsigned Offset =
287-
(Dst & AMDGPU::Hwreg::OFFSET_MASK_) >> AMDGPU::Hwreg::OFFSET_SHIFT_;
288283
unsigned Mask = maskTrailingOnes<unsigned>(Width) << Offset;
289284

290285
// If an InsertionPoint is set we will insert a setreg there.

llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,35 +1698,21 @@ int64_t getHwregId(const StringRef Name, const MCSubtargetInfo &STI) {
16981698
return (Idx < 0) ? Idx : Opr[Idx].Encoding;
16991699
}
17001700

1701-
bool isValidHwreg(int64_t Id) {
1702-
return 0 <= Id && isUInt<ID_WIDTH_>(Id);
1703-
}
1701+
bool isValidHwreg(int64_t Id) { return 0 <= Id && isUInt<HwregId::Width>(Id); }
17041702

17051703
bool isValidHwregOffset(int64_t Offset) {
1706-
return 0 <= Offset && isUInt<OFFSET_WIDTH_>(Offset);
1704+
return 0 <= Offset && isUInt<HwregOffset::Width>(Offset);
17071705
}
17081706

17091707
bool isValidHwregWidth(int64_t Width) {
1710-
return 0 <= (Width - 1) && isUInt<WIDTH_M1_WIDTH_>(Width - 1);
1711-
}
1712-
1713-
uint64_t encodeHwreg(uint64_t Id, uint64_t Offset, uint64_t Width) {
1714-
return (Id << ID_SHIFT_) |
1715-
(Offset << OFFSET_SHIFT_) |
1716-
((Width - 1) << WIDTH_M1_SHIFT_);
1708+
return 0 <= (Width - 1) && isUInt<HwregSize::Width>(Width - 1);
17171709
}
17181710

17191711
StringRef getHwreg(unsigned Id, const MCSubtargetInfo &STI) {
17201712
int Idx = getOprIdx<const MCSubtargetInfo &>(Id, Opr, OPR_SIZE, STI);
17211713
return (Idx < 0) ? "" : Opr[Idx].Name;
17221714
}
17231715

1724-
void decodeHwreg(unsigned Val, unsigned &Id, unsigned &Offset, unsigned &Width) {
1725-
Id = (Val & ID_MASK_) >> ID_SHIFT_;
1726-
Offset = (Val & OFFSET_MASK_) >> OFFSET_SHIFT_;
1727-
Width = ((Val & WIDTH_M1_MASK_) >> WIDTH_M1_SHIFT_) + 1;
1728-
}
1729-
17301716
} // namespace Hwreg
17311717

17321718
//===----------------------------------------------------------------------===//

llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,35 @@ getNumVGPRBlocks(const MCSubtargetInfo *STI, unsigned NumSGPRs,
322322

323323
} // end namespace IsaInfo
324324

325+
// Represents a field in an encoded value.
326+
template <unsigned HighBit, unsigned LowBit, unsigned D = 0>
327+
struct EncodingField {
328+
static_assert(HighBit >= LowBit, "Invalid bit range!");
329+
static constexpr unsigned Offset = LowBit;
330+
static constexpr unsigned Width = HighBit - LowBit + 1;
331+
332+
using ValueType = unsigned;
333+
static constexpr ValueType Default = D;
334+
335+
ValueType Value;
336+
constexpr EncodingField(ValueType Value) : Value(Value) {}
337+
338+
constexpr uint64_t encode() const { return Value; }
339+
static ValueType decode(uint64_t Encoded) { return Encoded; }
340+
};
341+
342+
// A helper for encoding and decoding multiple fields.
343+
template <typename... Fields> struct EncodingFields {
344+
static constexpr uint64_t encode(Fields... Values) {
345+
return ((Values.encode() << Values.Offset) | ...);
346+
}
347+
348+
static std::tuple<typename Fields::ValueType...> decode(uint64_t Encoded) {
349+
return {Fields::decode((Encoded >> Fields::Offset) &
350+
maxUIntN(Fields::Width))...};
351+
}
352+
};
353+
325354
LLVM_READONLY
326355
int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx);
327356

@@ -1021,6 +1050,17 @@ unsigned encodeStorecntDscnt(const IsaVersion &Version, const Waitcnt &Decoded);
10211050

10221051
namespace Hwreg {
10231052

1053+
using HwregId = EncodingField<5, 0>;
1054+
using HwregOffset = EncodingField<10, 6>;
1055+
1056+
struct HwregSize : EncodingField<15, 11, 32> {
1057+
using EncodingField::EncodingField;
1058+
constexpr uint64_t encode() const { return Value - 1; }
1059+
static ValueType decode(uint64_t Encoded) { return Encoded + 1; }
1060+
};
1061+
1062+
using HwregEncoding = EncodingFields<HwregId, HwregOffset, HwregSize>;
1063+
10241064
LLVM_READONLY
10251065
int64_t getHwregId(const StringRef Name, const MCSubtargetInfo &STI);
10261066

@@ -1033,14 +1073,9 @@ bool isValidHwregOffset(int64_t Offset);
10331073
LLVM_READNONE
10341074
bool isValidHwregWidth(int64_t Width);
10351075

1036-
LLVM_READNONE
1037-
uint64_t encodeHwreg(uint64_t Id, uint64_t Offset, uint64_t Width);
1038-
10391076
LLVM_READNONE
10401077
StringRef getHwreg(unsigned Id, const MCSubtargetInfo &STI);
10411078

1042-
void decodeHwreg(unsigned Val, unsigned &Id, unsigned &Offset, unsigned &Width);
1043-
10441079
} // namespace Hwreg
10451080

10461081
namespace DepCtr {

0 commit comments

Comments
 (0)