diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index e823972ba864b7..40fa3b7a00dd74 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -5966,8 +5966,6 @@ class Compiler bool fgOptimizeSwitchBranches(BasicBlock* block); - bool fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev); - bool fgOptimizeSwitchJumps(); #ifdef DEBUG void fgPrintEdgeWeights(); diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 39440510a60e7e..4675c6208bdbd9 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -1442,109 +1442,6 @@ void Compiler::fgUnreachableBlock(BasicBlock* block) fgRemoveBlockAsPred(block); } -//------------------------------------------------------------- -// fgRemoveConditionalJump: Remove or morph a jump when we jump to the same -// block when both the condition is true or false. Remove the branch condition, -// but leave any required side effects. -// -// Arguments: -// block - block with conditional branch -// -void Compiler::fgRemoveConditionalJump(BasicBlock* block) -{ - noway_assert(block->KindIs(BBJ_COND) && block->TrueTargetIs(block->GetFalseTarget())); - assert(compRationalIRForm == block->IsLIR()); - - FlowEdge* flow = fgGetPredForBlock(block->GetFalseTarget(), block); - noway_assert(flow->getDupCount() == 2); - - // Change the BBJ_COND to BBJ_ALWAYS, and adjust the refCount and dupCount. - --block->GetFalseTarget()->bbRefs; - block->SetKind(BBJ_ALWAYS); - block->SetFlags(BBF_NONE_QUIRK); - flow->decrementDupCount(); - -#ifdef DEBUG - if (verbose) - { - printf("Block " FMT_BB " becoming a BBJ_ALWAYS to " FMT_BB " (jump target is the same whether the condition" - " is true or false)\n", - block->bbNum, block->GetTarget()->bbNum); - } -#endif - - // Remove the block jump condition - - if (block->IsLIR()) - { - LIR::Range& blockRange = LIR::AsRange(block); - - GenTree* test = blockRange.LastNode(); - assert(test->OperIsConditionalJump()); - - bool isClosed; - unsigned sideEffects; - LIR::ReadOnlyRange testRange = blockRange.GetTreeRange(test, &isClosed, &sideEffects); - - // TODO-LIR: this should really be checking GTF_ALL_EFFECT, but that produces unacceptable - // diffs compared to the existing backend. - if (isClosed && ((sideEffects & GTF_SIDE_EFFECT) == 0)) - { - // If the jump and its operands form a contiguous, side-effect-free range, - // remove them. - blockRange.Delete(this, block, std::move(testRange)); - } - else - { - // Otherwise, just remove the jump node itself. - blockRange.Remove(test, true); - } - } - else - { - Statement* test = block->lastStmt(); - GenTree* tree = test->GetRootNode(); - - noway_assert(tree->gtOper == GT_JTRUE); - - GenTree* sideEffList = nullptr; - - if (tree->gtFlags & GTF_SIDE_EFFECT) - { - gtExtractSideEffList(tree, &sideEffList); - - if (sideEffList) - { - noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT); -#ifdef DEBUG - if (verbose) - { - printf("Extracted side effects list from condition...\n"); - gtDispTree(sideEffList); - printf("\n"); - } -#endif - } - } - - // Delete the cond test or replace it with the side effect tree - if (sideEffList == nullptr) - { - fgRemoveStmt(block, test); - } - else - { - test->SetRootNode(sideEffList); - - if (fgNodeThreading != NodeThreading::None) - { - gtSetStmtInfo(test); - fgSetStmtSeq(test); - } - } - } -} - //------------------------------------------------------------- // fgOptimizeBranchToEmptyUnconditional: // Optimize a jump to an empty block which ends in an unconditional branch. @@ -2610,27 +2507,25 @@ bool Compiler::fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock* } //------------------------------------------------------------- -// fgOptimizeBranchToNext: -// Optimize a block which has a branch to the following block +// fgRemoveConditionalJump: +// Optimize a BBJ_COND block that unconditionally jumps to the same target // // Arguments: -// block - block with a BBJ_COND jump kind -// bNext - target that block jumps to regardless of its condition -// bPrev - block which is prior to the first block +// block - BBJ_COND block with identical true/false targets // -// Returns: true if changes were made -// -bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev) +void Compiler::fgRemoveConditionalJump(BasicBlock* block) { assert(block->KindIs(BBJ_COND)); - assert(block->TrueTargetIs(bNext)); - assert(block->FalseTargetIs(bNext)); - assert(block->PrevIs(bPrev)); + assert(block->TrueTargetIs(block->GetFalseTarget())); + + BasicBlock* target = block->GetTrueTarget(); #ifdef DEBUG if (verbose) { - printf("\nRemoving conditional jump to next block (" FMT_BB " -> " FMT_BB ")\n", block->bbNum, bNext->bbNum); + printf("Block " FMT_BB " becoming a BBJ_ALWAYS to " FMT_BB " (jump target is the same whether the condition" + " is true or false)\n", + block->bbNum, target->bbNum); } #endif // DEBUG @@ -2729,17 +2624,19 @@ bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, Basi } } - /* Conditional is gone - always jump to the next block */ + /* Conditional is gone - always jump to target */ block->SetKind(BBJ_ALWAYS); + assert(block->TargetIs(target)); + + // TODO-NoFallThrough: Set BBF_NONE_QUIRK only when false target is the next block + block->SetFlags(BBF_NONE_QUIRK); /* Update bbRefs and bbNum - Conditional predecessors to the same * block are counted twice so we have to remove one of them */ - noway_assert(bNext->countOfInEdges() > 1); - fgRemoveRefPred(bNext, block); - - return true; + noway_assert(target->countOfInEdges() > 1); + fgRemoveRefPred(target, block); } //------------------------------------------------------------- @@ -4928,12 +4825,15 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication, bool isPhase) { // TODO-NoFallThrough: Fix above condition once bbFalseTarget can diverge from bbNext assert(block->FalseTargetIs(bNext)); - if (fgOptimizeBranchToNext(block, bNext, bPrev)) - { - change = true; - modified = true; - bDest = nullptr; - } + fgRemoveConditionalJump(block); + + assert(block->KindIs(BBJ_ALWAYS)); + assert(block->TargetIs(bNext)); + change = true; + modified = true; + + // Skip jump optimizations, and try to compact block and bNext later + bDest = nullptr; } }