diff options
-rw-r--r-- | src/coreclr/jit/block.cpp | 132 | ||||
-rw-r--r-- | src/coreclr/jit/block.h | 34 | ||||
-rw-r--r-- | src/coreclr/jit/compiler.h | 2 | ||||
-rw-r--r-- | src/coreclr/jit/dataflow.h | 2 | ||||
-rw-r--r-- | src/coreclr/jit/flowgraph.cpp | 267 | ||||
-rw-r--r-- | src/coreclr/jit/jitstd/vector.h | 4 | ||||
-rw-r--r-- | src/coreclr/jit/lsra.cpp | 14 | ||||
-rw-r--r-- | src/coreclr/jit/optimizer.cpp | 34 | ||||
-rw-r--r-- | src/coreclr/jit/ssabuilder.cpp | 18 | ||||
-rw-r--r-- | src/coreclr/jit/valuenum.cpp | 6 | ||||
-rw-r--r-- | src/tests/JIT/Regression/JitBlue/GitHub_18056/Bool_And_Op_cs_do.csproj | 1 |
11 files changed, 359 insertions, 155 deletions
diff --git a/src/coreclr/jit/block.cpp b/src/coreclr/jit/block.cpp index 3c6fd6297df..f2b14599335 100644 --- a/src/coreclr/jit/block.cpp +++ b/src/coreclr/jit/block.cpp @@ -15,6 +15,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #pragma hdrstop #endif +#include "jitstd/algorithm.h" + #if MEASURE_BLOCK_SIZE /* static */ size_t BasicBlock::s_Size; @@ -34,7 +36,7 @@ flowList* ShuffleHelper(unsigned hash, flowList* res) flowList* head = res; for (flowList *prev = nullptr; res != nullptr; prev = res, res = res->flNext) { - unsigned blkHash = (hash ^ (res->flBlock->bbNum << 16) ^ res->flBlock->bbNum); + unsigned blkHash = (hash ^ (res->getBlock()->bbNum << 16) ^ res->getBlock()->bbNum); if (((blkHash % 1879) & 1) && prev != nullptr) { // Swap res with head. @@ -164,7 +166,7 @@ flowList* Compiler::BlockPredsWithEH(BasicBlock* blk) for (flowList* tryStartPreds = tryStart->bbPreds; tryStartPreds != nullptr; tryStartPreds = tryStartPreds->flNext) { - res = new (this, CMK_FlowList) flowList(tryStartPreds->flBlock, res); + res = new (this, CMK_FlowList) flowList(tryStartPreds->getBlock(), res); #if MEASURE_BLOCK_SIZE genFlowNodeCnt += 1; @@ -206,6 +208,126 @@ flowList* Compiler::BlockPredsWithEH(BasicBlock* blk) return res; } +//------------------------------------------------------------------------ +// checkPredListOrder: see if pred list is properly ordered +// +// Returns: +// false if pred list is not in increasing bbNum order. +// +bool BasicBlock::checkPredListOrder() +{ + unsigned lastBBNum = 0; + for (flowList* pred = bbPreds; pred != nullptr; pred = pred->flNext) + { + const unsigned bbNum = pred->getBlock()->bbNum; + if (bbNum <= lastBBNum) + { + assert(bbNum != lastBBNum); + return false; + } + lastBBNum = bbNum; + } + return true; +} + +//------------------------------------------------------------------------ +// ensurePredListOrder: ensure all pred list entries appear in increasing +// bbNum order. +// +// Arguments: +// compiler - current compiler instance +// +void BasicBlock::ensurePredListOrder(Compiler* compiler) +{ + // First, check if list is already in order. + // + if (checkPredListOrder()) + { + return; + } + + reorderPredList(compiler); + assert(checkPredListOrder()); +} + +//------------------------------------------------------------------------ +// reorderPredList: relink pred list in increasing bbNum order. +// +// Arguments: +// compiler - current compiler instance +// +void BasicBlock::reorderPredList(Compiler* compiler) +{ + // Count number or entries. + // + int count = 0; + for (flowList* pred = bbPreds; pred != nullptr; pred = pred->flNext) + { + count++; + } + + // If only 0 or 1 entry, nothing to reorder. + // + if (count < 2) + { + return; + } + + // Allocate sort vector if needed. + // + if (compiler->fgPredListSortVector == nullptr) + { + CompAllocator allocator = compiler->getAllocator(CMK_FlowList); + compiler->fgPredListSortVector = new (allocator) jitstd::vector<flowList*>(allocator); + } + + jitstd::vector<flowList*>* const sortVector = compiler->fgPredListSortVector; + sortVector->clear(); + + // Fill in the vector from the list. + // + for (flowList* pred = bbPreds; pred != nullptr; pred = pred->flNext) + { + sortVector->push_back(pred); + } + + // Sort by increasing bbNum + // + struct flowListBBNumCmp + { + bool operator()(const flowList* f1, const flowList* f2) + { + return f1->getBlock()->bbNum < f2->getBlock()->bbNum; + } + }; + + jitstd::sort(sortVector->begin(), sortVector->end(), flowListBBNumCmp()); + + // Rethread the list. + // + flowList* last = nullptr; + + for (flowList* current : *sortVector) + { + if (last == nullptr) + { + bbPreds = current; + } + else + { + last->flNext = current; + } + + last = current; + } + + last->flNext = nullptr; + + // Note this lastPred is only used transiently. + // + bbLastPred = last; +} + #ifdef DEBUG //------------------------------------------------------------------------ @@ -401,11 +523,11 @@ unsigned BasicBlock::dspPreds() printf(","); count += 1; } - printf(FMT_BB, pred->flBlock->bbNum); + printf(FMT_BB, pred->getBlock()->bbNum); count += 4; // Account for %02u only handling 2 digits, but we can display more than that. - unsigned digits = CountDigits(pred->flBlock->bbNum); + unsigned digits = CountDigits(pred->getBlock()->bbNum); if (digits > 2) { count += digits - 2; @@ -746,7 +868,7 @@ BasicBlock* BasicBlock::GetUniquePred(Compiler* compiler) } else { - return bbPreds->flBlock; + return bbPreds->getBlock(); } } diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h index 89a442e2f8b..02c37361e83 100644 --- a/src/coreclr/jit/block.h +++ b/src/coreclr/jit/block.h @@ -863,6 +863,12 @@ struct BasicBlock : private LIR::Range flowList* bbPreds; // ptr to list of predecessors }; + // Pred list maintenance + // + bool checkPredListOrder(); + void ensurePredListOrder(Compiler* compiler); + void reorderPredList(Compiler* compiler); + BlockSet bbReach; // Set of all blocks that can reach this one BasicBlock* bbIDom; // Represent the closest dominator to this block (called the Immediate // Dominator) used to compute the dominance tree. @@ -1230,19 +1236,33 @@ struct BasicBlockList struct flowList { - flowList* flNext; // The next BasicBlock in the list, nullptr for end of list. - BasicBlock* flBlock; // The BasicBlock of interest. - unsigned flDupCount; // The count of duplicate "edges" (use only for switch stmts) +public: + flowList* flNext; // The next BasicBlock in the list, nullptr for end of list. private: + BasicBlock* m_block; // The BasicBlock of interest. BasicBlock::weight_t flEdgeWeightMin; BasicBlock::weight_t flEdgeWeightMax; public: + unsigned flDupCount; // The count of duplicate "edges" (use only for switch stmts) + +public: + BasicBlock* getBlock() const + { + return m_block; + } + + void setBlock(BasicBlock* newBlock) + { + m_block = newBlock; + } + BasicBlock::weight_t edgeWeightMin() const { return flEdgeWeightMin; } + BasicBlock::weight_t edgeWeightMax() const { return flEdgeWeightMax; @@ -1257,12 +1277,8 @@ public: bool setEdgeWeightMaxChecked(BasicBlock::weight_t newWeight, BasicBlock::weight_t slop, bool* wbUsedSlop); void setEdgeWeights(BasicBlock::weight_t newMinWeight, BasicBlock::weight_t newMaxWeight); - flowList() : flNext(nullptr), flBlock(nullptr), flDupCount(0), flEdgeWeightMin(0), flEdgeWeightMax(0) - { - } - - flowList(BasicBlock* blk, flowList* rest) - : flNext(rest), flBlock(blk), flDupCount(0), flEdgeWeightMin(0), flEdgeWeightMax(0) + flowList(BasicBlock* block, flowList* rest) + : flNext(rest), m_block(block), flEdgeWeightMin(0), flEdgeWeightMax(0), flDupCount(0) { } }; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 2376314965f..1cdebfb9c3c 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4647,6 +4647,8 @@ public: bool fgPrintInlinedMethods; #endif + jitstd::vector<flowList*>* fgPredListSortVector; + //------------------------------------------------------------------------- void fgInit(); diff --git a/src/coreclr/jit/dataflow.h b/src/coreclr/jit/dataflow.h index 307ce02770f..3f2ff1cc72a 100644 --- a/src/coreclr/jit/dataflow.h +++ b/src/coreclr/jit/dataflow.h @@ -61,7 +61,7 @@ void DataFlow::ForwardAnalysis(TCallback& callback) flowList* preds = m_pCompiler->BlockPredsWithEH(block); for (flowList* pred = preds; pred; pred = pred->flNext) { - callback.Merge(block, pred->flBlock, preds); + callback.Merge(block, pred->getBlock(), preds); } } diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 46c4e75cdfb..cab86e8dd4b 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -178,6 +178,8 @@ void Compiler::fgInit() fgHasSwitch = false; fgBlockCounts = nullptr; + + fgPredListSortVector = nullptr; } //------------------------------------------------------------------------ @@ -1322,7 +1324,7 @@ flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred) for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext) { - if (blockPred == pred->flBlock) + if (blockPred == pred->getBlock()) { return pred; } @@ -1361,7 +1363,7 @@ flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred, for (predPrevAddr = &block->bbPreds, pred = *predPrevAddr; pred != nullptr; predPrevAddr = &pred->flNext, pred = *predPrevAddr) { - if (blockPred == pred->flBlock) + if (blockPred == pred->getBlock()) { *ptrToPred = predPrevAddr; return pred; @@ -1402,7 +1404,7 @@ flowList* Compiler::fgSpliceOutPred(BasicBlock* block, BasicBlock* blockPred) flowList* oldEdge = nullptr; // Is this the first block in the pred list? - if (blockPred == block->bbPreds->flBlock) + if (blockPred == block->bbPreds->getBlock()) { oldEdge = block->bbPreds; block->bbPreds = block->bbPreds->flNext; @@ -1410,7 +1412,7 @@ flowList* Compiler::fgSpliceOutPred(BasicBlock* block, BasicBlock* blockPred) else { flowList* pred; - for (pred = block->bbPreds; (pred->flNext != nullptr) && (blockPred != pred->flNext->flBlock); + for (pred = block->bbPreds; (pred->flNext != nullptr) && (blockPred != pred->flNext->getBlock()); pred = pred->flNext) { // empty @@ -1499,9 +1501,9 @@ flowList* Compiler::fgAddRefPred(BasicBlock* block, { listp = &flowLast->flNext; - assert(flowLast->flBlock->bbNum <= blockPred->bbNum); + assert(flowLast->getBlock()->bbNum <= blockPred->bbNum); - if (flowLast->flBlock == blockPred) + if (flowLast->getBlock() == blockPred) { flow = flowLast; } @@ -1511,12 +1513,12 @@ flowList* Compiler::fgAddRefPred(BasicBlock* block, { // References are added randomly, so we have to search. // - while ((*listp != nullptr) && ((*listp)->flBlock->bbNum < blockPred->bbNum)) + while ((*listp != nullptr) && ((*listp)->getBlock()->bbNum < blockPred->bbNum)) { listp = &(*listp)->flNext; } - if ((*listp != nullptr) && ((*listp)->flBlock == blockPred)) + if ((*listp != nullptr) && ((*listp)->getBlock() == blockPred)) { flow = *listp; } @@ -1530,7 +1532,6 @@ flowList* Compiler::fgAddRefPred(BasicBlock* block, } else { - flow = new (this, CMK_FlowList) flowList(); #if MEASURE_BLOCK_SIZE genFlowNodeCnt += 1; @@ -1540,12 +1541,11 @@ flowList* Compiler::fgAddRefPred(BasicBlock* block, // Any changes to the flow graph invalidate the dominator sets. fgModified = true; - // Insert the new edge in the list in the correct ordered location. - flow->flNext = *listp; - *listp = flow; - - flow->flBlock = blockPred; + // Create new edge in the list in the correct ordered location. + // + flow = new (this, CMK_FlowList) flowList(blockPred, *listp); flow->flDupCount = 1; + *listp = flow; if (initializingPreds) { @@ -1588,6 +1588,11 @@ flowList* Compiler::fgAddRefPred(BasicBlock* block, flow->setEdgeWeights(BB_ZERO_WEIGHT, BB_MAX_WEIGHT); } } + + // Pred list should (still) be ordered. + // + assert(block->checkPredListOrder()); + return flow; } @@ -1771,7 +1776,7 @@ void Compiler::fgRemoveBlockAsPred(BasicBlock* block) while (bNext->countOfInEdges() > 0) { - fgRemoveRefPred(bNext, bNext->bbPreds->flBlock); + fgRemoveRefPred(bNext, bNext->bbPreds->getBlock()); } } @@ -2064,19 +2069,28 @@ void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, Bas } } -/***************************************************************************** - * Updates the predecessor list for 'block' by replacing 'oldPred' with 'newPred'. - * Note that a block can only appear once in the preds list (for normal preds, not - * cheap preds): if a predecessor has multiple ways to get to this block, then - * flDupCount will be >1, but the block will still appear exactly once. Thus, this - * function assumes that all branches from the predecessor (practically, that all - * switch cases that target this block) are changed to branch from the new predecessor, - * with the same dup count. - * - * Note that the block bbRefs is not changed, since 'block' has the same number of - * references as before, just from a different predecessor block. - */ - +//------------------------------------------------------------------------ +// fgReplacePred: update the predecessor list, swapping one pred for another +// +// Arguments: +// block - block with the pred list we want to update +// oldPred - pred currently appearing in block's pred list +// newPred - pred that will take oldPred's place. +// +// Notes: +// +// A block can only appear once in the preds list (for normal preds, not +// cheap preds): if a predecessor has multiple ways to get to this block, then +// flDupCount will be >1, but the block will still appear exactly once. Thus, this +// function assumes that all branches from the predecessor (practically, that all +// switch cases that target this block) are changed to branch from the new predecessor, +// with the same dup count. +// +// Note that the block bbRefs is not changed, since 'block' has the same number of +// references as before, just from a different predecessor block. +// +// Also note this may cause sorting of the pred list. +// void Compiler::fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock* newPred) { noway_assert(block != nullptr); @@ -2084,16 +2098,24 @@ void Compiler::fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock* noway_assert(newPred != nullptr); assert(!fgCheapPredsValid); - flowList* pred; + bool modified = false; - for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext) + for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext) { - if (oldPred == pred->flBlock) + if (oldPred == pred->getBlock()) { - pred->flBlock = newPred; + pred->setBlock(newPred); + modified = true; break; } } + + // We may now need to reorder the pred list. + // + if (modified) + { + block->ensurePredListOrder(this); + } } /***************************************************************************** @@ -2125,7 +2147,7 @@ bool Compiler::fgDominate(BasicBlock* b1, BasicBlock* b2) for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext) { - if (!fgDominate(b1, pred->flBlock)) + if (!fgDominate(b1, pred->getBlock())) { return false; } @@ -2198,7 +2220,7 @@ bool Compiler::fgReachable(BasicBlock* b1, BasicBlock* b2) for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext) { - if (fgReachable(b1, pred->flBlock)) + if (fgReachable(b1, pred->getBlock())) { return true; } @@ -2310,7 +2332,7 @@ void Compiler::fgComputeReachabilitySets() for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); /* Union the predecessor's reachability set into newReach */ BlockSetOps::UnionD(this, newReach, predBlock->bbReach); @@ -2512,7 +2534,7 @@ bool Compiler::fgRemoveUnreachableBlocks() unsigned blockNum = block->bbNum; for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); if (blockNum <= predBlock->bbNum) { if (predBlock->bbJumpKind == BBJ_CALLFINALLY) @@ -2884,7 +2906,7 @@ void Compiler::fgComputeDoms() // (with bbRoot as the only basic block in it) set as flRoot. // Later on, we clear their predecessors and let them to be nullptr again. // Since we number basic blocks starting at one, the imaginary entry block is conveniently numbered as zero. - flowList flRoot; + BasicBlock bbRoot; bbRoot.bbPreds = nullptr; @@ -2892,8 +2914,8 @@ void Compiler::fgComputeDoms() bbRoot.bbIDom = &bbRoot; bbRoot.bbPostOrderNum = 0; bbRoot.bbFlags = 0; - flRoot.flNext = nullptr; - flRoot.flBlock = &bbRoot; + + flowList flRoot(&bbRoot, nullptr); fgBBInvPostOrder[0] = &bbRoot; @@ -2964,7 +2986,7 @@ void Compiler::fgComputeDoms() // Pick up the first processed predecesor of the current block. for (first = block->bbPreds; first != nullptr; first = first->flNext) { - if (BlockSetOps::IsMember(this, processedBlks, first->flBlock->bbNum)) + if (BlockSetOps::IsMember(this, processedBlks, first->getBlock()->bbNum)) { break; } @@ -2973,21 +2995,21 @@ void Compiler::fgComputeDoms() // We assume the first processed predecessor will be the // immediate dominator and then compute the forward flow analysis. - newidom = first->flBlock; + newidom = first->getBlock(); for (flowList* p = block->bbPreds; p != nullptr; p = p->flNext) { - if (p->flBlock == first->flBlock) + if (p->getBlock() == first->getBlock()) { continue; } - if (p->flBlock->bbIDom != nullptr) + if (p->getBlock()->bbIDom != nullptr) { // fgIntersectDom is basically the set intersection between // the dominance sets of the new IDom and the current predecessor // Since the nodes are ordered in DFS inverse post order and // IDom induces a tree, fgIntersectDom actually computes // the lowest common ancestor in the dominator tree. - newidom = fgIntersectDom(p->flBlock, newidom); + newidom = fgIntersectDom(p->getBlock(), newidom); } } @@ -10524,7 +10546,7 @@ bool Compiler::fgCanCompactBlocks(BasicBlock* block, BasicBlock* bNext) // (if they are valid) for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext) { - if (pred->flBlock->bbJumpKind == BBJ_SWITCH) + if (pred->getBlock()->bbJumpKind == BBJ_SWITCH) { return false; } @@ -10583,11 +10605,11 @@ void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext) block->bbFlags |= BBF_JMP_TARGET; for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext) { - fgReplaceJumpTarget(pred->flBlock, block, bNext); + fgReplaceJumpTarget(pred->getBlock(), block, bNext); - if (pred->flBlock != block) + if (pred->getBlock() != block) { - fgAddRefPred(block, pred->flBlock); + fgAddRefPred(block, pred->getBlock()); } } bNext->bbPreds = nullptr; @@ -10595,7 +10617,7 @@ void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext) else { noway_assert(bNext->bbPreds->flNext == nullptr); - noway_assert(bNext->bbPreds->flBlock == block); + noway_assert(bNext->bbPreds->getBlock() == block); } /* Start compacting - move all the statements in the second block to the first block */ @@ -10845,22 +10867,6 @@ void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext) ehUpdateForDeletedBlock(bNext); - /* If we're collapsing a block created after the dominators are - computed, rename the block and reuse dominator information from - the other block */ - if (fgDomsComputed && block->bbNum > fgDomBBcount) - { - BlockSetOps::Assign(this, block->bbReach, bNext->bbReach); - BlockSetOps::ClearD(this, bNext->bbReach); - - block->bbIDom = bNext->bbIDom; - bNext->bbIDom = nullptr; - - // In this case, there's no need to update the preorder and postorder numbering - // since we're changing the bbNum, this makes the basic block all set. - block->bbNum = bNext->bbNum; - } - /* Set the jump targets */ switch (bNext->bbJumpKind) @@ -10939,6 +10945,45 @@ void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext) break; } + // If we're collapsing a block created after the dominators are + // computed, copy block number the block and reuse dominator + // information from bNext to block. + // + // Note we have to do this renumbering after the full set of pred list + // updates above, since those updates rely on stable bbNums; if we renumber + // before the updates, we can create pred lists with duplicate m_block->bbNum + // values (though different m_blocks). + // + if (fgDomsComputed && (block->bbNum > fgDomBBcount)) + { + BlockSetOps::Assign(this, block->bbReach, bNext->bbReach); + BlockSetOps::ClearD(this, bNext->bbReach); + + block->bbIDom = bNext->bbIDom; + bNext->bbIDom = nullptr; + + // In this case, there's no need to update the preorder and postorder numbering + // since we're changing the bbNum, this makes the basic block all set. + // + JITDUMP("Renumbering BB%02u to be BB%02u to preserve dominator information\n", block->bbNum, bNext->bbNum); + + block->bbNum = bNext->bbNum; + + // Because we may have reordered pred lists when we swapped in + // block for bNext above, we now need to re-reorder pred lists + // to reflect the bbNum update. + // + // This process of reordering and re-reordering could likely be avoided + // via a different update strategy. But because it's probably rare, + // and we avoid most of the work if pred lists are already in order, + // we'll just ensure everything is properly ordered. + // + for (BasicBlock* checkBlock = fgFirstBB; checkBlock != nullptr; checkBlock = checkBlock->bbNext) + { + checkBlock->ensurePredListOrder(this); + } + } + fgUpdateLoopsAfterCompacting(block, bNext); #if DEBUG @@ -11568,7 +11613,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) for (flowList* pred = block->bbPreds; pred; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); /* Are we changing a loop backedge into a forward jump? */ @@ -11837,15 +11882,22 @@ BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst) return jmpBlk; } -/***************************************************************************** - Walk the flow graph, reassign block numbers to keep them in ascending order. - Returns 'true' if any renumbering was actually done, OR if we change the - maximum number of assigned basic blocks (this can happen if we do inlining, - create a new, high-numbered block, then that block goes away. We go to - renumber the blocks, none of them actually change number, but we shrink the - maximum assigned block number. This affects the block set epoch). -*/ - +//------------------------------------------------------------------------ +// fgRenumberBlocks: update block bbNums to reflect bbNext order +// +// Returns: +// true if blocks were renumbered or maxBBNum was updated. +// +// Notes: +// Walk the flow graph, reassign block numbers to keep them in ascending order. +// Return 'true' if any renumbering was actually done, OR if we change the +// maximum number of assigned basic blocks (this can happen if we do inlining, +// create a new, high-numbered block, then that block goes away. We go to +// renumber the blocks, none of them actually change number, but we shrink the +// maximum assigned block number. This affects the block set epoch). +// +// As a consequence of renumbering, block pred lists may need to be reordered. +// bool Compiler::fgRenumberBlocks() { // If we renumber the blocks the dominator information will be out-of-date @@ -11909,6 +11961,16 @@ bool Compiler::fgRenumberBlocks() } } + // If we renumbered, then we may need to reorder some pred lists. + // + if (renumbered && fgComputePredsDone) + { + for (block = fgFirstBB; block != nullptr; block = block->bbNext) + { + block->ensurePredListOrder(this); + } + } + #ifdef DEBUG if (verbose) { @@ -12134,19 +12196,19 @@ bool Compiler::fgExpandRarelyRunBlocks() if (bPrevPrev == nullptr) { // Initially we select the first block in the bbPreds list - bPrevPrev = pred->flBlock; + bPrevPrev = pred->getBlock(); continue; } - // Walk the flow graph lexically forward from pred->flBlock + // Walk the flow graph lexically forward from pred->getBlock() // if we find (block == bPrevPrev) then - // pred->flBlock is an earlier predecessor. - for (tmpbb = pred->flBlock; tmpbb != nullptr; tmpbb = tmpbb->bbNext) + // pred->getBlock() is an earlier predecessor. + for (tmpbb = pred->getBlock(); tmpbb != nullptr; tmpbb = tmpbb->bbNext) { if (tmpbb == bPrevPrev) { /* We found an ealier predecessor */ - bPrevPrev = pred->flBlock; + bPrevPrev = pred->getBlock(); break; } else if (tmpbb == bPrev) @@ -12202,7 +12264,7 @@ bool Compiler::fgExpandRarelyRunBlocks() for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext) { /* Find the fall through predecessor, if any */ - if (!pred->flBlock->isRunRarely()) + if (!pred->getBlock()->isRunRarely()) { rare = false; break; @@ -12737,9 +12799,9 @@ void Compiler::fgClearFinallyTargetBit(BasicBlock* block) for (flowList* pred = block->bbPreds; pred; pred = pred->flNext) { - if (pred->flBlock->bbJumpKind == BBJ_ALWAYS && pred->flBlock->bbJumpDest == block) + if (pred->getBlock()->bbJumpKind == BBJ_ALWAYS && pred->getBlock()->bbJumpDest == block) { - BasicBlock* pPrev = pred->flBlock->bbPrev; + BasicBlock* pPrev = pred->getBlock()->bbPrev; if (pPrev != NULL) { if (pPrev->bbJumpKind == BBJ_CALLFINALLY) @@ -12892,7 +12954,7 @@ bool Compiler::fgAnyIntraHandlerPreds(BasicBlock* block) for (pred = block->bbPreds; pred; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); if (fgIsIntraHandlerPred(predBlock, block)) { @@ -12942,7 +13004,7 @@ void Compiler::fgInsertFuncletPrologBlock(BasicBlock* block) for (flowList* pred = block->bbPreds; pred; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); if (!fgIsIntraHandlerPred(predBlock, block)) { // It's a jump from outside the handler; add it to the newHead preds list and remove @@ -13435,7 +13497,7 @@ void Compiler::fgPrintEdgeWeights() printf(" Edge weights into " FMT_BB " :", bDst->bbNum); for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext) { - bSrc = edge->flBlock; + bSrc = edge->getBlock(); // This is the control flow edge (bSrc -> bDst) printf(FMT_BB " ", bSrc->bbNum); @@ -13578,7 +13640,7 @@ BasicBlock::weight_t Compiler::fgComputeMissingBlockWeights() if (bDst->countOfInEdges() == 1) { // Only one block flows into bDst - bSrc = bDst->bbPreds->flBlock; + bSrc = bDst->bbPreds->getBlock(); // Does this block flow into only one other block if (bSrc->bbJumpKind == BBJ_NONE) @@ -13620,7 +13682,7 @@ BasicBlock::weight_t Compiler::fgComputeMissingBlockWeights() // Does only one block flow into bOnlyNext if (bOnlyNext->countOfInEdges() == 1) { - noway_assert(bOnlyNext->bbPreds->flBlock == bDst); + noway_assert(bOnlyNext->bbPreds->getBlock() == bDst); // We know the exact weight of bDst newWeight = bOnlyNext->bbWeight; @@ -13772,7 +13834,7 @@ void Compiler::fgComputeEdgeWeights() { bool assignOK = true; - bSrc = edge->flBlock; + bSrc = edge->getBlock(); // We are processing the control flow edge (bSrc -> bDst) numEdges++; @@ -13850,7 +13912,7 @@ void Compiler::fgComputeEdgeWeights() bool assignOK = true; // We are processing the control flow edge (bSrc -> bDst) - bSrc = edge->flBlock; + bSrc = edge->getBlock(); slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1; if (bSrc->bbJumpKind == BBJ_COND) @@ -13939,7 +14001,7 @@ void Compiler::fgComputeEdgeWeights() for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext) { // We are processing the control flow edge (bSrc -> bDst) - bSrc = edge->flBlock; + bSrc = edge->getBlock(); maxEdgeWeightSum += edge->edgeWeightMax(); minEdgeWeightSum += edge->edgeWeightMin(); @@ -13953,7 +14015,7 @@ void Compiler::fgComputeEdgeWeights() bool assignOK = true; // We are processing the control flow edge (bSrc -> bDst) - bSrc = edge->flBlock; + bSrc = edge->getBlock(); slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1; // otherMaxEdgesWeightSum is the sum of all of the other edges flEdgeWeightMax values @@ -14064,7 +14126,7 @@ EARLY_EXIT:; { for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext) { - bSrc = edge->flBlock; + bSrc = edge->getBlock(); // This is the control flow edge (bSrc -> bDst) if (edge->edgeWeightMin() != edge->edgeWeightMax()) @@ -14364,9 +14426,9 @@ bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block) bool okToMerge = true; // assume it's ok for (flowList* pred = block->bbPreds; pred; pred = pred->flNext) { - if (pred->flBlock->bbJumpKind == BBJ_EHCATCHRET) + if (pred->getBlock()->bbJumpKind == BBJ_EHCATCHRET) { - assert(pred->flBlock->bbJumpDest == block); + assert(pred->getBlock()->bbJumpDest == block); okToMerge = false; // we can't get rid of the empty block break; } @@ -15734,7 +15796,7 @@ void Compiler::fgReorderBlocks() // Examine all of the other edges into bDest for (flowList* edge = bDest->bbPreds; edge != nullptr; edge = edge->flNext) { - BasicBlock* bTemp = edge->flBlock; + BasicBlock* bTemp = edge->getBlock(); if ((bTemp != bPrev) && (bTemp->bbWeight >= bPrev->bbWeight)) { @@ -20363,7 +20425,7 @@ bool Compiler::fgDumpFlowGraph(Phases phase) flowList* edge; for (edge = bTarget->bbPreds; edge != nullptr; edge = edge->flNext, edgeNum++) { - BasicBlock* bSource = edge->flBlock; + BasicBlock* bSource = edge->getBlock(); double sourceWeightDivisor; if (bSource->bbWeight == BB_ZERO_WEIGHT) { @@ -21210,7 +21272,7 @@ unsigned BBPredsChecker::CheckBBPreds(BasicBlock* block, unsigned curTraversalSt { blockRefs += pred->flDupCount; - BasicBlock* blockPred = pred->flBlock; + BasicBlock* blockPred = pred->getBlock(); // Make sure this pred is part of the BB list. assert(blockPred->bbTraversalStamp == curTraversalStamp); @@ -21229,6 +21291,11 @@ unsigned BBPredsChecker::CheckBBPreds(BasicBlock* block, unsigned curTraversalSt assert(CheckJump(blockPred, block)); } + + // Make sure preds are in increasting BBnum order + // + assert(block->checkPredListOrder()); + return blockRefs; } @@ -26624,7 +26691,7 @@ PhaseStatus Compiler::fgTailMergeThrows() // the canonical block instead. for (flowList* predEdge = nonCanonicalBlock->bbPreds; predEdge != nullptr; predEdge = nextPredEdge) { - BasicBlock* const predBlock = predEdge->flBlock; + BasicBlock* const predBlock = predEdge->getBlock(); nextPredEdge = predEdge->flNext; switch (predBlock->bbJumpKind) @@ -26971,7 +27038,7 @@ void Compiler::fgDebugCheckProfileData() for (flowList* edge = succBlock->bbPreds; edge != nullptr; edge = edge->flNext) { - if (edge->flBlock == block) + if (edge->getBlock() == block) { succEdge = edge; break; diff --git a/src/coreclr/jit/jitstd/vector.h b/src/coreclr/jit/jitstd/vector.h index 30a84771772..4e603ec0a35 100644 --- a/src/coreclr/jit/jitstd/vector.h +++ b/src/coreclr/jit/jitstd/vector.h @@ -953,7 +953,7 @@ T* vector<T, Allocator>::iterator::operator&() template <typename T, typename Allocator> vector<T, Allocator>::iterator::operator T*() { - return &m_pElem; + return m_pElem; } // const_iterator @@ -1151,7 +1151,7 @@ T* vector<T, Allocator>::reverse_iterator::operator&() template <typename T, typename Allocator> vector<T, Allocator>::reverse_iterator::operator T*() { - return &m_pElem; + return m_pElem; } // const_reverse_iterator diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 83f010226e3..5add9f563e5 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -942,7 +942,7 @@ void LinearScan::setBlockSequence() bool hasUniquePred = (block->GetUniquePred(compiler) != nullptr); for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); if (!hasUniquePred) { if (predBlock->NumSucc(compiler) > 1) @@ -1192,7 +1192,7 @@ void LinearScan::addToBlockSequenceWorkList(BlockSet sequencedBlockSet, BasicBlo flowList* pred; for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext) { - BlockSetOps::AddElemD(compiler, predSet, pred->flBlock->bbNum); + BlockSetOps::AddElemD(compiler, predSet, pred->getBlock()->bbNum); } // If either a rarely run block or all its preds are already sequenced, use block's weight to sequence @@ -2457,7 +2457,7 @@ BasicBlock* LinearScan::findPredBlockForLiveIn(BasicBlock* block, { for (flowList* pred = otherBlock->bbPreds; pred != nullptr; pred = pred->flNext) { - BasicBlock* otherPred = pred->flBlock; + BasicBlock* otherPred = pred->getBlock(); if (otherPred->bbNum == blockInfo[otherBlock->bbNum].predBBNum) { predBlock = otherPred; @@ -2477,7 +2477,7 @@ BasicBlock* LinearScan::findPredBlockForLiveIn(BasicBlock* block, { for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext) { - BasicBlock* candidatePredBlock = pred->flBlock; + BasicBlock* candidatePredBlock = pred->getBlock(); if (isBlockVisited(candidatePredBlock)) { @@ -8713,7 +8713,7 @@ void LinearScan::resolveEdges() VarToRegMap toVarToRegMap = getInVarToRegMap(block->bbNum); for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); VarToRegMap fromVarToRegMap = getOutVarToRegMap(predBlock->bbNum); VarSetOps::Iter iter(compiler, block->bbLiveIn); unsigned varIndex = 0; @@ -11137,8 +11137,8 @@ void LinearScan::verifyFinalAllocation() { dumpRegRecordTitle(); printf(shortRefPositionFormat, 0, 0); - assert(currentBlock->bbPreds != nullptr && currentBlock->bbPreds->flBlock != nullptr); - printf(bbRefPosFormat, currentBlock->bbNum, currentBlock->bbPreds->flBlock->bbNum); + assert(currentBlock->bbPreds != nullptr && currentBlock->bbPreds->getBlock() != nullptr); + printf(bbRefPosFormat, currentBlock->bbNum, currentBlock->bbPreds->getBlock()->bbNum); dumpRegRecords(); } diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index e19d7f903bb..e134915cfe9 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -161,18 +161,16 @@ void Compiler::optMarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk, bool ex for (flowList* pred = begBlk->bbPreds; pred != nullptr; pred = pred->flNext) { /* Is this a backedge? */ - if (pred->flBlock->bbNum >= begBlk->bbNum) + if (pred->getBlock()->bbNum >= begBlk->bbNum) { - flowList* flow = new (this, CMK_FlowList) flowList(); + flowList* flow = new (this, CMK_FlowList) flowList(pred->getBlock(), backedgeList); #if MEASURE_BLOCK_SIZE genFlowNodeCnt += 1; genFlowNodeSize += sizeof(flowList); #endif // MEASURE_BLOCK_SIZE - flow->flNext = backedgeList; - flow->flBlock = pred->flBlock; - backedgeList = flow; + backedgeList = flow; } } @@ -199,7 +197,7 @@ void Compiler::optMarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk, bool ex for (flowList* tmp = backedgeList; tmp != nullptr; tmp = tmp->flNext) { - BasicBlock* backedge = tmp->flBlock; + BasicBlock* backedge = tmp->getBlock(); if (!curBlk->isRunRarely()) { @@ -299,7 +297,7 @@ void Compiler::optUnmarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk) for (flowList* pred = begBlk->bbPreds; pred != nullptr; pred = pred->flNext) { - curBlk = pred->flBlock; + curBlk = pred->getBlock(); /* is this a backward edge? (from curBlk to begBlk) */ @@ -1235,7 +1233,7 @@ bool Compiler::optRecordLoop(BasicBlock* head, // i.e. every pred of ENTRY other than HEAD is in the loop. for (flowList* predEdge = entry->bbPreds; predEdge; predEdge = predEdge->flNext) { - BasicBlock* predBlock = predEdge->flBlock; + BasicBlock* predBlock = predEdge->getBlock(); if ((predBlock != head) && !optLoopTable[loopInd].lpContains(predBlock)) { goto DONE_LOOP; @@ -1379,7 +1377,7 @@ void Compiler::optCheckPreds() // make sure this pred is part of the BB list for (blockPred = fgFirstBB; blockPred; blockPred = blockPred->bbNext) { - if (blockPred == pred->flBlock) + if (blockPred == pred->getBlock()) { break; } @@ -1868,7 +1866,7 @@ private: // Add preds to the worklist, checking for side-entries. for (flowList* predIter = block->bbPreds; predIter != nullptr; predIter = predIter->flNext) { - BasicBlock* pred = predIter->flBlock; + BasicBlock* pred = predIter->getBlock(); unsigned int testNum = PositionNum(pred); @@ -1955,7 +1953,7 @@ private: // This must be a block we inserted to connect fall-through after moving blocks. // To determine if it's in the loop or not, use the number of its unique predecessor // block. - assert(block->bbPreds->flBlock == block->bbPrev); + assert(block->bbPreds->getBlock() == block->bbPrev); assert(block->bbPreds->flNext == nullptr); return block->bbPrev->bbNum; } @@ -2146,7 +2144,7 @@ private: // algorithm, and isn't desirable layout anyway. for (flowList* predIter = newMoveAfter->bbPreds; predIter != nullptr; predIter = predIter->flNext) { - unsigned int predNum = predIter->flBlock->bbNum; + unsigned int predNum = predIter->getBlock()->bbNum; if ((predNum >= top->bbNum) && (predNum <= bottom->bbNum) && !loopBlocks.IsMember(predNum)) { @@ -2216,7 +2214,7 @@ private: { for (flowList* predIter = testBlock->bbPreds; predIter != nullptr; predIter = predIter->flNext) { - BasicBlock* testPred = predIter->flBlock; + BasicBlock* testPred = predIter->getBlock(); unsigned int predPosNum = PositionNum(testPred); unsigned int firstNonLoopPosNum = PositionNum(firstNonLoopBlock); unsigned int lastNonLoopPosNum = PositionNum(lastNonLoopBlock); @@ -2445,7 +2443,7 @@ void Compiler::optFindNaturalLoops() for (flowList* pred = top->bbPreds; pred; pred = pred->flNext) { - if (search.FindLoop(head, top, pred->flBlock)) + if (search.FindLoop(head, top, pred->getBlock())) { // Found a loop; record it and see if we've hit the limit. bool recordedLoop = search.RecordLoop(); @@ -2842,7 +2840,7 @@ bool Compiler::optCanonicalizeLoop(unsigned char loopInd) bool firstPred = true; for (flowList* topPred = t->bbPreds; topPred != nullptr; topPred = topPred->flNext) { - BasicBlock* topPredBlock = topPred->flBlock; + BasicBlock* topPredBlock = topPred->getBlock(); // Skip if topPredBlock is in the loop. // Note that this uses block number to detect membership in the loop. We are adding blocks during @@ -4452,7 +4450,7 @@ void Compiler::optOptimizeLoops() { /* Is this a loop candidate? - We look for "back edges" */ - BasicBlock* bottom = pred->flBlock; + BasicBlock* bottom = pred->getBlock(); /* is this a backward edge? (from BOTTOM to TOP) */ @@ -5452,7 +5450,7 @@ void Compiler::optEnsureUniqueHead(unsigned loopInd, BasicBlock::weight_t ambien for (flowList* predEntry = e->bbPreds; predEntry; predEntry = predEntry->flNext) { - BasicBlock* predBlock = predEntry->flBlock; + BasicBlock* predBlock = predEntry->getBlock(); // Skip if predBlock is in the loop. if (t->bbNum <= predBlock->bbNum && predBlock->bbNum <= b->bbNum) @@ -7489,7 +7487,7 @@ void Compiler::fgCreateLoopPreHeader(unsigned lnum) for (flowList* pred = top->bbPreds; pred; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); if (fgDominate(top, predBlock)) { diff --git a/src/coreclr/jit/ssabuilder.cpp b/src/coreclr/jit/ssabuilder.cpp index 62efd8696da..46671f8444b 100644 --- a/src/coreclr/jit/ssabuilder.cpp +++ b/src/coreclr/jit/ssabuilder.cpp @@ -255,9 +255,9 @@ void SsaBuilder::ComputeImmediateDom(BasicBlock** postOrder, int count) BasicBlock* predBlock = nullptr; for (flowList* pred = m_pCompiler->BlockPredsWithEH(block); pred; pred = pred->flNext) { - if (BitVecOps::IsMember(&m_visitedTraits, m_visited, pred->flBlock->bbNum)) + if (BitVecOps::IsMember(&m_visitedTraits, m_visited, pred->getBlock()->bbNum)) { - predBlock = pred->flBlock; + predBlock = pred->getBlock(); break; } } @@ -272,14 +272,14 @@ void SsaBuilder::ComputeImmediateDom(BasicBlock** postOrder, int count) BasicBlock* bbIDom = predBlock; for (flowList* pred = m_pCompiler->BlockPredsWithEH(block); pred; pred = pred->flNext) { - if (predBlock != pred->flBlock) + if (predBlock != pred->getBlock()) { - BasicBlock* domAncestor = IntersectDom(pred->flBlock, bbIDom); - // The result may be NULL if "block" and "pred->flBlock" are part of a + BasicBlock* domAncestor = IntersectDom(pred->getBlock(), bbIDom); + // The result may be NULL if "block" and "pred->getBlock()" are part of a // cycle -- neither is guaranteed ordered wrt the other in reverse postorder, - // so we may be computing the IDom of "block" before the IDom of "pred->flBlock" has + // so we may be computing the IDom of "block" before the IDom of "pred->getBlock()" has // been computed. But that's OK -- if they're in a cycle, they share the same immediate - // dominator, so the contribution of "pred->flBlock" is not necessary to compute + // dominator, so the contribution of "pred->getBlock()" is not necessary to compute // the result. if (domAncestor != nullptr) { @@ -356,7 +356,7 @@ void SsaBuilder::ComputeDominanceFrontiers(BasicBlock** postOrder, int count, Bl for (flowList* pred = blockPreds; pred != nullptr; pred = pred->flNext) { - DBG_SSA_JITDUMP(" Considering predecessor " FMT_BB ".\n", pred->flBlock->bbNum); + DBG_SSA_JITDUMP(" Considering predecessor " FMT_BB ".\n", pred->getBlock()->bbNum); // If we've found a B2, then consider the possible B1's. We start with // B2, since a block dominates itself, then traverse upwards in the dominator @@ -366,7 +366,7 @@ void SsaBuilder::ComputeDominanceFrontiers(BasicBlock** postOrder, int count, Bl // Along this way, make "block"/B3 part of the dom frontier of the B1. // When we reach this immediate dominator, the definition no longer applies, since this // potential B1 *does* dominate "block"/B3, so we stop. - for (BasicBlock* b1 = pred->flBlock; (b1 != nullptr) && (b1 != block->bbIDom); // !root && !loop + for (BasicBlock* b1 = pred->getBlock(); (b1 != nullptr) && (b1 != block->bbIDom); // !root && !loop b1 = b1->bbIDom) { DBG_SSA_JITDUMP(" Adding " FMT_BB " to dom frontier of pred dom " FMT_BB ".\n", block->bbNum, diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 447b3e3e6a4..d5c0a9755a5 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -5606,7 +5606,7 @@ struct ValueNumberState bool allNonLoopPredsDone = true; for (flowList* pred = m_comp->BlockPredsWithEH(cand); pred != nullptr; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); if (!m_comp->optLoopTable[lnum].lpContains(predBlock)) { if (!GetVisitBit(predBlock->bbNum, BVB_complete)) @@ -5663,7 +5663,7 @@ struct ValueNumberState bool allPredsVisited = true; for (flowList* pred = m_comp->BlockPredsWithEH(succ); pred != nullptr; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); if (!GetVisitBit(predBlock->bbNum, BVB_complete)) { allPredsVisited = false; @@ -6174,7 +6174,7 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind, bool multipleNonLoopPreds = false; for (flowList* pred = BlockPredsWithEH(entryBlock); pred != nullptr; pred = pred->flNext) { - BasicBlock* predBlock = pred->flBlock; + BasicBlock* predBlock = pred->getBlock(); if (!optLoopTable[loopNum].lpContains(predBlock)) { if (nonLoopPred == nullptr) diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18056/Bool_And_Op_cs_do.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18056/Bool_And_Op_cs_do.csproj index 92c9b36ffdf..c5ae67f62f2 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18056/Bool_And_Op_cs_do.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18056/Bool_And_Op_cs_do.csproj @@ -6,7 +6,6 @@ <PropertyGroup> <DebugType>Full</DebugType> <Optimize>True</Optimize> - <JitOptimizationSensitive>True</JitOptimizationSensitive> </PropertyGroup> <ItemGroup> <Compile Include="Bool_And_Op.cs" /> |