Skip to content

Commit 5d32412

Browse files
jgu222Zuul
authored andcommitted
In order to mark divergent BB accurate for loop, it might
scan loop twice. Added code to pre-scan loop. Change-Id: I7e5fcca3008d00fcd4d240a1cc7b8bfd9f9c1072
1 parent 2c6c523 commit 5d32412

File tree

3 files changed

+128
-76
lines changed

3 files changed

+128
-76
lines changed

visa/FlowGraph.cpp

Lines changed: 122 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,6 +2789,14 @@ void FlowGraph::markSimdBlocks(std::map<std::string, G4_BB*>& labelMap, FuncInfo
27892789
// If all active simd lanes on entry to shader/kernel are
27902790
// active in a BB, that BB is NOT divergent; otherwise,
27912791
// it is divergent.
2792+
//
2793+
// Note that this does not require the number of all the
2794+
// active simd lanes equals to the simd dispatch width!
2795+
// For example, simd8 kernel might have 4 active lanes
2796+
// on entry to the kernel, thus if any BB of the kernel
2797+
// has less than 4 active lanes, it is divergent! As
2798+
// matter of fact, the entry BB must not be divergent.
2799+
//
27922800
// Note: this will be used to replace inSIMDCF gradually.
27932801
void FlowGraph::markDivergentBBs()
27942802
{
@@ -2847,6 +2855,9 @@ void FlowGraph::markDivergentBBs()
28472855
LastJoinBBId = -1;
28482856
}
28492857
};
2858+
auto isPriorToLastJoin = [&](G4_BB* aBB) ->bool {
2859+
return (int)aBB->getId() < LastJoinBBId;
2860+
};
28502861

28512862
if (BBs.empty())
28522863
{
@@ -2899,12 +2910,76 @@ void FlowGraph::markDivergentBBs()
28992910
}
29002911
}
29012912

