Commit 89eeca9c authored by Junjie Gu's avatar Junjie Gu Committed by gbsbuild

Added initial code to insert lifetime start to visa to assist visa liveness analysis.

Currently, it is off by default. The initial code only inserts lifetime start for a few
variables. More to come. No Functional change

Change-Id: I054d9311e0ad439704c38884c47e2543624968a2
parent fa39f0d2
......@@ -5284,5 +5284,14 @@ void CEncoder::File(std::string& s)
V(vKernel->AppendVISAMiscFileInst(s.c_str()));
}
void CEncoder::Lifetime(VISAVarLifetime StartOrEnd, CVariable* dst)
{
SModifier noMod; // Default is no mod.
noMod.init();
VISA_VectorOpnd* srcOpnd = GetSourceOperand(dst, noMod);
V(vKernel->AppendVISALifetime(StartOrEnd, srcOpnd));
}
}
......@@ -282,6 +282,7 @@ public:
void AddPair(CVariable *Lo, CVariable *Hi, CVariable *L0, CVariable *H0, CVariable *L1, CVariable *H1);
void SubPair(CVariable *Lo, CVariable *Hi, CVariable *L0, CVariable *H0, CVariable *L1, CVariable *H1);
inline void dp4a(CVariable* dst, CVariable* src0, CVariable* src1, CVariable* src2);
void Lifetime(VISAVarLifetime StartOrEnd, CVariable* dst);
// VME
void SendVmeIme(
CVariable* bindingTableIndex,
......
......@@ -161,6 +161,7 @@ uint EmitPass::DecideInstanceAndSlice(llvm::BasicBlock &blk, SDAG &sdag, bool &s
}
else
{
m_destination = nullptr;
if (StoreInst *ST = dyn_cast<StoreInst>(sdag.m_root))
{
// Limit to OpenCL so far as it has uniform load/store support.
......@@ -418,9 +419,9 @@ bool EmitPass::runOnFunction(llvm::Function &F)
m_currShader->SetCoalescingEngineHelper(m_CE);
}
auto VRA = &getAnalysis<VariableReuseAnalysis>();
m_currShader->SetVariableReuseAnalysis(VRA);
VRA->BeginFunction(&F, numLanes(m_SimdMode));
m_VRA = &getAnalysis<VariableReuseAnalysis>();
m_currShader->SetVariableReuseAnalysis(m_VRA);
m_VRA->BeginFunction(&F, numLanes(m_SimdMode));
if (!m_FGA || m_FGA->isGroupHead(&F))
{
......@@ -478,8 +479,8 @@ bool EmitPass::runOnFunction(llvm::Function &F)
if (i != 0)
{
IF_DEBUG_INFO_IF(m_pDebugEmitter, m_pDebugEmitter->BeginEncodingMark();)
// create a label
m_encoder->Label(block.id);
// create a label
m_encoder->Label(block.id);
m_encoder->Push();
IF_DEBUG_INFO_IF(m_pDebugEmitter, m_pDebugEmitter->EndEncodingMark();)
}
......@@ -490,23 +491,24 @@ bool EmitPass::runOnFunction(llvm::Function &F)
PerLaneOffsetVars.clear();
// Variable reuse per-block states.
VariableReuseAnalysis::EnterBlockRAII EnterBlock(VRA, block.bb);
VariableReuseAnalysis::EnterBlockRAII EnterBlock(m_VRA, block.bb);
// go through the list in reverse order
auto I = block.m_dags.rbegin(), E = block.m_dags.rend();
while (I != E)
{
if ((*I).m_root->getDebugLoc())
Instruction* llvmInst = (*I).m_root;
if (llvmInst->getDebugLoc())
{
unsigned int curLineNumber = (*I).m_root->getDebugLoc().getLine();
auto&& srcFile = (*I).m_root->getDebugLoc()->getScope()->getFilename();
auto&& srcDir = (*I).m_root->getDebugLoc()->getScope()->getDirectory();
unsigned int curLineNumber = llvmInst->getDebugLoc().getLine();
auto&& srcFile = llvmInst->getDebugLoc()->getScope()->getFilename();
auto&& srcDir = llvmInst->getDebugLoc()->getScope()->getDirectory();
if (!curSrcFile.equals(srcFile) || !curSrcDir.equals(srcDir))
{
curSrcFile = srcFile;
curSrcDir = srcDir;
IF_DEBUG_INFO_IF(m_pDebugEmitter, m_pDebugEmitter->BeginEncodingMark();)
std::string fileName = std::string(curSrcDir);
std::string fileName = std::string(curSrcDir);
fileName += std::string(curSrcFile);
m_encoder->File(fileName);
IF_DEBUG_INFO_IF(m_pDebugEmitter, m_pDebugEmitter->EndEncodingMark();)
......@@ -514,36 +516,39 @@ bool EmitPass::runOnFunction(llvm::Function &F)
if (curLineNumber != lineNo)
{
IF_DEBUG_INFO_IF(m_pDebugEmitter, m_pDebugEmitter->BeginEncodingMark();)
m_encoder->Loc(curLineNumber);
m_encoder->Loc(curLineNumber);
IF_DEBUG_INFO_IF(m_pDebugEmitter, m_pDebugEmitter->EndEncodingMark();)
lineNo = curLineNumber;
lineNo = curLineNumber;
}
}
bool slicing = false;
uint numInstance = DecideInstanceAndSlice(*(block.bb), (*I), slicing);
assert(numInstance == 1 || numInstance == 2);
if (slicing && !disableSlicing)
{
IF_DEBUG_INFO_IF(m_pDebugEmitter, m_pDebugEmitter->BeginEncodingMark();)
I = emitInSlice(block, I);
I = emitInSlice(block, I);
IF_DEBUG_INFO_IF(m_pDebugEmitter, m_pDebugEmitter->EndEncodingMark();)
llvmInst = (*I).m_root;
}
if (I != E)
{
auto llvmInst = (*I).m_root;
IF_DEBUG_INFO_IF(m_pDebugEmitter, m_pDebugEmitter->BeginInstruction(llvmInst);)
// before inserting the terminator, initialize constant pool & insert the de-ssa moves
if (isa<BranchInst>((*I).m_root))
{
m_encoder->SetSecondHalf(false);
// insert constant initializations.
InitConstant(block.bb);
// insert the de-ssa movs.
MovPhiSources(block.bb);
}
// before inserting the terminator, initialize constant pool & insert the de-ssa moves
if (isa<BranchInst>(llvmInst))
{
m_encoder->SetSecondHalf(false);
// insert constant initializations.
InitConstant(block.bb);
// insert the de-ssa movs.
MovPhiSources(block.bb);
// Insert lifetime start if there are any
emitLifetimeStartAtEndOfBB(block.bb);
}
// If slicing happens, then recalculate the number of instances.
if (slicing)
......@@ -553,9 +558,13 @@ bool EmitPass::runOnFunction(llvm::Function &F)
if (llvmtoVISADump)
{
rootToVISAId.try_emplace((*I).m_root, m_encoder->GetVISAKernel()->getvIsaInstCount() + 1);
rootToVISAId.try_emplace(llvmInst, m_encoder->GetVISAKernel()->getvIsaInstCount() + 1);
}
// Insert lifetime start if legal. Note taht m_destination
// shall be nullptr if this instruction has no dst.
emitLifetimeStart(m_destination, block.bb, llvmInst, true);
DstModifier init;
if (numInstance < 2)
{
......@@ -690,6 +699,8 @@ EmitPass::emitInSlice(SBasicBlock& block, SBasicBlock::reverse_iterator I)
m_encoder->SetSecondHalf(false); // the 1st-half slice for simd32
while (slicing)
{
emitLifetimeStart(m_destination, block.bb, (*sliceIter).m_root, false);
(*sliceIter).m_pattern->Emit(this, init);
++sliceIter;
slicing = false;
......@@ -710,6 +721,8 @@ EmitPass::emitInSlice(SBasicBlock& block, SBasicBlock::reverse_iterator I)
// uniform op only emit once
if (numInstance > 1)
{
emitLifetimeStart(m_destination, block.bb, (*sliceIter).m_root, false);
(*sliceIter).m_pattern->Emit(this, init);
}
}
......@@ -1072,6 +1085,27 @@ void EmitPass::InitConstant(llvm::BasicBlock *BB)
}
}
void EmitPass::emitLifetimeStartAtEndOfBB(BasicBlock* BB)
{
if (IGC_IS_FLAG_DISABLED(EnableVATemp)) {
return;
}
auto II = m_VRA->m_LifetimeAtEndOfBB.find(BB);
if (II != m_VRA->m_LifetimeAtEndOfBB.end())
{
TinyPtrVector<Value*>& ARVs = II->second;
for (int i = 0, sz = (int)ARVs.size(); i < sz; ++i)
{
Value* RootVal = ARVs[i];
CVariable* Var = GetSymbol(RootVal);
// vISA info inst, no m_encoder->Push() needed.
m_encoder->Lifetime(LIFETIME_START, Var);
}
}
}
std::pair<Value *, Value *> EmitPass::getPairOutput(Value *V) const {
auto I = m_pattern->PairOutputMap.find(V);
assert(I != m_pattern->PairOutputMap.end());
......@@ -7471,6 +7505,40 @@ CVariable *EmitPass::Add(CVariable *Src0, CVariable *Src1, const CVariable *DstP
return Dst;
}
// Insert lifetime start right before instruction I if it is a candidate.
void EmitPass::emitLifetimeStart(CVariable* Var, BasicBlock* BB, Instruction* I, bool ForAllInstance)
{
if (IGC_IS_FLAG_DISABLED(EnableVATemp) || Var == nullptr) {
return;
}
Value* ARV = m_VRA->getAliasRootValue(I);
auto II = m_VRA->m_LifetimeAt1stDefOfBB.find(ARV);
if (II != m_VRA->m_LifetimeAt1stDefOfBB.end())
{
// Insert lifetime start on the root value
// Note that lifetime is a kind of info directive,
// thus no m_encoder->Push() is needed.
CVariable* RootVar = GetSymbol(ARV);
if (ForAllInstance)
{
for (uint instance = 0; instance < RootVar->GetNumberInstance(); instance++)
{
m_encoder->SetSecondHalf(instance == 0 ? false : true);
m_encoder->Lifetime(LIFETIME_START, RootVar);
}
}
else {
// Current instance, set already in the calling context.
m_encoder->Lifetime(LIFETIME_START, RootVar);
}
// Once inserted, remove it from map to
// prevent from inserting again.
m_VRA->m_LifetimeAt1stDefOfBB.erase(II);
}
}
void EmitPass::emitGEP(llvm::Instruction* I)
{
GetElementPtrInst &GEP = cast<GetElementPtrInst>(*I);
......
......@@ -159,6 +159,10 @@ public:
// Only remaining GEPs are for scratch in GFX path
void emitGEP(llvm::Instruction* inst);
// Emit lifetime start right before inst V. If ForAllInstance is true, emit lifestart
// for both instances; otherwise, just the current instance set in the calling context.
void emitLifetimeStart(CVariable* Var, llvm::BasicBlock* BB, llvm::Instruction* I, bool ForAllInstance);
// set the predicate with current active channels
void emitPredicateFromChannelIP(CVariable* dst, CVariable* alias = NULL);
......@@ -386,6 +390,7 @@ public:
void MovPhiSources(llvm::BasicBlock* bb);
void InitConstant(llvm::BasicBlock *BB);
void emitLifetimeStartAtEndOfBB(llvm::BasicBlock* BB);
std::pair<llvm::Value *, llvm::Value *> getPairOutput(llvm::Value *) const;
......@@ -467,6 +472,7 @@ public:
CEncoder* m_encoder;
const llvm::DataLayout* m_DL;
CoalescingEngine* m_CE;
VariableReuseAnalysis* m_VRA;
ModuleMetaData* m_moduleMD;
bool m_canAbortOnSpill;
......
......@@ -28,10 +28,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "Compiler/CISACodeGen/PatternMatchPass.hpp"
#include "Compiler/CISACodeGen/DeSSA.hpp"
#include "Compiler/CISACodeGen/CoalescingEngine.hpp"
#include "Compiler/CISACodeGen/BlockCoalescing.hpp"
#include "common/LLVMWarningsPush.hpp"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Dominators.h"
#include "llvm/ADT/TinyPtrVector.h"
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
......@@ -105,11 +107,13 @@ public:
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
// AU.addRequired<RegisterEstimator>();
AU.setPreservesAll();
AU.addRequired<llvm::DominatorTreeWrapperPass>();
AU.addRequired<WIAnalysis>();
AU.addRequired<LiveVarsAnalysis>();
AU.addRequired<CodeGenPatternMatch>();
AU.addRequired<DeSSA>();
AU.addRequired<CoalescingEngine>();
AU.addRequired<BlockCoalescing>();
AU.addRequired<CodeGenContextWrapper>();
}
......@@ -175,6 +179,14 @@ public:
int getCongruentClassSize(llvm::Value* V);
bool isSameSizeValue(llvm::Value* V0, llvm::Value* V1);
// getRootValue():
// return dessa root value; if dessa root value
// is null, return itself.
llvm::Value* getRootValue(llvm::Value* V);
// getAliasRootValue()
// return alias root value if it exists, itself otherwise.
llvm::Value *getAliasRootValue(llvm::Value* V);
/// printAlias - print value aliasing info in human readable form
void printAlias(llvm::raw_ostream &OS, const llvm::Function* F = nullptr) const;
/// dumpAalias - dump alias info to dbgs().
......@@ -186,7 +198,16 @@ public:
AliasRootMapTy m_AliasRootMap; // aliasee -> all its aliasers.
// No need to emit code for instructions in this map due to aliasing
llvm::DenseMap <llvm::Instruction*, int > m_HasBecomeNoopInsts;
llvm::DenseMap <llvm::Instruction*, int> m_HasBecomeNoopInsts;
// For emitting livetime start to visa to assist liveness analysis
// 1. m_LifetimeAt1stDefInBB : aliasee -> BB
// Once a first def is encounted, add lifetime start and clear
// this map entry afterwards.
// 2. m_LifetimeAtEndOfBB : BB -> set of values
// Add lifetime start for all values in the set at the end of BB.
llvm::DenseMap<llvm::Value*, llvm::BasicBlock*> m_LifetimeAt1stDefOfBB;
llvm::DenseMap<llvm::BasicBlock*, llvm::TinyPtrVector<llvm::Value*> > m_LifetimeAtEndOfBB;
private:
void reset() {
......@@ -264,14 +285,20 @@ private:
llvm::InsertElementInst* LastIEI,
llvm::SmallVector<SSubVector, 4>& SVs);
void getAllValues(
llvm::SmallVector<llvm::Value*, 8>& AllValues,
llvm::Value* Aliasee);
CodeGenContext* m_pCtx;
WIAnalysis* m_WIA;
LiveVars* m_LV;
DeSSA* m_DeSSA;
CodeGenPatternMatch* m_PatternMatch;
CoalescingEngine* m_coalescingEngine;
llvm::DominatorTree *m_DT;
const llvm::DataLayout* m_DL;
/// Current Function; set on entry to runOnFunction
/// and unset on exit to runOnFunction
llvm::Function* m_F;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment