1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00

[MC] Widen the functional unit type from 32 to 64 bits.

Summary:
The type used to represent functional units in MC is
'unsigned', which is 32 bits wide. This is currently
not a problem in any upstream target as no one seems
to have hit the limit on this yet, but in our
downstream one, we need to define more than 32
functional units.

Increasing the size does not seem to cause a huge
size increase in the binary (an llc debug build went
from 1366497672 to 1366523984, a difference of 26k),
so perhaps it would be acceptable to have this patch
applied upstream as well.

Subscribers: hiraditya, jsji, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D71210
This commit is contained in:
Bevin Hansson 2019-12-09 16:22:57 +01:00
parent 9d9c7e75ed
commit d148a7c68f
8 changed files with 27 additions and 22 deletions

View File

@ -16,6 +16,7 @@
#define LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
#include "llvm/MC/MCInstrItineraries.h"
#include <cassert>
#include <cstddef>
#include <cstring>
@ -37,7 +38,7 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer {
// bottom-up scheduler, then the scoreboard cycles are the inverse of the
// scheduler's cycles.
class Scoreboard {
unsigned *Data = nullptr;
InstrStage::FuncUnits *Data = nullptr;
// The maximum number of cycles monitored by the Scoreboard. This
// value is determined based on the target itineraries to ensure
@ -56,7 +57,7 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer {
size_t getDepth() const { return Depth; }
unsigned& operator[](size_t idx) const {
InstrStage::FuncUnits& operator[](size_t idx) const {
// Depth is expected to be a power-of-2.
assert(Depth && !(Depth & (Depth - 1)) &&
"Scoreboard was not initialized properly!");
@ -67,7 +68,7 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer {
void reset(size_t d = 1) {
if (!Data) {
Depth = d;
Data = new unsigned[Depth];
Data = new InstrStage::FuncUnits[Depth];
}
memset(Data, 0, Depth * sizeof(Data[0]));

View File

@ -61,8 +61,11 @@ struct InstrStage {
Reserved = 1
};
/// Bitmask representing a set of functional units.
typedef uint64_t FuncUnits;
unsigned Cycles_; ///< Length of stage in machine cycles
unsigned Units_; ///< Choice of functional units
FuncUnits Units_; ///< Choice of functional units
int NextCycles_; ///< Number of machine cycles to next stage
ReservationKinds Kind_; ///< Kind of the FU reservation
@ -72,7 +75,7 @@ struct InstrStage {
}
/// Returns the choice of FUs.
unsigned getUnits() const {
FuncUnits getUnits() const {
return Units_;
}

View File

@ -909,7 +909,7 @@ namespace {
struct FuncUnitSorter {
const InstrItineraryData *InstrItins;
const MCSubtargetInfo *STI;
DenseMap<unsigned, unsigned> Resources;
DenseMap<InstrStage::FuncUnits, unsigned> Resources;
FuncUnitSorter(const TargetSubtargetInfo &TSI)
: InstrItins(TSI.getInstrItineraryData()), STI(&TSI) {}
@ -917,14 +917,15 @@ struct FuncUnitSorter {
// Compute the number of functional unit alternatives needed
// at each stage, and take the minimum value. We prioritize the
// instructions by the least number of choices first.
unsigned minFuncUnits(const MachineInstr *Inst, unsigned &F) const {
unsigned minFuncUnits(const MachineInstr *Inst,
InstrStage::FuncUnits &F) const {
unsigned SchedClass = Inst->getDesc().getSchedClass();
unsigned min = UINT_MAX;
if (InstrItins && !InstrItins->isEmpty()) {
for (const InstrStage &IS :
make_range(InstrItins->beginStage(SchedClass),
InstrItins->endStage(SchedClass))) {
unsigned funcUnits = IS.getUnits();
InstrStage::FuncUnits funcUnits = IS.getUnits();
unsigned numAlternatives = countPopulation(funcUnits);
if (numAlternatives < min) {
min = numAlternatives;
@ -970,7 +971,7 @@ struct FuncUnitSorter {
for (const InstrStage &IS :
make_range(InstrItins->beginStage(SchedClass),
InstrItins->endStage(SchedClass))) {
unsigned FuncUnits = IS.getUnits();
InstrStage::FuncUnits FuncUnits = IS.getUnits();
if (countPopulation(FuncUnits) == 1)
Resources[FuncUnits]++;
}
@ -998,7 +999,7 @@ struct FuncUnitSorter {
/// Return true if IS1 has less priority than IS2.
bool operator()(const MachineInstr *IS1, const MachineInstr *IS2) const {
unsigned F1 = 0, F2 = 0;
InstrStage::FuncUnits F1 = 0, F2 = 0;
unsigned MFUs1 = minFuncUnits(IS1, F1);
unsigned MFUs2 = minFuncUnits(IS2, F2);
if (MFUs1 == MFUs2)

View File

@ -92,10 +92,11 @@ LLVM_DUMP_METHOD void ScoreboardHazardRecognizer::Scoreboard::dump() const {
last--;
for (unsigned i = 0; i <= last; i++) {
unsigned FUs = (*this)[i];
InstrStage::FuncUnits FUs = (*this)[i];
dbgs() << "\t";
for (int j = 31; j >= 0; j--)
dbgs() << ((FUs & (1 << j)) ? '1' : '0');
for (int j = std::numeric_limits<InstrStage::FuncUnits>::digits - 1;
j >= 0; j--)
dbgs() << ((FUs & (1ULL << j)) ? '1' : '0');
dbgs() << '\n';
}
}
@ -142,7 +143,7 @@ ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
break;
}
unsigned freeUnits = IS->getUnits();
InstrStage::FuncUnits freeUnits = IS->getUnits();
switch (IS->getReservationKind()) {
case InstrStage::Required:
// Required FUs conflict with both reserved and required ones
@ -193,7 +194,7 @@ void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
"Scoreboard depth exceeded!");
unsigned freeUnits = IS->getUnits();
InstrStage::FuncUnits freeUnits = IS->getUnits();
switch (IS->getReservationKind()) {
case InstrStage::Required:
// Required FUs conflict with both reserved and required ones
@ -206,7 +207,7 @@ void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
}
// reduce to a single unit
unsigned freeUnit = 0;
InstrStage::FuncUnits freeUnit = 0;
do {
freeUnit = freeUnits;
freeUnits = freeUnit & (freeUnit - 1);

View File

@ -4485,7 +4485,7 @@ uint64_t HexagonInstrInfo::getType(const MachineInstr &MI) const {
return (F >> HexagonII::TypePos) & HexagonII::TypeMask;
}
unsigned HexagonInstrInfo::getUnits(const MachineInstr &MI) const {
InstrStage::FuncUnits HexagonInstrInfo::getUnits(const MachineInstr &MI) const {
const InstrItineraryData &II = *Subtarget.getInstrItineraryData();
const InstrStage &IS = *II.beginStage(MI.getDesc().getSchedClass());

View File

@ -465,7 +465,7 @@ public:
short getRegForm(const MachineInstr &MI) const;
unsigned getSize(const MachineInstr &MI) const;
uint64_t getType(const MachineInstr &MI) const;
unsigned getUnits(const MachineInstr &MI) const;
InstrStage::FuncUnits getUnits(const MachineInstr &MI) const;
MachineBasicBlock::instr_iterator expandVGatherPseudo(MachineInstr &MI) const;

View File

@ -1060,8 +1060,7 @@ bool HexagonPacketizerList::ignorePseudoInstruction(const MachineInstr &MI,
// we ignore the instruction.
const MCInstrDesc& TID = MI.getDesc();
auto *IS = ResourceTracker->getInstrItins()->beginStage(TID.getSchedClass());
unsigned FuncUnits = IS->getUnits();
return !FuncUnits;
return !IS->getUnits();
}
bool HexagonPacketizerList::isSoloInstruction(const MachineInstr &MI) {

View File

@ -396,8 +396,8 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
<< "namespace " << Name << "FU {\n";
for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
OS << " const unsigned " << FUs[j]->getName()
<< " = 1 << " << j << ";\n";
OS << " const InstrStage::FuncUnits " << FUs[j]->getName()
<< " = 1ULL << " << j << ";\n";
OS << "} // end namespace " << Name << "FU\n";