mirror of
https://github.com/intel/intel-graphics-compiler.git
synced 2025-10-30 08:18:26 +08:00
Add an analysis to check if an instruction's def reaches the end of its parent basic block.
Change-Id: I72cffd9681266cce0b87115c84a23c423ad6c4dc
This commit is contained in:
@ -270,6 +270,7 @@ set(GenX_Common_Headers
|
||||
InstSplit.h
|
||||
VarSplit.h
|
||||
Attributes.hpp
|
||||
LocalDataflow.h
|
||||
${LocalScheduler_HEADERS}
|
||||
)
|
||||
set(GenX_CISA_dis_Common_Headers
|
||||
|
||||
@ -1,6 +1,32 @@
|
||||
/*===================== begin_copyright_notice ==================================
|
||||
|
||||
Copyright (c) 2017 Intel Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
======================= end_copyright_notice ==================================*/
|
||||
#include "FlowGraph.h"
|
||||
#include "BitSet.h"
|
||||
#include "BuildIR.h"
|
||||
#include "LocalDataflow.h"
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@ -530,3 +556,113 @@ void FlowGraph::resetLocalDataFlowData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DefEscapeBBAnalysis::analyzeBB(G4_BB* bb)
|
||||
{
|
||||
// active defines in this BB, organized by root declare
|
||||
invalidateBB(bb);
|
||||
std::unordered_map<G4_Declare*, std::vector<G4_INST*> > activeDefines;
|
||||
std::vector<G4_INST*> escapedDefs;
|
||||
for (auto inst : *bb)
|
||||
{
|
||||
if (!inst->getDst())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// analyze GRF/Address dst
|
||||
auto dst = inst->getDst();
|
||||
|
||||
if (dst->isIndirect())
|
||||
{
|
||||
escapedDefs.push_back(inst);
|
||||
}
|
||||
else if (dst->getTopDcl())
|
||||
{
|
||||
auto dcl = dst->getTopDcl()->getRootDeclare();
|
||||
auto&& iter = activeDefines.find(dcl);
|
||||
if (iter == activeDefines.end())
|
||||
{
|
||||
// first define for dcl in this BB
|
||||
activeDefines[dcl] = { inst };
|
||||
}
|
||||
else
|
||||
{
|
||||
auto&& vec = iter->second;
|
||||
// note size may shrink!
|
||||
for (int i = 0; i < (int)vec.size(); ++i)
|
||||
{
|
||||
|
||||
auto prevInst = vec[i];
|
||||
if (inst->getMaskOffset() != prevInst->getMaskOffset() ||
|
||||
(prevInst->isWriteEnableInst() && !inst->isWriteEnableInst()) ||
|
||||
dst->getExecTypeSize() != prevInst->getDst()->getExecTypeSize())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto rel = dst->compareOperand(prevInst->getDst());
|
||||
if (rel == Rel_eq || rel == Rel_gt)
|
||||
{
|
||||
std::swap(vec[i], vec[vec.size() - 1]);
|
||||
vec.pop_back();
|
||||
#ifdef _DEBUG
|
||||
std::cerr << "Inst:\t";
|
||||
prevInst->dump();
|
||||
std::cerr << "killed by Inst:\t";
|
||||
inst->dump();
|
||||
auto killIter = killedDefs.find(bb);
|
||||
if (killIter == killedDefs.end())
|
||||
{
|
||||
killedDefs[bb] = { prevInst };
|
||||
}
|
||||
else
|
||||
{
|
||||
auto&& killedVec = killIter->second;
|
||||
killedVec.push_back(prevInst);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
vec.push_back(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto&& iter : activeDefines)
|
||||
{
|
||||
auto&& vec = iter.second;
|
||||
for (auto I : vec)
|
||||
{
|
||||
escapedDefs.push_back(I);
|
||||
}
|
||||
}
|
||||
escapedInsts[bb] = escapedDefs;
|
||||
}
|
||||
|
||||
void DefEscapeBBAnalysis::print(ostream& OS) const
|
||||
{
|
||||
for (auto&& iter : escapedInsts)
|
||||
{
|
||||
G4_BB* bb = iter.first;
|
||||
OS << "BB" << bb->getId() << ":\n";
|
||||
OS << "Escaped inst:\n";
|
||||
for (auto&& inst : iter.second)
|
||||
{
|
||||
OS << "\t";
|
||||
inst->print(OS);
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
auto&& killIt = killedDefs.find(bb);
|
||||
if (killIt != killedDefs.end())
|
||||
{
|
||||
OS << "Killed inst:\n";
|
||||
for (auto&& inst : killIt->second)
|
||||
{
|
||||
OS << "\t";
|
||||
inst->print(OS);
|
||||
}
|
||||
}
|
||||
#endif // _DEBUG
|
||||
OS << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
100
visa/LocalDataflow.h
Normal file
100
visa/LocalDataflow.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*===================== begin_copyright_notice ==================================
|
||||
|
||||
Copyright (c) 2017 Intel Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
======================= end_copyright_notice ==================================*/
|
||||
|
||||
#ifndef _LOCAL_DATAFLOW_H
|
||||
#define _LOCAL_DATAFLOW_H
|
||||
|
||||
#include "FlowGraph.h"
|
||||
#include "BuildIR.h"
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace vISA;
|
||||
using namespace std;
|
||||
|
||||
// ToDo: move Local dataflow here and make it a class
|
||||
|
||||
namespace {
|
||||
|
||||
// A simple local (within one BB) analysis that checks if a def escapes (i.e., reaches the end of BB without other defines killing it).
|
||||
// This information may be helpful for a number of optimizations by determining if a define has only local effect.
|
||||
// Destination may be GRF or Address (i.e., direct DstRegRegion).
|
||||
// Acc and other special ARFs are not considered as their defintions should always be local.
|
||||
// Flag dst (i.e., conditional modifier) is currently not handled; while adding it is possible it may lead to confusion for instructions with both dst and condMod.
|
||||
// To reduce compilation overhead and implementation complexity only a single killing defintion is considered for now;
|
||||
// this is conservative but should cover most pratical cases as our input is almost SSA.
|
||||
class DefEscapeBBAnalysis
|
||||
{
|
||||
|
||||
const FlowGraph& fg;
|
||||
|
||||
// all escaped inst for this BB
|
||||
// If BB is not in the map, it means we need to run analysis for this BB
|
||||
// ToDo: assumption is that there should not be many escaped inst. Can change to vector to set later if desired.
|
||||
std::unordered_map<G4_BB*, std::vector<G4_INST*> > escapedInsts;
|
||||
|
||||
#ifdef _DEBUG
|
||||
// for debugging only, record instructions that were killed in the BB
|
||||
std::unordered_map<G4_BB*, std::vector<G4_INST*> > killedDefs;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
DefEscapeBBAnalysis(const FlowGraph& cfg) : fg(cfg) {}
|
||||
|
||||
DefEscapeBBAnalysis(const DefEscapeBBAnalysis& analysis) = delete;
|
||||
|
||||
virtual ~DefEscapeBBAnalysis() = default;
|
||||
|
||||
void run()
|
||||
{
|
||||
for (auto&& bb : const_cast<FlowGraph&>(fg))
|
||||
{
|
||||
analyzeBB(bb);
|
||||
}
|
||||
}
|
||||
|
||||
void analyzeBB(G4_BB* bb);
|
||||
|
||||
bool isBBValid(G4_BB* bb) const { return escapedInsts.count(bb); }
|
||||
void invalidate() { escapedInsts.clear(); }
|
||||
void invalidateBB(G4_BB* bb) { escapedInsts.erase(bb); }
|
||||
bool isEscaped(G4_BB* bb, G4_INST* inst)
|
||||
{
|
||||
if (!isBBValid(bb))
|
||||
{
|
||||
analyzeBB(bb);
|
||||
}
|
||||
auto&& vec = escapedInsts.find(bb)->second;
|
||||
return std::find(vec.begin(), vec.end(), inst) != vec.end();
|
||||
}
|
||||
void print(std::ostream& OS) const;
|
||||
void dump() const
|
||||
{
|
||||
print(std::cerr);
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // _LOCAL_DATAFLOW_H
|
||||
Reference in New Issue
Block a user