Skip to content

Commit

Permalink
JIT: Remove most fgConnectFallThrough calls (#97488)
Browse files Browse the repository at this point in the history
Part of #93020. This change adds back in most of #97191 and #96609, except for any significant changes to the flowgraph optimization passes to reduce churn. With this change, the false target of a BBJ_COND can diverge from the next block until Compiler::optOptimizeLayout, in which we reestablish implicit fall-through with fgConnectFallThrough to preserve the existing block reordering behavior. Note that the deferral of these fall-through fixups causes diffs in the edge weights, which can alter the behavior of fgReorderBlocks, hence some of the size regressions
  • Loading branch information
amanasifkhalid authored Jan 29, 2024
1 parent 8a0b3f3 commit 3115a9c
Show file tree
Hide file tree
Showing 23 changed files with 276 additions and 305 deletions.
20 changes: 10 additions & 10 deletions src/coreclr/jit/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,18 +301,20 @@ bool BasicBlock::CanRemoveJumpToNext(Compiler* compiler) const
}

//------------------------------------------------------------------------
// CanRemoveJumpToFalseTarget: determine if jump to false target can be omitted
// CanRemoveJumpToTarget: determine if jump to target can be omitted
//
// Arguments:
// target - true/false target of the BBJ_COND block
// compiler - current compiler instance
//
// Returns:
// true if block is a BBJ_COND that can fall into its false target
// true if block is a BBJ_COND that can fall into target
//
bool BasicBlock::CanRemoveJumpToFalseTarget(Compiler* compiler) const
bool BasicBlock::CanRemoveJumpToTarget(BasicBlock* target, Compiler* compiler) const
{
assert(KindIs(BBJ_COND));
return NextIs(bbFalseTarget) && !hasAlign() && !compiler->fgInDifferentRegions(this, bbFalseTarget);
assert(TrueTargetIs(target) || FalseTargetIs(target));
return NextIs(target) && !compiler->fgInDifferentRegions(this, target);
}

//------------------------------------------------------------------------
Expand Down Expand Up @@ -855,8 +857,7 @@ void BasicBlock::CopyTarget(Compiler* compiler, const BasicBlock* from)
SetEhf(new (compiler, CMK_BasicBlock) BBehfDesc(compiler, from->GetEhfTargets()));
break;
case BBJ_COND:
// TODO-NoFallThrough: Copy false target, too?
SetCond(from->GetTrueTarget(), Next());
SetCond(from->GetTrueTarget(), from->GetFalseTarget());
break;
case BBJ_ALWAYS:
SetKindAndTarget(from->GetKind(), from->GetTarget());
Expand Down Expand Up @@ -897,8 +898,7 @@ void BasicBlock::TransferTarget(BasicBlock* from)
from->bbEhfTargets = nullptr; // Make sure nobody uses the descriptor after this.
break;
case BBJ_COND:
// TODO-NoFallThrough: Copy false target, too?
SetCond(from->GetTrueTarget(), Next());
SetCond(from->GetTrueTarget(), from->GetFalseTarget());
break;
case BBJ_ALWAYS:
SetKindAndTarget(from->GetKind(), from->GetTarget());
Expand Down Expand Up @@ -1183,7 +1183,7 @@ unsigned BasicBlock::NumSucc() const
return 1;

case BBJ_COND:
if (bbTarget == bbNext)
if (bbTrueTarget == bbFalseTarget)
{
return 1;
}
Expand Down Expand Up @@ -1308,7 +1308,7 @@ unsigned BasicBlock::NumSucc(Compiler* comp)
return 1;

case BBJ_COND:
if (bbTarget == bbNext)
if (bbTrueTarget == bbFalseTarget)
{
return 1;
}
Expand Down
13 changes: 2 additions & 11 deletions src/coreclr/jit/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ struct BasicBlock : private LIR::Range

bool CanRemoveJumpToNext(Compiler* compiler) const;

bool CanRemoveJumpToFalseTarget(Compiler* compiler) const;
bool CanRemoveJumpToTarget(BasicBlock* target, Compiler* compiler) const;

