Skip to content

Commit

Permalink
JIT: Allow BBJ_COND false target to diverge from bbNext in layout opt…
Browse files Browse the repository at this point in the history
…imization phase (dotnet#96609)

Next step for dotnet#93020. Working backwards through the JIT flowgraph phases, this change allows bbFalseTarget to diverge from bbNext in Compiler::optOptimizeLayout and onwards.
  • Loading branch information
amanasifkhalid authored Jan 17, 2024
1 parent 3b58f10 commit 5598dac
Show file tree
Hide file tree
Showing 19 changed files with 364 additions and 286 deletions.
14 changes: 8 additions & 6 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 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 @@ -1170,7 +1172,7 @@ unsigned BasicBlock::NumSucc() const
return 1;

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

case BBJ_COND:
if (bbTarget == bbNext)
if (bbTrueTarget == bbFalseTarget)
{
return 1;
}
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/jit/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,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 @@ -669,7 +669,6 @@ struct BasicBlock : private LIR::Range
{
assert(KindIs(BBJ_COND));
assert(bbTrueTarget != nullptr);
assert(target != nullptr);
return (bbTrueTarget == target);
}

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

void SetCond(BasicBlock* trueTarget, BasicBlock* falseTarget)
{
// Switch lowering may temporarily set a block to a BBJ_COND
// with a null false target if it is the last block in the list.
// This invalid state is eventually fixed, so allow it in the below assert.
assert((falseTarget != nullptr) || (falseTarget == bbNext));
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 @@ -4650,6 +4650,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 @@ -4877,6 +4884,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 @@ -397,7 +397,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 @@ -2621,9 +2621,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
26 changes: 24 additions & 2 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 @@ -4874,16 +4881,31 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)

case GT_JCC:
{
#if !FEATURE_FIXED_OUT_ARGS
BasicBlock* tgtBlock = compiler->compCurBB->KindIs(BBJ_COND) ? compiler->compCurBB->GetTrueTarget()
: compiler->compCurBB->GetTarget();
#if !FEATURE_FIXED_OUT_ARGS
assert((tgtBlock->bbTgtStkDepth * sizeof(int) == genStackLevel) || isFramePointerUsed());
#endif // !FEATURE_FIXED_OUT_ARGS

GenTreeCC* jcc = treeNode->AsCC();
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))
{
emit->emitIns_J(ins, compiler->compCurBB->GetTrueTarget(), (int)1 /* cc */);

// 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);
}
}
else
{
emit->emitIns_J(ins, compiler->compCurBB->GetTarget(), (int)1 /* cc */);
}
}
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 @@ -3920,6 +3920,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 @@ -1453,6 +1453,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: 1 addition & 3 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5956,7 +5956,7 @@ class Compiler

void fgUpdateLoopsAfterCompacting(BasicBlock* block, BasicBlock* bNext);

BasicBlock* fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst);
BasicBlock* fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst, bool noFallThroughQuirk = false);

bool fgRenumberBlocks();

Expand Down Expand Up @@ -6003,8 +6003,6 @@ class Compiler

bool fgOptimizeSwitchBranches(BasicBlock* block);

bool fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev);

bool fgOptimizeSwitchJumps();
#ifdef DEBUG
void fgPrintEdgeWeights();
Expand Down
Loading

0 comments on commit 5598dac

Please sign in to comment.