2021-06-01 22:15:58 +00:00
|
|
|
/*========================== begin_copyright_notice ============================
|
2020-01-22 22:26:44 -08:00
|
|
|
|
2021-06-01 22:15:58 +00:00
|
|
|
Copyright (C) 2019-2021 Intel Corporation
|
2020-01-22 22:26:44 -08:00
|
|
|
|
2021-06-01 22:15:58 +00:00
|
|
|
SPDX-License-Identifier: MIT
|
2020-01-22 22:26:44 -08:00
|
|
|
|
2021-06-01 22:15:58 +00:00
|
|
|
============================= end_copyright_notice ===========================*/
|
2020-01-22 22:26:44 -08:00
|
|
|
|
|
|
|
|
#ifndef _VARSPLIT_H_
|
|
|
|
|
#define _VARSPLIT_H_
|
|
|
|
|
|
|
|
|
|
#include "BuildIR.h"
|
2022-10-13 22:33:42 +00:00
|
|
|
#include "FlowGraph.h"
|
2021-10-07 08:30:01 +00:00
|
|
|
#include "RPE.h"
|
2020-01-22 22:26:44 -08:00
|
|
|
|
2022-10-13 22:33:42 +00:00
|
|
|
namespace vISA {
|
2020-01-22 22:26:44 -08:00
|
|
|
class LiveRange;
|
2021-10-07 08:30:01 +00:00
|
|
|
class GraphColor;
|
|
|
|
|
class RPE;
|
|
|
|
|
class GlobalRA;
|
|
|
|
|
|
|
|
|
|
// store mapping of a split variable to original variable. if any split
|
|
|
|
|
// variable is spilled, we can reuse spill location of original variable.
|
|
|
|
|
// also store all instructions emitted in preheader, loop exit for each
|
|
|
|
|
// split variable. this helps eliminate those instruction in case the
|
|
|
|
|
// split variable itself spills.
|
2022-10-13 22:33:42 +00:00
|
|
|
class SplitResults {
|
2021-10-07 08:30:01 +00:00
|
|
|
public:
|
2022-10-13 22:33:42 +00:00
|
|
|
G4_Declare *origDcl = nullptr;
|
|
|
|
|
std::unordered_map<G4_BB *, std::unordered_set<G4_INST *>> insts;
|
2021-10-07 08:30:01 +00:00
|
|
|
};
|
|
|
|
|
|
2022-10-13 22:33:42 +00:00
|
|
|
class CComparator {
|
2022-07-01 05:25:06 +00:00
|
|
|
public:
|
2022-10-13 22:33:42 +00:00
|
|
|
bool operator()(const G4_Declare *first, const G4_Declare *second) const {
|
|
|
|
|
return first->getDeclId() < second->getDeclId();
|
|
|
|
|
}
|
2022-07-01 05:25:06 +00:00
|
|
|
};
|
|
|
|
|
|
2022-10-13 22:33:42 +00:00
|
|
|
class LoopVarSplit {
|
2021-10-07 08:30:01 +00:00
|
|
|
public:
|
2022-10-13 22:33:42 +00:00
|
|
|
LoopVarSplit(G4_Kernel &k, GraphColor *c,
|
|
|
|
|
const LivenessAnalysis *liveAnalysis);
|
|
|
|
|
~LoopVarSplit() { delete rpe; }
|
2023-11-30 09:25:24 +00:00
|
|
|
LoopVarSplit(const LoopVarSplit&) = delete;
|
|
|
|
|
LoopVarSplit& operator=(const LoopVarSplit&) = delete;
|
2022-10-13 22:33:42 +00:00
|
|
|
|
|
|
|
|
void run();
|
|
|
|
|
|
|
|
|
|
std::vector<G4_SrcRegRegion *> getReads(G4_Declare *dcl, Loop &loop);
|
|
|
|
|
std::vector<G4_DstRegRegion *> getWrites(G4_Declare *dcl, Loop &loop);
|
|
|
|
|
unsigned int getMaxRegPressureInLoop(Loop &loop);
|
|
|
|
|
void dump(std::ostream &of = std::cerr);
|
|
|
|
|
|
|
|
|
|
static void removeAllSplitInsts(GlobalRA *gra, G4_Declare *dcl);
|
|
|
|
|
static void removeSplitInsts(GlobalRA *gra, G4_Declare *spillDcl, G4_BB *bb);
|
|
|
|
|
static bool removeFromPreheader(GlobalRA *gra, G4_Declare *spillDcl,
|
|
|
|
|
G4_BB *bb, INST_LIST_ITER filledInstIter);
|
|
|
|
|
static bool removeFromLoopExit(GlobalRA *gra, G4_Declare *spillDcl, G4_BB *bb,
|
|
|
|
|
INST_LIST_ITER filledInstIter);
|
|
|
|
|
static const std::unordered_set<G4_INST *> getSplitInsts(GlobalRA *gra,
|
|
|
|
|
G4_BB *bb);
|
2021-10-07 08:30:01 +00:00
|
|
|
|
|
|
|
|
private:
|
2022-10-13 22:33:42 +00:00
|
|
|
const unsigned int cLargeLoop = 500;
|
|
|
|
|
|
|
|
|
|
bool split(G4_Declare *dcl, Loop &loop);
|
|
|
|
|
void copy(G4_BB *bb, G4_Declare *dst, G4_Declare *src,
|
|
|
|
|
SplitResults *splitData, bool isDefault32bMask,
|
2023-12-04 06:29:56 +00:00
|
|
|
bool isDefault64bMask, bool pushBack = true);
|
2022-10-13 22:33:42 +00:00
|
|
|
void replaceSrc(G4_SrcRegRegion *src, G4_Declare *dcl, const Loop &loop);
|
|
|
|
|
void replaceDst(G4_DstRegRegion *dst, G4_Declare *dcl, const Loop &loop);
|
|
|
|
|
G4_Declare *getNewDcl(G4_Declare *dcl1, G4_Declare *dcl2, const Loop &loop);
|
|
|
|
|
std::vector<Loop *> getLoopsToSplitAround(G4_Declare *dcl);
|
|
|
|
|
void adjustLoopMaxPressure(Loop &loop, unsigned int numRows);
|
|
|
|
|
|
|
|
|
|
G4_Kernel &kernel;
|
|
|
|
|
GraphColor *coloring = nullptr;
|
|
|
|
|
RPE *rpe = nullptr;
|
|
|
|
|
VarReferences references;
|
|
|
|
|
|
|
|
|
|
// store set of dcls marked as spill in current RA iteration
|
|
|
|
|
std::unordered_set<G4_Declare *> spilledDclSet;
|
|
|
|
|
|
|
|
|
|
// store spill cost for each dcl
|
|
|
|
|
std::map<G4_Declare *, float, CComparator> dclSpillCost;
|
|
|
|
|
|
|
|
|
|
std::unordered_map<const Loop *,
|
|
|
|
|
std::unordered_map<G4_Declare *, G4_Declare *>>
|
|
|
|
|
oldNewDclPerLoop;
|
|
|
|
|
|
|
|
|
|
std::unordered_map<Loop *, std::unordered_set<G4_Declare *>> splitsPerLoop;
|
|
|
|
|
|
|
|
|
|
std::unordered_map<Loop *, unsigned int> maxRegPressureCache;
|
|
|
|
|
|
|
|
|
|
std::unordered_map<Loop *, unsigned int> scalarBytesSplit;
|
|
|
|
|
|
|
|
|
|
// a spilled dcl may be split multiple times, once per loop
|
|
|
|
|
// store this information to uplevel to GlobalRA class so
|
|
|
|
|
// anytime we spill a split variable, we reuse spill location.
|
|
|
|
|
// Orig dcl, vector<Tmp Dcl, Loop>
|
|
|
|
|
std::unordered_map<G4_Declare *, std::vector<std::pair<G4_Declare *, Loop *>>>
|
|
|
|
|
splitResults;
|
|
|
|
|
|
|
|
|
|
class Size {
|
|
|
|
|
public:
|
|
|
|
|
enum class State {
|
|
|
|
|
Undef = 0,
|
|
|
|
|
Small = 1,
|
|
|
|
|
Large = 2,
|
2022-09-13 11:28:09 +00:00
|
|
|
};
|
2022-10-13 22:33:42 +00:00
|
|
|
State state = State::Undef;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::unordered_map<Loop *, Size> loopSizeCache;
|
|
|
|
|
|
|
|
|
|
bool isLargeLoop(Loop &loop) {
|
|
|
|
|
auto &size = loopSizeCache[&loop];
|
|
|
|
|
if (size.state != Size::State::Undef)
|
|
|
|
|
return size.state == Size::State::Large;
|
|
|
|
|
unsigned int instCount = 0;
|
|
|
|
|
std::for_each(loop.getBBs().begin(), loop.getBBs().end(),
|
|
|
|
|
[&instCount](G4_BB *bb) { instCount += bb->size(); });
|
|
|
|
|
if (instCount > cLargeLoop)
|
|
|
|
|
size.state = Size::State::Large;
|
|
|
|
|
return size.state == Size::State::Large;
|
|
|
|
|
}
|
2021-10-07 08:30:01 +00:00
|
|
|
};
|
2020-01-22 22:26:44 -08:00
|
|
|
|
2022-10-13 22:33:42 +00:00
|
|
|
class VarProperties {
|
2020-01-22 22:26:44 -08:00
|
|
|
public:
|
2022-10-13 22:33:42 +00:00
|
|
|
enum class AccessGranularity { OneGrf = 1, TwoGrf = 2, Unknown = 3 };
|
|
|
|
|
|
|
|
|
|
AccessGranularity ag = AccessGranularity::Unknown;
|
|
|
|
|
unsigned int numDefs = 0;
|
|
|
|
|
std::pair<G4_DstRegRegion *, G4_BB *> def;
|
|
|
|
|
std::vector<std::pair<G4_SrcRegRegion *, G4_BB *>> srcs;
|
|
|
|
|
bool candidateDef = false;
|
|
|
|
|
bool legitCandidate = true;
|
|
|
|
|
|
|
|
|
|
// API to check whether variable is local or global
|
|
|
|
|
bool isDefUsesInSameBB() {
|
|
|
|
|
auto defBB = def.second;
|
|
|
|
|
for (auto src : srcs) {
|
|
|
|
|
if (src.second != defBB)
|
|
|
|
|
return false;
|
2020-04-23 03:38:10 -07:00
|
|
|
}
|
2022-10-13 22:33:42 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2020-04-23 03:38:10 -07:00
|
|
|
|
2022-10-13 22:33:42 +00:00
|
|
|
bool isPartDclUsed(unsigned int lb, unsigned int rb) {
|
|
|
|
|
// Return true if lb/rb is part of any src regions
|
|
|
|
|
for (auto &src : srcs) {
|
|
|
|
|
if (src.first->getLeftBound() >= lb && src.first->getRightBound() <= rb)
|
|
|
|
|
return true;
|
2020-01-22 22:26:44 -08:00
|
|
|
}
|
2022-10-13 22:33:42 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2020-01-22 22:26:44 -08:00
|
|
|
};
|
2022-10-13 22:33:42 +00:00
|
|
|
}; // namespace vISA
|
2020-01-22 22:26:44 -08:00
|
|
|
#endif
|