unsigned GetTargetOffs() const
{
Expand Down Expand Up @@ -663,19 +663,13 @@ struct BasicBlock : private LIR::Range
{
assert(KindIs(BBJ_COND));
assert(bbTrueTarget != nullptr);
assert(target != nullptr);
return (bbTrueTarget == target);
}

BasicBlock* GetFalseTarget() const
{
assert(KindIs(BBJ_COND));

// So long as bbFalseTarget tracks bbNext in SetNext(), it is possible for bbFalseTarget to be null
// if this block is unlinked from the block list.
// So check bbNext before triggering the assert if bbFalseTarget is null.
// TODO-NoFallThrough: Remove IsLast() check once bbFalseTarget isn't hard-coded to bbNext
assert((bbFalseTarget != nullptr) || IsLast());
assert(bbFalseTarget != nullptr);
return bbFalseTarget;
}

Expand All @@ -690,15 +684,12 @@ struct BasicBlock : private LIR::Range
{
assert(KindIs(BBJ_COND));
assert(bbFalseTarget != nullptr);
assert(target != nullptr);
return (bbFalseTarget == target);
}

void SetCond(BasicBlock* trueTarget, BasicBlock* falseTarget)
{
assert(trueTarget != nullptr);
// TODO-NoFallThrough: Allow falseTarget to diverge from bbNext
assert(falseTarget == bbNext);
bbKind = BBJ_COND;
bbTrueTarget = trueTarget;
bbFalseTarget = falseTarget;
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/jit/codegenarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,13 @@ void CodeGen::genCodeForJTrue(GenTreeOp* jtrue)
regNumber reg = genConsumeReg(op);
inst_RV_RV(INS_tst, reg, reg, genActualType(op));
inst_JMP(EJ_ne, compiler->compCurBB->GetTrueTarget());

// If we cannot fall into the false target, emit a jump to it
BasicBlock* falseTarget = compiler->compCurBB->GetFalseTarget();
if (!compiler->compCurBB->CanRemoveJumpToTarget(falseTarget, compiler))
{
inst_JMP(EJ_jmp, falseTarget);
}
}

//------------------------------------------------------------------------
Expand Down
14 changes: 14 additions & 0 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4708,6 +4708,13 @@ void CodeGen::genCodeForJTrue(GenTreeOp* jtrue)
GenTree* op = jtrue->gtGetOp1();
regNumber reg = genConsumeReg(op);
GetEmitter()->emitIns_J_R(INS_cbnz, emitActualTypeSize(op), compiler->compCurBB->GetTrueTarget(), reg);

// If we cannot fall into the false target, emit a jump to it
BasicBlock* falseTarget = compiler->compCurBB->GetFalseTarget();
if (!compiler->compCurBB->CanRemoveJumpToTarget(falseTarget, compiler))
{
inst_JMP(EJ_jmp, falseTarget);
}
}

//------------------------------------------------------------------------
Expand Down Expand Up @@ -4935,6 +4942,13 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree)

GetEmitter()->emitIns_J_R(ins, attr, compiler->compCurBB->GetTrueTarget(), reg);
}

// If we cannot fall into the false target, emit a jump to it
BasicBlock* falseTarget = compiler->compCurBB->GetFalseTarget();
if (!compiler->compCurBB->CanRemoveJumpToTarget(falseTarget, compiler))
{
inst_JMP(EJ_jmp, falseTarget);
}
}

//---------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ void CodeGen::genMarkLabelsForCodegen()
block->GetTrueTarget()->SetFlags(BBF_HAS_LABEL);

// If we need a jump to the false target, give it a label
if (!block->CanRemoveJumpToFalseTarget(compiler))
if (!block->CanRemoveJumpToTarget(block->GetFalseTarget(), compiler))
{
JITDUMP(" " FMT_BB " : branch target\n", block->GetFalseTarget()->bbNum);
block->GetFalseTarget()->SetFlags(BBF_HAS_LABEL);
Expand Down
5 changes: 3 additions & 2 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2643,9 +2643,10 @@ void CodeGen::genCodeForJcc(GenTreeCC* jcc)
inst_JCC(jcc->gtCondition, compiler->compCurBB->GetTrueTarget());

// If we cannot fall into the false target, emit a jump to it
if (!compiler->compCurBB->CanRemoveJumpToFalseTarget(compiler))
BasicBlock* falseTarget = compiler->compCurBB->GetFalseTarget();
if (!compiler->compCurBB->CanRemoveJumpToTarget(falseTarget, compiler))
{
inst_JMP(EJ_jmp, compiler->compCurBB->GetFalseTarget());
inst_JMP(EJ_jmp, falseTarget);
}
}

