Files
intel-graphics-compiler/visa/SpillCode.cpp
DianaChen f0962ad863 IGA: Clean-up gcc warnings
Clean-up gcc warnings, such as
-Werror=misleading-indentation
-Werror=catch-value
-Werror=class-memaccess
-Werror=unused-variable
-Werror=unused-but-set-variable
2025-07-01 18:23:24 +02:00

720 lines
24 KiB
C++

/*========================== begin_copyright_notice ============================
Copyright (C) 2017-2021 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#include "SpillCode.h"
#include "BuildIR.h"
#include "FlowGraph.h"
#include "PointsToAnalysis.h"
#include <vector>
#ifdef _DEBUG
#define _DEBUG_SPILL
#endif
using namespace vISA;
void splice(G4_BB *bb, INST_LIST_ITER iter, INST_LIST &instList,
unsigned int CISAOff);
//
// create a declare to hold the spill value of var
//
G4_Declare *SpillManager::createNewSpillLocDeclare(G4_Declare *dcl) {
if (dcl->getRegFile() == G4_FLAG) {
vISA_ASSERT(dcl->getElemType() == Type_UW || dcl->getElemType() == Type_W,
"flag reg's type should be UW");
vISA_ASSERT(dcl->getNumElems() <= builder.getNumFlagRegisters(),
"Flag reg Spill size exceeds limit");
} else if (dcl->getRegFile() == G4_ADDRESS) {
// if we are dealing with type other than UW, e.g., B, then we need to
// take care different data type reg moves of spill code. For now, just
// assume data types of addr reg are UW
//
[[maybe_unused]] G4_Type type = dcl->getElemType();
vISA_ASSERT(type == Type_UW || type == Type_W || type == Type_UD ||
type == Type_D,
"addr reg's type should be UW or UD");
vISA_ASSERT(dcl->getNumElems() <= builder.getNumAddrRegisters(),
"Addr reg Spill size exceeds limit");
}
G4_Declare *sp = dcl->getSpilledDeclare();
if (sp == NULL) // not yet created
{
sp = builder.createAddrFlagSpillLoc(dcl);
gra.setBBId(sp, bbId);
}
return sp;
}
//
// replicate dcl for temporary use (loading value from SPILL location)
//
G4_Declare *SpillManager::createNewTempAddrDeclare(G4_Declare *dcl) {
const char *name = builder.getNameString(16, "Temp_ADDR_%d", tempDclId++);
vISA_ASSERT(dcl->getElemType() == Type_UW || dcl->getElemType() == Type_W,
"addr reg's type should be UW");
vISA_ASSERT(dcl->getNumRows() == 1, "Temp_ADDR should be only 1 row");
vISA_ASSERT(dcl->getNumElems() <= builder.getNumAddrRegisters(),
"Temp_ADDR element number exceeds maximum value");
G4_Declare *sp = builder.createDeclare(name, G4_ADDRESS, dcl->getNumElems(),
1, // 1 row
Type_UW);
gra.setBBId(sp, bbId);
// Live range of new temp addrs is short so that there is no point spilling
// them. indicate this is for newly created addr temp so that RA won't spill
// it in subsequent RA allocation
gra.addAddrFlagSpillDcl(sp);
return sp;
}
G4_Declare *SpillManager::createNewTempFlagDeclare(G4_Declare *dcl) {
const char *name = builder.getNameString(32, "Temp_FSPILL_%d", tempDclId++);
vISA_ASSERT(dcl->getRegFile() == G4_FLAG, "dcl should be a flag");
G4_Declare *sp = builder.createFlag(dcl->getNumberFlagElements(), name);
gra.setBBId(sp, bbId);
sp->copyAlign(dcl);
gra.copyAlignment(sp, dcl);
gra.addAddrFlagSpillDcl(sp);
return sp;
}
//
// replicate dcl for temporary use (loading value from SPILL location)
//
G4_Declare *SpillManager::createNewTempAddrDeclare(G4_Declare *dcl,
uint16_t num_reg) {
const char *name = builder.getNameString(16, "Temp_ADDR_%d", tempDclId++);
G4_Type type = dcl->getElemType();
vISA_ASSERT(type == Type_UW || type == Type_W || type == Type_UD ||
type == Type_D,
"addr reg's type should be UW or UD");
vISA_ASSERT(dcl->getNumRows() == 1, "Temp_ADDR should be only 1 row");
vISA_ASSERT(dcl->getNumElems() <= builder.getNumAddrRegisters(),
"Temp_ADDR exceeds 16 bytes");
G4_Declare *sp = builder.createDeclare(name, G4_ADDRESS, num_reg,
1, // 1 row
type);
gra.setBBId(sp, bbId);
// Live range of new temp addrs is short so that there is no point spilling
// them. indicate this is for newly created addr temp so that RA won't spill
// it in subsequent RA allocation
gra.addAddrFlagSpillDcl(sp);
return sp;
}
G4_Declare *SpillManager::createNewTempScalarDeclare(G4_Declare *dcl) {
const char *name = builder.getNameString(32, "Temp_SCALAR_%d", tempDclId++);
G4_Declare *sp =
builder.createDeclare(name, G4_SCALAR, 1, 1, dcl->getElemType());
gra.setBBId(sp, bbId);
sp->copyAlign(dcl);
auto subAlign = Get_G4_SubRegAlign_From_Size((uint16_t)dcl->getElemSize(),
builder.getPlatform(),
builder.getGRFAlign());
sp->setSubRegAlign(subAlign);
gra.addAddrFlagSpillDcl(sp);
return sp;
}
//
// generate a reg to reg mov inst for addr/flag spill
// mov dst(dRegOff,dSubRegOff)<1> src(sRegOff,sSubRegOff)<nRegs;nRegs,1>
//
void SpillManager::genRegMov(G4_BB *bb, INST_LIST_ITER it, G4_VarBase *src,
unsigned short sSubRegOff, G4_VarBase *dst,
unsigned nRegs, bool useNoMask = true) {
builder.instList.clear();
uint16_t dSubRegOff = 0;
for (uint16_t i = builder.getNumAddrRegisters(); i != 0 && nRegs != 0;
i >>= 1) // 16, 8, 4, 2, 1
{
if (nRegs >= i) {
//
// create loc(0,locOff)<nRegs;nRegs,1> operand
//
/*
Flag registers should always be scalar regions
*/
G4_Type type = Type_W;
const RegionDesc *srcRgn = NULL;
G4_ExecSize execSize{i};
if (src->isFlag() || dst->isFlag()) {
type = Type_UW;
if (i == 2) {
type = Type_UD;
execSize = g4::SIMD1;
} else if (i > 2) {
vISA_ASSERT(false, "unsupported flag width");
}
srcRgn = builder.getRegionScalar();
} else {
srcRgn =
(i == 1) ? builder.getRegionScalar() : builder.getRegionStride1();
}
G4_SrcRegRegion *s = builder.createSrc(src, 0, sSubRegOff, srcRgn, type);
//
// create a0.aOff<1>
//
G4_DstRegRegion *d = builder.createDst(dst, 0, dSubRegOff, 1, type);
if (execSize != kernel.getSimdSize()) {
// NoMask must be used in this case
useNoMask = true;
}
// mov (nRegs) a0.aOff<1> loc(0,locOff)<4;4,1>
builder.createMov(execSize, d, s,
useNoMask ? InstOpt_WriteEnable : InstOpt_NoOpt, true);
sSubRegOff += i;
dSubRegOff += i;
nRegs -= i;
}
}
vISA_ASSERT(nRegs == 0, ERROR_SPILLCODE);
if (gra.EUFusionNoMaskWANeeded()) {
for (auto inst : builder.instList) {
if (inst->isWriteEnableInst()) {
gra.addEUFusionNoMaskWAInst(bb, inst);
}
}
}
//
// insert newly created insts from builder to instList
//
splice(bb, it, builder.instList, currCISAOffset);
}
//
// check if dst is spilled & insert spill code
//
void SpillManager::replaceSpilledDst(
G4_BB *bb,
INST_LIST_ITER it, // where new insts will be inserted
G4_INST *inst, std::vector<G4_Operand *> &operands_analyzed,
std::vector<G4_Declare *> &declares_created) {
G4_DstRegRegion *dst = inst->getDst();
if (dst == NULL)
return;
if (dst->getBase()->isRegAllocPartaker() &&
dst->getBase()->asRegVar()->getDeclare()->getSpilledDeclare() !=
NULL) // spilled base
{
// create a dst region with spill loc
// original dst region V100_uw(0,0)<1>:uw ==>
// new dst region SP_uw(0,0)<1>:uw
G4_Declare *spDcl =
dst->getBase()->asRegVar()->getDeclare()->getSpilledDeclare();
if (dst->getRegAccess() == Direct) {
G4_DstRegRegion rgn(builder, *dst,
spDcl->getRegVar()); // using spDcl as new base
if (rgn.getHorzStride() == UNDEFINED_SHORT && dst->isFlag()) {
// Flag as destination has undefined hstride
// For replacing it with spill range, make hstride 1
rgn.setHorzStride(1);
}
G4_DstRegRegion *d = builder.createDstRegRegion(rgn);
inst->setDest(d);
} else if (dst->getRegAccess() == IndirGRF) {
// add (1) r[V100_uw(0,0),0]<1>:f V124_f(0,0)<0;1,0>:f 1
// indirect access' base must be addr reg so we need to create a temp addr
// live range to load value from V100's spill loc e.g., mov (1)
// T_uw(0,0)<1>:uw SPILL_LOC_V100_uw(0,0)<0;1,0>:uw
// add (1) r[T_uw(0,0),0]<1>:f V124_f(0,0)<0;1,0>:f 1
//
// create declare for temp addr live range
//
G4_Declare *tmpDcl = NULL;
bool match_found = false;
for (unsigned int j = 0, je = operands_analyzed.size(); j < je; j++) {
G4_SrcRegRegion *analyzed_src =
static_cast<G4_SrcRegRegion *>(operands_analyzed[j]);
if (analyzed_src != NULL &&
analyzed_src->getBase()->asRegVar()->getDeclare() ==
dst->getBase()->asRegVar()->getDeclare() &&
analyzed_src->getSubRegOff() == dst->getSubRegOff() &&
!analyzed_src->getRegion()->isRegionWH()) {
tmpDcl = declares_created[j];
match_found = true;
}
}
if (!match_found) {
tmpDcl = createNewTempAddrDeclare(spDcl);
//
// generate mov Tmp(0,0)<1> SPILL_LOC_V100(0,0)
//
genRegMov(bb, it, spDcl->getRegVar(), 0, tmpDcl->getRegVar(),
tmpDcl->getNumElems());
}
G4_DstRegRegion rgn(builder, *dst,
tmpDcl->getRegVar()); // using tmpDcl as new base
G4_DstRegRegion *d = match_found
? builder.createDstWithNewSubRegOff(&rgn, 0)
: builder.createDstRegRegion(rgn);
inst->setDest(d);
if (!match_found) {
pointsToAnalysis.insertAndMergeFilledAddr(dst->getBase()->asRegVar(),
tmpDcl->getRegVar());
}
} else
vISA_ASSERT(false, "Unknown reg access");
}
}
//
// check if src is spilled and insert spill code to load spilled value
//
void SpillManager::replaceSpilledSrc(
G4_BB *bb,
INST_LIST_ITER it, // where new insts will be inserted
G4_INST *inst, unsigned i, std::vector<G4_Operand *> &operands_analyzed,
std::vector<G4_Declare *> &declares_created) {
G4_Operand *src = inst->getSrc(i);
if (src == NULL)
return;
//
// go ahead replace src (addr reg) with spill GRF
//
if (src->isSrcRegRegion() &&
src->asSrcRegRegion()->getBase()->isRegAllocPartaker() &&
src->asSrcRegRegion()
->getBase()
->asRegVar()
->getDeclare()
->getSpilledDeclare() != NULL) // spilled base
{
// create a src region with spill loc
// original src region V100_uw(0,0)<0;1,0>:uw
// new src region SP_uw(0,0)<0;1,0>:uw
G4_SrcRegRegion *ss = src->asSrcRegRegion();
G4_Declare *srcDcl = ss->getBase()->asRegVar()->getDeclare();
G4_Declare *spDcl = srcDcl->getSpilledDeclare();
if (ss->getRegAccess() == Direct) {
G4_SrcRegRegion *s;
if (inst->isSplitSend() && i == 3) {
G4_Declare *tmpDcl = createNewTempAddrDeclare(spDcl, 1);
tmpDcl->setSubRegAlign(Four_Word);
gra.setSubRegAlign(tmpDcl, Four_Word);
// (W) mov (1) tmpDcl<1>:ud spDcl<0;1,0>:ud
auto movSrc =
builder.createSrcRegRegion(spDcl, builder.getRegionScalar());
auto movDst = builder.createDstRegRegion(tmpDcl, 1);
G4_INST *movInst = builder.createMov(g4::SIMD1, movDst, movSrc,
InstOpt_WriteEnable, false);
bb->insertBefore(it, movInst);
if (gra.EUFusionNoMaskWANeeded()) {
gra.addEUFusionNoMaskWAInst(bb, movInst);
}
s = builder.createSrc(tmpDcl->getRegVar(), 0, 0, ss->getRegion(),
spDcl->getElemType());
inst->setSrc(s, i);
} else {
s = builder.createSrcWithNewBase(
ss, spDcl->getRegVar()); // using spDcl as new base
}
inst->setSrc(s, i);
} else if (ss->getRegAccess() == IndirGRF) {
// add (2) V124_f(0,0)<1>:f r[V100_uw(0,0),0]<4;2,2>:f 1
// indirect access' base must be addr reg so we need to create a temp addr
// live range to load value from V100's spill loc e.g., mov (1)
// T(0,0)<1>:uw SPILL_LOC_V100_uw(0,0)<0;1,0>:uw
// add (2) V124_f(0,0)<1>:f r[T(0,0),0]<4;2,2>:f 1
//
// create declare for temp addr live range
//
uint16_t num_reg = 1;
// if access is VxH copy number of addresses based on execution size of
// instruction
if (ss->getRegion()->isRegionWH()) {
num_reg = inst->getExecSize();
}
G4_Declare *tmpDcl = NULL;
bool match_found = false;
for (unsigned int j = 0; j < i; j++) {
G4_SrcRegRegion *analyzed_src = (G4_SrcRegRegion *)operands_analyzed[j];
if (analyzed_src != NULL &&
analyzed_src->getBase()->asRegVar()->getDeclare() ==
ss->getBase()->asRegVar()->getDeclare() &&
analyzed_src->getSubRegOff() == ss->getSubRegOff()) {
tmpDcl = declares_created[j];
match_found = true;
}
}
if (!match_found) {
tmpDcl = createNewTempAddrDeclare(spDcl, num_reg);
operands_analyzed[i] = ss;
declares_created[i] = tmpDcl;
bool isNoMask = (inst->getOption() & InstOpt_WriteEnable) != 0;
//
// generate mov Tmp(0,0)<1> SPILL_LOC_V100(0,0)
//
genRegMov(bb, it, spDcl->getRegVar(), ss->getSubRegOff(),
tmpDcl->getRegVar(), tmpDcl->getNumElems(),
isNoMask);
auto pseudoKill =
builder.createPseudoKill(tmpDcl, PseudoKillType::Other, false);
bb->insertBefore(std::prev(it), pseudoKill);
}
// create new src from the temp address variable, with offset 0
auto s = builder.createIndirectSrc(ss->getModifier(), tmpDcl->getRegVar(),
ss->getRegOff(), 0, ss->getRegion(),
ss->getType(), ss->getAddrImm());
inst->setSrc(s, i);
if (!match_found) {
pointsToAnalysis.insertAndMergeFilledAddr(ss->getBase()->asRegVar(),
tmpDcl->getRegVar());
}
} else
vISA_ASSERT(false, "Unknown reg access");
}
}
//
// check if predicate is spilled & insert fill code
//
void SpillManager::replaceSpilledPredicate(
G4_BB *bb,
INST_LIST_ITER it, // where new insts will be inserted
G4_INST *inst) {
G4_Predicate *predicate = inst->getPredicate();
if (predicate == NULL)
return;
G4_VarBase *flagReg = predicate->getBase();
if (flagReg->asRegVar()->isRegAllocPartaker()) {
G4_Declare *flagDcl = flagReg->asRegVar()->getDeclare();
G4_Declare *spDcl = flagDcl->getSpilledDeclare();
if (spDcl != NULL) {
G4_Declare *tmpDcl = createNewTempFlagDeclare(flagDcl);
genRegMov(bb, it, spDcl->getRegVar(), 0, tmpDcl->getRegVar(),
tmpDcl->getNumElems());
G4_Predicate *new_pred =
builder.createPredicate(predicate->getState(), tmpDcl->getRegVar(), 0,
predicate->getControl());
inst->setPredicate(new_pred);
++numFlagSpillLoad;
}
}
}
bool SpillManager::checkDefUseDomRel(G4_Operand *dst, G4_BB *defBB) {
auto dcl = dst->getTopDcl();
// check whether this def dominates all its uses
auto uses = refs.getUses(dcl);
for (auto &use : *uses) {
auto useBB = std::get<1>(use);
// check if def dominates use
if (!defBB->dominates(useBB))
return false;
if (defBB == useBB) {
// defBB dominates useBB since its the same BB.
// ensure def instruction appears lexically before use BB.
auto useInst = std::get<0>(use);
if (dst->getInst()->getLexicalId() > useInst->getLexicalId())
return false;
}
}
// if def is in loop then ensure all uses are in same loop level
// or inner loop nest of def's closest loop.
auto defLoop = gra.kernel.fg.getLoops().getInnerMostLoop(defBB);
if (defLoop) {
// since def is in loop, check whether uses are also in same loop.
for (auto &use : *uses) {
auto useBB = std::get<1>(use);
auto useLoop = gra.kernel.fg.getLoops().getInnerMostLoop(useBB);
if (!useLoop)
return false;
if (!useLoop->fullSubset(defLoop))
return false;
}
}
return true;
}
bool SpillManager::isDominatingDef(G4_Operand *opnd, G4_BB *bb) {
// return true if this opnd is dominates all other defs
auto dcl = opnd->getTopDcl();
auto defs = refs.getDefs(dcl);
for (auto &def : *defs) {
auto otherDefBB = std::get<1>(def);
if (!bb->dominates(otherDefBB))
return false;
if (bb == otherDefBB) {
auto otherDefInst = std::get<0>(def);
if (opnd->getInst()->getLexicalId() > otherDefInst->getLexicalId())
return false;
}
}
return true;
}
// update RMW information for flag operands
void SpillManager::updateRMWNeeded() {
if (!gra.kernel.getOption(vISA_SkipRedundantFillInRMW))
return;
auto isRMWNeededForSpill = [&](G4_BB *bb, G4_Operand *spilledRegion) {
bool isUniqueDef = (refs.getDefCount(spilledRegion->getTopDcl()) < 2);
// Check0 : Def is NoMask, -- checked before inserting RMW fill already
// Check1 : Def is unique def OR def is dominating all other defs,
// Check2 : Def is in loop L and all use(s) of dcl are in loop L or it's
// inner loop nest Check3 : Flowgraph is reducible RMW_Not_Needed = Check0
// || (Check1 && Check2 && Check3)
bool RMW_Needed = true;
if ((isUniqueDef || isDominatingDef(spilledRegion, bb)) &&
kernel.fg.isReducible() && checkDefUseDomRel(spilledRegion, bb)) {
RMW_Needed = false;
}
return RMW_Needed;
};
auto isOpndSpilled = [&](G4_Operand *opnd) {
auto base = opnd->getBase();
if (base && base->isRegVar() && base->asRegVar()->isRegAllocPartaker()) {
auto dstRegVar = base->asRegVar();
if (dstRegVar && base->asRegVar()->getDeclare()->getSpilledDeclare())
return true;
}
return false;
};
// update rmw set if opnd is spilled, nop if opnd isnt spilled.
auto updateRMW = [&](G4_BB *bb, G4_Operand *opnd) {
auto RMW_Needed = isRMWNeededForSpill(bb, opnd);
if (!RMW_Needed) {
// Any spilled dst region that doesnt need RMW
// is added to noRMWNeeded set. This set is later
// checked when inserting spill/fill code.
noRMWNeeded.insert(opnd);
}
};
// First pass to setup lexical ids of instruction so dominator relation can be
// computed correctly intra-BB.
unsigned int lexId = 0;
for (auto bb : gra.kernel.fg.getBBList()) {
for (auto inst : bb->getInstList()) {
inst->setLexicalId(lexId++);
}
}
for (auto bb : gra.kernel.fg.getBBList()) {
for (auto inst : bb->getInstList()) {
if (inst->isPseudoKill())
continue;
// flags are used only as cond modifiers with non-NoMask
auto condMod = inst->getCondMod();
if (condMod && isOpndSpilled(condMod)) {
updateRMW(bb, condMod);
}
}
}
}
//
// check if flag dst is spilled and insert spill code
//
void SpillManager::replaceSpilledFlagCondMod(
G4_BB *bb,
INST_LIST_ITER it, // where new insts will be inserted
G4_INST *inst) {
G4_CondMod *mod = inst->getCondMod();
if (mod == NULL)
return;
G4_VarBase *flagReg = mod->getBase();
if (flagReg != NULL && flagReg->asRegVar()->isRegAllocPartaker()) {
G4_Declare *flagDcl = flagReg->asRegVar()->getDeclare();
G4_Declare *spDcl = flagDcl->getSpilledDeclare();
if (spDcl != NULL) {
G4_Declare *tmpDcl;
G4_Predicate *predicate = inst->getPredicate();
if (predicate != NULL) {
G4_VarBase *flagReg = predicate->getBase();
tmpDcl = flagReg->asRegVar()->getDeclare();
} else {
tmpDcl = createNewTempFlagDeclare(flagDcl);
}
// Need to pre-load the spill GRF if the inst isn't going to write the
// full spilled GRF variable.
if (flagDcl->getNumberFlagElements() > inst->getExecSize() ||
(!bb->isAllLaneActive() && !inst->isWriteEnableInst())) {
// Conditional modifier must use same flag register as predicate.
// So if conditional modifier needs pre-fill, the prediciate must be
// filled already.
if (noRMWNeeded.find(mod) == noRMWNeeded.end() && predicate == NULL) {
genRegMov(bb, it, spDcl->getRegVar(), 0, tmpDcl->getRegVar(),
tmpDcl->getNumElems());
++numFlagSpillLoad;
} else {
// insert kill for temp flag
auto pseudoKill =
builder.createPseudoKill(tmpDcl, PseudoKillType::Other, false);
bb->insertBefore(it, pseudoKill);
}
}
G4_CondMod *newCondMod =
builder.createCondMod(mod->getMod(), tmpDcl->getRegVar(), 0);
inst->setCondMod(newCondMod);
genRegMov(bb, ++it, tmpDcl->getRegVar(), 0, spDcl->getRegVar(),
tmpDcl->getNumElems());
++numFlagSpillStore;
}
}
}
//
// go over all declares and allocate spill locations
//
void SpillManager::createSpillLocations(const G4_Kernel &kernel) {
// set spill flag to indicate which vars are spilled
for (const LiveRange *lr : spilledLRs) {
G4_Declare *dcl = lr->getVar()->getDeclare();
dcl->setSpillFlag();
vISA_ASSERT(lr->getPhyReg() == NULL,
"Spilled Live Range shouldn't have physical reg");
vISA_ASSERT(lr->getSpillCost() < MAXSPILLCOST,
"ERROR: spill live range with infinite spill cost");
// create spill loc for holding spilled addr regs
createNewSpillLocDeclare(dcl);
}
// take care of alias declares
for (G4_Declare *dcl : kernel.Declares) {
if (!dcl->getRegVar()->isRegAllocPartaker()) // skip non reg alloc candidate
continue;
if (dcl->getAliasDeclare() != NULL && // dcl is not a representative declare
dcl->getAliasDeclare()
->isSpilled()) // dcl's representative decl is spilled
{
G4_Declare *sp = createNewSpillLocDeclare(dcl);
// when doing RA multiple times (due to spill code), we don't want to set
// alias information more than once
if (sp->getAliasDeclare() == NULL) {
sp->setAliasDeclare(dcl->getAliasDeclare()->getSpilledDeclare(),
dcl->getAliasOffset());
}
}
}
}
bool isSpillCandidateForLifetimeOpRemoval(G4_INST *inst) {
if (inst->isPseudoKill()) {
return inst->getDst()->isSpilled();
} else if (inst->isLifeTimeEnd()) {
return inst->getSrc(0)->asSrcRegRegion()->isSpilled();
}
return false;
}
void SpillManager::insertSpillCode() {
//
// create spill locations
//
createSpillLocations(kernel);
updateRMWNeeded();
for (G4_BB *bb : kernel.fg) {
bbId = bb->getId();
//
// handle spill code for the current BB
//
// In one iteration remove all spilled lifetime.start/end
// ops.
bb->erase(std::remove_if(bb->begin(), bb->end(),
isSpillCandidateForLifetimeOpRemoval),
bb->end());
for (INST_LIST_ITER inst_it = bb->begin(); inst_it != bb->end();) {
G4_INST *inst = *inst_it;
currCISAOffset = inst->getVISAId();
const unsigned numSrc = inst->getNumSrc();
std::vector<G4_Operand *> operands_analyzed(numSrc, nullptr);
std::vector<G4_Declare *> declares_created(numSrc, nullptr);
// insert spill inst for spilled srcs
for (unsigned i = 0; i < numSrc; i++) {
replaceSpilledSrc(bb, inst_it, inst, i, operands_analyzed,
declares_created);
}
// insert spill inst for spilled dst
replaceSpilledDst(bb, inst_it, inst, operands_analyzed, declares_created);
//
// Process predicate
//
G4_Predicate *predicate = inst->getPredicate();
if (predicate != NULL) {
replaceSpilledPredicate(bb, inst_it, inst);
}
//
// Process condMod
//
G4_CondMod *mod = inst->getCondMod();
if (mod != NULL && mod->getBase() != NULL) {
replaceSpilledFlagCondMod(bb, inst_it, inst);
}
inst_it++;
}
bbId = UINT_MAX;
}
}