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

View File

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

View File

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

View File

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

View File

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

View File

@ -465,7 +465,7 @@ public:
short getRegForm(const MachineInstr &MI) const; short getRegForm(const MachineInstr &MI) const;
unsigned getSize(const MachineInstr &MI) const; unsigned getSize(const MachineInstr &MI) const;
uint64_t getType(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; MachineBasicBlock::instr_iterator expandVGatherPseudo(MachineInstr &MI) const;

View File

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

View File

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