Expand Down
17 changes: 17 additions & 0 deletions src/coreclr/jit/codegenloongarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4330,6 +4330,13 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree)
assert(regs != 0);

emit->emitIns_J(ins, compiler->compCurBB->GetTrueTarget(), regs); // 5-bits;

// If we cannot fall into the false target, emit a jump to it
BasicBlock* falseTarget = compiler->compCurBB->GetFalseTarget();
if (!compiler->compCurBB->CanRemoveJumpToTarget(falseTarget, compiler))
{
inst_JMP(EJ_jmp, falseTarget);
}
}

//---------------------------------------------------------------------
Expand Down Expand Up @@ -4884,6 +4891,16 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
assert(jcc->gtCondition.Is(GenCondition::EQ, GenCondition::NE));
instruction ins = jcc->gtCondition.Is(GenCondition::EQ) ? INS_bceqz : INS_bcnez;
emit->emitIns_J(ins, tgtBlock, (int)1 /* cc */);

if (compiler->compCurBB->KindIs(BBJ_COND))
{
// If we cannot fall into the false target, emit a jump to it
BasicBlock* falseTarget = compiler->compCurBB->GetFalseTarget();
if (!compiler->compCurBB->CanRemoveJumpToTarget(falseTarget, compiler))
{
inst_JMP(EJ_jmp, falseTarget);
}
}
}
break;

Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/jit/codegenriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4243,6 +4243,13 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree)
assert(regs != 0);

emit->emitIns_J(ins, compiler->compCurBB->GetTrueTarget(), regs); // 5-bits;

// If we cannot fall into the false target, emit a jump to it
BasicBlock* falseTarget = compiler->compCurBB->GetFalseTarget();
if (!compiler->compCurBB->CanRemoveJumpToTarget(falseTarget, compiler))
{
inst_JMP(EJ_jmp, falseTarget);
}
}

//---------------------------------------------------------------------
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,13 @@ void CodeGen::genCodeForJTrue(GenTreeOp* jtrue)
regNumber reg = genConsumeReg(op);
inst_RV_RV(INS_test, reg, reg, genActualType(op));
inst_JMP(EJ_jne, compiler->compCurBB->GetTrueTarget());

// If we cannot fall into the false target, emit a jump to it
BasicBlock* falseTarget = compiler->compCurBB->GetFalseTarget();
if (!compiler->compCurBB->CanRemoveJumpToTarget(falseTarget, compiler))
{
inst_JMP(EJ_jmp, falseTarget);
}
}

//------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2189,7 +2189,7 @@ class FlowGraphNaturalLoop
bool HasDef(unsigned lclNum);

bool CanDuplicate(INDEBUG(const char** reason));
void Duplicate(BasicBlock** insertAfter, BlockToBlockMap* map, weight_t weightScale, bool bottomNeedsRedirection);
void Duplicate(BasicBlock** insertAfter, BlockToBlockMap* map, weight_t weightScale);

#ifdef DEBUG
static void Dump(FlowGraphNaturalLoop* loop);
Expand Down Expand Up @@ -6783,7 +6783,7 @@ class Compiler
bool optCompactLoop(FlowGraphNaturalLoop* loop);
BasicBlock* optFindLoopCompactionInsertionPoint(FlowGraphNaturalLoop* loop, BasicBlock* top);
BasicBlock* optTryAdvanceLoopCompactionInsertionPoint(FlowGraphNaturalLoop* loop, BasicBlock* insertionPoint, BasicBlock* top, BasicBlock* bottom);
bool optLoopCompactionFixupFallThrough(BasicBlock* block, BasicBlock* oldNext, BasicBlock* newNext);
bool optLoopCompactionFixupFallThrough(BasicBlock* block, BasicBlock* newNext);
bool optCreatePreheader(FlowGraphNaturalLoop* loop);
void optSetPreheaderWeight(FlowGraphNaturalLoop* loop, BasicBlock* preheader);

Expand Down
Loading

0 comments on commit 3115a9c

Please sign in to comment.