2913+
// Check if the BB referred to by CurrIT needs to update lastJoin and do
2914+
// updating if so. The IterEnd is the end iterator of current function
2915+
// that CurrIT refers to.
2916+
//
2917+
// 1. update lastJoinBB if needed
2918+
// 2. set up divergence for entry of subroutines if divergent
2919+
//
2920+
auto updateLastJoinForBB = [&](BB_LIST_ITER& CurrIT, BB_LIST_ITER& IterEnd) ->bool
2921+
{
2922+
G4_BB* aBB = *CurrIT;
2923+
if (aBB->size() == 0)
2924+
{
2925+
return false;
2926+
}
2927+
2928+
int old_lastJoinBBId = LastJoinBBId;
2929+
2930+
G4_INST* lastInst = aBB->back();
2931+
if ((lastInst->opcode() == G4_while ||
2932+
(lastInst->opcode() == G4_goto && lastInst->asCFInst()->isBackward())) &&
2933+
(!lastInst->asCFInst()->isUniform() || aBB->isDivergent()))
2934+
{
2935+
if (CurrIT != IterEnd) {
2936+
auto NI = CurrIT;
2937+
++NI;
2938+
G4_BB* joinBB = *NI;
2939+
pushJoin(joinBB);
2940+
}
2941+
}
2942+
else if (((lastInst->opcode() == G4_goto && !lastInst->asCFInst()->isBackward()) ||
2943+
lastInst->opcode() == G4_break) &&
2944+
(!lastInst->asCFInst()->isUniform() || aBB->isDivergent()))
2945+
{
2946+
// forward goto/break : the last Succ BB is our target BB
2947+
// For break, it should be the BB right after while inst.
2948+
G4_BB* joinBB = aBB->Succs.back();
2949+
pushJoin(joinBB);
2950+
}
2951+
else if (lastInst->opcode() == G4_if &&
2952+
(!lastInst->asCFInst()->isUniform() || aBB->isDivergent()))
2953+
{
2954+
G4_Label* labelInst = lastInst->asCFInst()->getUip();
2955+
G4_BB* joinBB = findLabelBB(CurrIT, IterEnd, labelInst->getLabel());
2956+
assert(joinBB && "ICE(vISA) : missing endif label!");
2957+
pushJoin(joinBB);
2958+
}
2959+
else if (lastInst->opcode() == G4_call || lastInst->opcode() == G4_pseudo_fcall)
2960+
{
2961+
// If this function is already in divergent branch, the callee
2962+
// must be in a divergent branch!.
2963+
if (aBB->isDivergent() || lastInst->getPredicate() != nullptr)
2964+
{
2965+
FuncInfo* calleeFunc = aBB->getCalleeInfo();
2966+
if (funcInfoIndex.count(calleeFunc))
2967+
{
2968+
int ix = funcInfoIndex[calleeFunc];
2969+
allFuncs[ix].InvokedFromDivergentBB = true;
2970+
}
2971+
}
2972+
}
2973+
2974+
return old_lastJoinBBId != LastJoinBBId;
2975+
};
2976+
29022977
for (int i = 0; i < numFuncs; ++i)
29032978
{
29042979
// each function: [IT, IE)
2905-
BB_LIST_ITER& IT = allFuncs[i].StartI;
2980+
BB_LIST_ITER& IS = allFuncs[i].StartI;
29062981
BB_LIST_ITER& IE = allFuncs[i].EndI;
2907-
if (IT == IE)
2982+
if (IS == IE)
29082983
{
29092984
// sanity check
29102985
continue;
@@ -2913,7 +2988,7 @@ void FlowGraph::markDivergentBBs()
29132988
if (allFuncs[i].InvokedFromDivergentBB)
29142989
{
29152990
// subroutine's divergent on entry. Mark every BB as divergent
2916-
for (; IT != IE; ++IT)
2991+
for (auto IT = IS; IT != IE; ++IT)
29172992
{
29182993
G4_BB* BB = *IT;
29192994

@@ -2941,15 +3016,32 @@ void FlowGraph::markDivergentBBs()
29413016
}
29423017

29433018
LastJoinBBId = -1;
2944-
for (; IT != IE; ++IT)
3019+
for (auto IT = IS; IT != IE; ++IT)
29453020
{
29463021
G4_BB* BB = *IT;
29473022

2948-
// This handles cases in which BB has endif/while/join as well as others
2949-
// so we don't need to explicitly check whether BB has endif/while/join, etc.
3023+
// join could be: explicit (join inst) or implicit (endif/while)
29503024
popJoinIfMatch(BB);
29513025

29523026
// Handle loop
3027+
// Loop needs to be scanned twice in order to get an accurate marking.
3028+
// For example,
3029+
// L:
3030+
// B1:
3031+
// if (p0) goto B2
3032+
// ...
3033+
// else
3034+
// if (p1) goto OUT
3035+
// endif
3036+
// B2:
3037+
// (p2) goto L
3038+
// B3:
3039+
// OUT:
3040+
//
3041+
// We don't know whether B1 is divergent until the entire loop body has been
3042+
// scanned, so that we know any out-of-loop gotos (goto out and goto L in this
3043+
// case). This require scanning the loop twice.
3044+
//
29533045
for (auto iter = BB->Preds.begin(), iterEnd = BB->Preds.end(); iter != iterEnd; ++iter)
29543046
{
29553047
G4_BB* predBB = *iter;
@@ -2965,9 +3057,17 @@ void FlowGraph::markDivergentBBs()
29653057
// not loop
29663058
continue;
29673059
}
3060+
3061+
// If lastJoin is already after loop end, no need to scan loop twice
3062+
// as all BBs in the loop must be divergent
3063+
if (isPriorToLastJoin(predBB))
3064+
{
3065+
continue;
3066+
}
3067+
29683068
BB_LIST_ITER LoopIterEnd = std::find(BBs.begin(), BBs.end(), predBB);
29693069

2970-
// joinBB is the BB right after backward-goto/while
3070+
// joinBB of a loop is the BB right after backward-goto/while
29713071
BB_LIST_ITER loopJoinIter = LoopIterEnd;
29723072
++loopJoinIter;
29733073
if (loopJoinIter == BBs.end())
@@ -2983,87 +3083,37 @@ void FlowGraph::markDivergentBBs()
29833083
}
29843084
continue;
29853085
}
3086+
3087+
// If backward goto/while is divergent, update lastJoin with
3088+
// loop's join BB. No need to pre-scan loop!
29863089
G4_BB* joinBB = *loopJoinIter;
3090+
if (!bInst->asCFInst()->isUniform() &&
3091+
bInst->opcode() != G4_jmpi)
3092+
{
3093+
pushJoin(joinBB);
3094+
continue;
3095+
}
29873096

2988-
// Scan loop to find any out-of-loop branch, set join if found
3097+
// pre-scan loop to find any out-of-loop branch, set join if found
29893098
for (auto LoopIter = IT; LoopIter != LoopIterEnd; ++LoopIter)
29903099
{
2991-
G4_BB* BB1 = *LoopIter;
2992-
if (BB1->size() == 0)
3100+
if (updateLastJoinForBB(LoopIter, IE))
29933101
{
2994-
continue;
2995-
}
2996-
G4_INST* tmpInst = BB1->back();
2997-
if (tmpInst->opcode() == G4_break || tmpInst->opcode() == G4_goto)
2998-
{ // Assume divergent. todo: going over loop twice to find if it's divergent.
2999-
G4_BB* newJoinBB = joinBB;
3000-
if (tmpInst->opcode() == G4_goto)
3102+
if (isPriorToLastJoin(predBB))
30013103
{
3002-
G4_BB* targetBB = BB1->Succs.back();
3003-
if (targetBB->getId() <= predBB->getId())
3004-
{
3005-
continue;
3006-
}
3007-
newJoinBB = targetBB;
3104+
continue;
30083105
}
3009-
3010-
// Need to find a 1st join, the other joins will
3011-
// be examined within the outer loop.
3012-
pushJoin(newJoinBB);
3013-
break;
30143106
}
30153107
}
3016-
3017-
if (!bInst->asCFInst()->isUniform() &&
3018-
bInst->opcode() != G4_jmpi)
3019-
{
3020-
pushJoin(joinBB);
3021-
}
30223108
}
30233109

3024-
if ((int)BB->getId() < LastJoinBBId) {
3110+
if (isPriorToLastJoin(BB)) {
30253111
BB->setDivergent(true);
30263112
// set InSIMDFlow as well, will merge these two fields gradually
30273113
BB->setInSimdFlow(true);
30283114
}
30293115

3030-
if (BB->size() == 0)
3031-
{
3032-
continue;
3033-
}
3034-
3035-
G4_INST* lastInst = BB->back();
3036-
if (((lastInst->opcode() == G4_goto && !lastInst->asCFInst()->isBackward()) ||
3037-
lastInst->opcode() == G4_break) &&
3038-
(!lastInst->asCFInst()->isUniform() || BB->isDivergent()))
3039-
{
3040-
// forward goto/break : the last Succ BB is our target BB
3041-
// For break, it should be the BB right after while inst.
3042-
G4_BB* joinBB = BB->Succs.back();
3043-
pushJoin(joinBB);
3044-
}
3045-
else if (lastInst->opcode() == G4_if &&
3046-
(!lastInst->asCFInst()->isUniform() || BB->isDivergent()))
3047-
{
3048-
G4_Label* labelInst = lastInst->asCFInst()->getUip();
3049-
G4_BB* joinBB = findLabelBB(IT, IE, labelInst->getLabel());
3050-
assert(joinBB && "ICE(vISA) : missing endif label!");
3051-
pushJoin(joinBB);
3052-
}
3053-
else if (lastInst->opcode() == G4_call || lastInst->opcode() == G4_pseudo_fcall)
3054-
{
3055-
// If this function is already in divergent branch, the callee
3056-
// must be in a divergent branch!.
3057-
if (BB->isDivergent() || lastInst->getPredicate() != nullptr)
3058-
{
3059-
FuncInfo* calleeFunc = BB->getCalleeInfo();
3060-
if (funcInfoIndex.count(calleeFunc))
3061-
{
3062-
int ix = funcInfoIndex[calleeFunc];
3063-
allFuncs[ix].InvokedFromDivergentBB = true;
3064-
}
3065-
}
3066-
}
3116+
(void)updateLastJoinForBB(IT, IE);
30673117
}
30683118
}
30693119
return;

visa/FlowGraph.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ class G4_BB
290290
bool inSimdFlow;
291291

292292
// If a BB is divergent, this field is set to true. By divergent, it means
293-
// that among all active lanes on entry to shader/kernel, some lanes are not
294-
// (potentially) active in this BB.
293+
// that among all active lanes on entry to shader/kernel, not all lanes may
294+
// be active in this BB.
295295
// Note : this field will be used to replace inSimdFlow.
296296
bool divergent;
297297

visa/Gen4_IR.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,8 +1219,10 @@ class G4_InstCF : public G4_INST
12191219
// True if this is a backward branch.
12201220
bool isBackwardBr;
12211221

1222-
// True if this branch is a uniform (all active lanes goes to the same target)
1223-
// Valid for if/while/break/goto/jmpi only. This could be encoded in instOpt
1222+
// True if this branch is a uniform. By uniform, it means that all active lanes
1223+
// at the branch goes to the same target (Valid for if/while/break/goto/jmpi only.
1224+
// This info could be encoded in instOpt.). Note that all active lanes at the
1225+
// branch could be subset of all active lanes on entry to shader/kernel.
12241226
bool isUniformBr;
12251227

12261228
public:

0 commit comments

Comments
 (0)