Remove the old coalescing code as it is no longer

needed. More will be deleted in the next few submits.

Change-Id: I3165519e13d3d8eda6c2cdbaa0d6f81930bccda7
This commit is contained in:
Gu, Junjie
2019-09-04 12:25:55 -07:00
committed by sys_zuul
parent 8d46933660
commit be063c524b
2 changed files with 0 additions and 464 deletions

View File

@ -856,130 +856,9 @@ void VariableReuseAnalysis::visitCallInst(CallInst& I)
}
}
void VariableReuseAnalysis::visitCastInst(CastInst& I)
{
if (IGC_GET_FLAG_VALUE(EnableVATemp) < 1 ||
IGC_GET_FLAG_VALUE(EnableDeSSAAlias) > 1)
return;
if (!canBeAlias(&I)) {
return;
}
// Set alias of dst to CastInst's src
// As CastInst is noop, its definition is dropped and
// only its uses are merged to src's liveness info.
Value* D = &I;
Value* S = I.getOperand(0);
SSubVecDesc SV;
SV.BaseVector = S;
SV.StartElementOffset = 0;
if (addAlias(D, SV)) {
m_HasBecomeNoopInsts[&I] = 1;
}
else {
// If D is aliased to another value already, it cannot
// alias to S again. But we can check if S can be aliased
// to D.
SV.BaseVector = D;
if (addAlias(S, SV)) {
m_HasBecomeNoopInsts[&I] = 1;
}
}
// This is probably not needed!
// Extend S's liveness to contain D's
// m_LV->mergeUseFrom(S, D);
}
// to be deleted
void VariableReuseAnalysis::visitInsertElementInst(InsertElementInst& I)
{
if (IGC_GET_FLAG_VALUE(VATemp) == 0) {
// old code
visitInsertElementInst_toBeDeleted(I);
return;
}
}
void VariableReuseAnalysis::visitInsertElementInst_toBeDeleted(InsertElementInst& I)
{
if (IGC_GET_FLAG_VALUE(EnableVATemp) < 2)
return;
// Two cases for sub-vector aliasing:
// 1. extractFrom: sub-vector is created from a base vector.
// For example:
// given base: int8 b; a sub-vector s (int4) can be:
// s = (int4)(b.s4, b.s5, b.s6, b.s7) // extract and insert in llvm
// In this case, 's' becomes a part of 'b'.
// 2. insertTo: sub-vector is used to create a base vector.
// For example:
// given sub-vector int4 s0, s1; int8 vector b is created like:
// b = (int8) (s0, s1) // extract and insert
// In this case, both s0 and s1 ecome part of b.
// Start insertElement pattern from the first InsertElement, ie, one with UndefValue.
if (!isa<UndefValue>(I.getOperand(0)))
return;
VectorType* VTy = cast<VectorType>(I.getType());
int nelts = (int)VTy->getNumElements();
// Sanity
if (nelts < 2)
return;
VecEltTy AllElts(nelts);
ValueVectorTy AllIEIs;
if (!checkAndGetAllInsertElements(&I, AllIEIs, AllElts)) {
return;
}
assert(AllIEIs.size() == nelts && "ICE: wrong the number of IEIs!");
InsertElementInst* LastIEI = cast<InsertElementInst>(AllIEIs.back());
SSubVecDesc SV;
SmallVector<SSubVecDesc, 4> SVs;
if (IsExtractFrom(AllElts, &I, LastIEI, SV))
{
if (addAlias(LastIEI, SV))
{
for (int i = 0, sz = (int)AllIEIs.size(); i < sz; ++i)
{
Instruction* Inst = cast<Instruction>(AllIEIs[i]);
m_HasBecomeNoopInsts[Inst] = 1;
}
}
return;
}
SVs.clear();
if (IsInsertTo(AllElts, &I, LastIEI, SVs))
{
for (int i = 0, sz = (int)SVs.size(); i < sz; ++i)
{
SSubVecDesc& subvec = SVs[i];
Value* aliaser = subvec.BaseVector;
subvec.BaseVector = LastIEI;
if (addAlias(aliaser, subvec)) {
VectorType* Ty = dyn_cast<VectorType>(aliaser->getType());
int sz = Ty ? (int)Ty->getNumElements() : 1;
int startIx = (int)subvec.StartElementOffset;
for (int i = startIx, e = startIx + sz; i < e; ++i) {
Instruction* Inst = cast<Instruction>(AllIEIs[i]);
m_HasBecomeNoopInsts[Inst] = 1;
}
}
}
return;
}
}
void VariableReuseAnalysis::visitExtractElementInst(ExtractElementInst& I)
{
if (IGC_GET_FLAG_VALUE(VATemp) == 0) {
visitExtractElementInst_toBeDeleted(I);
return;
}
@ -1050,345 +929,6 @@ void VariableReuseAnalysis::visitExtractElementInst(ExtractElementInst& I)
m_HasBecomeNoopInsts[EEI] = 1;
}
void VariableReuseAnalysis::visitExtractElementInst_toBeDeleted(ExtractElementInst& I)
{
// Only handles ExtractElements whose indexes are all known constants.
if (IGC_GET_FLAG_VALUE(EnableVATemp) < 2)
return;
if (m_HasBecomeNoopInsts.count(&I))
return;
// Process all Extract elements of the vector operand.
// Do it when the function sees "e0 = EEI V, 0"
ConstantInt* Idx = dyn_cast<ConstantInt>(I.getIndexOperand());
if (!Idx || Idx->getZExtValue() != 0) {
return;
}
Value* Vec = I.getVectorOperand();
if (isAliasedValue(Vec))
{
return;
}
VectorType* VTy = cast<VectorType>(Vec->getType());
int nelts = (int)VTy->getNumElements();
SmallVector<ExtractElementInst*, 8> allEEs(nelts, nullptr);
allEEs[0] = &I;
for (auto user : Vec->users())
{
ExtractElementInst* EEI = dyn_cast<ExtractElementInst>(user);
if (!EEI || EEI == &I)
{
continue;
}
ConstantInt* Index = dyn_cast<ConstantInt>(EEI->getIndexOperand());
if (!Index)
{
continue;
}
int ix = (int)Index->getZExtValue();
if (ix < nelts && allEEs[ix] == nullptr)
{
allEEs[ix] = EEI;
}
}
for (int i = 0; i < nelts; ++i)
{
ExtractElementInst* EEI = allEEs[i];
if (!EEI || isAliasedValue(EEI) ||
(m_WIA && m_WIA->whichDepend(EEI) != m_WIA->whichDepend(Vec)))
{
continue;
}
if (aliasHasInterference(EEI, Vec)) {
continue;
}
SSubVecDesc SV;
SV.BaseVector = Vec;
SV.StartElementOffset = i;
if (addAlias(EEI, SV)) {
m_HasBecomeNoopInsts[EEI] = 1;
}
}
}
bool VariableReuseAnalysis::isLocalValue(Value* V)
{
Instruction* I = dyn_cast<Instruction>(V);
if (!I)
return false;
BasicBlock* BB = I->getParent();
return !m_LV->isLiveIn(I, *BB) && !m_LV->isLiveOut(I, *BB);
}
// Return true if live ranges of aliaser and aliasee overlap. The
// difference between this one and hasInterference() is that both aliaser
// and aliasee in this function are excluded from congruent class
// as they are with the identical value (that is why they are aliased).
bool VariableReuseAnalysis::aliasHasInterference(Value* Aliaser, Value* Aliasee)
{
// As two aliased variables have the identical value, their interference
// does not prevent merging them into a single variable (overlapping or not,
// they still have the same value).
if (!m_DeSSA) {
return false;
}
if (IGC_GET_FLAG_VALUE(EnableVATemp) < 3)
{
// should have this check ?
if (getCongruentClassSize(Aliaser) != 1 ||
getCongruentClassSize(Aliasee) != 1) {
return true;
}
return false;
}
// THis is for EnableVATemp =3
// [todo] find a better way to handle alias with values whose
// congruent class has more than one values.
SmallVector<Value*, 8> Aliasercc; // Aliaser's congruent class
SmallVector<Value*, 8> Aliaseecc; // Aliasee's congruent class
m_DeSSA->getAllValuesInCongruentClass(Aliaser, Aliasercc);
m_DeSSA->getAllValuesInCongruentClass(Aliasee, Aliaseecc);
// Check every pair of values in two congruent classes
// and exclude Aliaser and Aliasee.
Value* AliaserInsEltRoot = m_DeSSA->getInsEltRoot(Aliaser);
Value* AliaseeInsEltRoot = m_DeSSA->getInsEltRoot(Aliasee);
for (int i = 0, sz0 = (int)Aliasercc.size(); i < sz0; ++i)
{
Value* val0 = Aliasercc[i];
for (int j = 0, sz1 = (int)Aliaseecc.size(); j < sz1; ++j)
{
Value* val1 = Aliaseecc[j];
if (val0 == AliaserInsEltRoot && val1 == AliaseeInsEltRoot)
continue;
if (m_LV->hasInterference(val0, val1))
return true;
}
}
return false;
}
// Return true if V0 and V1's live ranges overlap, return false otherwise.
bool VariableReuseAnalysis::hasInterference(Value* V0, Value* V1)
{
// Key assumption about Congruent class (dessa)/LVInfo(LiveVars):
// 1. Single-definition liveness
// LVInfo has liveness info for each llvm value, which has a single
// definition throughout its live ranges. This is what LLVM's value means.
// 2. Multiple-definition congruent class
// If two values are combined, they should be in the same congruent class,
// not by extending liveness to reflect both.
//
// For example:
// 1: v0 = 10
// 2: = v0 (last use)
// 3: v1 = 20
// 4: = v1 (last use)
// Assume v0 and v1 are combined, they will be put in the same congruent class.
// We will not extend v0's liveness to "4" (same for v1).
//
// Another example:
// 1: v0 = 10
// 2: = v0 (last use)
// 3: v1 = bitcast v0
// 4: = v1 (last use)
// then we can just extend v0's liveness to "4", and v1 to be alias to v0.
//
SmallVector<Value*, 8> V0cc; // V0's congruent class
SmallVector<Value*, 8> V1cc; // V1's congruent class
if (m_DeSSA) {
m_DeSSA->getAllValuesInCongruentClass(V0, V0cc);
m_DeSSA->getAllValuesInCongruentClass(V1, V1cc);
}
else {
V0cc.push_back(V0);
V1cc.push_back(V1);
}
// Check every pair of values in two congruent classes
for (int i = 0, sz0 = (int)V0cc.size(); i < sz0; ++i)
{
Value* val0 = V0cc[i];
for (int j = 0, sz1 = (int)V1cc.size(); j < sz1; ++j)
{
Value* val1 = V1cc[j];
if (m_LV->hasInterference(val0, val1))
return true;
}
}
return false;
}
// Check if src and dst of CastInst can be an alias to each other. It is used
// for checking alias-possible instructions such as bitcast/inttoptr/ptrtoint.
//
// This is trivial for LLVM IR, as LLVM IR is SSA. But after DeSSA,
// need to check other values in their congruent classes.
//
bool VariableReuseAnalysis::canBeAlias(CastInst* I)
{
if (hasBeenPayloadCoalesced(I)) {
return false;
}
if (!isNoOpInst(I, m_pCtx)) {
return false;
}
// Set alias of dst to CastInst's src
// As CastInst is noop, its definition is dropped and
// only its uses are merged to src's liveness info.
Value* D = I;
Value* S = I->getOperand(0);
if (isa<Constant>(S)) {
return false;
}
if (hasBeenPayloadCoalesced(S)) {
return false;
}
if (!m_DeSSA) {
// No congruent class, so it can be alias!
return true;
}
if (getCongruentClassSize(D) != 1 ||
getCongruentClassSize(S) != 1 ||
(m_WIA && m_WIA->whichDepend(D) != m_WIA->whichDepend(S))) {
return false;
}
return true;
}
// Check if the vector value of InsertElement is
// a sub-vector of another one, return true if so.
bool VariableReuseAnalysis::IsExtractFrom(
VecEltTy& AllElts, InsertElementInst* FirstIEI,
InsertElementInst* LastIEI, SSubVecDesc& SV)
{
int nelts = (int)AllElts.size();
Value* BaseVec = AllElts[0].Vec;
int BaseStartIx = AllElts[0].EltIx;
VectorType* BVTy = dyn_cast<VectorType>(BaseVec->getType());
if (BVTy == nullptr) {
// Base is not a vector, so IEI cannot be
// a subvector of another vector!
return false;
}
int base_nelts = (int)BVTy->getNumElements();
// If Base's size is smaller than IEI's, IEI cannot be sub-vector
if (base_nelts < nelts) {
return false;
}
for (int i = 1; i < nelts; ++i)
{
if (AllElts[i].Vec != BaseVec ||
AllElts[i].EltIx != (BaseStartIx + i))
return false;
}
// Don't do it if any of them is payload-coalesced
if (hasBeenPayloadCoalesced(LastIEI) ||
hasBeenPayloadCoalesced(BaseVec) ||
(m_WIA && m_WIA->whichDepend(LastIEI) != m_WIA->whichDepend(BaseVec)))
{
return false;
}
if (aliasHasInterference(LastIEI, BaseVec)) {
return false;
}
SV.StartElementOffset = BaseStartIx;
SV.BaseVector = BaseVec;
return true;
}
bool VariableReuseAnalysis::IsInsertTo(
VecEltTy& AllElts, InsertElementInst* FirstIEI,
InsertElementInst* LastIEI, SmallVector<SSubVecDesc, 4> & SVs)
{
int nelts = (int)AllElts.size();
Value* SubVec = AllElts[0].Vec;
int SubStartIx = 0;
for (int i = 0; i < nelts; ++i)
{
// 1. AllElts[i].Vec must be SubVec.
// 2. Check the next SubVec, if it change, the current
// element is the last one of the crrent SubVec;
// and SSubVecDesc will be created if the SubVec meets
// the condition.
if ((i - SubStartIx) != AllElts[i].EltIx) {
return false;
}
Value* NextSub = (i < (nelts - 1)) ? AllElts[i + 1].Vec : nullptr;
if (SubVec != NextSub)
{
// NextSub should be the new sub vector. Make sure it is not in SVs
// Note this works for speical case in which NextSub = nullptr.
for (int j = 0, sz = (int)SVs.size(); j < sz; ++j) {
if (SVs[j].BaseVector == NextSub) {
return false;
}
}
// End of the SubVec.
VectorType* BVTy = dyn_cast<VectorType>(SubVec->getType());
int sub_nelts = BVTy ? (int)BVTy->getNumElements() : 1;
// If Sub's size is not smaller than IEI's, or not all sub's
// elements are used, skip.
if (sub_nelts >= nelts || (i - SubStartIx) != (sub_nelts - 1)) {
return false;
}
SSubVecDesc sv;
sv.BaseVector = SubVec; // note that this is sub, not base!
sv.StartElementOffset = SubStartIx;
SVs.push_back(sv);
SubVec = NextSub;
SubStartIx = i + 1;
}
}
// If IEI or any of its sub vector has been payload-coalesced, skip.
if (hasBeenPayloadCoalesced(LastIEI)) {
return false;
}
for (int i = 0, sz = (int)SVs.size(); i < sz; ++i)
{
Value* SubVec = SVs[i].BaseVector;
if (hasBeenPayloadCoalesced(SubVec) ||
(m_WIA && m_WIA->whichDepend(LastIEI) != m_WIA->whichDepend(SubVec))) {
return false;
}
}
for (int i = 0, sz = (int)SVs.size(); i < sz; ++i)
{
Value* SubVec = SVs[i].BaseVector;
if (aliasHasInterference(SubVec, LastIEI)) {
return false;
}
}
return true;
}
void VariableReuseAnalysis::printAlias(raw_ostream& OS, const Function* F) const
{
// Assign each inst/arg a unique integer so that the output