From 311b5e2fe413c6c74a2a3680ab54d8a978651472 Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Fri, 29 Mar 2019 15:17:37 -0700 Subject: Use GenTreeStmt* where it is implied. (#22963) * Extract `impAppendStmt` and `impExtractLastStmt`. * Delete `BEG_STMTS` fake stmt. Use new functions to keep the list updated. * Retype `impTreeList` and `impTreeLast` as statements. Rename `impTreeList` and `impTreeLast` to show that they are statements. * Fix fields that have to be stmt. * Start using GenTreeStmt. Change `optVNAssertionPropCurStmt` to use GenTreeStmt. Replace `GenTree* stmt = block->bbTreeList` with `GenTreeStmt* stmt = block->firstStmt()`. Save results of `FirstNonPhiDef` as `GenTreeStmt`. * Replace do-while with for loop. * Change type inside VNAssertionPropVisitorInfo. * Delete unused args fron `optVNConstantPropOnTree`. * Update fields to be stmt. Update optVNConstantPropCurStmt to use Stmt. Change `lvDefStmt` to stmt. Update LoopCloning structs. Update `optDebugLogLoopCloning`. Make `compCurStmt` a statement. Update declaration name in `BuildNode`. * Clean simple cpp files. Clean valuenum. Clean ssabuilder. Clean simd. Clean optcse. Clean loopcloning. Clean copyprop. Clean optimizer part1. * Start cleaning importer, morph, flowgraph, gentree. * Continue clean functons. Clean assertionprop. Clean morph. Clean gentree. Clean flowgraph. Clean compiler. Clean rangecheck. Clean indirectcalltransofrmer. Clean others. * Create some temp stmt. * Delete unnecessary noway_assert and casts. * Init `impStmtList` and `impLastStmt` in release. * Response review 1. --- src/jit/assertionprop.cpp | 120 ++++++++------- src/jit/block.cpp | 22 +-- src/jit/block.h | 2 +- src/jit/codegencommon.cpp | 8 +- src/jit/codegenlinear.cpp | 19 +-- src/jit/compiler.cpp | 22 +-- src/jit/compiler.h | 195 ++++++++++++------------- src/jit/compiler.hpp | 11 +- src/jit/copyprop.cpp | 12 +- src/jit/earlyprop.cpp | 4 +- src/jit/flowgraph.cpp | 283 ++++++++++++++---------------------- src/jit/gentree.cpp | 84 +++++------ src/jit/gentree.h | 12 +- src/jit/gtlist.h | 2 - src/jit/importer.cpp | 273 +++++++++++++++++----------------- src/jit/indirectcalltransformer.cpp | 30 ++-- src/jit/liveness.cpp | 25 ++-- src/jit/loopcloning.cpp | 4 +- src/jit/loopcloning.h | 12 +- src/jit/lsra.h | 2 +- src/jit/morph.cpp | 207 +++++++++++++------------- src/jit/optcse.cpp | 79 ++++------ src/jit/optimizer.cpp | 146 +++++++++---------- src/jit/rangecheck.cpp | 20 +-- src/jit/rangecheck.h | 6 +- src/jit/rationalize.cpp | 9 +- src/jit/rationalize.h | 2 +- src/jit/simd.cpp | 6 +- src/jit/ssabuilder.cpp | 29 ++-- src/jit/valuenum.cpp | 21 ++- 30 files changed, 755 insertions(+), 912 deletions(-) diff --git a/src/jit/assertionprop.cpp b/src/jit/assertionprop.cpp index 3747b2edca..8bb8ce4418 100644 --- a/src/jit/assertionprop.cpp +++ b/src/jit/assertionprop.cpp @@ -277,8 +277,8 @@ void Compiler::optAddCopies() continue; } - GenTree* stmt; - unsigned copyLclNum = lvaGrabTemp(false DEBUGARG("optAddCopies")); + GenTreeStmt* stmt; + unsigned copyLclNum = lvaGrabTemp(false DEBUGARG("optAddCopies")); // Because lvaGrabTemp may have reallocated the lvaTable, ensure varDsc // is still in sync with lvaTable[lclNum]; @@ -438,12 +438,11 @@ void Compiler::optAddCopies() /* Locate the assignment to varDsc in the lvDefStmt */ stmt = varDsc->lvDefStmt; - noway_assert(stmt->gtOper == GT_STMT); optAddCopyLclNum = lclNum; // in optAddCopyAsgnNode = nullptr; // out - fgWalkTreePre(&stmt->gtStmt.gtStmtExpr, Compiler::optAddCopiesCallback, (void*)this, false); + fgWalkTreePre(&stmt->gtStmtExpr, Compiler::optAddCopiesCallback, (void*)this, false); noway_assert(optAddCopyAsgnNode); @@ -477,7 +476,7 @@ void Compiler::optAddCopies() if (verbose) { printf("\nIntroducing a new copy for V%02u\n", lclNum); - gtDispTree(stmt->gtStmt.gtStmtExpr); + gtDispTree(stmt->gtStmtExpr); printf("\n"); } #endif @@ -2373,13 +2372,13 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab // appropriately decremented. The ref-counts of variables in the side-effect // nodes will be retained. // -GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* stmt, GenTree* tree) +GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) { if (tree->OperGet() == GT_JTRUE) { // Treat JTRUE separately to extract side effects into respective statements rather // than using a COMMA separated op1. - return optVNConstantPropOnJTrue(block, stmt, tree); + return optVNConstantPropOnJTrue(block, tree); } // If relop is part of JTRUE, this should be optimized as part of the parent JTRUE. // Or if relop is part of QMARK or anything else, we simply bail here. @@ -2594,7 +2593,7 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* stmt, Gen */ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion, GenTree* tree, - GenTree* stmt DEBUGARG(AssertionIndex index)) + GenTreeStmt* stmt DEBUGARG(AssertionIndex index)) { unsigned lclNum = tree->gtLclVarCommon.gtLclNum; @@ -2783,7 +2782,7 @@ bool Compiler::optAssertionProp_LclVarTypeCheck(GenTree* tree, LclVarDsc* lclVar */ GenTree* Compiler::optCopyAssertionProp(AssertionDsc* curAssertion, GenTree* tree, - GenTree* stmt DEBUGARG(AssertionIndex index)) + GenTreeStmt* stmt DEBUGARG(AssertionIndex index)) { const AssertionDsc::AssertionDscOp1& op1 = curAssertion->op1; const AssertionDsc::AssertionDscOp2& op2 = curAssertion->op2; @@ -2852,7 +2851,7 @@ GenTree* Compiler::optCopyAssertionProp(AssertionDsc* curAssertion, * be nullptr. Returns the modified tree, or nullptr if no assertion prop took place. */ -GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt) { assert(tree->gtOper == GT_LCL_VAR); // If we have a var definition then bail or @@ -3049,7 +3048,7 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_T * Returns the modified tree, or nullptr if no assertion prop took place */ -GenTree* Compiler::optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt) { assert(tree->OperKind() & GTK_RELOP); @@ -3078,7 +3077,7 @@ GenTree* Compiler::optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* * perform Value numbering based relop assertion propagation on the tree. * */ -GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt) { GenTree* newTree = tree; GenTree* op1 = tree->gtOp.gtOp1; @@ -3298,7 +3297,7 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, Gen * perform local variable name based relop assertion propagation on the tree. * */ -GenTree* Compiler::optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt) { assert(tree->OperGet() == GT_EQ || tree->OperGet() == GT_NE); @@ -3392,7 +3391,7 @@ GenTree* Compiler::optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenT * * Returns the modified tree, or nullptr if no assertion prop took place. */ -GenTree* Compiler::optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt) { assert(tree->gtOper == GT_CAST); @@ -3489,7 +3488,7 @@ GenTree* Compiler::optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTree* t * Given a tree with an array bounds check node, eliminate it because it was * checked already in the program. */ -GenTree* Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt) { // Remove the bounds check as part of the GT_COMMA node since we need parent pointer to remove nodes. // When processing visits the bounds check, it sets the throw kind to None if the check is redundant. @@ -3512,7 +3511,7 @@ GenTree* Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* * */ -GenTree* Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt) { assert(tree->OperIsIndir()); @@ -3657,7 +3656,7 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALAR * Returns the modified tree, or nullptr if no assertion prop took place. * */ -GenTree* Compiler::optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, GenTree* stmt) +GenTree* Compiler::optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call) { if ((call->gtFlags & GTF_CALL_NULLCHECK) == 0) { @@ -3704,9 +3703,9 @@ GenTree* Compiler::optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, Gen * */ -GenTree* Compiler::optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, GenTree* stmt) +GenTree* Compiler::optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, GenTreeStmt* stmt) { - if (optNonNullAssertionProp_Call(assertions, call, stmt)) + if (optNonNullAssertionProp_Call(assertions, call)) { return optAssertionProp_Update(call, call, stmt); } @@ -3761,7 +3760,7 @@ GenTree* Compiler::optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCal * Given a tree consisting of a comma node with a bounds check, remove any * redundant bounds check that has already been checked in the program flow. */ -GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree) { if (optLocalAssertionProp) { @@ -3896,7 +3895,7 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree * */ -GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenTreeStmt* stmt) { noway_assert(newTree != nullptr); @@ -3955,7 +3954,7 @@ GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenT * Returns the modified tree, or nullptr if no assertion prop took place. */ -GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt) +GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt) { switch (tree->gtOper) { @@ -3970,7 +3969,7 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, return optAssertionProp_Ind(assertions, tree, stmt); case GT_ARR_BOUNDS_CHECK: - return optAssertionProp_BndsChk(assertions, tree, stmt); + return optAssertionProp_BndsChk(assertions, tree); case GT_COMMA: return optAssertionProp_Comma(assertions, tree, stmt); @@ -4501,17 +4500,15 @@ ASSERT_TP* Compiler::optComputeAssertionGen() { ASSERT_TP* jumpDestGen = fgAllocateTypeForEachBlk(); - for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { ASSERT_TP valueGen = BitVecOps::MakeEmpty(apTraits); GenTree* jtrue = nullptr; // Walk the statement trees in this basic block. - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - noway_assert(stmt->gtOper == GT_STMT); - - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { if (tree->gtOper == GT_JTRUE) { @@ -4641,10 +4638,10 @@ ASSERT_TP* Compiler::optInitAssertionDataflowFlags() // Callback data for the VN based constant prop visitor. struct VNAssertionPropVisitorInfo { - Compiler* pThis; - GenTree* stmt; - BasicBlock* block; - VNAssertionPropVisitorInfo(Compiler* pThis, BasicBlock* block, GenTree* stmt) + Compiler* pThis; + GenTreeStmt* stmt; + BasicBlock* block; + VNAssertionPropVisitorInfo(Compiler* pThis, BasicBlock* block, GenTreeStmt* stmt) : pThis(pThis), stmt(stmt), block(block) { } @@ -4734,8 +4731,7 @@ GenTree* Compiler::optPrepareTreeForReplacement(GenTree* oldTree, GenTree* newTr // // Arguments: // block - The block that contains the JTrue. -// stmt - The JTrue stmt which can be evaluated to a constant. -// tree - The JTrue node whose relop evaluates to 0 or non-zero value. +// test - The JTrue node whose relop evaluates to 0 or non-zero value. // // Return Value: // The jmpTrue tree node that has relop of the form "0 =/!= 0". @@ -4757,7 +4753,7 @@ GenTree* Compiler::optPrepareTreeForReplacement(GenTree* oldTree, GenTree* newTr // sensitive to adding new statements. Hence the change is not made directly // into fgFoldConditional. // -GenTree* Compiler::optVNConstantPropOnJTrue(BasicBlock* block, GenTree* stmt, GenTree* test) +GenTree* Compiler::optVNConstantPropOnJTrue(BasicBlock* block, GenTree* test) { GenTree* relop = test->gtGetOp1(); @@ -4802,7 +4798,7 @@ GenTree* Compiler::optVNConstantPropOnJTrue(BasicBlock* block, GenTree* stmt, Ge // these side effects from the JTrue stmt before insert them back here. while (sideEffList != nullptr) { - GenTree* newStmt; + GenTreeStmt* newStmt; if (sideEffList->OperGet() == GT_COMMA) { newStmt = fgInsertStmtNearEnd(block, sideEffList->gtGetOp1()); @@ -4815,7 +4811,7 @@ GenTree* Compiler::optVNConstantPropOnJTrue(BasicBlock* block, GenTree* stmt, Ge } // fgMorphBlockStmt could potentially affect stmts after the current one, // for example when it decides to fgRemoveRestOfBlock. - fgMorphBlockStmt(block, newStmt->AsStmt() DEBUGARG(__FUNCTION__)); + fgMorphBlockStmt(block, newStmt DEBUGARG(__FUNCTION__)); } return test; @@ -4841,7 +4837,7 @@ GenTree* Compiler::optVNConstantPropOnJTrue(BasicBlock* block, GenTree* stmt, Ge // evaluates to constant, then the tree is replaced by its side effects and // the constant node. // -Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, GenTree* stmt, GenTree* tree) +Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, GenTreeStmt* stmt, GenTree* tree) { // Don't propagate floating-point constants into a TYP_STRUCT LclVar // This can occur for HFA return values (see hfa_sf3E_r.exe) @@ -4912,7 +4908,7 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, Gen } // Perform the constant propagation - GenTree* newTree = optVNConstantPropOnTree(block, stmt, tree); + GenTree* newTree = optVNConstantPropOnTree(block, tree); if (newTree == nullptr) { // Not propagated, keep going. @@ -4951,13 +4947,13 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, Gen // indirections. This is different from flow based assertions and helps // unify VN based constant prop and non-null prop in a single pre-order walk. // -void Compiler::optVnNonNullPropCurStmt(BasicBlock* block, GenTree* stmt, GenTree* tree) +void Compiler::optVnNonNullPropCurStmt(BasicBlock* block, GenTreeStmt* stmt, GenTree* tree) { ASSERT_TP empty = BitVecOps::UninitVal(); GenTree* newTree = nullptr; if (tree->OperGet() == GT_CALL) { - newTree = optNonNullAssertionProp_Call(empty, tree->AsCall(), stmt); + newTree = optNonNullAssertionProp_Call(empty, tree->AsCall()); } else if (tree->OperIsIndir()) { @@ -5005,7 +5001,7 @@ Compiler::fgWalkResult Compiler::optVNAssertionPropCurStmtVisitor(GenTree** ppTr * Returns the skipped next stmt if the current statement or next few * statements got removed, else just returns the incoming stmt. */ -GenTree* Compiler::optVNAssertionPropCurStmt(BasicBlock* block, GenTree* stmt) +GenTreeStmt* Compiler::optVNAssertionPropCurStmt(BasicBlock* block, GenTreeStmt* stmt) { // TODO-Review: EH successor/predecessor iteration seems broken. // See: SELF_HOST_TESTS_ARM\jit\Directed\ExcepFilters\fault\fault.exe @@ -5015,23 +5011,23 @@ GenTree* Compiler::optVNAssertionPropCurStmt(BasicBlock* block, GenTree* stmt) } // Preserve the prev link before the propagation and morph. - GenTree* prev = (stmt == block->firstStmt()) ? nullptr : stmt->gtPrev; + GenTreeStmt* prev = (stmt == block->firstStmt()) ? nullptr : stmt->getPrevStmt(); // Perform VN based assertion prop first, in case we don't find // anything in assertion gen. optAssertionPropagatedCurrentStmt = false; VNAssertionPropVisitorInfo data(this, block, stmt); - fgWalkTreePre(&stmt->gtStmt.gtStmtExpr, Compiler::optVNAssertionPropCurStmtVisitor, &data); + fgWalkTreePre(&stmt->gtStmtExpr, Compiler::optVNAssertionPropCurStmtVisitor, &data); if (optAssertionPropagatedCurrentStmt) { - fgMorphBlockStmt(block, stmt->AsStmt() DEBUGARG("optVNAssertionPropCurStmt")); + fgMorphBlockStmt(block, stmt DEBUGARG("optVNAssertionPropCurStmt")); } // Check if propagation removed statements starting from current stmt. // If so, advance to the next good statement. - GenTree* nextStmt = (prev == nullptr) ? block->firstStmt() : prev->gtNext; + GenTreeStmt* nextStmt = (prev == nullptr) ? block->firstStmt() : prev->getNextStmt(); return nextStmt; } @@ -5066,25 +5062,25 @@ void Compiler::optAssertionPropMain() fgRemoveRestOfBlock = false; - GenTree* stmt = block->bbTreeList; - while (stmt) + GenTreeStmt* stmt = block->firstStmt(); + while (stmt != nullptr) { // We need to remove the rest of the block. if (fgRemoveRestOfBlock) { fgRemoveStmt(block, stmt); - stmt = stmt->gtNext; + stmt = stmt->getNextStmt(); continue; } else { // Perform VN based assertion prop before assertion gen. - GenTree* nextStmt = optVNAssertionPropCurStmt(block, stmt); + GenTreeStmt* nextStmt = optVNAssertionPropCurStmt(block, stmt); // Propagation resulted in removal of the remaining stmts, perform it. if (fgRemoveRestOfBlock) { - stmt = stmt->gtNext; + stmt = stmt->getNextStmt(); continue; } @@ -5097,13 +5093,13 @@ void Compiler::optAssertionPropMain() } // Perform assertion gen for control flow based assertions. - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { optAssertionGen(tree); } // Advance the iterator - stmt = stmt->gtNext; + stmt = stmt->getNextStmt(); } } @@ -5169,26 +5165,24 @@ void Compiler::optAssertionPropMain() fgRemoveRestOfBlock = false; // Walk the statement trees in this basic block - GenTree* stmt = block->FirstNonPhiDef(); - while (stmt) + GenTreeStmt* stmt = block->FirstNonPhiDef(); + while (stmt != nullptr) { - noway_assert(stmt->gtOper == GT_STMT); - // Propagation tells us to remove the rest of the block. Remove it. if (fgRemoveRestOfBlock) { fgRemoveStmt(block, stmt); - stmt = stmt->gtNext; + stmt = stmt->getNextStmt(); continue; } // Preserve the prev link before the propagation and morph, to check if propagation // removes the current stmt. - GenTree* prev = (stmt == block->firstStmt()) ? nullptr : stmt->gtPrev; + GenTreeStmt* prevStmt = (stmt == block->firstStmt()) ? nullptr : stmt->getPrevStmt(); optAssertionPropagatedCurrentStmt = false; // set to true if a assertion propagation took place // and thus we must morph, set order, re-link - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { if (tree->OperIs(GT_JTRUE)) { @@ -5228,13 +5222,13 @@ void Compiler::optAssertionPropMain() } #endif // Re-morph the statement. - fgMorphBlockStmt(block, stmt->AsStmt() DEBUGARG("optAssertionPropMain")); + fgMorphBlockStmt(block, stmt DEBUGARG("optAssertionPropMain")); } // Check if propagation removed statements starting from current stmt. // If so, advance to the next good statement. - GenTree* nextStmt = (prev == nullptr) ? block->firstStmt() : prev->gtNext; - stmt = (stmt == nextStmt) ? stmt->gtNext : nextStmt; + GenTreeStmt* nextStmt = (prevStmt == nullptr) ? block->firstStmt() : prevStmt->getNextStmt(); + stmt = (stmt == nextStmt) ? stmt->getNextStmt() : nextStmt; } optAssertionPropagatedCurrentStmt = false; // clear it back as we are done with stmts. } diff --git a/src/jit/block.cpp b/src/jit/block.cpp index 8d1a83f5b4..dfba5c6a1f 100644 --- a/src/jit/block.cpp +++ b/src/jit/block.cpp @@ -631,9 +631,9 @@ bool BasicBlock::CloneBlockState( to->bbTgtStkDepth = from->bbTgtStkDepth; #endif // DEBUG - for (GenTree* fromStmt = from->bbTreeList; fromStmt != nullptr; fromStmt = fromStmt->gtNext) + for (GenTreeStmt* fromStmt = from->firstStmt(); fromStmt != nullptr; fromStmt = fromStmt->getNextStmt()) { - auto newExpr = compiler->gtCloneExpr(fromStmt->gtStmt.gtStmtExpr, 0, varNum, varVal); + auto newExpr = compiler->gtCloneExpr(fromStmt->gtStmtExpr, 0, varNum, varVal); if (!newExpr) { // gtCloneExpr doesn't handle all opcodes, so may fail to clone a statement. @@ -809,37 +809,37 @@ bool BasicBlock::isEmpty() GenTreeStmt* BasicBlock::FirstNonPhiDef() { - GenTree* stmt = bbTreeList; + GenTreeStmt* stmt = firstStmt(); if (stmt == nullptr) { return nullptr; } - GenTree* tree = stmt->gtStmt.gtStmtExpr; + GenTree* tree = stmt->gtStmtExpr; while ((tree->OperGet() == GT_ASG && tree->gtOp.gtOp2->OperGet() == GT_PHI) || (tree->OperGet() == GT_STORE_LCL_VAR && tree->gtOp.gtOp1->OperGet() == GT_PHI)) { - stmt = stmt->gtNext; + stmt = stmt->getNextStmt(); if (stmt == nullptr) { return nullptr; } - tree = stmt->gtStmt.gtStmtExpr; + tree = stmt->gtStmtExpr; } - return stmt->AsStmt(); + return stmt; } -GenTree* BasicBlock::FirstNonPhiDefOrCatchArgAsg() +GenTreeStmt* BasicBlock::FirstNonPhiDefOrCatchArgAsg() { - GenTree* stmt = FirstNonPhiDef(); + GenTreeStmt* stmt = FirstNonPhiDef(); if (stmt == nullptr) { return nullptr; } - GenTree* tree = stmt->gtStmt.gtStmtExpr; + GenTree* tree = stmt->gtStmtExpr; if ((tree->OperGet() == GT_ASG && tree->gtOp.gtOp2->OperGet() == GT_CATCH_ARG) || (tree->OperGet() == GT_STORE_LCL_VAR && tree->gtOp.gtOp1->OperGet() == GT_CATCH_ARG)) { - stmt = stmt->gtNext; + stmt = stmt->getNextStmt(); } return stmt; } diff --git a/src/jit/block.h b/src/jit/block.h index 56b1c7313d..d186a79176 100644 --- a/src/jit/block.h +++ b/src/jit/block.h @@ -1076,7 +1076,7 @@ struct BasicBlock : private LIR::Range // Returns the first statement in the statement list of "this" that is // not an SSA definition (a lcl = phi(...) assignment). GenTreeStmt* FirstNonPhiDef(); - GenTree* FirstNonPhiDefOrCatchArgAsg(); + GenTreeStmt* FirstNonPhiDefOrCatchArgAsg(); BasicBlock() : bbLiveIn(VarSetOps::UninitVal()), bbLiveOut(VarSetOps::UninitVal()) { diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index 03e171bc2c..e54342a1d5 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -11243,13 +11243,13 @@ void CodeGen::genIPmappingGen() //block has an IL offset and appears in eeBoundaries. for (BasicBlock * block = compiler->fgFirstBB; block != nullptr; block = block->bbNext) { - if ((block->bbRefs > 1) && (block->bbTreeList != nullptr)) + GenTreeStmt* stmt = block->firstStmt(); + if ((block->bbRefs > 1) && (stmt != nullptr)) { - noway_assert(block->bbTreeList->gtOper == GT_STMT); bool found = false; - if (block->bbTreeList->gtStmt.gtStmtILoffsx != BAD_IL_OFFSET) + if (stmt->gtStmtILoffsx != BAD_IL_OFFSET) { - IL_OFFSET ilOffs = jitGetILoffs(block->bbTreeList->gtStmt.gtStmtILoffsx); + IL_OFFSET ilOffs = jitGetILoffs(stmt->gtStmtILoffsx); for (unsigned i = 0; i < eeBoundariesCount; ++i) { if (eeBoundaries[i].ilOffset == ilOffs) diff --git a/src/jit/codegenlinear.cpp b/src/jit/codegenlinear.cpp index 72f9fa68db..6b16e30e89 100644 --- a/src/jit/codegenlinear.cpp +++ b/src/jit/codegenlinear.cpp @@ -411,28 +411,25 @@ void CodeGen::genCodeForBBlist() // Do we have a new IL offset? if (node->OperGet() == GT_IL_OFFSET) { + GenTreeStmt* ilOffset = node->AsStmt(); genEnsureCodeEmitted(currentILOffset); - currentILOffset = node->gtStmt.gtStmtILoffsx; + currentILOffset = ilOffset->gtStmtILoffsx; genIPmappingAdd(currentILOffset, firstMapping); firstMapping = false; - } - #ifdef DEBUG - if (node->OperGet() == GT_IL_OFFSET) - { - noway_assert(node->gtStmt.gtStmtLastILoffs <= compiler->info.compILCodeSize || - node->gtStmt.gtStmtLastILoffs == BAD_IL_OFFSET); + assert(ilOffset->gtStmtLastILoffs <= compiler->info.compILCodeSize || + ilOffset->gtStmtLastILoffs == BAD_IL_OFFSET); - if (compiler->opts.dspCode && compiler->opts.dspInstrs && - node->gtStmt.gtStmtLastILoffs != BAD_IL_OFFSET) + if (compiler->opts.dspCode && compiler->opts.dspInstrs && ilOffset->gtStmtLastILoffs != BAD_IL_OFFSET) { - while (genCurDispOffset <= node->gtStmt.gtStmtLastILoffs) + while (genCurDispOffset <= ilOffset->gtStmtLastILoffs) { genCurDispOffset += dumpSingleInstr(compiler->info.compCode, genCurDispOffset, "> "); } } - } + #endif // DEBUG + } genCodeForTreeNode(node); if (node->gtHasReg() && node->IsUnusedValue()) diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index fe02e2c42b..c70e90da6a 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -4896,7 +4896,7 @@ void Compiler::ResetOptAnnotations() { stmt->gtFlags &= ~GTF_STMT_HAS_CSE; - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree != nullptr; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { tree->ClearVN(); tree->ClearAssertion(); @@ -6930,9 +6930,9 @@ Compiler::NodeToIntMap* Compiler::FindReachableNodesInNodeTestData() for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { - for (GenTree* stmt = block->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt()) { - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { TestLabelAndNum tlAndN; @@ -7161,10 +7161,6 @@ void Compiler::compCallArgStats() GenTree* args; GenTree* argx; - BasicBlock* block; - GenTree* stmt; - GenTree* call; - unsigned argNum; unsigned argDWordNum; @@ -7183,13 +7179,11 @@ void Compiler::compCallArgStats() assert(fgStmtListThreaded); - for (block = fgFirstBB; block; block = block->bbNext) + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { - for (stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - assert(stmt->gtOper == GT_STMT); - - for (call = stmt->gtStmt.gtStmtList; call; call = call->gtNext) + for (GenTree* call = stmt->gtStmtList; call != nullptr; call = call->gtNext) { if (call->gtOper != GT_CALL) continue; @@ -8819,9 +8813,7 @@ void cBlockIR(Compiler* comp, BasicBlock* block) if (comp->compRationalIRForm) { - GenTree* tree; - - foreach_treenode_execution_order(tree, stmt) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { cNodeIR(comp, tree); } diff --git a/src/jit/compiler.h b/src/jit/compiler.h index eefa345e6e..87581856dd 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -810,9 +810,9 @@ public: BYTE* lvGcLayout; // GC layout info for structs #if ASSERTION_PROP - BlockSet lvRefBlks; // Set of blocks that contain refs - GenTree* lvDefStmt; // Pointer to the statement with the single definition - void lvaDisqualifyVar(); // Call to disqualify a local variable from use in optAddCopies + BlockSet lvRefBlks; // Set of blocks that contain refs + GenTreeStmt* lvDefStmt; // Pointer to the statement with the single definition + void lvaDisqualifyVar(); // Call to disqualify a local variable from use in optAddCopies #endif var_types TypeGet() const { @@ -2460,11 +2460,11 @@ public: GenTree* gtNewAssignNode(GenTree* dst, GenTree* src); - GenTree* gtNewTempAssign(unsigned tmp, - GenTree* val, - GenTree** pAfterStmt = nullptr, - IL_OFFSETX ilOffset = BAD_IL_OFFSET, - BasicBlock* block = nullptr); + GenTree* gtNewTempAssign(unsigned tmp, + GenTree* val, + GenTreeStmt** pAfterStmt = nullptr, + IL_OFFSETX ilOffset = BAD_IL_OFFSET, + BasicBlock* block = nullptr); GenTree* gtNewRefCOMfield(GenTree* objPtr, CORINFO_RESOLVED_TOKEN* pResolvedToken, @@ -2518,13 +2518,13 @@ public: // Create copy of an inline or guarded devirtualization candidate tree. GenTreeCall* gtCloneCandidateCall(GenTreeCall* call); - GenTree* gtReplaceTree(GenTree* stmt, GenTree* tree, GenTree* replacementTree); + GenTree* gtReplaceTree(GenTreeStmt* stmt, GenTree* tree, GenTree* replacementTree); - void gtUpdateSideEffects(GenTree* stmt, GenTree* tree); + void gtUpdateSideEffects(GenTreeStmt* stmt, GenTree* tree); void gtUpdateTreeAncestorsSideEffects(GenTree* tree); - void gtUpdateStmtSideEffects(GenTree* stmt); + void gtUpdateStmtSideEffects(GenTreeStmt* stmt); void gtUpdateNodeSideEffects(GenTree* tree); @@ -2568,7 +2568,7 @@ public: unsigned gtSetEvalOrder(GenTree* tree); - void gtSetStmtInfo(GenTree* stmt); + void gtSetStmtInfo(GenTreeStmt* stmt); // Returns "true" iff "node" has any of the side effects in "flags". bool gtNodeHasSideEffects(GenTree* node, unsigned flags); @@ -2732,7 +2732,7 @@ public: static fgWalkPreFn gtMarkColonCond; static fgWalkPreFn gtClearColonCond; - GenTree** gtFindLink(GenTree* stmt, GenTree* node); + GenTree** gtFindLink(GenTreeStmt* stmt, GenTree* node); bool gtHasCatchArg(GenTree* tree); typedef ArrayStack GenTreeStack; @@ -3063,7 +3063,7 @@ public: void lvaAllocOutgoingArgSpaceVar(); // Set up lvaOutgoingArgSpaceVar - VARSET_VALRET_TP lvaStmtLclMask(GenTree* stmt); + VARSET_VALRET_TP lvaStmtLclMask(GenTreeStmt* stmt); #ifdef DEBUG struct lvaStressLclFldArgs @@ -3533,8 +3533,8 @@ protected: //----------------- Manipulating the trees and stmts ---------------------- - GenTree* impTreeList; // Trees for the BB being imported - GenTree* impTreeLast; // The last tree for the current BB + GenTreeStmt* impStmtList; // Statements for the BB being imported. + GenTreeStmt* impLastStmt; // The last statement for the current BB. public: enum @@ -3544,43 +3544,46 @@ public: }; void impBeginTreeList(); - void impEndTreeList(BasicBlock* block, GenTree* firstStmt, GenTree* lastStmt); + void impEndTreeList(BasicBlock* block, GenTreeStmt* firstStmt, GenTreeStmt* lastStmt); void impEndTreeList(BasicBlock* block); - void impAppendStmtCheck(GenTree* stmt, unsigned chkLevel); - void impAppendStmt(GenTree* stmt, unsigned chkLevel); - void impInsertStmtBefore(GenTree* stmt, GenTree* stmtBefore); - GenTree* impAppendTree(GenTree* tree, unsigned chkLevel, IL_OFFSETX offset); - void impInsertTreeBefore(GenTree* tree, IL_OFFSETX offset, GenTree* stmtBefore); - void impAssignTempGen(unsigned tmp, - GenTree* val, - unsigned curLevel, - GenTree** pAfterStmt = nullptr, - IL_OFFSETX ilOffset = BAD_IL_OFFSET, - BasicBlock* block = nullptr); + void impAppendStmtCheck(GenTreeStmt* stmt, unsigned chkLevel); + void impAppendStmt(GenTreeStmt* stmt, unsigned chkLevel); + void impAppendStmt(GenTreeStmt* stmt); + void impInsertStmtBefore(GenTreeStmt* stmt, GenTreeStmt* stmtBefore); + GenTreeStmt* impAppendTree(GenTree* tree, unsigned chkLevel, IL_OFFSETX offset); + void impInsertTreeBefore(GenTree* tree, IL_OFFSETX offset, GenTreeStmt* stmtBefore); + void impAssignTempGen(unsigned tmp, + GenTree* val, + unsigned curLevel, + GenTreeStmt** pAfterStmt = nullptr, + IL_OFFSETX ilOffset = BAD_IL_OFFSET, + BasicBlock* block = nullptr); void impAssignTempGen(unsigned tmpNum, GenTree* val, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel, - GenTree** pAfterStmt = nullptr, + GenTreeStmt** pAfterStmt = nullptr, IL_OFFSETX ilOffset = BAD_IL_OFFSET, BasicBlock* block = nullptr); + + GenTreeStmt* impExtractLastStmt(); GenTree* impCloneExpr(GenTree* tree, GenTree** clone, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel, - GenTree** pAfterStmt DEBUGARG(const char* reason)); + GenTreeStmt** pAfterStmt DEBUGARG(const char* reason)); GenTree* impAssignStruct(GenTree* dest, GenTree* src, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel, - GenTree** pAfterStmt = nullptr, + GenTreeStmt** pAfterStmt = nullptr, IL_OFFSETX ilOffset = BAD_IL_OFFSET, BasicBlock* block = nullptr); GenTree* impAssignStructPtr(GenTree* dest, GenTree* src, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel, - GenTree** pAfterStmt = nullptr, + GenTreeStmt** pAfterStmt = nullptr, IL_OFFSETX ilOffset = BAD_IL_OFFSET, BasicBlock* block = nullptr); @@ -3653,8 +3656,8 @@ private: bool impNestedStackSpill; // For displaying instrs with generated native code (-n:B) - GenTree* impLastILoffsStmt; // oldest stmt added for which we did not gtStmtLastILoffs - void impNoteLastILoffs(); + GenTreeStmt* impLastILoffsStmt; // oldest stmt added for which we did not gtStmtLastILoffs + void impNoteLastILoffs(); #endif /* IL offset of the stmt currently being imported. It gets set to @@ -4247,7 +4250,7 @@ public: BasicBlock* fgSplitBlockAtBeginning(BasicBlock* curr); BasicBlock* fgSplitBlockAtEnd(BasicBlock* curr); - BasicBlock* fgSplitBlockAfterStatement(BasicBlock* curr, GenTree* stmt); + BasicBlock* fgSplitBlockAfterStatement(BasicBlock* curr, GenTreeStmt* stmt); BasicBlock* fgSplitBlockAfterNode(BasicBlock* curr, GenTree* node); // for LIR BasicBlock* fgSplitEdge(BasicBlock* curr, BasicBlock* succ); @@ -4257,8 +4260,8 @@ public: GenTreeStmt* fgNewStmtFromTree(GenTree* tree, IL_OFFSETX offs); GenTree* fgGetTopLevelQmark(GenTree* expr, GenTree** ppDst = nullptr); - void fgExpandQmarkForCastInstOf(BasicBlock* block, GenTree* stmt); - void fgExpandQmarkStmt(BasicBlock* block, GenTree* expr); + void fgExpandQmarkForCastInstOf(BasicBlock* block, GenTreeStmt* stmt); + void fgExpandQmarkStmt(BasicBlock* block, GenTreeStmt* stmt); void fgExpandQmarkNodes(); void fgMorph(); @@ -4813,9 +4816,9 @@ public: void fgRemoveEmptyBlocks(); - void fgRemoveStmt(BasicBlock* block, GenTree* stmt); + void fgRemoveStmt(BasicBlock* block, GenTreeStmt* stmt); - bool fgCheckRemoveStmt(BasicBlock* block, GenTree* stmt); + bool fgCheckRemoveStmt(BasicBlock* block, GenTreeStmt* stmt); void fgCreateLoopPreHeader(unsigned lnum); @@ -4941,7 +4944,7 @@ public: void fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth = 0); void fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, bool dumpTrees); void fgDispBasicBlocks(bool dumpTrees = false); - void fgDumpStmtTree(GenTree* stmt, unsigned bbNum); + void fgDumpStmtTree(GenTreeStmt* stmt, unsigned bbNum); void fgDumpBlock(BasicBlock* block); void fgDumpTrees(BasicBlock* firstBlock, BasicBlock* lastBlock); @@ -4952,7 +4955,7 @@ public: void fgDebugCheckBlockLinks(); void fgDebugCheckLinks(bool morphTrees = false); void fgDebugCheckStmtsList(BasicBlock* block, bool morphTrees); - void fgDebugCheckNodeLinks(BasicBlock* block, GenTree* stmt); + void fgDebugCheckNodeLinks(BasicBlock* block, GenTreeStmt* stmt); void fgDebugCheckNodesUniqueness(); void fgDebugCheckFlags(GenTree* tree); @@ -5088,7 +5091,9 @@ public: #ifdef DEBUG public: - static bool fgBlockContainsStatementBounded(BasicBlock* block, GenTree* stmt, bool answerOnBoundExceeded = true); + static bool fgBlockContainsStatementBounded(BasicBlock* block, + GenTreeStmt* stmt, + bool answerOnBoundExceeded = true); #endif public: @@ -5098,14 +5103,14 @@ public: // Used by linear scan register allocation GenTreeStmt* fgInsertStmtNearEnd(BasicBlock* block, GenTree* node); private: - GenTree* fgInsertStmtAtBeg(BasicBlock* block, GenTree* stmt); - GenTree* fgInsertStmtAfter(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt); + GenTreeStmt* fgInsertStmtAtBeg(BasicBlock* block, GenTree* node); + GenTreeStmt* fgInsertStmtAfter(BasicBlock* block, GenTreeStmt* insertionPoint, GenTreeStmt* stmt); public: // Used by linear scan register allocation - GenTree* fgInsertStmtBefore(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt); + GenTreeStmt* fgInsertStmtBefore(BasicBlock* block, GenTreeStmt* insertionPoint, GenTreeStmt* stmt); private: - GenTree* fgInsertStmtListAfter(BasicBlock* block, GenTree* stmtAfter, GenTree* stmtList); + GenTreeStmt* fgInsertStmtListAfter(BasicBlock* block, GenTreeStmt* stmtAfter, GenTreeStmt* stmtList); // Create a new temporary variable to hold the result of *ppTree, // and transform the graph accordingly. @@ -5126,7 +5131,7 @@ private: GenTree* fgSetTreeSeq(GenTree* tree, GenTree* prev = nullptr, bool isLIR = false); void fgSetTreeSeqHelper(GenTree* tree, bool isLIR); void fgSetTreeSeqFinish(GenTree* tree, bool isLIR); - void fgSetStmtSeq(GenTree* tree); + void fgSetStmtSeq(GenTreeStmt* stmt); void fgSetBlockOrder(BasicBlock* block); //------------------------- Morphing -------------------------------------- @@ -5218,12 +5223,12 @@ private: bool ignoreUsedInSIMDIntrinsic = false); GenTree* fgMorphFieldAssignToSIMDIntrinsicSet(GenTree* tree); GenTree* fgMorphFieldToSIMDIntrinsicGet(GenTree* tree); - bool fgMorphCombineSIMDFieldAssignments(BasicBlock* block, GenTree* stmt); - void impMarkContiguousSIMDFieldAssignments(GenTree* stmt); + bool fgMorphCombineSIMDFieldAssignments(BasicBlock* block, GenTreeStmt* stmt); + void impMarkContiguousSIMDFieldAssignments(GenTreeStmt* stmt); // fgPreviousCandidateSIMDFieldAsgStmt is only used for tracking previous simd field assignment // in function: Complier::impMarkContiguousSIMDFieldAssignments. - GenTree* fgPreviousCandidateSIMDFieldAsgStmt; + GenTreeStmt* fgPreviousCandidateSIMDFieldAsgStmt; #endif // FEATURE_SIMD GenTree* fgMorphArrayIndex(GenTree* tree); @@ -5252,12 +5257,12 @@ private: void fgMorphTailCall(GenTreeCall* call, void* pfnCopyArgs); GenTree* fgGetStubAddrArg(GenTreeCall* call); void fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCall* recursiveTailCall); - GenTree* fgAssignRecursiveCallArgToCallerParam(GenTree* arg, - fgArgTabEntry* argTabEntry, - BasicBlock* block, - IL_OFFSETX callILOffset, - GenTree* tmpAssignmentInsertionPoint, - GenTree* paramAssignmentInsertionPoint); + GenTreeStmt* fgAssignRecursiveCallArgToCallerParam(GenTree* arg, + fgArgTabEntry* argTabEntry, + BasicBlock* block, + IL_OFFSETX callILOffset, + GenTreeStmt* tmpAssignmentInsertionPoint, + GenTreeStmt* paramAssignmentInsertionPoint); static int fgEstimateCallStackSize(GenTreeCall* call); GenTree* fgMorphCall(GenTreeCall* call); void fgMorphCallInline(GenTreeCall* call, InlineResult* result); @@ -5384,8 +5389,8 @@ private: unsigned fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo); void fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* result); void fgInsertInlineeBlocks(InlineInfo* pInlineInfo); - GenTree* fgInlinePrependStatements(InlineInfo* inlineInfo); - void fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTree* stmt); + GenTreeStmt* fgInlinePrependStatements(InlineInfo* inlineInfo); + void fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTreeStmt* stmt); #if FEATURE_MULTIREG_RET GenTree* fgGetStructAsStructPtr(GenTree* tree); @@ -5468,7 +5473,7 @@ private: public: void optInit(); - void optRemoveRangeCheck(GenTree* tree, GenTree* stmt); + void optRemoveRangeCheck(GenTree* tree, GenTreeStmt* stmt); bool optIsRangeCheckRemovable(GenTree* tree); protected: @@ -5861,7 +5866,7 @@ protected: void optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmarkLoop = false); - bool optIsLoopTestEvalIntoTemp(GenTree* test, GenTree** newTest); + bool optIsLoopTestEvalIntoTemp(GenTreeStmt* testStmt, GenTreeStmt** newTestStmt); unsigned optIsLoopIncrTree(GenTree* incr); bool optCheckIterInLoopTest(unsigned loopInd, GenTree* test, BasicBlock* from, BasicBlock* to, unsigned iterVar); bool optComputeIterInfo(GenTree* incr, BasicBlock* from, BasicBlock* to, unsigned* pIterVar); @@ -5980,7 +5985,7 @@ protected: { treeStmtLst* tslNext; GenTree* tslTree; // tree node - GenTree* tslStmt; // statement containing the tree + GenTreeStmt* tslStmt; // statement containing the tree BasicBlock* tslBlock; // block containing the statement }; @@ -6001,9 +6006,9 @@ protected: unsigned csdDefWtCnt; // weighted def count unsigned csdUseWtCnt; // weighted use count (excluding the implicit uses at defs) - GenTree* csdTree; // treenode containing the 1st occurance - GenTree* csdStmt; // stmt containing the 1st occurance - BasicBlock* csdBlock; // block containing the 1st occurance + GenTree* csdTree; // treenode containing the 1st occurance + GenTreeStmt* csdStmt; // stmt containing the 1st occurance + BasicBlock* csdBlock; // block containing the 1st occurance treeStmtLst* csdTreeList; // list of matching tree nodes: head treeStmtLst* csdTreeLast; // list of matching tree nodes: tail @@ -6074,7 +6079,7 @@ public: protected: void optValnumCSE_Init(); - unsigned optValnumCSE_Index(GenTree* tree, GenTree* stmt); + unsigned optValnumCSE_Index(GenTree* tree, GenTreeStmt* stmt); unsigned optValnumCSE_Locate(); void optValnumCSE_InitDataFlow(); void optValnumCSE_DataFlow(); @@ -6141,7 +6146,7 @@ public: VARSET_TP optCopyPropKillSet; // Copy propagation functions. - void optCopyProp(BasicBlock* block, GenTree* stmt, GenTree* tree, LclNumToGenTreePtrStack* curSsaName); + void optCopyProp(BasicBlock* block, GenTreeStmt* stmt, GenTree* tree, LclNumToGenTreePtrStack* curSsaName); void optBlockCopyPropPopStacks(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName); void optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName); bool optIsSsaLocal(GenTree* tree); @@ -6519,10 +6524,10 @@ protected: AssertionIndex optMaxAssertionCount; public: - void optVnNonNullPropCurStmt(BasicBlock* block, GenTree* stmt, GenTree* tree); - fgWalkResult optVNConstantPropCurStmt(BasicBlock* block, GenTree* stmt, GenTree* tree); - GenTree* optVNConstantPropOnJTrue(BasicBlock* block, GenTree* stmt, GenTree* test); - GenTree* optVNConstantPropOnTree(BasicBlock* block, GenTree* stmt, GenTree* tree); + void optVnNonNullPropCurStmt(BasicBlock* block, GenTreeStmt* stmt, GenTree* tree); + fgWalkResult optVNConstantPropCurStmt(BasicBlock* block, GenTreeStmt* stmt, GenTree* tree); + GenTree* optVNConstantPropOnJTrue(BasicBlock* block, GenTree* test); + GenTree* optVNConstantPropOnTree(BasicBlock* block, GenTree* tree); GenTree* optPrepareTreeForReplacement(GenTree* extractTree, GenTree* replaceTree); AssertionIndex GetAssertionCount() @@ -6544,8 +6549,8 @@ public: #endif // Assertion prop data flow functions. - void optAssertionPropMain(); - GenTree* optVNAssertionPropCurStmt(BasicBlock* block, GenTree* stmt); + void optAssertionPropMain(); + GenTreeStmt* optVNAssertionPropCurStmt(BasicBlock* block, GenTreeStmt* stmt); bool optIsTreeKnownIntValue(bool vnBased, GenTree* tree, ssize_t* pConstant, unsigned* pIconFlags); ASSERT_TP* optInitAssertionDataflowFlags(); ASSERT_TP* optComputeAssertionGen(); @@ -6592,24 +6597,24 @@ public: bool optAssertionProp_LclVarTypeCheck(GenTree* tree, LclVarDsc* lclVarDsc, LclVarDsc* copyVarDsc); GenTree* optCopyAssertionProp(AssertionDsc* curAssertion, GenTree* tree, - GenTree* stmt DEBUGARG(AssertionIndex index)); + GenTreeStmt* stmt DEBUGARG(AssertionIndex index)); GenTree* optConstantAssertionProp(AssertionDsc* curAssertion, GenTree* tree, - GenTree* stmt DEBUGARG(AssertionIndex index)); + GenTreeStmt* stmt DEBUGARG(AssertionIndex index)); // Assertion propagation functions. - GenTree* optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt); - GenTree* optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt); - GenTree* optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt); - GenTree* optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt); - GenTree* optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, GenTree* stmt); - GenTree* optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt); - GenTree* optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt); - GenTree* optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt); - GenTree* optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt); - GenTree* optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTree* stmt); - GenTree* optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenTree* stmt); - GenTree* optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, GenTree* stmt); + GenTree* optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt); + GenTree* optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt); + GenTree* optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt); + GenTree* optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt); + GenTree* optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, GenTreeStmt* stmt); + GenTree* optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt); + GenTree* optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt); + GenTree* optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree); + GenTree* optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt); + GenTree* optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, GenTreeStmt* stmt); + GenTree* optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenTreeStmt* stmt); + GenTree* optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call); // Implied assertion functions. void optImpliedAssertions(AssertionIndex assertionIndex, ASSERT_TP& activeAssertions); @@ -6634,8 +6639,8 @@ public: { LoopCloneContext* context; unsigned loopNum; - GenTree* stmt; - LoopCloneVisitorInfo(LoopCloneContext* context, unsigned loopNum, GenTree* stmt) + GenTreeStmt* stmt; + LoopCloneVisitorInfo(LoopCloneContext* context, unsigned loopNum, GenTreeStmt* stmt) : context(context), loopNum(loopNum), stmt(nullptr) { } @@ -6653,7 +6658,7 @@ public: bool optCanCloneLoops(); #ifdef DEBUG - void optDebugLogLoopCloning(BasicBlock* block, GenTree* insertBefore); + void optDebugLogLoopCloning(BasicBlock* block, GenTreeStmt* insertBefore); #endif void optPerformStaticOptimizations(unsigned loopNum, LoopCloneContext* context DEBUGARG(bool fastPath)); bool optComputeDerefConditions(unsigned loopNum, LoopCloneContext* context); @@ -8720,8 +8725,8 @@ public: unsigned compBasicBlockID; #endif - BasicBlock* compCurBB; // the current basic block in process - GenTree* compCurStmt; // the current statement in process + BasicBlock* compCurBB; // the current basic block in process + GenTreeStmt* compCurStmt; // the current statement in process #ifdef DEBUG unsigned compCurStmtNum; // to give all statements an increasing StmtNum when printing dumps #endif @@ -10309,14 +10314,6 @@ extern BasicBlock dummyBB; /*****************************************************************************/ /*****************************************************************************/ -// foreach_treenode_execution_order: An iterator that iterates through all the tree -// nodes of a statement in execution order. -// __stmt: a GT_STMT type GenTree* -// __node: a GenTree*, already declared, that gets updated with each node in the statement, in execution order - -#define foreach_treenode_execution_order(__node, __stmt) \ - for ((__node) = (__stmt)->gtStmt.gtStmtList; (__node); (__node) = (__node)->gtNext) - // foreach_block: An iterator over all blocks in the function. // __compiler: the Compiler* object // __block : a BasicBlock*, already declared, that gets updated each iteration. diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp index 2eb5ac7b08..901a58ec9e 100644 --- a/src/jit/compiler.hpp +++ b/src/jit/compiler.hpp @@ -1308,10 +1308,9 @@ inline GenTree* Compiler::gtUnusedValNode(GenTree* expr) * operands */ -inline void Compiler::gtSetStmtInfo(GenTree* stmt) +inline void Compiler::gtSetStmtInfo(GenTreeStmt* stmt) { - assert(stmt->gtOper == GT_STMT); - GenTree* expr = stmt->gtStmt.gtStmtExpr; + GenTree* expr = stmt->gtStmtExpr; /* Recursively process the expression */ @@ -1817,17 +1816,15 @@ inline void LclVarDsc::incRefCnts(BasicBlock::weight_t weight, Compiler* comp, R * referenced in a statement. */ -inline VARSET_VALRET_TP Compiler::lvaStmtLclMask(GenTree* stmt) +inline VARSET_VALRET_TP Compiler::lvaStmtLclMask(GenTreeStmt* stmt) { - GenTree* tree; unsigned varNum; LclVarDsc* varDsc; VARSET_TP lclMask(VarSetOps::MakeEmpty(this)); - assert(stmt->gtOper == GT_STMT); assert(fgStmtListThreaded); - for (tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { if (tree->gtOper != GT_LCL_VAR) { diff --git a/src/jit/copyprop.cpp b/src/jit/copyprop.cpp index 4611e91b54..29aa92e0d7 100644 --- a/src/jit/copyprop.cpp +++ b/src/jit/copyprop.cpp @@ -29,9 +29,9 @@ */ void Compiler::optBlockCopyPropPopStacks(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName) { - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { if (!tree->IsLocal()) { @@ -128,7 +128,7 @@ int Compiler::optCopyProp_LclVarScore(LclVarDsc* lclVarDsc, LclVarDsc* copyVarDs // tree - The tree to perform copy propagation on // curSsaName - The map from lclNum to its recently live definitions as a stack -void Compiler::optCopyProp(BasicBlock* block, GenTree* stmt, GenTree* tree, LclNumToGenTreePtrStack* curSsaName) +void Compiler::optCopyProp(BasicBlock* block, GenTreeStmt* stmt, GenTree* tree, LclNumToGenTreePtrStack* curSsaName) { // TODO-Review: EH successor/predecessor iteration seems broken. if (block->bbCatchTyp == BBCT_FINALLY || block->bbCatchTyp == BBCT_FAULT) @@ -315,12 +315,12 @@ void Compiler::optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curS // There are no definitions at the start of the block. So clear it. compCurLifeTree = nullptr; VarSetOps::Assign(this, compCurLife, block->bbLiveIn); - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { VarSetOps::ClearD(this, optCopyPropKillSet); // Walk the tree to find if any local variable can be replaced with current live definitions. - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { treeLifeUpdater.UpdateLife(tree); @@ -347,7 +347,7 @@ void Compiler::optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curS } // This logic must be in sync with SSA renaming process. - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { if (!optIsSsaLocal(tree)) { diff --git a/src/jit/earlyprop.cpp b/src/jit/earlyprop.cpp index bd4c222664..084ed9bdef 100644 --- a/src/jit/earlyprop.cpp +++ b/src/jit/earlyprop.cpp @@ -195,7 +195,7 @@ void Compiler::optEarlyProp() // Walk the stmt tree in linear order to rewrite any array length reference with a // constant array length. bool isRewritten = false; - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree != nullptr; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { GenTree* rewrittenTree = optEarlyPropRewriteTree(tree); if (rewrittenTree != nullptr) @@ -258,7 +258,7 @@ GenTree* Compiler::optEarlyPropRewriteTree(GenTree* tree) // * stmtExpr void (top level) // \--* indir int // \--* lclVar ref V02 loc0 - if (compCurStmt->gtStmt.gtStmtExpr == tree) + if (compCurStmt->gtStmtExpr == tree) { return nullptr; } diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index 3f830f6f4c..976b0a30cb 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -270,7 +270,7 @@ void Compiler::fgInstrumentMethod() HRESULT res = info.compCompHnd->allocBBProfileBuffer(countOfBlocks, &bbProfileBufferStart); - GenTree* stmt; + GenTreeStmt* stmt; if (!SUCCEEDED(res)) { @@ -507,12 +507,12 @@ bool Compiler::fgBBisScratch(BasicBlock* block) // budget doing this per method compiled. // If the budget is exceeded, return 'answerOnBoundExceeded' as the answer. /* static */ -bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, GenTree* stmt, bool answerOnBoundExceeded /*= true*/) +bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, + GenTreeStmt* stmt, + bool answerOnBoundExceeded /*= true*/) { const __int64 maxLinks = 1000000000; - assert(stmt->gtOper == GT_STMT); - __int64* numTraversed = &JitTls::GetCompiler()->compNumStatementLinksTraversed; if (*numTraversed > maxLinks) @@ -539,7 +539,7 @@ bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, GenTree* stmt, // // Arguments: // block - The block into which 'stmt' will be inserted. -// stmt - The statement to be inserted. +// node - The node to be inserted. // // Return Value: // Returns the new (potentially) GT_STMT node. @@ -550,18 +550,23 @@ bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, GenTree* stmt, // In other cases, if there are any phi assignments and/or an assignment of // the GT_CATCH_ARG, we insert after those. -GenTree* Compiler::fgInsertStmtAtBeg(BasicBlock* block, GenTree* stmt) +GenTreeStmt* Compiler::fgInsertStmtAtBeg(BasicBlock* block, GenTree* node) { - if (stmt->gtOper != GT_STMT) + GenTreeStmt* stmt; + if (node->gtOper == GT_STMT) + { + stmt = node->AsStmt(); + } + else { - stmt = gtNewStmt(stmt); + stmt = gtNewStmt(node); } GenTree* list = block->firstStmt(); if (!stmt->IsPhiDefnStmt()) { - GenTree* insertBeforeStmt = block->FirstNonPhiDefOrCatchArgAsg(); + GenTreeStmt* insertBeforeStmt = block->FirstNonPhiDefOrCatchArgAsg(); if (insertBeforeStmt != nullptr) { return fgInsertStmtBefore(block, insertBeforeStmt, stmt); @@ -743,11 +748,9 @@ GenTreeStmt* Compiler::fgInsertStmtNearEnd(BasicBlock* block, GenTree* node) * Note that the gtPrev list of statement nodes is circular, but the gtNext list is not. */ -GenTree* Compiler::fgInsertStmtAfter(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt) +GenTreeStmt* Compiler::fgInsertStmtAfter(BasicBlock* block, GenTreeStmt* insertionPoint, GenTreeStmt* stmt) { assert(block->bbTreeList != nullptr); - noway_assert(insertionPoint->gtOper == GT_STMT); - noway_assert(stmt->gtOper == GT_STMT); assert(fgBlockContainsStatementBounded(block, insertionPoint)); assert(!fgBlockContainsStatementBounded(block, stmt, false)); @@ -779,11 +782,9 @@ GenTree* Compiler::fgInsertStmtAfter(BasicBlock* block, GenTree* insertionPoint, // Insert the given tree or statement before GT_STMT node "insertionPoint". // Returns the newly inserted GT_STMT node. -GenTree* Compiler::fgInsertStmtBefore(BasicBlock* block, GenTree* insertionPoint, GenTree* stmt) +GenTreeStmt* Compiler::fgInsertStmtBefore(BasicBlock* block, GenTreeStmt* insertionPoint, GenTreeStmt* stmt) { assert(block->bbTreeList != nullptr); - noway_assert(insertionPoint->gtOper == GT_STMT); - noway_assert(stmt->gtOper == GT_STMT); assert(fgBlockContainsStatementBounded(block, insertionPoint)); assert(!fgBlockContainsStatementBounded(block, stmt, false)); @@ -817,22 +818,22 @@ GenTree* Compiler::fgInsertStmtBefore(BasicBlock* block, GenTree* insertionPoint * Return the last statement stmtList. */ -GenTree* Compiler::fgInsertStmtListAfter(BasicBlock* block, // the block where stmtAfter is in. - GenTree* stmtAfter, // the statement where stmtList should be inserted - // after. - GenTree* stmtList) +GenTreeStmt* Compiler::fgInsertStmtListAfter(BasicBlock* block, // the block where stmtAfter is in. + GenTreeStmt* stmtAfter, // the statement where stmtList should be inserted + // after. + GenTreeStmt* stmtList) { // Currently we can handle when stmtAfter and stmtList are non-NULL. This makes everything easy. - noway_assert(stmtAfter && stmtAfter->gtOper == GT_STMT); - noway_assert(stmtList && stmtList->gtOper == GT_STMT); + noway_assert(stmtAfter); + noway_assert(stmtList); - GenTree* stmtLast = stmtList->gtPrev; // Last statement in a non-empty list, circular in the gtPrev list. + GenTreeStmt* stmtLast = stmtList->getPrevStmt(); // Last statement in a non-empty list, circular in the gtPrev list. noway_assert(stmtLast); noway_assert(stmtLast->gtNext == nullptr); - GenTree* stmtNext = stmtAfter->gtNext; + GenTreeStmt* stmtNext = stmtAfter->getNextStmt(); - if (!stmtNext) + if (stmtNext == nullptr) { stmtAfter->gtNext = stmtList; stmtList->gtPrev = stmtAfter; @@ -3895,11 +3896,11 @@ bool Compiler::fgCreateGCPoll(GCPollType pollType, BasicBlock* block) // // More formally, if control flow targets an instruction, that instruction must be the // start of a new sequence point. - if (newStmt->gtNext) + GenTreeStmt* nextStmt = newStmt->getNextStmt(); + if (nextStmt != nullptr) { // Is it possible for gtNext to be NULL? - noway_assert(newStmt->gtNext->gtOper == GT_STMT); - newStmt->gtStmtILoffsx = newStmt->gtNextStmt->gtStmtILoffsx; + newStmt->gtStmtILoffsx = nextStmt->gtStmtILoffsx; } } @@ -9220,12 +9221,11 @@ IL_OFFSET Compiler::fgFindBlockILOffset(BasicBlock* block) // could have a similar function for LIR that searches for GT_IL_OFFSET nodes. assert(!block->IsLIR()); - for (GenTree* stmt = block->bbTreeList; stmt != nullptr; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - assert(stmt->IsStatement()); - if (stmt->gtStmt.gtStmtILoffsx != BAD_IL_OFFSET) + if (stmt->gtStmtILoffsx != BAD_IL_OFFSET) { - return jitGetILoffs(stmt->gtStmt.gtStmtILoffsx); + return jitGetILoffs(stmt->gtStmtILoffsx); } } @@ -9321,13 +9321,13 @@ BasicBlock* Compiler::fgSplitBlockAtEnd(BasicBlock* curr) // fgSplitBlockAfterStatement - Split the given block, with all code after // the given statement going into the second block. //------------------------------------------------------------------------------ -BasicBlock* Compiler::fgSplitBlockAfterStatement(BasicBlock* curr, GenTree* stmt) +BasicBlock* Compiler::fgSplitBlockAfterStatement(BasicBlock* curr, GenTreeStmt* stmt) { assert(!curr->IsLIR()); // No statements in LIR, so you can't use this function. BasicBlock* newBlock = fgSplitBlockAtEnd(curr); - if (stmt) + if (stmt != nullptr) { newBlock->bbTreeList = stmt->gtNext; if (newBlock->bbTreeList) @@ -9898,13 +9898,11 @@ void Compiler::fgRemoveEmptyBlocks() * */ -void Compiler::fgRemoveStmt(BasicBlock* block, GenTree* node) +void Compiler::fgRemoveStmt(BasicBlock* block, GenTreeStmt* stmt) { - noway_assert(node); assert(fgOrder == FGOrderTree); GenTreeStmt* tree = block->firstStmt(); - GenTreeStmt* stmt = node->AsStmt(); #ifdef DEBUG if (verbose && @@ -10004,15 +10002,13 @@ inline bool OperIsControlFlow(genTreeOps oper) * Returns true if it did remove the statement. */ -bool Compiler::fgCheckRemoveStmt(BasicBlock* block, GenTree* node) +bool Compiler::fgCheckRemoveStmt(BasicBlock* block, GenTreeStmt* stmt) { if (opts.compDbgCode) { return false; } - GenTreeStmt* stmt = node->AsStmt(); - GenTree* tree = stmt->gtStmtExpr; genTreeOps oper = tree->OperGet(); @@ -10299,19 +10295,19 @@ void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext) } // Now proceed with the updated bbTreeLists. - GenTree* stmtList1 = block->firstStmt(); - GenTree* stmtList2 = bNext->firstStmt(); + GenTreeStmt* stmtList1 = block->firstStmt(); + GenTreeStmt* stmtList2 = bNext->firstStmt(); /* the block may have an empty list */ - if (stmtList1) + if (stmtList1 != nullptr) { - GenTree* stmtLast1 = block->lastStmt(); + GenTreeStmt* stmtLast1 = block->lastStmt(); /* The second block may be a GOTO statement or something with an empty bbTreeList */ - if (stmtList2) + if (stmtList2 != nullptr) { - GenTree* stmtLast2 = bNext->lastStmt(); + GenTreeStmt* stmtLast2 = bNext->lastStmt(); /* append list2 to list 1 */ @@ -13943,7 +13939,7 @@ bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block) } else { - GenTree* nopStmt = fgInsertStmtAtEnd(block, nop); + GenTreeStmt* nopStmt = fgInsertStmtAtEnd(block, nop); fgSetStmtSeq(nopStmt); gtSetStmtInfo(nopStmt); } @@ -14457,7 +14453,7 @@ bool Compiler::fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock* GenTree* cloned = gtCloneExpr(stmt->gtStmtExpr); noway_assert(cloned); - GenTree* jmpStmt = gtNewStmt(cloned); + GenTreeStmt* jmpStmt = gtNewStmt(cloned); block->bbJumpKind = BBJ_COND; block->bbJumpDest = target->bbJumpDest; @@ -14727,9 +14723,8 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) assert(!bJump->IsLIR()); assert(!bDest->IsLIR()); - GenTreeStmt* stmt; - unsigned estDupCostSz = 0; - for (stmt = bDest->firstStmt(); stmt; stmt = stmt->gtNextStmt) + unsigned estDupCostSz = 0; + for (GenTreeStmt* stmt = bDest->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt) { GenTree* expr = stmt->gtStmtExpr; @@ -14830,101 +14825,64 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) /* Looks good - duplicate the conditional block */ - GenTree* newStmtList = nullptr; // new stmt list to be added to bJump - GenTree* newStmtLast = nullptr; - bool cloneExprFailed = false; + GenTreeStmt* newStmtList = nullptr; // new stmt list to be added to bJump + GenTreeStmt* newLastStmt = nullptr; /* Visit all the statements in bDest */ - for (GenTree* curStmt = bDest->bbTreeList; curStmt; curStmt = curStmt->gtNext) + for (GenTreeStmt* curStmt = bDest->firstStmt(); curStmt != nullptr; curStmt = curStmt->getNextStmt()) { - /* Clone/substitute the expression */ - - stmt = gtCloneExpr(curStmt)->AsStmt(); - - // cloneExpr doesn't handle everything + // Clone/substitute the expression. + GenTreeStmt* stmt = gtCloneExpr(curStmt)->AsStmt(); + // cloneExpr doesn't handle everything. if (stmt == nullptr) { - cloneExprFailed = true; - break; + return false; } /* Append the expression to our list */ if (newStmtList != nullptr) { - newStmtLast->gtNext = stmt; + newLastStmt->gtNext = stmt; } else { newStmtList = stmt; } - stmt->gtPrev = newStmtLast; - newStmtLast = stmt; - } - - if (cloneExprFailed) - { - return false; - } - - noway_assert(newStmtLast != nullptr); - noway_assert(stmt != nullptr); - noway_assert(stmt->gtOper == GT_STMT); - - if ((newStmtLast == nullptr) || (stmt == nullptr) || (stmt->gtOper != GT_STMT)) - { - return false; + stmt->gtPrev = newLastStmt; + newLastStmt = stmt; } - /* Get to the condition node from the statement tree */ - - GenTree* condTree = stmt->gtStmtExpr; + // Get to the condition node from the statement tree. + GenTree* condTree = newLastStmt->gtStmtExpr; noway_assert(condTree->gtOper == GT_JTRUE); - if (condTree->gtOper != GT_JTRUE) - { - return false; - } - - // - // Set condTree to the operand to the GT_JTRUE - // + // Set condTree to the operand to the GT_JTRUE. condTree = condTree->gtOp.gtOp1; - // - // This condTree has to be a RelOp comparison - // + // This condTree has to be a RelOp comparison. if (condTree->OperIsCompare() == false) { return false; } - // - // Find the last statement in the bJump block - // - GenTreeStmt* lastStmt = nullptr; - for (stmt = bJump->firstStmt(); stmt; stmt = stmt->gtNextStmt) - { - lastStmt = stmt; - } - stmt = bJump->firstStmt(); - - /* Join the two linked lists */ - newStmtLast->gtNext = nullptr; + // Join the two linked lists. + GenTreeStmt* lastStmt = bJump->lastStmt(); if (lastStmt != nullptr) { - stmt->gtPrev = newStmtLast; + GenTreeStmt* stmt = bJump->firstStmt(); + stmt->gtPrev = newLastStmt; lastStmt->gtNext = newStmtList; newStmtList->gtPrev = lastStmt; } else { bJump->bbTreeList = newStmtList; - newStmtList->gtPrev = newStmtLast; + newStmtList->gtPrev = newLastStmt; } // @@ -14994,7 +14952,7 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) { // Dump out the newStmtList that we created printf("\nfgOptimizeBranch added these statements(s) at the end of " FMT_BB ":\n", bJump->bbNum); - for (stmt = newStmtList->AsStmt(); stmt; stmt = stmt->gtNextStmt) + for (GenTreeStmt* stmt = newStmtList; stmt != nullptr; stmt = stmt->getNextStmt()) { gtDispTree(stmt); } @@ -16102,9 +16060,9 @@ void Compiler::fgReorderBlocks() if (bPrev->bbJumpKind == BBJ_COND) { /* Reverse the bPrev jump condition */ - GenTree* condTest = bPrev->lastStmt(); + GenTreeStmt* condTestStmt = bPrev->lastStmt(); - condTest = condTest->gtStmt.gtStmtExpr; + GenTree* condTest = condTestStmt->gtStmtExpr; noway_assert(condTest->gtOper == GT_JTRUE); condTest->gtOp.gtOp1 = gtReverseCond(condTest->gtOp.gtOp1); @@ -19009,24 +18967,22 @@ void Compiler::fgSetBlockOrder() /*****************************************************************************/ -void Compiler::fgSetStmtSeq(GenTree* tree) +void Compiler::fgSetStmtSeq(GenTreeStmt* stmt) { GenTree list; // helper node that we use to start the StmtList // It's located in front of the first node in the list - noway_assert(tree->gtOper == GT_STMT); - /* Assign numbers and next/prev links for this tree */ fgTreeSeqNum = 0; fgTreeSeqLst = &list; fgTreeSeqBeg = nullptr; - fgSetTreeSeqHelper(tree->gtStmt.gtStmtExpr, false); + fgSetTreeSeqHelper(stmt->gtStmtExpr, false); /* Record the address of the first node */ - tree->gtStmt.gtStmtList = fgTreeSeqBeg; + stmt->gtStmtList = fgTreeSeqBeg; #ifdef DEBUG @@ -19042,7 +18998,7 @@ void Compiler::fgSetStmtSeq(GenTree* tree) GenTree* temp; GenTree* last; - for (temp = list.gtNext, last = &list; temp; last = temp, temp = temp->gtNext) + for (temp = list.gtNext, last = &list; temp != nullptr; last = temp, temp = temp->gtNext) { if (temp->gtPrev != last) { @@ -19056,10 +19012,10 @@ void Compiler::fgSetStmtSeq(GenTree* tree) BAD_LIST:; printf("\n"); - gtDispTree(tree->gtStmt.gtStmtExpr); + gtDispTree(stmt->gtStmtExpr); printf("\n"); - for (GenTree* bad = &list; bad; bad = bad->gtNext) + for (GenTree* bad = &list; bad != nullptr; bad = bad->gtNext) { printf(" entry at "); printTreeID(bad); @@ -19096,42 +19052,32 @@ void Compiler::fgSetStmtSeq(GenTree* tree) void Compiler::fgSetBlockOrder(BasicBlock* block) { - GenTree* tree; - - tree = block->bbTreeList; - if (!tree) - { - return; - } - - for (;;) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - fgSetStmtSeq(tree); + fgSetStmtSeq(stmt); /* Are there any more trees in this basic block? */ - if (tree->gtNext == nullptr) + if (stmt->gtNext == nullptr) { /* last statement in the tree list */ - noway_assert(block->lastStmt() == tree); + noway_assert(block->lastStmt() == stmt); break; } #ifdef DEBUG - if (block->bbTreeList == tree) + if (block->bbTreeList == stmt) { /* first statement in the list */ - noway_assert(tree->gtPrev->gtNext == nullptr); + assert(stmt->gtPrev->gtNext == nullptr); } else { - noway_assert(tree->gtPrev->gtNext == tree); + assert(stmt->gtPrev->gtNext == stmt); } - noway_assert(tree->gtNext->gtPrev == tree); + assert(stmt->gtNext->gtPrev == stmt); #endif // DEBUG - - tree = tree->gtNext; } } @@ -19204,26 +19150,18 @@ unsigned Compiler::fgGetCodeEstimate(BasicBlock* block) break; } - GenTree* tree = block->FirstNonPhiDef(); - if (tree) + for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt()) { - do + if (stmt->gtCostSz < MAX_COST) { - noway_assert(tree->gtOper == GT_STMT); - - if (tree->gtCostSz < MAX_COST) - { - costSz += tree->gtCostSz; - } - else - { - // We could walk the tree to find out the real gtCostSz, - // but just using MAX_COST for this trees code size works OK - costSz += tree->gtCostSz; - } - - tree = tree->gtNext; - } while (tree); + costSz += stmt->gtCostSz; + } + else + { + // We could walk the tree to find out the real gtCostSz, + // but just using MAX_COST for this trees code size works OK + costSz += stmt->gtCostSz; + } } return costSz; @@ -20468,7 +20406,7 @@ void Compiler::fgDispBasicBlocks(bool dumpTrees) /*****************************************************************************/ // Increment the stmtNum and dump the tree using gtDispTree // -void Compiler::fgDumpStmtTree(GenTree* stmt, unsigned bbNum) +void Compiler::fgDumpStmtTree(GenTreeStmt* stmt, unsigned bbNum) { compCurStmtNum++; // Increment the current stmtNum @@ -20480,7 +20418,7 @@ void Compiler::fgDumpStmtTree(GenTree* stmt, unsigned bbNum) } else { - gtDispTree(stmt->gtStmt.gtStmtExpr); + gtDispTree(stmt->gtStmtExpr); } } @@ -20497,10 +20435,11 @@ void Compiler::fgDumpBlock(BasicBlock* block) if (!block->IsLIR()) { - for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt) + GenTreeStmt* firstStmt = block->firstStmt(); + for (GenTreeStmt* stmt = firstStmt; stmt != nullptr; stmt = stmt->getNextStmt()) { fgDumpStmtTree(stmt, block->bbNum); - if (stmt == block->bbTreeList) + if (stmt == firstStmt) { block->bbStmtNum = compCurStmtNum; // Set the block->bbStmtNum } @@ -21488,7 +21427,7 @@ void Compiler::fgDebugCheckFlagsHelper(GenTree* tree, unsigned treeFlags, unsign // DEBUG routine to check correctness of the internal gtNext, gtPrev threading of a statement. // This threading is only valid when fgStmtListThreaded is true. // This calls an alternate method for FGOrderLinear. -void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node) +void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTreeStmt* stmt) { // LIR blocks are checked using BasicBlock::CheckLIR(). if (block->IsLIR()) @@ -21497,8 +21436,6 @@ void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node) // TODO: return? } - GenTreeStmt* stmt = node->AsStmt(); - assert(fgStmtListThreaded); noway_assert(stmt->gtStmtList); @@ -22866,7 +22803,7 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) #ifdef DEBUG - GenTree* currentDumpStmt = nullptr; + GenTreeStmt* currentDumpStmt = nullptr; if (verbose) { @@ -22889,7 +22826,7 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) } // Prepend statements - GenTree* stmtAfter = fgInlinePrependStatements(pInlineInfo); + GenTreeStmt* stmtAfter = fgInlinePrependStatements(pInlineInfo); #ifdef DEBUG if (verbose) @@ -22916,7 +22853,7 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // Inlinee contains just one BB. So just insert its statement list to topBlock. if (InlineeCompiler->fgFirstBB->bbTreeList) { - stmtAfter = fgInsertStmtListAfter(iciBlock, stmtAfter, InlineeCompiler->fgFirstBB->bbTreeList); + stmtAfter = fgInsertStmtListAfter(iciBlock, stmtAfter, InlineeCompiler->fgFirstBB->firstStmt()); // Copy inlinee bbFlags to caller bbFlags. const unsigned __int64 inlineeBlockFlags = InlineeCompiler->fgFirstBB->bbFlags; @@ -22934,12 +22871,10 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) { do { - currentDumpStmt = currentDumpStmt->gtNext; + currentDumpStmt = currentDumpStmt->getNextStmt(); printf("\n"); - noway_assert(currentDumpStmt->gtOper == GT_STMT); - gtDispTree(currentDumpStmt); printf("\n"); @@ -23219,14 +23154,14 @@ _Done: // and are are given the same inline context as the call any calls // added here will appear to have been part of the immediate caller. -GenTree* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) +GenTreeStmt* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) { BasicBlock* block = inlineInfo->iciBlock; GenTreeStmt* callStmt = inlineInfo->iciStmt; IL_OFFSETX callILOffset = callStmt->gtStmtILoffsx; GenTreeStmt* postStmt = callStmt->gtNextStmt; - GenTree* afterStmt = callStmt; // afterStmt is the place where the new statements should be inserted after. - GenTree* newStmt = nullptr; + GenTreeStmt* afterStmt = callStmt; // afterStmt is the place where the new statements should be inserted after. + GenTreeStmt* newStmt = nullptr; GenTreeCall* call = inlineInfo->iciCall->AsCall(); noway_assert(call->gtOper == GT_CALL); @@ -23599,7 +23534,7 @@ GenTree* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) // we skip nulling the locals, since it can interfere // with tail calls introduced by the local. -void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTree* stmtAfter) +void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTreeStmt* stmtAfter) { // If this inlinee was passed a runtime lookup generic context and // ignores it, we can decrement the "generic context was used" ref @@ -23649,8 +23584,8 @@ void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* bloc JITDUMP("fgInlineAppendStatements: nulling out gc ref inlinee locals.\n"); - GenTree* callStmt = inlineInfo->iciStmt; - IL_OFFSETX callILOffset = callStmt->gtStmt.gtStmtILoffsx; + GenTreeStmt* callStmt = inlineInfo->iciStmt; + IL_OFFSETX callILOffset = callStmt->gtStmtILoffsx; CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo; const unsigned lclCnt = InlineeMethodInfo->locals.numArgs; InlLclVarInfo* lclVarInfo = inlineInfo->lclVarInfo; @@ -23700,8 +23635,8 @@ void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* bloc } // Assign null to the local. - GenTree* nullExpr = gtNewTempAssign(tmpNum, gtNewZeroConNode(lclTyp)); - GenTree* nullStmt = gtNewStmt(nullExpr, callILOffset); + GenTree* nullExpr = gtNewTempAssign(tmpNum, gtNewZeroConNode(lclTyp)); + GenTreeStmt* nullStmt = gtNewStmt(nullExpr, callILOffset); if (stmtAfter == nullptr) { diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 69e774cf9b..833d115cb2 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -571,17 +571,11 @@ void GenTree::DumpNodeSizes(FILE* fp) void Compiler::fgWalkAllTreesPre(fgWalkPreFn* visitor, void* pCallBackData) { - BasicBlock* block; - - for (block = fgFirstBB; block; block = block->bbNext) + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { - GenTree* tree; - - for (tree = block->bbTreeList; tree; tree = tree->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - assert(tree->gtOper == GT_STMT); - - fgWalkTreePre(&tree->gtStmt.gtStmtExpr, visitor, pCallBackData); + fgWalkTreePre(&stmt->gtStmtExpr, visitor, pCallBackData); } } } @@ -3591,7 +3585,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) // under a struct assignment would not be considered for addressing modes. if (compCurStmt != nullptr) { - GenTree* expr = compCurStmt->gtStmt.gtStmtExpr; + GenTree* expr = compCurStmt->gtStmtExpr; if ((expr->OperGet() == GT_ASG) && ((expr->gtGetOp1() == tree) || (expr->gtGetOp2() == tree))) { @@ -7619,7 +7613,7 @@ GenTreeCall* Compiler::gtCloneCandidateCall(GenTreeCall* call) // but this method will sequence 'replacementTree', and insert it into the // proper place in the statement sequence. -GenTree* Compiler::gtReplaceTree(GenTree* stmt, GenTree* tree, GenTree* replacementTree) +GenTree* Compiler::gtReplaceTree(GenTreeStmt* stmt, GenTree* tree, GenTree* replacementTree) { assert(fgStmtListThreaded); assert(tree != nullptr); @@ -7629,14 +7623,14 @@ GenTree* Compiler::gtReplaceTree(GenTree* stmt, GenTree* tree, GenTree* replacem GenTree** treePtr = nullptr; GenTree* treeParent = tree->gtGetParent(&treePtr); - assert(treeParent != nullptr || tree == stmt->gtStmt.gtStmtExpr); + assert(treeParent != nullptr || tree == stmt->gtStmtExpr); if (treePtr == nullptr) { // Replace the stmt expr and rebuild the linear order for "stmt". assert(treeParent == nullptr); assert(fgOrder != FGOrderLinear); - stmt->gtStmt.gtStmtExpr = tree; + stmt->gtStmtExpr = tree; fgSetStmtSeq(stmt); } else @@ -7683,8 +7677,8 @@ GenTree* Compiler::gtReplaceTree(GenTree* stmt, GenTree* tree, GenTree* replacem { // Update the linear oder start of "stmt" if treeFirstNode // appears to have replaced the original first node. - assert(treeFirstNode == stmt->gtStmt.gtStmtList); - stmt->gtStmt.gtStmtList = fgGetFirstNode(replacementTree); + assert(treeFirstNode == stmt->gtStmtList); + stmt->gtStmtList = fgGetFirstNode(replacementTree); } if (treeNextNode != nullptr) @@ -7708,7 +7702,7 @@ GenTree* Compiler::gtReplaceTree(GenTree* stmt, GenTree* tree, GenTree* replacem // Note: If tree's order hasn't been established, the method updates side effect // flags on all statement's nodes. -void Compiler::gtUpdateSideEffects(GenTree* stmt, GenTree* tree) +void Compiler::gtUpdateSideEffects(GenTreeStmt* stmt, GenTree* tree) { if (fgStmtListThreaded) { @@ -7743,9 +7737,9 @@ void Compiler::gtUpdateTreeAncestorsSideEffects(GenTree* tree) // Arguments: // stmt - The statement to update side effects on -void Compiler::gtUpdateStmtSideEffects(GenTree* stmt) +void Compiler::gtUpdateStmtSideEffects(GenTreeStmt* stmt) { - fgWalkTree(&stmt->gtStmt.gtStmtExpr, fgUpdateSideEffectsPre, fgUpdateSideEffectsPost); + fgWalkTree(&stmt->gtStmtExpr, fgUpdateSideEffectsPre, fgUpdateSideEffectsPost); } //------------------------------------------------------------------------ @@ -9705,16 +9699,17 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, __in __in_z _ { if (opts.compDbgInfo) { - IL_OFFSET endIL = tree->gtStmt.gtStmtLastILoffs; + GenTreeStmt* stmt = tree->AsStmt(); + IL_OFFSET endIL = stmt->gtStmtLastILoffs; printf("(IL "); - if (tree->gtStmt.gtStmtILoffsx == BAD_IL_OFFSET) + if (stmt->gtStmtILoffsx == BAD_IL_OFFSET) { printf(" ???"); } else { - printf("0x%03X", jitGetILoffs(tree->gtStmt.gtStmtILoffsx)); + printf("0x%03X", jitGetILoffs(stmt->gtStmtILoffsx)); } printf("..."); if (endIL == BAD_IL_OFFSET) @@ -12572,12 +12567,9 @@ GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions assert(op->IsBoxedValue()); // grab related parts for the optimization - GenTreeBox* box = op->AsBox(); - GenTree* asgStmt = box->gtAsgStmtWhenInlinedBoxValue; - GenTree* copyStmt = box->gtCopyStmtWhenInlinedBoxValue; - - assert(asgStmt->gtOper == GT_STMT); - assert(copyStmt->gtOper == GT_STMT); + GenTreeBox* box = op->AsBox(); + GenTreeStmt* asgStmt = box->gtAsgStmtWhenInlinedBoxValue; + GenTreeStmt* copyStmt = box->gtCopyStmtWhenInlinedBoxValue; JITDUMP("gtTryRemoveBoxUpstreamEffects: %s to %s of BOX (valuetype)" " [%06u] (assign/newobj [%06u] copy [%06u])\n", @@ -12586,7 +12578,7 @@ GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions dspTreeID(asgStmt), dspTreeID(copyStmt)); // If we don't recognize the form of the assign, bail. - GenTree* asg = asgStmt->gtStmt.gtStmtExpr; + GenTree* asg = asgStmt->gtStmtExpr; if (asg->gtOper != GT_ASG) { JITDUMP(" bailing; unexpected assignment op %s\n", GenTree::OpName(asg->gtOper)); @@ -12633,7 +12625,7 @@ GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions } // If we don't recognize the form of the copy, bail. - GenTree* copy = copyStmt->gtStmt.gtStmtExpr; + GenTree* copy = copyStmt->gtStmtExpr; if (copy->gtOper != GT_ASG) { // GT_RET_EXPR is a tolerable temporary failure. @@ -12788,7 +12780,7 @@ GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions // value as the copy is fairly cheap and likely // the optimizer can trim things down to just the // minimal side effect parts. - copyStmt->gtStmt.gtStmtExpr = copySrc; + copyStmt->gtStmtExpr = copySrc; JITDUMP(" to scalar read via [%06u]\n", dspTreeID(copySrc)); } else @@ -12797,7 +12789,7 @@ GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions // source struct; there's no need to read the // entire thing, and no place to put it. assert(copySrc->gtOper == GT_OBJ || copySrc->gtOper == GT_IND || copySrc->gtOper == GT_FIELD); - copyStmt->gtStmt.gtStmtExpr = copySrc; + copyStmt->gtStmtExpr = copySrc; if (options == BR_REMOVE_AND_NARROW || options == BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE) { @@ -12950,11 +12942,11 @@ GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp) } else { - const unsigned thisTmp = lvaGrabTemp(true DEBUGARG("Enum:HasFlag this temp")); - GenTree* thisAsg = gtNewTempAssign(thisTmp, thisVal); - GenTree* thisAsgStmt = thisOp->AsBox()->gtCopyStmtWhenInlinedBoxValue; - thisAsgStmt->gtStmt.gtStmtExpr = thisAsg; - thisValOpt = gtNewLclvNode(thisTmp, type); + const unsigned thisTmp = lvaGrabTemp(true DEBUGARG("Enum:HasFlag this temp")); + GenTree* thisAsg = gtNewTempAssign(thisTmp, thisVal); + GenTreeStmt* thisAsgStmt = thisOp->AsBox()->gtCopyStmtWhenInlinedBoxValue; + thisAsgStmt->gtStmtExpr = thisAsg; + thisValOpt = gtNewLclvNode(thisTmp, type); } if (flagVal->IsIntegralConst()) @@ -12966,12 +12958,12 @@ GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp) } else { - const unsigned flagTmp = lvaGrabTemp(true DEBUGARG("Enum:HasFlag flag temp")); - GenTree* flagAsg = gtNewTempAssign(flagTmp, flagVal); - GenTree* flagAsgStmt = flagOp->AsBox()->gtCopyStmtWhenInlinedBoxValue; - flagAsgStmt->gtStmt.gtStmtExpr = flagAsg; - flagValOpt = gtNewLclvNode(flagTmp, type); - flagValOptCopy = gtNewLclvNode(flagTmp, type); + const unsigned flagTmp = lvaGrabTemp(true DEBUGARG("Enum:HasFlag flag temp")); + GenTree* flagAsg = gtNewTempAssign(flagTmp, flagVal); + GenTreeStmt* flagAsgStmt = flagOp->AsBox()->gtCopyStmtWhenInlinedBoxValue; + flagAsgStmt->gtStmtExpr = flagAsg; + flagValOpt = gtNewLclvNode(flagTmp, type); + flagValOptCopy = gtNewLclvNode(flagTmp, type); } // Turn the call into (thisValTmp & flagTmp) == flagTmp. @@ -14425,7 +14417,7 @@ DONE: // May set compFloatingPointUsed. GenTree* Compiler::gtNewTempAssign( - unsigned tmp, GenTree* val, GenTree** pAfterStmt, IL_OFFSETX ilOffset, BasicBlock* block) + unsigned tmp, GenTree* val, GenTreeStmt** pAfterStmt, IL_OFFSETX ilOffset, BasicBlock* block) { // Self-assignment is a nop. if (val->OperGet() == GT_LCL_VAR && val->gtLclVarCommon.gtLclNum == tmp) @@ -15157,13 +15149,11 @@ static Compiler::fgWalkResult gtFindLinkCB(GenTree** pTree, Compiler::fgWalkData return Compiler::WALK_CONTINUE; } -GenTree** Compiler::gtFindLink(GenTree* stmt, GenTree* node) +GenTree** Compiler::gtFindLink(GenTreeStmt* stmt, GenTree* node) { - assert(stmt->gtOper == GT_STMT); - FindLinkData data = {node, nullptr}; - fgWalkResult result = fgWalkTreePre(&stmt->gtStmt.gtStmtExpr, gtFindLinkCB, &data); + fgWalkResult result = fgWalkTreePre(&stmt->gtStmtExpr, gtFindLinkCB, &data); if (result == WALK_ABORT) { diff --git a/src/jit/gentree.h b/src/jit/gentree.h index 6893c35ce4..5d45427a39 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -2812,14 +2812,14 @@ struct GenTreeBox : public GenTreeUnOp } // This is the statement that contains the assignment tree when the node is an inlined GT_BOX on a value // type - GenTree* gtAsgStmtWhenInlinedBoxValue; + GenTreeStmt* gtAsgStmtWhenInlinedBoxValue; // And this is the statement that copies from the value being boxed to the box payload - GenTree* gtCopyStmtWhenInlinedBoxValue; + GenTreeStmt* gtCopyStmtWhenInlinedBoxValue; - GenTreeBox(var_types type, - GenTree* boxOp, - GenTree* asgStmtWhenInlinedBoxValue, - GenTree* copyStmtWhenInlinedBoxValue) + GenTreeBox(var_types type, + GenTree* boxOp, + GenTreeStmt* asgStmtWhenInlinedBoxValue, + GenTreeStmt* copyStmtWhenInlinedBoxValue) : GenTreeUnOp(GT_BOX, type, boxOp) , gtAsgStmtWhenInlinedBoxValue(asgStmtWhenInlinedBoxValue) , gtCopyStmtWhenInlinedBoxValue(copyStmtWhenInlinedBoxValue) diff --git a/src/jit/gtlist.h b/src/jit/gtlist.h index 2421a8f033..c46bfefd72 100644 --- a/src/jit/gtlist.h +++ b/src/jit/gtlist.h @@ -244,8 +244,6 @@ GTNODE(CALL , GenTreeCall ,0,(GTK_SPECIAL|GTK_NOCONTAIN)) //----------------------------------------------------------------------------- // Statement operator nodes: //----------------------------------------------------------------------------- - -GTNODE(BEG_STMTS , GenTree ,0,(GTK_SPECIAL|GTK_NOVALUE))// used only temporarily in importer by impBegin/EndTreeList() GTNODE(STMT , GenTreeStmt ,0,(GTK_SPECIAL|GTK_NOVALUE))// top-level list nodes in bbTreeList GTNODE(RETURN , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) // return from current function diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index 5e012e3672..a69d5589a9 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -63,12 +63,10 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void Compiler::impInit() { - + impStmtList = impLastStmt = nullptr; #ifdef DEBUG - impTreeList = nullptr; - impTreeLast = nullptr; impInlinedCodeSize = 0; -#endif +#endif // DEBUG } /***************************************************************************** @@ -409,15 +407,12 @@ void Compiler::impRestoreStackState(SavedStack* savePtr) } } -/***************************************************************************** - * - * Get the tree list started for a new basic block. - */ +//------------------------------------------------------------------------ +// impBeginTreeList: Get the tree list started for a new basic block. +// inline void Compiler::impBeginTreeList() { - assert(impTreeList == nullptr && impTreeLast == nullptr); - - impTreeList = impTreeLast = new (this, GT_BEG_STMTS) GenTree(GT_BEG_STMTS, TYP_VOID); + assert(impStmtList == nullptr && impLastStmt == nullptr); } /***************************************************************************** @@ -427,11 +422,8 @@ inline void Compiler::impBeginTreeList() * directly only for handling CEE_LEAVEs out of finally-protected try's. */ -inline void Compiler::impEndTreeList(BasicBlock* block, GenTree* firstStmt, GenTree* lastStmt) +inline void Compiler::impEndTreeList(BasicBlock* block, GenTreeStmt* firstStmt, GenTreeStmt* lastStmt) { - assert(firstStmt->gtOper == GT_STMT); - assert(lastStmt->gtOper == GT_STMT); - /* Make the list circular, so that we can easily walk it backwards */ firstStmt->gtPrev = lastStmt; @@ -446,42 +438,35 @@ inline void Compiler::impEndTreeList(BasicBlock* block, GenTree* firstStmt, GenT block->bbFlags |= BBF_IMPORTED; } -/***************************************************************************** - * - * Store the current tree list in the given basic block. - */ - +//------------------------------------------------------------------------ +// impEndTreeList: Store the current tree list in the given basic block. +// +// Arguments: +// block - the basic block to store into. +// inline void Compiler::impEndTreeList(BasicBlock* block) { - assert(impTreeList->gtOper == GT_BEG_STMTS); - - GenTree* firstTree = impTreeList->gtNext; - - if (!firstTree) + if (impStmtList == nullptr) { - /* The block should not already be marked as imported */ + // The block should not already be marked as imported. assert((block->bbFlags & BBF_IMPORTED) == 0); - // Empty block. Just mark it as imported + // Empty block. Just mark it as imported. block->bbFlags |= BBF_IMPORTED; } else { - // Ignore the GT_BEG_STMTS - assert(firstTree->gtPrev == impTreeList); - - impEndTreeList(block, firstTree, impTreeLast); + impEndTreeList(block, impStmtList, impLastStmt); } #ifdef DEBUG if (impLastILoffsStmt != nullptr) { - impLastILoffsStmt->gtStmt.gtStmtLastILoffs = compIsForInlining() ? BAD_IL_OFFSET : impCurOpcOffs; - impLastILoffsStmt = nullptr; + impLastILoffsStmt->gtStmtLastILoffs = compIsForInlining() ? BAD_IL_OFFSET : impCurOpcOffs; + impLastILoffsStmt = nullptr; } - - impTreeList = impTreeLast = nullptr; #endif + impStmtList = impLastStmt = nullptr; } /***************************************************************************** @@ -490,12 +475,11 @@ inline void Compiler::impEndTreeList(BasicBlock* block) * that this has only limited value as we can only check [0..chkLevel). */ -inline void Compiler::impAppendStmtCheck(GenTree* stmt, unsigned chkLevel) +inline void Compiler::impAppendStmtCheck(GenTreeStmt* stmt, unsigned chkLevel) { #ifndef DEBUG return; #else - assert(stmt->gtOper == GT_STMT); if (chkLevel == (unsigned)CHECK_SPILL_ALL) { @@ -507,7 +491,7 @@ inline void Compiler::impAppendStmtCheck(GenTree* stmt, unsigned chkLevel) return; } - GenTree* tree = stmt->gtStmt.gtStmtExpr; + GenTree* tree = stmt->gtStmtExpr; // Calls can only be appended if there are no GTF_GLOB_EFFECT on the stack @@ -556,11 +540,8 @@ inline void Compiler::impAppendStmtCheck(GenTree* stmt, unsigned chkLevel) * interference with stmt and spill if needed. */ -inline void Compiler::impAppendStmt(GenTree* stmt, unsigned chkLevel) +inline void Compiler::impAppendStmt(GenTreeStmt* stmt, unsigned chkLevel) { - assert(stmt->gtOper == GT_STMT); - noway_assert(impTreeLast != nullptr); - if (chkLevel == (unsigned)CHECK_SPILL_ALL) { chkLevel = verCurrentState.esStackDepth; @@ -573,7 +554,7 @@ inline void Compiler::impAppendStmt(GenTree* stmt, unsigned chkLevel) /* If the statement being appended has any side-effects, check the stack to see if anything needs to be spilled to preserve correct ordering. */ - GenTree* expr = stmt->gtStmt.gtStmtExpr; + GenTree* expr = stmt->gtStmtExpr; unsigned flags = expr->gtFlags & GTF_GLOB_EFFECT; // Assignment to (unaliased) locals don't count as a side-effect as @@ -634,14 +615,7 @@ inline void Compiler::impAppendStmt(GenTree* stmt, unsigned chkLevel) impAppendStmtCheck(stmt, chkLevel); - /* Point 'prev' at the previous node, so that we can walk backwards */ - - stmt->gtPrev = impTreeLast; - - /* Append the expression statement to the list */ - - impTreeLast->gtNext = stmt; - impTreeLast = stmt; + impAppendStmt(stmt); #ifdef FEATURE_SIMD impMarkContiguousSIMDFieldAssignments(stmt); @@ -650,7 +624,7 @@ inline void Compiler::impAppendStmt(GenTree* stmt, unsigned chkLevel) /* Once we set impCurStmtOffs in an appended tree, we are ready to report the following offsets. So reset impCurStmtOffs */ - if (impTreeLast->gtStmt.gtStmtILoffsx == impCurStmtOffs) + if (impLastStmt->gtStmtILoffsx == impCurStmtOffs) { impCurStmtOffsSet(BAD_IL_OFFSET); } @@ -669,21 +643,62 @@ inline void Compiler::impAppendStmt(GenTree* stmt, unsigned chkLevel) #endif } +//------------------------------------------------------------------------ +// impAppendStmt: Add the statement to the current stmts list. +// +// Arguments: +// stmt - the statement to add. +// +inline void Compiler::impAppendStmt(GenTreeStmt* stmt) +{ + if (impStmtList == nullptr) + { + // The stmt is the first in the list. + impStmtList = stmt; + } + else + { + // Append the expression statement to the existing list. + impLastStmt->gtNext = stmt; + stmt->gtPrev = impLastStmt; + } + impLastStmt = stmt; +} + +//------------------------------------------------------------------------ +// impExtractLastStmt: Extract the last statement from the current stmts list. +// +// Return Value: +// The extracted statement. +// +// Notes: +// It assumes that the stmt will be reinserted later. +// +GenTreeStmt* Compiler::impExtractLastStmt() +{ + assert(impLastStmt != nullptr); + + GenTreeStmt* stmt = impLastStmt; + impLastStmt = impLastStmt->gtPrevStmt; + if (impLastStmt == nullptr) + { + impStmtList = nullptr; + } + return stmt; +} + /***************************************************************************** * * Insert the given GT_STMT "stmt" before GT_STMT "stmtBefore" */ -inline void Compiler::impInsertStmtBefore(GenTree* stmt, GenTree* stmtBefore) +inline void Compiler::impInsertStmtBefore(GenTreeStmt* stmt, GenTreeStmt* stmtBefore) { - assert(stmt->gtOper == GT_STMT); - assert(stmtBefore->gtOper == GT_STMT); - - GenTree* stmtPrev = stmtBefore->gtPrev; - stmt->gtPrev = stmtPrev; - stmt->gtNext = stmtBefore; - stmtPrev->gtNext = stmt; - stmtBefore->gtPrev = stmt; + GenTreeStmt* stmtPrev = stmtBefore->getPrevStmt(); + stmt->gtPrev = stmtPrev; + stmt->gtNext = stmtBefore; + stmtPrev->gtNext = stmt; + stmtBefore->gtPrev = stmt; } /***************************************************************************** @@ -692,19 +707,19 @@ inline void Compiler::impInsertStmtBefore(GenTree* stmt, GenTree* stmtBefore) * Return the newly created statement. */ -GenTree* Compiler::impAppendTree(GenTree* tree, unsigned chkLevel, IL_OFFSETX offset) +GenTreeStmt* Compiler::impAppendTree(GenTree* tree, unsigned chkLevel, IL_OFFSETX offset) { assert(tree); /* Allocate an 'expression statement' node */ - GenTree* expr = gtNewStmt(tree, offset); + GenTreeStmt* stmt = gtNewStmt(tree, offset); /* Append the statement to the current block's stmt list */ - impAppendStmt(expr, chkLevel); + impAppendStmt(stmt, chkLevel); - return expr; + return stmt; } /***************************************************************************** @@ -712,17 +727,15 @@ GenTree* Compiler::impAppendTree(GenTree* tree, unsigned chkLevel, IL_OFFSETX of * Insert the given exression tree before GT_STMT "stmtBefore" */ -void Compiler::impInsertTreeBefore(GenTree* tree, IL_OFFSETX offset, GenTree* stmtBefore) +void Compiler::impInsertTreeBefore(GenTree* tree, IL_OFFSETX offset, GenTreeStmt* stmtBefore) { - assert(stmtBefore->gtOper == GT_STMT); - /* Allocate an 'expression statement' node */ - GenTree* expr = gtNewStmt(tree, offset); + GenTreeStmt* stmt = gtNewStmt(tree, offset); /* Append the statement to the current block's stmt list */ - impInsertStmtBefore(expr, stmtBefore); + impInsertStmtBefore(stmt, stmtBefore); } /***************************************************************************** @@ -731,12 +744,12 @@ void Compiler::impInsertTreeBefore(GenTree* tree, IL_OFFSETX offset, GenTree* st * curLevel is the stack level for which the spill to the temp is being done. */ -void Compiler::impAssignTempGen(unsigned tmp, - GenTree* val, - unsigned curLevel, - GenTree** pAfterStmt, /* = NULL */ - IL_OFFSETX ilOffset, /* = BAD_IL_OFFSET */ - BasicBlock* block /* = NULL */ +void Compiler::impAssignTempGen(unsigned tmp, + GenTree* val, + unsigned curLevel, + GenTreeStmt** pAfterStmt, /* = NULL */ + IL_OFFSETX ilOffset, /* = BAD_IL_OFFSET */ + BasicBlock* block /* = NULL */ ) { GenTree* asg = gtNewTempAssign(tmp, val); @@ -745,8 +758,8 @@ void Compiler::impAssignTempGen(unsigned tmp, { if (pAfterStmt) { - GenTree* asgStmt = gtNewStmt(asg, ilOffset); - *pAfterStmt = fgInsertStmtAfter(block, *pAfterStmt, asgStmt); + GenTreeStmt* asgStmt = gtNewStmt(asg, ilOffset); + *pAfterStmt = fgInsertStmtAfter(block, *pAfterStmt, asgStmt); } else { @@ -763,7 +776,7 @@ void Compiler::impAssignTempGen(unsigned tmpNum, GenTree* val, CORINFO_CLASS_HANDLE structType, unsigned curLevel, - GenTree** pAfterStmt, /* = NULL */ + GenTreeStmt** pAfterStmt, /* = NULL */ IL_OFFSETX ilOffset, /* = BAD_IL_OFFSET */ BasicBlock* block /* = NULL */ ) @@ -805,8 +818,8 @@ void Compiler::impAssignTempGen(unsigned tmpNum, { if (pAfterStmt) { - GenTree* asgStmt = gtNewStmt(asg, ilOffset); - *pAfterStmt = fgInsertStmtAfter(block, *pAfterStmt, asgStmt); + GenTreeStmt* asgStmt = gtNewStmt(asg, ilOffset); + *pAfterStmt = fgInsertStmtAfter(block, *pAfterStmt, asgStmt); } else { @@ -1052,13 +1065,13 @@ GenTreeArgList* Compiler::impPopRevList(unsigned count, CORINFO_SIG_INFO* sig, u // The tree that should be appended to the statement list that represents the assignment. // // Notes: -// Temp assignments may be appended to impTreeList if spilling is necessary. +// Temp assignments may be appended to impStmtList if spilling is necessary. GenTree* Compiler::impAssignStruct(GenTree* dest, GenTree* src, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel, - GenTree** pAfterStmt, /* = nullptr */ + GenTreeStmt** pAfterStmt, /* = nullptr */ IL_OFFSETX ilOffset, /* = BAD_IL_OFFSET */ BasicBlock* block /* = nullptr */ ) @@ -1131,13 +1144,13 @@ GenTree* Compiler::impAssignStruct(GenTree* dest, // The tree that should be appended to the statement list that represents the assignment. // // Notes: -// Temp assignments may be appended to impTreeList if spilling is necessary. +// Temp assignments may be appended to impStmtList if spilling is necessary. GenTree* Compiler::impAssignStructPtr(GenTree* destAddr, GenTree* src, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel, - GenTree** pAfterStmt, /* = NULL */ + GenTreeStmt** pAfterStmt, /* = NULL */ IL_OFFSETX ilOffset, /* = BAD_IL_OFFSET */ BasicBlock* block /* = NULL */ ) @@ -1347,7 +1360,7 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr, // Insert op1 after '*pAfterStmt' *pAfterStmt = fgInsertStmtAfter(block, *pAfterStmt, gtNewStmt(src->gtOp.gtOp1, ilOffset)); } - else if (impTreeLast != nullptr) + else if (impLastStmt != nullptr) { // Do the side-effect as a separate statement. impAppendTree(src->gtOp.gtOp1, curLevel, ilOffset); @@ -1453,17 +1466,17 @@ GenTree* Compiler::impGetStructAddr(GenTree* structVal, { assert(structVal->gtOp.gtOp2->gtType == type); // Second thing is the struct - GenTree* oldTreeLast = impTreeLast; - structVal->gtOp.gtOp2 = impGetStructAddr(structVal->gtOp.gtOp2, structHnd, curLevel, willDeref); - structVal->gtType = TYP_BYREF; + GenTreeStmt* oldLastStmt = impLastStmt; + structVal->gtOp.gtOp2 = impGetStructAddr(structVal->gtOp.gtOp2, structHnd, curLevel, willDeref); + structVal->gtType = TYP_BYREF; - if (oldTreeLast != impTreeLast) + if (oldLastStmt != impLastStmt) { // Some temp assignment statement was placed on the statement list // for Op2, but that would be out of order with op1, so we need to // spill op1 onto the statement list after whatever was last // before we recursed on Op2 (i.e. before whatever Op2 appended). - impInsertTreeBefore(structVal->gtOp.gtOp1, impCurStmtOffs, oldTreeLast->gtNext); + impInsertTreeBefore(structVal->gtOp.gtOp1, impCurStmtOffs, oldLastStmt->getNextStmt()); structVal->gtOp.gtOp1 = gtNewNothingNode(); } @@ -2608,7 +2621,7 @@ GenTree* Compiler::impCloneExpr(GenTree* tree, GenTree** pClone, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel, - GenTree** pAfterStmt DEBUGARG(const char* reason)) + GenTreeStmt** pAfterStmt DEBUGARG(const char* reason)) { if (!(tree->gtFlags & GTF_GLOB_EFFECT)) { @@ -2646,9 +2659,8 @@ inline void Compiler::impCurStmtOffsSet(IL_OFFSET offs) { if (compIsForInlining()) { - GenTree* callStmt = impInlineInfo->iciStmt; - assert(callStmt->gtOper == GT_STMT); - impCurStmtOffs = callStmt->gtStmt.gtStmtILoffsx; + GenTreeStmt* callStmt = impInlineInfo->iciStmt; + impCurStmtOffs = callStmt->gtStmtILoffsx; } else { @@ -2714,15 +2726,14 @@ void Compiler::impNoteLastILoffs() // We should have added a statement for the current basic block // Is this assert correct ? - assert(impTreeLast); - assert(impTreeLast->gtOper == GT_STMT); + assert(impLastStmt); - impTreeLast->gtStmt.gtStmtLastILoffs = compIsForInlining() ? BAD_IL_OFFSET : impCurOpcOffs; + impLastStmt->gtStmtLastILoffs = compIsForInlining() ? BAD_IL_OFFSET : impCurOpcOffs; } else { - impLastILoffsStmt->gtStmt.gtStmtLastILoffs = compIsForInlining() ? BAD_IL_OFFSET : impCurOpcOffs; - impLastILoffsStmt = nullptr; + impLastILoffsStmt->gtStmtLastILoffs = compIsForInlining() ? BAD_IL_OFFSET : impCurOpcOffs; + impLastILoffsStmt = nullptr; } } @@ -3056,12 +3067,9 @@ GenTree* Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO* sig) // If it's not then we just return NULL and we don't optimize this call // - // - // It is possible the we don't have any statements in the block yet - // - if (impTreeLast->gtOper != GT_STMT) + // It is possible the we don't have any statements in the block yet. + if (impLastStmt == nullptr) { - assert(impTreeLast->gtOper == GT_BEG_STMTS); return nullptr; } @@ -3069,7 +3077,7 @@ GenTree* Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO* sig) // We start by looking at the last statement, making sure it's an assignment, and // that the target of the assignment is the array passed to InitializeArray. // - GenTree* arrayAssignment = impTreeLast->gtStmt.gtStmtExpr; + GenTree* arrayAssignment = impLastStmt->gtStmtExpr; if ((arrayAssignment->gtOper != GT_ASG) || (arrayAssignment->gtOp.gtOp1->gtOper != GT_LCL_VAR) || (arrayLocalNode->gtOper != GT_LCL_VAR) || (arrayAssignment->gtOp.gtOp1->gtLclVarCommon.gtLclNum != arrayLocalNode->gtLclVarCommon.gtLclNum)) @@ -4513,7 +4521,7 @@ void Compiler::verConvertBBToThrowVerificationException(BasicBlock* block DEBUGA #ifdef DEBUG // we need this since BeginTreeList asserts otherwise - impTreeList = impTreeLast = nullptr; + impStmtList = impLastStmt = nullptr; block->bbFlags &= ~BBF_IMPORTED; if (logMsg) @@ -5806,7 +5814,7 @@ void Compiler::impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken) GenTree* asg = gtNewTempAssign(impBoxTemp, op1); - GenTree* asgStmt = impAppendTree(asg, (unsigned)CHECK_SPILL_NONE, impCurStmtOffs); + GenTreeStmt* asgStmt = impAppendTree(asg, (unsigned)CHECK_SPILL_NONE, impCurStmtOffs); op1 = gtNewLclvNode(impBoxTemp, TYP_REF); op2 = gtNewIconNode(TARGET_POINTER_SIZE, TYP_I_IMPL); @@ -5847,7 +5855,7 @@ void Compiler::impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken) impSpillSideEffects(true, (unsigned)CHECK_SPILL_ALL DEBUGARG("impImportAndPushBox")); // Set up this copy as a second assignment. - GenTree* copyStmt = impAppendTree(op1, (unsigned)CHECK_SPILL_NONE, impCurStmtOffs); + GenTreeStmt* copyStmt = impAppendTree(op1, (unsigned)CHECK_SPILL_NONE, impCurStmtOffs); op1 = gtNewLclvNode(impBoxTemp, TYP_REF); @@ -9103,7 +9111,7 @@ void Compiler::impImportLeave(BasicBlock* block) } #endif - GenTree* lastStmt; + GenTreeStmt* lastStmt; if (endCatches) { @@ -9113,11 +9121,11 @@ void Compiler::impImportLeave(BasicBlock* block) } else { - lastStmt = endLFin; + lastStmt = endLFin->AsStmt(); } // note that this sets BBF_IMPORTED on the block - impEndTreeList(callBlock, endLFin, lastStmt); + impEndTreeList(callBlock, endLFin->AsStmt(), lastStmt); } step = fgNewBBafter(BBJ_ALWAYS, callBlock, true); @@ -9194,7 +9202,7 @@ void Compiler::impImportLeave(BasicBlock* block) } #endif - GenTree* lastStmt; + GenTreeStmt* lastStmt; if (endCatches) { @@ -9204,10 +9212,10 @@ void Compiler::impImportLeave(BasicBlock* block) } else { - lastStmt = endLFin; + lastStmt = endLFin->AsStmt(); } - impEndTreeList(finalStep, endLFin, lastStmt); + impEndTreeList(finalStep, endLFin->AsStmt(), lastStmt); finalStep->bbJumpDest = leaveTarget; // this is the ultimate destination of the LEAVE @@ -16748,7 +16756,7 @@ SPILLSTACK: // on the stack, its lifetime is hard to determine, simply // don't reuse such temps. - GenTree* addStmt = nullptr; + GenTreeStmt* addStmt = nullptr; /* Do the successors of 'block' have any other predecessors ? We do not want to do some of the optimizations related to multiRef @@ -16760,14 +16768,9 @@ SPILLSTACK: { case BBJ_COND: - /* Temporarily remove the 'jtrue' from the end of the tree list */ + addStmt = impExtractLastStmt(); - assert(impTreeLast); - assert(impTreeLast->gtOper == GT_STMT); - assert(impTreeLast->gtStmt.gtStmtExpr->gtOper == GT_JTRUE); - - addStmt = impTreeLast; - impTreeLast = impTreeLast->gtPrev; + assert(addStmt->gtStmtExpr->gtOper == GT_JTRUE); /* Note if the next block has more than one ancestor */ @@ -16807,14 +16810,8 @@ SPILLSTACK: BasicBlock** jmpTab; unsigned jmpCnt; - /* Temporarily remove the GT_SWITCH from the end of the tree list */ - - assert(impTreeLast); - assert(impTreeLast->gtOper == GT_STMT); - assert(impTreeLast->gtStmt.gtStmtExpr->gtOper == GT_SWITCH); - - addStmt = impTreeLast; - impTreeLast = impTreeLast->gtPrev; + addStmt = impExtractLastStmt(); + assert(addStmt->gtStmtExpr->gtOper == GT_SWITCH); jmpCnt = block->bbJumpSwt->bbsCount; jmpTab = block->bbJumpSwt->bbsDstTab; @@ -16965,9 +16962,9 @@ SPILLSTACK: are spilling to the temps already used by a previous block), we need to spill addStmt */ - if (addStmt && !newTemps && gtHasRef(addStmt->gtStmt.gtStmtExpr, tempNum, false)) + if (addStmt != nullptr && !newTemps && gtHasRef(addStmt->gtStmtExpr, tempNum, false)) { - GenTree* addTree = addStmt->gtStmt.gtStmtExpr; + GenTree* addTree = addStmt->gtStmtExpr; if (addTree->gtOper == GT_JTRUE) { @@ -17025,7 +17022,7 @@ SPILLSTACK: /* Put back the 'jtrue'/'switch' if we removed it earlier */ - if (addStmt) + if (addStmt != nullptr) { impAppendStmt(addStmt, (unsigned)CHECK_SPILL_NONE); } @@ -19181,9 +19178,6 @@ BOOL Compiler::impInlineIsGuaranteedThisDerefBeforeAnySideEffects(GenTree* ad BasicBlock* block = compCurBB; - GenTree* stmt; - GenTree* expr; - if (block != fgFirstBB) { return FALSE; @@ -19200,10 +19194,9 @@ BOOL Compiler::impInlineIsGuaranteedThisDerefBeforeAnySideEffects(GenTree* ad return FALSE; } - for (stmt = impTreeList->gtNext; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = impStmtList; stmt != nullptr; stmt = stmt->gtNextStmt) { - expr = stmt->gtStmt.gtStmtExpr; - + GenTree* expr = stmt->gtStmtExpr; if (GTF_GLOBALLY_VISIBLE_SIDE_EFFECTS(expr->gtFlags)) { return FALSE; diff --git a/src/jit/indirectcalltransformer.cpp b/src/jit/indirectcalltransformer.cpp index e0782b5b73..44dc345853 100644 --- a/src/jit/indirectcalltransformer.cpp +++ b/src/jit/indirectcalltransformer.cpp @@ -333,14 +333,14 @@ private: // virtual void CreateCheck() { - checkBlock = CreateAndInsertBasicBlock(BBJ_COND, currBlock); - GenTree* fatPointerMask = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, FAT_POINTER_MASK); - GenTree* fptrAddressCopy = compiler->gtCloneExpr(fptrAddress); - GenTree* fatPointerAnd = compiler->gtNewOperNode(GT_AND, TYP_I_IMPL, fptrAddressCopy, fatPointerMask); - GenTree* zero = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, 0); - GenTree* fatPointerCmp = compiler->gtNewOperNode(GT_NE, TYP_INT, fatPointerAnd, zero); - GenTree* jmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, fatPointerCmp); - GenTree* jmpStmt = compiler->fgNewStmtFromTree(jmpTree, stmt->gtStmt.gtStmtILoffsx); + checkBlock = CreateAndInsertBasicBlock(BBJ_COND, currBlock); + GenTree* fatPointerMask = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, FAT_POINTER_MASK); + GenTree* fptrAddressCopy = compiler->gtCloneExpr(fptrAddress); + GenTree* fatPointerAnd = compiler->gtNewOperNode(GT_AND, TYP_I_IMPL, fptrAddressCopy, fatPointerMask); + GenTree* zero = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, 0); + GenTree* fatPointerCmp = compiler->gtNewOperNode(GT_NE, TYP_INT, fatPointerAnd, zero); + GenTree* jmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, fatPointerCmp); + GenTreeStmt* jmpStmt = compiler->fgNewStmtFromTree(jmpTree, stmt->gtStmtILoffsx); compiler->fgInsertStmtAtEnd(checkBlock, jmpStmt); } @@ -350,8 +350,8 @@ private: // virtual void CreateThen() { - thenBlock = CreateAndInsertBasicBlock(BBJ_ALWAYS, checkBlock); - GenTree* copyOfOriginalStmt = compiler->gtCloneExpr(stmt)->AsStmt(); + thenBlock = CreateAndInsertBasicBlock(BBJ_ALWAYS, checkBlock); + GenTreeStmt* copyOfOriginalStmt = compiler->gtCloneExpr(stmt)->AsStmt(); compiler->fgInsertStmtAtEnd(thenBlock, copyOfOriginalStmt); } @@ -566,8 +566,8 @@ private: { const unsigned thisTempNum = compiler->lvaGrabTemp(true DEBUGARG("guarded devirt this temp")); // lvaSetClass(thisTempNum, ...); - GenTree* asgTree = compiler->gtNewTempAssign(thisTempNum, thisTree); - GenTree* asgStmt = compiler->fgNewStmtFromTree(asgTree, stmt->gtStmt.gtStmtILoffsx); + GenTree* asgTree = compiler->gtNewTempAssign(thisTempNum, thisTree); + GenTreeStmt* asgStmt = compiler->fgNewStmtFromTree(asgTree, stmt->gtStmtILoffsx); compiler->fgInsertStmtAtEnd(checkBlock, asgStmt); thisTree = compiler->gtNewLclvNode(thisTempNum, TYP_REF); @@ -586,9 +586,9 @@ private: GenTree* targetMethodTable = compiler->gtNewIconEmbClsHndNode(clsHnd); // Compare and jump to else (which does the indirect call) if NOT equal - GenTree* methodTableCompare = compiler->gtNewOperNode(GT_NE, TYP_INT, targetMethodTable, methodTable); - GenTree* jmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, methodTableCompare); - GenTree* jmpStmt = compiler->fgNewStmtFromTree(jmpTree, stmt->gtStmt.gtStmtILoffsx); + GenTree* methodTableCompare = compiler->gtNewOperNode(GT_NE, TYP_INT, targetMethodTable, methodTable); + GenTree* jmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, methodTableCompare); + GenTreeStmt* jmpStmt = compiler->fgNewStmtFromTree(jmpTree, stmt->gtStmtILoffsx); compiler->fgInsertStmtAtEnd(checkBlock, jmpStmt); } diff --git a/src/jit/liveness.cpp b/src/jit/liveness.cpp index 99f4db7da5..e06df340a3 100644 --- a/src/jit/liveness.cpp +++ b/src/jit/liveness.cpp @@ -487,7 +487,7 @@ void Compiler::fgPerBlockLocalVarLiveness() } else { - for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt) + for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt()) { compCurStmt = stmt; for (GenTree* node = stmt->gtStmtList; node != nullptr; node = node->gtNext) @@ -985,7 +985,7 @@ void Compiler::fgExtendDbgLifetimes() GenTree* initNode = gtNewAssignNode(varNode, zero); // Create a statement for the initializer, sequence it, and append it to the current BB. - GenTree* initStmt = gtNewStmt(initNode); + GenTreeStmt* initStmt = gtNewStmt(initNode); gtSetStmtInfo(initStmt); fgSetStmtSeq(initStmt); fgInsertStmtNearEnd(block, initStmt); @@ -1792,8 +1792,7 @@ void Compiler::fgComputeLife(VARSET_TP& life, VARSET_TP keepAliveVars(VarSetOps::Union(this, volatileVars, compCurBB->bbScope)); noway_assert(VarSetOps::IsSubset(this, keepAliveVars, life)); - noway_assert(compCurStmt->gtOper == GT_STMT); - noway_assert(endNode || (startNode == compCurStmt->gtStmt.gtStmtExpr)); + noway_assert(endNode || (startNode == compCurStmt->gtStmtExpr)); // NOTE: Live variable analysis will not work if you try // to use the result of an assignment node directly! @@ -2243,7 +2242,7 @@ bool Compiler::fgRemoveDeadStore(GenTree** pTree, /* This is a "NORMAL" statement with the * assignment node hanging from the GT_STMT node */ - noway_assert(compCurStmt->gtStmt.gtStmtExpr == asgNode); + noway_assert(compCurStmt->gtStmtExpr == asgNode); JITDUMP("top level assign\n"); /* Check for side effects */ @@ -2290,7 +2289,7 @@ bool Compiler::fgRemoveDeadStore(GenTree** pTree, /* Replace the assignment statement with the list of side effects */ noway_assert(sideEffList->gtOper != GT_STMT); - *pTree = compCurStmt->gtStmt.gtStmtExpr = sideEffList; + *pTree = compCurStmt->gtStmtExpr = sideEffList; #ifdef DEBUG *treeModf = true; #endif // DEBUG @@ -2635,7 +2634,7 @@ void Compiler::fgInterBlockLocalVarLiveness() { /* Get the first statement in the block */ - GenTree* firstStmt = block->FirstNonPhiDef(); + GenTreeStmt* firstStmt = block->FirstNonPhiDef(); if (firstStmt == nullptr) { @@ -2644,24 +2643,22 @@ void Compiler::fgInterBlockLocalVarLiveness() /* Walk all the statements of the block backwards - Get the LAST stmt */ - GenTree* nextStmt = block->bbTreeList->gtPrev; + GenTreeStmt* nextStmt = block->lastStmt(); do { #ifdef DEBUG bool treeModf = false; #endif // DEBUG - noway_assert(nextStmt); - noway_assert(nextStmt->gtOper == GT_STMT); + noway_assert(nextStmt != nullptr); compCurStmt = nextStmt; - nextStmt = nextStmt->gtPrev; + nextStmt = nextStmt->getPrevStmt(); /* Compute the liveness for each tree node in the statement */ bool stmtInfoDirty = false; - fgComputeLife(life, compCurStmt->gtStmt.gtStmtExpr, nullptr, volatileVars, - &stmtInfoDirty DEBUGARG(&treeModf)); + fgComputeLife(life, compCurStmt->gtStmtExpr, nullptr, volatileVars, &stmtInfoDirty DEBUGARG(&treeModf)); if (stmtInfoDirty) { @@ -2674,7 +2671,7 @@ void Compiler::fgInterBlockLocalVarLiveness() if (verbose && treeModf) { printf("\nfgComputeLife modified tree:\n"); - gtDispTree(compCurStmt->gtStmt.gtStmtExpr); + gtDispTree(compCurStmt->gtStmtExpr); printf("\n"); } #endif // DEBUG diff --git a/src/jit/loopcloning.cpp b/src/jit/loopcloning.cpp index f741ff81b7..14ee2d993d 100644 --- a/src/jit/loopcloning.cpp +++ b/src/jit/loopcloning.cpp @@ -687,13 +687,13 @@ void LoopCloneContext::CondToStmtInBlock(Compiler* comp cond = comp->gtNewOperNode(reverse ? GT_NE : GT_EQ, TYP_INT, cond, comp->gtNewIconNode(0)); // Add jmpTrue "cond == 0" to slow path. - GenTree* stmt = comp->fgNewStmtFromTree(comp->gtNewOperNode(GT_JTRUE, TYP_VOID, cond)); + GenTreeStmt* stmt = comp->fgNewStmtFromTree(comp->gtNewOperNode(GT_JTRUE, TYP_VOID, cond)); // Add stmt to the block. comp->fgInsertStmtAtEnd(block, stmt); // Remorph. - comp->fgMorphBlockStmt(block, stmt->AsStmt() DEBUGARG("Loop cloning condition")); + comp->fgMorphBlockStmt(block, stmt DEBUGARG("Loop cloning condition")); } //-------------------------------------------------------------------------------------------------- diff --git a/src/jit/loopcloning.h b/src/jit/loopcloning.h index d0ec6b6b98..a455377aeb 100644 --- a/src/jit/loopcloning.h +++ b/src/jit/loopcloning.h @@ -208,13 +208,13 @@ struct LcMdArrayOptInfo : public LcOptInfo */ struct LcJaggedArrayOptInfo : public LcOptInfo { - unsigned dim; // "dim" represents upto what level of the rank this optimization applies to. - // For example, a[i][j][k] could be the jagged array but if "dim" is 2, - // then this node is treated as though it were a[i][j] - ArrIndex arrIndex; // ArrIndex representation of the array. - GenTree* stmt; // "stmt" where the optimization opportunity occurs. + unsigned dim; // "dim" represents upto what level of the rank this optimization applies to. + // For example, a[i][j][k] could be the jagged array but if "dim" is 2, + // then this node is treated as though it were a[i][j] + ArrIndex arrIndex; // ArrIndex representation of the array. + GenTreeStmt* stmt; // "stmt" where the optimization opportunity occurs. - LcJaggedArrayOptInfo(ArrIndex& arrIndex, unsigned dim, GenTree* stmt) + LcJaggedArrayOptInfo(ArrIndex& arrIndex, unsigned dim, GenTreeStmt* stmt) : LcOptInfo(this, LcJaggedArray), dim(dim), arrIndex(arrIndex), stmt(stmt) { } diff --git a/src/jit/lsra.h b/src/jit/lsra.h index 8494699a0d..d1c8697fc9 100644 --- a/src/jit/lsra.h +++ b/src/jit/lsra.h @@ -1526,7 +1526,7 @@ private: #endif // !_TARGET_XARCH_ // This is the main entry point for building the RefPositions for a node. // These methods return the number of sources. - int BuildNode(GenTree* stmt); + int BuildNode(GenTree* tree); void getTgtPrefOperands(GenTreeOp* tree, bool& prefOp1, bool& prefOp2); bool supportsSpecialPutArg(); diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 78f43eb101..2369d1eda5 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -7715,19 +7715,19 @@ GenTree* Compiler::fgGetStubAddrArg(GenTreeCall* call) void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCall* recursiveTailCall) { assert(recursiveTailCall->IsTailCallConvertibleToLoop()); - GenTree* last = block->lastStmt(); - assert(recursiveTailCall == last->gtStmt.gtStmtExpr); + GenTreeStmt* lastStmt = block->lastStmt(); + assert(recursiveTailCall == lastStmt->gtStmtExpr); // Transform recursive tail call into a loop. - GenTree* earlyArgInsertionPoint = last; - IL_OFFSETX callILOffset = last->gtStmt.gtStmtILoffsx; + GenTreeStmt* earlyArgInsertionPoint = lastStmt; + IL_OFFSETX callILOffset = lastStmt->gtStmtILoffsx; // Hoist arg setup statement for the 'this' argument. GenTree* thisArg = recursiveTailCall->gtCallObjp; if (thisArg && !thisArg->IsNothingNode() && !thisArg->IsArgPlaceHolderNode()) { - GenTree* thisArgStmt = gtNewStmt(thisArg, callILOffset); + GenTreeStmt* thisArgStmt = gtNewStmt(thisArg, callILOffset); fgInsertStmtBefore(block, earlyArgInsertionPoint, thisArgStmt); } @@ -7770,8 +7770,8 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa // [000057] - A---------- \--* = int // [000056] D------N---- \--* lclVar int V01 arg1 - GenTree* tmpAssignmentInsertionPoint = last; - GenTree* paramAssignmentInsertionPoint = last; + GenTreeStmt* tmpAssignmentInsertionPoint = lastStmt; + GenTreeStmt* paramAssignmentInsertionPoint = lastStmt; // Process early args. They may contain both setup statements for late args and actual args. // Early args don't include 'this' arg. We need to account for that so that the call to gtArgEntryByArgNum @@ -7786,17 +7786,17 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa if ((earlyArg->gtFlags & GTF_LATE_ARG) != 0) { // This is a setup node so we need to hoist it. - GenTree* earlyArgStmt = gtNewStmt(earlyArg, callILOffset); + GenTreeStmt* earlyArgStmt = gtNewStmt(earlyArg, callILOffset); fgInsertStmtBefore(block, earlyArgInsertionPoint, earlyArgStmt); } else { // This is an actual argument that needs to be assigned to the corresponding caller parameter. fgArgTabEntry* curArgTabEntry = gtArgEntryByArgNum(recursiveTailCall, earlyArgIndex); - GenTree* paramAssignStmt = + GenTreeStmt* paramAssignStmt = fgAssignRecursiveCallArgToCallerParam(earlyArg, curArgTabEntry, block, callILOffset, tmpAssignmentInsertionPoint, paramAssignmentInsertionPoint); - if ((tmpAssignmentInsertionPoint == last) && (paramAssignStmt != nullptr)) + if ((tmpAssignmentInsertionPoint == lastStmt) && (paramAssignStmt != nullptr)) { // All temp assignments will happen before the first param assignment. tmpAssignmentInsertionPoint = paramAssignStmt; @@ -7813,11 +7813,11 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa // A late argument is an actual argument that needs to be assigned to the corresponding caller's parameter. GenTree* lateArg = lateArgs->Current(); fgArgTabEntry* curArgTabEntry = gtArgEntryByLateArgIndex(recursiveTailCall, lateArgIndex); - GenTree* paramAssignStmt = + GenTreeStmt* paramAssignStmt = fgAssignRecursiveCallArgToCallerParam(lateArg, curArgTabEntry, block, callILOffset, tmpAssignmentInsertionPoint, paramAssignmentInsertionPoint); - if ((tmpAssignmentInsertionPoint == last) && (paramAssignStmt != nullptr)) + if ((tmpAssignmentInsertionPoint == lastStmt) && (paramAssignStmt != nullptr)) { // All temp assignments will happen before the first param assignment. tmpAssignmentInsertionPoint = paramAssignStmt; @@ -7829,10 +7829,10 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa // block won't be in the loop (it's assumed to have no predecessors), we need to update the special local here. if (!info.compIsStatic && (lvaArg0Var != info.compThisArg)) { - var_types thisType = lvaTable[info.compThisArg].TypeGet(); - GenTree* arg0 = gtNewLclvNode(lvaArg0Var, thisType); - GenTree* arg0Assignment = gtNewAssignNode(arg0, gtNewLclvNode(info.compThisArg, thisType)); - GenTree* arg0AssignmentStmt = gtNewStmt(arg0Assignment, callILOffset); + var_types thisType = lvaTable[info.compThisArg].TypeGet(); + GenTree* arg0 = gtNewLclvNode(lvaArg0Var, thisType); + GenTree* arg0Assignment = gtNewAssignNode(arg0, gtNewLclvNode(info.compThisArg, thisType)); + GenTreeStmt* arg0AssignmentStmt = gtNewStmt(arg0Assignment, callILOffset); fgInsertStmtBefore(block, paramAssignmentInsertionPoint, arg0AssignmentStmt); } @@ -7873,15 +7873,15 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa GenTree* zero = gtNewZeroConNode(genActualType(lclType)); init = gtNewAssignNode(lcl, zero); } - GenTree* initStmt = gtNewStmt(init, callILOffset); - fgInsertStmtBefore(block, last, initStmt); + GenTreeStmt* initStmt = gtNewStmt(init, callILOffset); + fgInsertStmtBefore(block, lastStmt, initStmt); } } } } // Remove the call - fgRemoveStmt(block, last); + fgRemoveStmt(block, lastStmt); // Set the loop edge. Ensure we have a scratch block and then target the // next block. Loop detection needs to see a pred out of the loop, so @@ -7910,12 +7910,12 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa // Return Value: // parameter assignment statement if one was inserted; nullptr otherwise. -GenTree* Compiler::fgAssignRecursiveCallArgToCallerParam(GenTree* arg, - fgArgTabEntry* argTabEntry, - BasicBlock* block, - IL_OFFSETX callILOffset, - GenTree* tmpAssignmentInsertionPoint, - GenTree* paramAssignmentInsertionPoint) +GenTreeStmt* Compiler::fgAssignRecursiveCallArgToCallerParam(GenTree* arg, + fgArgTabEntry* argTabEntry, + BasicBlock* block, + IL_OFFSETX callILOffset, + GenTreeStmt* tmpAssignmentInsertionPoint, + GenTreeStmt* paramAssignmentInsertionPoint) { // Call arguments should be assigned to temps first and then the temps should be assigned to parameters because // some argument trees may reference parameters directly. @@ -7953,7 +7953,7 @@ GenTree* Compiler::fgAssignRecursiveCallArgToCallerParam(GenTree* arg, // any caller parameters. Some common cases are handled above but we may be able to eliminate // more temp assignments. - GenTree* paramAssignStmt = nullptr; + GenTreeStmt* paramAssignStmt = nullptr; if (needToAssignParameter) { if (argInTemp == nullptr) @@ -7961,12 +7961,12 @@ GenTree* Compiler::fgAssignRecursiveCallArgToCallerParam(GenTree* arg, // The argument is not assigned to a temp. We need to create a new temp and insert an assignment. // TODO: we can avoid a temp assignment if we can prove that the argument tree // doesn't involve any caller parameters. - unsigned tmpNum = lvaGrabTemp(true DEBUGARG("arg temp")); - lvaTable[tmpNum].lvType = arg->gtType; - GenTree* tempSrc = arg; - GenTree* tempDest = gtNewLclvNode(tmpNum, tempSrc->gtType); - GenTree* tmpAssignNode = gtNewAssignNode(tempDest, tempSrc); - GenTree* tmpAssignStmt = gtNewStmt(tmpAssignNode, callILOffset); + unsigned tmpNum = lvaGrabTemp(true DEBUGARG("arg temp")); + lvaTable[tmpNum].lvType = arg->gtType; + GenTree* tempSrc = arg; + GenTree* tempDest = gtNewLclvNode(tmpNum, tempSrc->gtType); + GenTree* tmpAssignNode = gtNewAssignNode(tempDest, tempSrc); + GenTreeStmt* tmpAssignStmt = gtNewStmt(tmpAssignNode, callILOffset); fgInsertStmtBefore(block, tmpAssignmentInsertionPoint, tmpAssignStmt); argInTemp = gtNewLclvNode(tmpNum, tempSrc->gtType); } @@ -8291,7 +8291,7 @@ GenTree* Compiler::fgMorphCall(GenTreeCall* call) assg = fgMorphTree(assg); // Create the assignment statement and insert it before the current statement. - GenTree* assgStmt = gtNewStmt(assg, compCurStmt->AsStmt()->gtStmtILoffsx); + GenTreeStmt* assgStmt = gtNewStmt(assg, compCurStmt->gtStmtILoffsx); fgInsertStmtBefore(compCurBB, compCurStmt, assgStmt); // Return the temp. @@ -15233,11 +15233,11 @@ bool Compiler::fgFoldConditional(BasicBlock* block) { noway_assert(block->bbTreeList && block->bbTreeList->gtPrev); - GenTree* stmt = block->bbTreeList->gtPrev; + GenTreeStmt* lastStmt = block->lastStmt(); - noway_assert(stmt->gtNext == nullptr); + noway_assert(lastStmt->gtNext == nullptr); - if (stmt->gtStmt.gtStmtExpr->gtOper == GT_CALL) + if (lastStmt->gtStmtExpr->gtOper == GT_CALL) { noway_assert(fgRemoveRestOfBlock); @@ -15260,13 +15260,13 @@ bool Compiler::fgFoldConditional(BasicBlock* block) goto DONE_COND; } - noway_assert(stmt->gtStmt.gtStmtExpr->gtOper == GT_JTRUE); + noway_assert(lastStmt->gtStmtExpr->gtOper == GT_JTRUE); /* Did we fold the conditional */ - noway_assert(stmt->gtStmt.gtStmtExpr->gtOp.gtOp1); + noway_assert(lastStmt->gtStmtExpr->gtOp.gtOp1); GenTree* cond; - cond = stmt->gtStmt.gtStmtExpr->gtOp.gtOp1; + cond = lastStmt->gtStmtExpr->gtOp.gtOp1; if (cond->OperKind() & GTK_CONST) { @@ -15278,7 +15278,7 @@ bool Compiler::fgFoldConditional(BasicBlock* block) /* remove the statement from bbTreelist - No need to update * the reference counts since there are no lcl vars */ - fgRemoveStmt(block, stmt); + fgRemoveStmt(block, lastStmt); // block is a BBJ_COND that we are folding the conditional for // bTaken is the path that will always be taken from block @@ -15441,11 +15441,11 @@ bool Compiler::fgFoldConditional(BasicBlock* block) { noway_assert(block->bbTreeList && block->bbTreeList->gtPrev); - GenTree* stmt = block->bbTreeList->gtPrev; + GenTreeStmt* lastStmt = block->lastStmt(); - noway_assert(stmt->gtNext == nullptr); + noway_assert(lastStmt->gtNext == nullptr); - if (stmt->gtStmt.gtStmtExpr->gtOper == GT_CALL) + if (lastStmt->gtStmtExpr->gtOper == GT_CALL) { noway_assert(fgRemoveRestOfBlock); @@ -15475,13 +15475,13 @@ bool Compiler::fgFoldConditional(BasicBlock* block) goto DONE_SWITCH; } - noway_assert(stmt->gtStmt.gtStmtExpr->gtOper == GT_SWITCH); + noway_assert(lastStmt->gtStmtExpr->gtOper == GT_SWITCH); /* Did we fold the conditional */ - noway_assert(stmt->gtStmt.gtStmtExpr->gtOp.gtOp1); + noway_assert(lastStmt->gtStmtExpr->gtOp.gtOp1); GenTree* cond; - cond = stmt->gtStmt.gtStmtExpr->gtOp.gtOp1; + cond = lastStmt->gtStmtExpr->gtOp.gtOp1; if (cond->OperKind() & GTK_CONST) { @@ -15492,7 +15492,7 @@ bool Compiler::fgFoldConditional(BasicBlock* block) /* remove the statement from bbTreelist - No need to update * the reference counts since there are no lcl vars */ - fgRemoveStmt(block, stmt); + fgRemoveStmt(block, lastStmt); /* modify the flow graph */ @@ -15718,8 +15718,6 @@ void Compiler::fgMorphStmts(BasicBlock* block, bool* lnot, bool* loadw) GenTree* prev = nullptr; for (; stmt != nullptr; prev = stmt->gtStmtExpr, stmt = stmt->gtNextStmt) { - assert(stmt->gtOper == GT_STMT); - if (fgRemoveRestOfBlock) { fgRemoveStmt(block, stmt); @@ -15883,16 +15881,16 @@ void Compiler::fgMorphStmts(BasicBlock* block, bool* lnot, bool* loadw) { if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH)) { - GenTree* first = block->bbTreeList; + GenTreeStmt* first = block->firstStmt(); noway_assert(first); - GenTree* last = first->gtPrev; - noway_assert(last && last->gtNext == nullptr); - GenTree* lastStmt = last->gtStmt.gtStmtExpr; + GenTreeStmt* lastStmt = block->lastStmt(); + noway_assert(lastStmt && lastStmt->gtNext == nullptr); + GenTree* last = lastStmt->gtStmtExpr; - if (((block->bbJumpKind == BBJ_COND) && (lastStmt->gtOper == GT_JTRUE)) || - ((block->bbJumpKind == BBJ_SWITCH) && (lastStmt->gtOper == GT_SWITCH))) + if (((block->bbJumpKind == BBJ_COND) && (last->gtOper == GT_JTRUE)) || + ((block->bbJumpKind == BBJ_SWITCH) && (last->gtOper == GT_SWITCH))) { - GenTree* op1 = lastStmt->gtOp.gtOp1; + GenTree* op1 = last->gtOp.gtOp1; if (op1->OperKind() & GTK_RELOP) { @@ -15900,7 +15898,7 @@ void Compiler::fgMorphStmts(BasicBlock* block, bool* lnot, bool* loadw) op1->gtFlags &= ~GTF_RELOP_JMP_USED; } - last->gtStmt.gtStmtExpr = fgMorphTree(op1); + lastStmt->gtStmtExpr = fgMorphTree(op1); } } @@ -16029,8 +16027,8 @@ void Compiler::fgMorphBlocks() // // TODO: Need to characterize the last top level stmt of a block ending with BBJ_RETURN. - GenTree* last = (block->bbTreeList != nullptr) ? block->bbTreeList->gtPrev : nullptr; - GenTree* ret = (last != nullptr) ? last->gtStmt.gtStmtExpr : nullptr; + GenTreeStmt* lastStmt = block->lastStmt(); + GenTree* ret = (lastStmt != nullptr) ? lastStmt->gtStmtExpr : nullptr; if ((ret != nullptr) && (ret->OperGet() == GT_RETURN) && ((ret->gtFlags & GTF_RET_MERGED) != 0)) { @@ -16061,9 +16059,8 @@ void Compiler::fgMorphBlocks() noway_assert(compMethodHasRetVal()); // This block must be ending with a GT_RETURN - noway_assert(last != nullptr); - noway_assert(last->gtOper == GT_STMT); - noway_assert(last->gtNext == nullptr); + noway_assert(lastStmt != nullptr); + noway_assert(lastStmt->getNextStmt() == nullptr); noway_assert(ret != nullptr); // GT_RETURN must have non-null operand as the method is returning the value assigned to @@ -16071,42 +16068,41 @@ void Compiler::fgMorphBlocks() noway_assert(ret->OperGet() == GT_RETURN); noway_assert(ret->gtGetOp1() != nullptr); - GenTree* pAfterStatement = last; - IL_OFFSETX offset = last->AsStmt()->gtStmtILoffsx; - GenTree* tree = + GenTreeStmt* pAfterStatement = lastStmt; + IL_OFFSETX offset = lastStmt->gtStmtILoffsx; + GenTree* tree = gtNewTempAssign(genReturnLocal, ret->gtGetOp1(), &pAfterStatement, offset, block); if (tree->OperIsCopyBlkOp()) { tree = fgMorphCopyBlock(tree); } - if (pAfterStatement == last) + if (pAfterStatement == lastStmt) { - last->gtStmt.gtStmtExpr = tree; + lastStmt->gtStmtExpr = tree; } else { // gtNewTempAssign inserted additional statements after last - fgRemoveStmt(block, last); - last = fgInsertStmtAfter(block, pAfterStatement, gtNewStmt(tree, offset)); + fgRemoveStmt(block, lastStmt); + lastStmt = fgInsertStmtAfter(block, pAfterStatement, gtNewStmt(tree, offset)); } // make sure that copy-prop ignores this assignment. - last->gtStmt.gtStmtExpr->gtFlags |= GTF_DONT_CSE; + lastStmt->gtStmtExpr->gtFlags |= GTF_DONT_CSE; } else if (ret != nullptr && ret->OperGet() == GT_RETURN) { // This block ends with a GT_RETURN - noway_assert(last != nullptr); - noway_assert(last->gtOper == GT_STMT); - noway_assert(last->gtNext == nullptr); + noway_assert(lastStmt != nullptr); + noway_assert(lastStmt->getNextStmt() == nullptr); // Must be a void GT_RETURN with null operand; delete it as this block branches to oneReturn // block noway_assert(ret->TypeGet() == TYP_VOID); noway_assert(ret->gtGetOp1() == nullptr); - fgRemoveStmt(block, last); + fgRemoveStmt(block, lastStmt); } #ifdef DEBUG if (verbose) @@ -16459,7 +16455,7 @@ GenTree* Compiler::fgGetTopLevelQmark(GenTree* expr, GenTree** ppDst /* = NULL * * tmp has the result. * */ -void Compiler::fgExpandQmarkForCastInstOf(BasicBlock* block, GenTree* stmt) +void Compiler::fgExpandQmarkForCastInstOf(BasicBlock* block, GenTreeStmt* stmt) { #ifdef DEBUG if (verbose) @@ -16469,7 +16465,7 @@ void Compiler::fgExpandQmarkForCastInstOf(BasicBlock* block, GenTree* stmt) } #endif // DEBUG - GenTree* expr = stmt->gtStmt.gtStmtExpr; + GenTree* expr = stmt->gtStmtExpr; GenTree* dst = nullptr; GenTree* qmark = fgGetTopLevelQmark(expr, &dst); @@ -16570,23 +16566,23 @@ void Compiler::fgExpandQmarkForCastInstOf(BasicBlock* block, GenTree* stmt) // Append cond1 as JTRUE to cond1Block GenTree* jmpTree = gtNewOperNode(GT_JTRUE, TYP_VOID, condExpr); - GenTree* jmpStmt = fgNewStmtFromTree(jmpTree, stmt->gtStmt.gtStmtILoffsx); + GenTree* jmpStmt = fgNewStmtFromTree(jmpTree, stmt->gtStmtILoffsx); fgInsertStmtAtEnd(cond1Block, jmpStmt); // Append cond2 as JTRUE to cond2Block jmpTree = gtNewOperNode(GT_JTRUE, TYP_VOID, cond2Expr); - jmpStmt = fgNewStmtFromTree(jmpTree, stmt->gtStmt.gtStmtILoffsx); + jmpStmt = fgNewStmtFromTree(jmpTree, stmt->gtStmtILoffsx); fgInsertStmtAtEnd(cond2Block, jmpStmt); // AsgBlock should get tmp = op1 assignment. trueExpr = gtNewTempAssign(dst->AsLclVarCommon()->GetLclNum(), trueExpr); - GenTree* trueStmt = fgNewStmtFromTree(trueExpr, stmt->gtStmt.gtStmtILoffsx); + GenTree* trueStmt = fgNewStmtFromTree(trueExpr, stmt->gtStmtILoffsx); fgInsertStmtAtEnd(asgBlock, trueStmt); // Since we are adding helper in the JTRUE false path, reverse the cond2 and add the helper. gtReverseCond(cond2Expr); GenTree* helperExpr = gtNewTempAssign(dst->AsLclVarCommon()->GetLclNum(), true2Expr); - GenTree* helperStmt = fgNewStmtFromTree(helperExpr, stmt->gtStmt.gtStmtILoffsx); + GenTree* helperStmt = fgNewStmtFromTree(helperExpr, stmt->gtStmtILoffsx); fgInsertStmtAtEnd(helperBlock, helperStmt); // Finally remove the nested qmark stmt. @@ -16651,9 +16647,9 @@ void Compiler::fgExpandQmarkForCastInstOf(BasicBlock* block, GenTree* stmt) * If the qmark assigns to a variable, then create tmps for "then" * and "else" results and assign the temp to the variable as a writeback step. */ -void Compiler::fgExpandQmarkStmt(BasicBlock* block, GenTree* stmt) +void Compiler::fgExpandQmarkStmt(BasicBlock* block, GenTreeStmt* stmt) { - GenTree* expr = stmt->gtStmt.gtStmtExpr; + GenTree* expr = stmt->gtStmtExpr; // Retrieve the Qmark node to be expanded. GenTree* dst = nullptr; @@ -16785,7 +16781,7 @@ void Compiler::fgExpandQmarkStmt(BasicBlock* block, GenTree* stmt) } GenTree* jmpTree = gtNewOperNode(GT_JTRUE, TYP_VOID, qmark->gtGetOp1()); - GenTree* jmpStmt = fgNewStmtFromTree(jmpTree, stmt->gtStmt.gtStmtILoffsx); + GenTree* jmpStmt = fgNewStmtFromTree(jmpTree, stmt->gtStmtILoffsx); fgInsertStmtAtEnd(condBlock, jmpStmt); // Remove the original qmark statement. @@ -16811,7 +16807,7 @@ void Compiler::fgExpandQmarkStmt(BasicBlock* block, GenTree* stmt) { trueExpr = gtNewTempAssign(lclNum, trueExpr); } - GenTree* trueStmt = fgNewStmtFromTree(trueExpr, stmt->gtStmt.gtStmtILoffsx); + GenTreeStmt* trueStmt = fgNewStmtFromTree(trueExpr, stmt->gtStmtILoffsx); fgInsertStmtAtEnd(thenBlock, trueStmt); } @@ -16822,7 +16818,7 @@ void Compiler::fgExpandQmarkStmt(BasicBlock* block, GenTree* stmt) { falseExpr = gtNewTempAssign(lclNum, falseExpr); } - GenTree* falseStmt = fgNewStmtFromTree(falseExpr, stmt->gtStmt.gtStmtILoffsx); + GenTreeStmt* falseStmt = fgNewStmtFromTree(falseExpr, stmt->gtStmtILoffsx); fgInsertStmtAtEnd(elseBlock, falseStmt); } @@ -16845,11 +16841,11 @@ void Compiler::fgExpandQmarkNodes() { if (compQmarkUsed) { - for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - GenTree* expr = stmt->gtStmt.gtStmtExpr; + GenTree* expr = stmt->gtStmtExpr; #ifdef DEBUG fgPreExpandQmarkChecks(expr); #endif @@ -16871,11 +16867,11 @@ void Compiler::fgExpandQmarkNodes() */ void Compiler::fgPostExpandQmarkChecks() { - for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - GenTree* expr = stmt->gtStmt.gtStmtExpr; + GenTree* expr = stmt->gtStmtExpr; fgWalkTreePre(&expr, Compiler::fgAssertNoQmark, nullptr); } } @@ -18770,9 +18766,9 @@ void Compiler::fgMarkAddressExposedLocals() // Make the current basic block address available globally compCurBB = block; - for (GenTree* stmt = block->bbTreeList; stmt != nullptr; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - visitor.VisitStmt(stmt->AsStmt()); + visitor.VisitStmt(stmt); } } } @@ -18794,11 +18790,10 @@ void Compiler::fgMarkAddressExposedLocals() // if this funciton successfully optimized the stmts, then return true. Otherwise // return false; -bool Compiler::fgMorphCombineSIMDFieldAssignments(BasicBlock* block, GenTree* stmt) +bool Compiler::fgMorphCombineSIMDFieldAssignments(BasicBlock* block, GenTreeStmt* stmt) { - noway_assert(stmt->gtOper == GT_STMT); - GenTree* tree = stmt->gtStmt.gtStmtExpr; + GenTree* tree = stmt->gtStmtExpr; assert(tree->OperGet() == GT_ASG); GenTree* originalLHS = tree->gtOp.gtOp1; @@ -18815,15 +18810,15 @@ bool Compiler::fgMorphCombineSIMDFieldAssignments(BasicBlock* block, GenTree* st return false; } - var_types simdType = getSIMDTypeForSize(simdSize); - int assignmentsCount = simdSize / genTypeSize(baseType) - 1; - int remainingAssignments = assignmentsCount; - GenTree* curStmt = stmt->gtNext; - GenTree* lastStmt = stmt; + var_types simdType = getSIMDTypeForSize(simdSize); + int assignmentsCount = simdSize / genTypeSize(baseType) - 1; + int remainingAssignments = assignmentsCount; + GenTreeStmt* curStmt = stmt->getNextStmt(); + GenTreeStmt* lastStmt = stmt; while (curStmt != nullptr && remainingAssignments > 0) { - GenTree* exp = curStmt->gtStmt.gtStmtExpr; + GenTree* exp = curStmt->gtStmtExpr; if (exp->OperGet() != GT_ASG) { break; @@ -18841,7 +18836,7 @@ bool Compiler::fgMorphCombineSIMDFieldAssignments(BasicBlock* block, GenTree* st prevRHS = curRHS; lastStmt = curStmt; - curStmt = curStmt->gtNext; + curStmt = curStmt->getNextStmt(); } if (remainingAssignments > 0) @@ -18865,7 +18860,7 @@ bool Compiler::fgMorphCombineSIMDFieldAssignments(BasicBlock* block, GenTree* st for (int i = 0; i < assignmentsCount; i++) { - fgRemoveStmt(block, stmt->gtNext); + fgRemoveStmt(block, stmt->getNextStmt()); } GenTree* copyBlkDst = createAddressNodeForSIMDInit(originalLHS, simdSize); @@ -18908,12 +18903,12 @@ bool Compiler::fgMorphCombineSIMDFieldAssignments(BasicBlock* block, GenTree* st GenTree* dstNode = gtNewOperNode(GT_IND, simdType, copyBlkDst); tree = gtNewAssignNode(dstNode, simdStructNode); - stmt->gtStmt.gtStmtExpr = tree; + stmt->gtStmtExpr = tree; // Since we generated a new address node which didn't exist before, // we should expose this address manually here. LocalAddressVisitor visitor(this); - visitor.VisitStmt(stmt->AsStmt()); + visitor.VisitStmt(stmt); #ifdef DEBUG if (verbose) diff --git a/src/jit/optcse.cpp b/src/jit/optcse.cpp index fd20c77058..31789328c3 100644 --- a/src/jit/optcse.cpp +++ b/src/jit/optcse.cpp @@ -394,7 +394,7 @@ void Compiler::optValnumCSE_Init() // we return that index. There currently is a limit on the number of CSEs // that we can have of MAX_CSE_CNT (64) // -unsigned Compiler::optValnumCSE_Index(GenTree* tree, GenTree* stmt) +unsigned Compiler::optValnumCSE_Index(GenTree* tree, GenTreeStmt* stmt) { unsigned key; unsigned hash; @@ -611,11 +611,8 @@ unsigned Compiler::optValnumCSE_Locate() { // Locate CSE candidates and assign them indices - for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { - GenTree* stmt; - GenTree* tree; - /* Make the block publicly available */ compCurBB = block; @@ -625,13 +622,11 @@ unsigned Compiler::optValnumCSE_Locate() noway_assert((block->bbFlags & (BBF_VISITED | BBF_MARKED)) == 0); /* Walk the statement trees in this basic block */ - for (stmt = block->FirstNonPhiDef(); stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt()) { - noway_assert(stmt->gtOper == GT_STMT); - /* We walk the tree in the forwards direction (bottom up) */ bool stmtHasArrLenCandidate = false; - for (tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { if (tree->OperIsCompare() && stmtHasArrLenCandidate) { @@ -998,11 +993,8 @@ void Compiler::optValnumCSE_Availablity() #endif EXPSET_TP available_cses = BitVecOps::MakeEmpty(cseTraits); - for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { - GenTree* stmt; - GenTree* tree; - // Make the block publicly available compCurBB = block; @@ -1015,13 +1007,11 @@ void Compiler::optValnumCSE_Availablity() // Walk the statement trees in this basic block - for (stmt = block->FirstNonPhiDef(); stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt()) { - noway_assert(stmt->gtOper == GT_STMT); - // We walk the tree in the forwards direction (bottom up) - for (tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { if (IS_CSE_INDEX(tree->gtCSEnum)) { @@ -2135,10 +2125,9 @@ public: do { /* Process the next node in the list */ - GenTree* exp = lst->tslTree; - GenTree* stm = lst->tslStmt; - noway_assert(stm->gtOper == GT_STMT); - BasicBlock* blk = lst->tslBlock; + GenTree* exp = lst->tslTree; + GenTreeStmt* stmt = lst->tslStmt; + BasicBlock* blk = lst->tslBlock; /* Advance to the next node in the list */ lst = lst->tslNext; @@ -2372,21 +2361,21 @@ public: // cannot add any new exceptions } - // Walk the statement 'stm' and find the pointer + // Walk the statement 'stmt' and find the pointer // in the tree is pointing to 'exp' // - GenTree** link = m_pCompiler->gtFindLink(stm, exp); + GenTree** link = m_pCompiler->gtFindLink(stmt, exp); #ifdef DEBUG if (link == nullptr) { printf("\ngtFindLink failed: stm="); - Compiler::printTreeID(stm); + Compiler::printTreeID(stmt); printf(", exp="); Compiler::printTreeID(exp); printf("\n"); printf("stm ="); - m_pCompiler->gtDispTree(stm); + m_pCompiler->gtDispTree(stmt); printf("\n"); printf("exp ="); m_pCompiler->gtDispTree(exp); @@ -2409,7 +2398,7 @@ public: assert(m_pCompiler->fgRemoveRestOfBlock == false); /* re-morph the statement */ - m_pCompiler->fgMorphBlockStmt(blk, stm->AsStmt() DEBUGARG("optValnumCSE")); + m_pCompiler->fgMorphBlockStmt(blk, stmt DEBUGARG("optValnumCSE")); } while (lst != nullptr); } @@ -2887,27 +2876,17 @@ void Compiler::optOptimizeCSEs() void Compiler::optCleanupCSEs() { - // We must clear the BBF_VISITED and BBF_MARKED flags - // - for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) + // We must clear the BBF_VISITED and BBF_MARKED flags. + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { - // And clear all the "visited" bits on the block - // + // And clear all the "visited" bits on the block. block->bbFlags &= ~(BBF_VISITED | BBF_MARKED); - /* Walk the statement trees in this basic block */ - - GenTree* stmt; - - // Initialize 'stmt' to the first non-Phi statement - stmt = block->FirstNonPhiDef(); - - for (; stmt; stmt = stmt->gtNext) + // Walk the statement trees in this basic block. + for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt()) { - noway_assert(stmt->gtOper == GT_STMT); - - /* We must clear the gtCSEnum field */ - for (GenTree* tree = stmt->gtStmt.gtStmtExpr; tree; tree = tree->gtPrev) + // We must clear the gtCSEnum field. + for (GenTree* tree = stmt->gtStmtExpr; tree; tree = tree->gtPrev) { tree->gtCSEnum = NO_CSE; } @@ -2929,18 +2908,12 @@ void Compiler::optEnsureClearCSEInfo() { assert((block->bbFlags & (BBF_VISITED | BBF_MARKED)) == 0); - /* Walk the statement trees in this basic block */ - - GenTree* stmt; - // Initialize 'stmt' to the first non-Phi statement - stmt = block->FirstNonPhiDef(); - - for (; stmt; stmt = stmt->gtNext) + GenTreeStmt* stmt = block->FirstNonPhiDef(); + // Walk the statement trees in this basic block + for (; stmt != nullptr; stmt = stmt->getNextStmt()) { - assert(stmt->gtOper == GT_STMT); - - for (GenTree* tree = stmt->gtStmt.gtStmtExpr; tree; tree = tree->gtPrev) + for (GenTree* tree = stmt->gtStmtExpr; tree; tree = tree->gtPrev) { assert(tree->gtCSEnum == NO_CSE); } diff --git a/src/jit/optimizer.cpp b/src/jit/optimizer.cpp index 0be4456d8d..431f4d5ab1 100644 --- a/src/jit/optimizer.cpp +++ b/src/jit/optimizer.cpp @@ -925,7 +925,7 @@ bool Compiler::optComputeIterInfo(GenTree* incr, BasicBlock* from, BasicBlock* t // Arguments: // testStmt - is the JTRUE statement that is of the form: jmpTrue (Vtmp != 0) // where Vtmp contains the actual loop test result. -// newStmt - contains the statement that is the actual test stmt involving +// newTestStmt - contains the statement that is the actual test stmt involving // the loop iterator. // // Return Value: @@ -939,9 +939,9 @@ bool Compiler::optComputeIterInfo(GenTree* incr, BasicBlock* from, BasicBlock* t // This method just retrieves what it thinks is the "test" node, // the callers are expected to verify that "iterVar" is used in the test. // -bool Compiler::optIsLoopTestEvalIntoTemp(GenTree* testStmt, GenTree** newTest) +bool Compiler::optIsLoopTestEvalIntoTemp(GenTreeStmt* testStmt, GenTreeStmt** newTestStmt) { - GenTree* test = testStmt->gtStmt.gtStmtExpr; + GenTree* test = testStmt->gtStmtExpr; if (test->gtOper != GT_JTRUE) { @@ -960,13 +960,13 @@ bool Compiler::optIsLoopTestEvalIntoTemp(GenTree* testStmt, GenTree** newTest) { // Get the previous statement to get the def (rhs) of Vtmp to see // if the "test" is evaluated into Vtmp. - GenTree* prevStmt = testStmt->gtPrev; + GenTreeStmt* prevStmt = testStmt->getPrevStmt(); if (prevStmt == nullptr) { return false; } - GenTree* tree = prevStmt->gtStmt.gtStmtExpr; + GenTree* tree = prevStmt->gtStmtExpr; if (tree->OperGet() == GT_ASG) { GenTree* lhs = tree->gtOp.gtOp1; @@ -977,7 +977,7 @@ bool Compiler::optIsLoopTestEvalIntoTemp(GenTree* testStmt, GenTree** newTest) { if (rhs->OperIsCompare()) { - *newTest = prevStmt; + *newTestStmt = prevStmt; return true; } } @@ -1031,19 +1031,19 @@ bool Compiler::optExtractInitTestIncr( // Check if last two statements in the loop body are the increment of the iterator // and the loop termination test. noway_assert(bottom->bbTreeList != nullptr); - GenTree* test = bottom->bbTreeList->gtPrev; - noway_assert(test != nullptr && test->gtNext == nullptr); + GenTreeStmt* testStmt = bottom->lastStmt(); + noway_assert(testStmt != nullptr && testStmt->gtNext == nullptr); - GenTree* newTest; - if (optIsLoopTestEvalIntoTemp(test, &newTest)) + GenTreeStmt* newTestStmt; + if (optIsLoopTestEvalIntoTemp(testStmt, &newTestStmt)) { - test = newTest; + testStmt = newTestStmt; } - // Check if we have the incr tree before the test tree, if we don't, + // Check if we have the incr stmt before the test stmt, if we don't, // check if incr is part of the loop "top". - GenTree* incr = test->gtPrev; - if (incr == nullptr || optIsLoopIncrTree(incr->gtStmt.gtStmtExpr) == BAD_VAR_NUM) + GenTreeStmt* incrStmt = testStmt->getPrevStmt(); + if (incrStmt == nullptr || optIsLoopIncrTree(incrStmt->gtStmtExpr) == BAD_VAR_NUM) { if (top == nullptr || top->bbTreeList == nullptr || top->bbTreeList->gtPrev == nullptr) { @@ -1051,10 +1051,10 @@ bool Compiler::optExtractInitTestIncr( } // If the prev stmt to loop test is not incr, then check if we have loop test evaluated into a tmp. - GenTree* topLast = top->bbTreeList->gtPrev; - if (optIsLoopIncrTree(topLast->gtStmt.gtStmtExpr) != BAD_VAR_NUM) + GenTreeStmt* toplastStmt = top->lastStmt(); + if (optIsLoopIncrTree(toplastStmt->gtStmtExpr) != BAD_VAR_NUM) { - incr = topLast; + incrStmt = toplastStmt; } else { @@ -1062,21 +1062,21 @@ bool Compiler::optExtractInitTestIncr( } } - assert(test != incr); + assert(testStmt != incrStmt); // Find the last statement in the loop pre-header which we expect to be the initialization of // the loop iterator. - GenTree* phdr = head->bbTreeList; - if (phdr == nullptr) + GenTreeStmt* phdrStmt = head->firstStmt(); + if (phdrStmt == nullptr) { return false; } - GenTree* init = phdr->gtPrev; - noway_assert(init != nullptr && (init->gtNext == nullptr)); + GenTreeStmt* initStmt = phdrStmt->getPrevStmt(); + noway_assert(initStmt != nullptr && (initStmt->gtNext == nullptr)); // If it is a duplicated loop condition, skip it. - if (init->gtFlags & GTF_STMT_CMPADD) + if (initStmt->gtFlags & GTF_STMT_CMPADD) { bool doGetPrev = true; #ifdef DEBUG @@ -1084,28 +1084,24 @@ bool Compiler::optExtractInitTestIncr( { // Previous optimization passes may have inserted compiler-generated // statements other than duplicated loop conditions. - doGetPrev = (init->gtPrev != nullptr); + doGetPrev = (initStmt->gtPrev != nullptr); } else { // Must be a duplicated loop condition. - noway_assert(init->gtStmt.gtStmtExpr->gtOper == GT_JTRUE); + noway_assert(initStmt->gtStmtExpr->gtOper == GT_JTRUE); } #endif // DEBUG if (doGetPrev) { - init = init->gtPrev; + initStmt = initStmt->getPrevStmt(); } - noway_assert(init != nullptr); + noway_assert(initStmt != nullptr); } - noway_assert(init->gtOper == GT_STMT); - noway_assert(test->gtOper == GT_STMT); - noway_assert(incr->gtOper == GT_STMT); - - *ppInit = init->gtStmt.gtStmtExpr; - *ppTest = test->gtStmt.gtStmtExpr; - *ppIncr = incr->gtStmt.gtStmtExpr; + *ppInit = initStmt->gtStmtExpr; + *ppTest = testStmt->gtStmtExpr; + *ppIncr = incrStmt->gtStmtExpr; return true; } @@ -1308,12 +1304,12 @@ bool Compiler::optRecordLoop(BasicBlock* head, block = block->bbNext; for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt) { - if (stmt->gtStmt.gtStmtExpr == incr) + if (stmt->gtStmtExpr == incr) { break; } printf("\n"); - gtDispTree(stmt->gtStmt.gtStmtExpr); + gtDispTree(stmt->gtStmtExpr); } } while (block != bottom); } @@ -3796,7 +3792,7 @@ void Compiler::optUnrollLoops() // Remove the test; we're doing a full unroll. GenTreeStmt* testCopyStmt = newBlock->lastStmt(); - GenTree* testCopyExpr = testCopyStmt->gtStmt.gtStmtExpr; + GenTree* testCopyExpr = testCopyStmt->gtStmtExpr; assert(testCopyExpr->gtOper == GT_JTRUE); GenTree* sideEffList = nullptr; gtExtractSideEffList(testCopyExpr, &sideEffList, GTF_SIDE_EFFECT | GTF_ORDER_SIDEEFF); @@ -3806,7 +3802,7 @@ void Compiler::optUnrollLoops() } else { - testCopyStmt->gtStmt.gtStmtExpr = sideEffList; + testCopyStmt->gtStmtExpr = sideEffList; } newBlock->bbJumpKind = BBJ_NONE; @@ -4024,21 +4020,21 @@ bool Compiler::optReachWithoutCall(BasicBlock* topBB, BasicBlock* botBB) * Find the loop termination test at the bottom of the loop */ -static GenTree* optFindLoopTermTest(BasicBlock* bottom) +static GenTreeStmt* optFindLoopTermTest(BasicBlock* bottom) { - GenTree* testt = bottom->bbTreeList; + GenTreeStmt* testStmt = bottom->firstStmt(); - assert(testt && testt->gtOper == GT_STMT); + assert(testStmt); - GenTree* result = testt->gtPrev; + GenTreeStmt* result = testStmt->getPrevStmt(); #ifdef DEBUG - while (testt->gtNext) + while (testStmt->gtNext != nullptr) { - testt = testt->gtNext; + testStmt = testStmt->getNextStmt(); } - assert(testt == result); + assert(testStmt == result); #endif return result; @@ -4132,7 +4128,7 @@ void Compiler::fgOptWhileLoop(BasicBlock* block) return; } - GenTree* condStmt = optFindLoopTermTest(bTest); + GenTreeStmt* condStmt = optFindLoopTermTest(bTest); // bTest must only contain only a jtrue with no other stmts, we will only clone // the conditional, so any other statements will not get cloned @@ -4145,9 +4141,7 @@ void Compiler::fgOptWhileLoop(BasicBlock* block) /* Get to the condition node from the statement tree */ - noway_assert(condStmt->gtOper == GT_STMT); - - GenTree* condTree = condStmt->gtStmt.gtStmtExpr; + GenTree* condTree = condStmt->gtStmtExpr; noway_assert(condTree->gtOper == GT_JTRUE); condTree = condTree->gtOp.gtOp1; @@ -4267,13 +4261,13 @@ void Compiler::fgOptWhileLoop(BasicBlock* block) /* Create a statement entry out of the condition and append the condition test at the end of 'block' */ - GenTree* copyOfCondStmt = fgInsertStmtAtEnd(block, condTree); + GenTreeStmt* copyOfCondStmt = fgInsertStmtAtEnd(block, condTree); copyOfCondStmt->gtFlags |= GTF_STMT_CMPADD; if (opts.compDbgInfo) { - copyOfCondStmt->gtStmt.gtStmtILoffsx = condStmt->gtStmt.gtStmtILoffsx; + copyOfCondStmt->gtStmtILoffsx = condStmt->gtStmtILoffsx; } // Flag the block that received the copy as potentially having an array/vtable @@ -4885,18 +4879,18 @@ bool Compiler::optComputeDerefConditions(unsigned loopNum, LoopCloneContext* con // // Arguments: // block - the block in which the helper call needs to be inserted. -// insertBefore - the tree before which the helper call will be inserted. +// insertBefore - the stmt before which the helper call will be inserted. // -void Compiler::optDebugLogLoopCloning(BasicBlock* block, GenTree* insertBefore) +void Compiler::optDebugLogLoopCloning(BasicBlock* block, GenTreeStmt* insertBefore) { if (JitConfig.JitDebugLogLoopCloning() == 0) { return; } - GenTree* logCall = gtNewHelperCallNode(CORINFO_HELP_DEBUG_LOG_LOOP_CLONING, TYP_VOID); - GenTree* stmt = fgNewStmtFromTree(logCall); + GenTree* logCall = gtNewHelperCallNode(CORINFO_HELP_DEBUG_LOG_LOOP_CLONING, TYP_VOID); + GenTreeStmt* stmt = fgNewStmtFromTree(logCall); fgInsertStmtBefore(block, insertBefore, stmt); - fgMorphBlockStmt(block, stmt->AsStmt() DEBUGARG("Debug log loop cloning")); + fgMorphBlockStmt(block, stmt DEBUGARG("Debug log loop cloning")); } #endif @@ -6041,7 +6035,6 @@ bool Compiler::optIsVarAssigned(BasicBlock* beg, BasicBlock* end, GenTree* skip, for (GenTreeStmt* stmt = beg->firstStmt(); stmt; stmt = stmt->gtNextStmt) { - noway_assert(stmt->gtOper == GT_STMT); if (fgWalkTreePre(&stmt->gtStmtExpr, optIsVarAssgCB, &desc)) { result = true; @@ -6104,9 +6097,8 @@ int Compiler::optIsSetAssgLoop(unsigned lnum, ALLVARSET_VALARG_TP vars, varRefKi { noway_assert(beg); - for (GenTreeStmt* stmt = beg->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt) + for (GenTreeStmt* stmt = beg->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->gtNextStmt) { - noway_assert(stmt->gtOper == GT_STMT); fgWalkTreePre(&stmt->gtStmtExpr, optIsVarAssgCB, &desc); if (desc.ivaMaskIncomplete) @@ -6238,7 +6230,7 @@ void Compiler::optPerformHoistExpr(GenTree* origExpr, unsigned lnum) compCurBB = preHead; hoist = fgMorphTree(hoist); - GenTree* hoistStmt = gtNewStmt(hoist); + GenTreeStmt* hoistStmt = gtNewStmt(hoist); hoistStmt->gtFlags |= GTF_STMT_CMPADD; /* simply append the statement at the end of the preHead's list */ @@ -6699,7 +6691,7 @@ void Compiler::optHoistLoopExprsForBlock(BasicBlock* blk, unsigned lnum, LoopHoi return; } - for (GenTreeStmt* stmt = blk->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt) + for (GenTreeStmt* stmt = blk->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt()) { GenTree* stmtTree = stmt->gtStmtExpr; bool hoistable; @@ -7337,9 +7329,9 @@ void Compiler::fgCreateLoopPreHeader(unsigned lnum) // into the phi via the loop header block will now flow through the preheader // block from the header block. - for (GenTree* stmt = top->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = top->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - GenTree* tree = stmt->gtStmt.gtStmtExpr; + GenTree* tree = stmt->gtStmtExpr; if (tree->OperGet() != GT_ASG) { break; @@ -7579,9 +7571,9 @@ void Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk) MemoryKindSet memoryHavoc = emptyMemoryKindSet; // Now iterate over the remaining statements, and their trees. - for (GenTree* stmts = blk->FirstNonPhiDef(); (stmts != nullptr); stmts = stmts->gtNext) + for (GenTreeStmt* stmt = blk->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt()) { - for (GenTree* tree = stmts->gtStmt.gtStmtList; (tree != nullptr); tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { genTreeOps oper = tree->OperGet(); @@ -7902,13 +7894,12 @@ void Compiler::AddModifiedElemTypeAllContainingLoops(unsigned lnum, CORINFO_CLAS // tree - Range check tree // stmt - Statement the tree belongs to -void Compiler::optRemoveRangeCheck(GenTree* tree, GenTree* stmt) +void Compiler::optRemoveRangeCheck(GenTree* tree, GenTreeStmt* stmt) { #if !REARRANGE_ADDS noway_assert(!"can't remove range checks without REARRANGE_ADDS right now"); #endif - noway_assert(stmt->gtOper == GT_STMT); noway_assert(tree->gtOper == GT_COMMA); GenTree* bndsChkTree = tree->gtOp.gtOp1; @@ -8113,13 +8104,12 @@ bool Compiler::optIdentifyLoopOptInfo(unsigned loopNum, LoopCloneContext* contex for (BasicBlock* block = beg; block != end->bbNext; block = block->bbNext) { compCurBB = block; - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { info.stmt = stmt; const bool lclVarsOnly = false; const bool computeStack = false; - fgWalkTreePre(&stmt->gtStmt.gtStmtExpr, optCanOptimizeByLoopCloningVisitor, &info, lclVarsOnly, - computeStack); + fgWalkTreePre(&stmt->gtStmtExpr, optCanOptimizeByLoopCloningVisitor, &info, lclVarsOnly, computeStack); } } @@ -8581,14 +8571,14 @@ void Compiler::optOptimizeBoolsGcStress(BasicBlock* condBlock) } noway_assert(condBlock->bbJumpKind == BBJ_COND); - GenTree* condStmt = condBlock->bbTreeList->gtPrev->gtStmt.gtStmtExpr; + GenTree* cond = condBlock->lastStmt()->gtStmtExpr; - noway_assert(condStmt->gtOper == GT_JTRUE); + noway_assert(cond->gtOper == GT_JTRUE); bool isBool; GenTree* relop; - GenTree* comparand = optIsBoolCond(condStmt, &relop, &isBool); + GenTree* comparand = optIsBoolCond(cond, &relop, &isBool); if (comparand == nullptr || !varTypeIsGC(comparand->TypeGet())) { @@ -8793,22 +8783,20 @@ void Compiler::optOptimizeBools() /* The second block must contain a single statement */ - GenTree* s2 = b2->bbTreeList; + GenTreeStmt* s2 = b2->firstStmt(); if (s2->gtPrev != s2) { continue; } - noway_assert(s2->gtOper == GT_STMT); - GenTree* t2 = s2->gtStmt.gtStmtExpr; + GenTree* t2 = s2->gtStmtExpr; noway_assert(t2->gtOper == GT_JTRUE); /* Find the condition for the first block */ - GenTree* s1 = b1->bbTreeList->gtPrev; + GenTreeStmt* s1 = b1->lastStmt(); - noway_assert(s1->gtOper == GT_STMT); - GenTree* t1 = s1->gtStmt.gtStmtExpr; + GenTree* t1 = s1->gtStmtExpr; noway_assert(t1->gtOper == GT_JTRUE); if (b2->countOfInEdges() > 1) diff --git a/src/jit/rangecheck.cpp b/src/jit/rangecheck.cpp index 8255afeecf..96fcaf9561 100644 --- a/src/jit/rangecheck.cpp +++ b/src/jit/rangecheck.cpp @@ -188,7 +188,7 @@ bool RangeCheck::BetweenBounds(Range& range, int lower, GenTree* upper) return false; } -void RangeCheck::OptimizeRangeCheck(BasicBlock* block, GenTree* stmt, GenTree* treeParent) +void RangeCheck::OptimizeRangeCheck(BasicBlock* block, GenTreeStmt* stmt, GenTree* treeParent) { // Check if we are dealing with a bounds check node. if (treeParent->OperGet() != GT_COMMA) @@ -1257,11 +1257,11 @@ void RangeCheck::MapStmtDefs(const Location& loc) struct MapMethodDefsData { - RangeCheck* rc; - BasicBlock* block; - GenTree* stmt; + RangeCheck* rc; + BasicBlock* block; + GenTreeStmt* stmt; - MapMethodDefsData(RangeCheck* rc, BasicBlock* block, GenTree* stmt) : rc(rc), block(block), stmt(stmt) + MapMethodDefsData(RangeCheck* rc, BasicBlock* block, GenTreeStmt* stmt) : rc(rc), block(block), stmt(stmt) { } }; @@ -1282,12 +1282,12 @@ Compiler::fgWalkResult MapMethodDefsVisitor(GenTree** ptr, Compiler::fgWalkData* void RangeCheck::MapMethodDefs() { // First, gather where all definitions occur in the program and store it in a map. - for (BasicBlock* block = m_pCompiler->fgFirstBB; block; block = block->bbNext) + for (BasicBlock* block = m_pCompiler->fgFirstBB; block != nullptr; block = block->bbNext) { - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { MapMethodDefsData data(this, block, stmt); - m_pCompiler->fgWalkTreePre(&stmt->gtStmt.gtStmtExpr, MapMethodDefsVisitor, &data, false, true); + m_pCompiler->fgWalkTreePre(&stmt->gtStmtExpr, MapMethodDefsVisitor, &data, false, true); } } m_fMappedDefs = true; @@ -1313,9 +1313,9 @@ void RangeCheck::OptimizeRangeChecks() // Walk through trees looking for arrBndsChk node and check if it can be optimized. for (BasicBlock* block = m_pCompiler->fgFirstBB; block; block = block->bbNext) { - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree; tree = tree->gtNext) { if (IsOverBudget()) { diff --git a/src/jit/rangecheck.h b/src/jit/rangecheck.h index 4c580e4739..643273d25d 100644 --- a/src/jit/rangecheck.h +++ b/src/jit/rangecheck.h @@ -415,10 +415,10 @@ public: struct Location { BasicBlock* block; - GenTree* stmt; + GenTreeStmt* stmt; GenTreeLclVarCommon* tree; GenTree* parent; - Location(BasicBlock* block, GenTree* stmt, GenTreeLclVarCommon* tree, GenTree* parent) + Location(BasicBlock* block, GenTreeStmt* stmt, GenTreeLclVarCommon* tree, GenTree* parent) : block(block), stmt(stmt), tree(tree), parent(parent) { } @@ -463,7 +463,7 @@ public: // Given a "tree" node, check if it contains array bounds check node and // optimize to remove it, if possible. Requires "stmt" and "block" that // contain the tree. - void OptimizeRangeCheck(BasicBlock* block, GenTree* stmt, GenTree* tree); + void OptimizeRangeCheck(BasicBlock* block, GenTreeStmt* stmt, GenTree* tree); // Given the index expression try to find its range. // The range of a variable depends on its rhs which in turn depends on its constituent variables. diff --git a/src/jit/rationalize.cpp b/src/jit/rationalize.cpp index d51634b6db..cf5f44acd1 100644 --- a/src/jit/rationalize.cpp +++ b/src/jit/rationalize.cpp @@ -228,10 +228,9 @@ void Rationalizer::RewriteIntrinsicAsUserCall(GenTree** use, ArrayStackgtOper == GT_STMT); - DBEXEC(TRUE, JitTls::GetCompiler()->fgDebugCheckNodeLinks(block, tree)); + DBEXEC(TRUE, JitTls::GetCompiler()->fgDebugCheckNodeLinks(block, stmt)); } // sanity checks that apply to all kinds of IR @@ -241,11 +240,11 @@ void Rationalizer::SanityCheck() BasicBlock* block; foreach_block(comp, block) { - for (GenTree* statement = block->bbTreeList; statement != nullptr; statement = statement->gtNext) + for (GenTreeStmt* statement = block->firstStmt(); statement != nullptr; statement = statement->getNextStmt()) { ValidateStatement(statement, block); - for (GenTree* tree = statement->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = statement->gtStmtList; tree; tree = tree->gtNext) { // QMARK nodes should have been removed before this phase. assert(tree->OperGet() != GT_QMARK); diff --git a/src/jit/rationalize.h b/src/jit/rationalize.h index 297db3618d..83ec879a74 100644 --- a/src/jit/rationalize.h +++ b/src/jit/rationalize.h @@ -15,7 +15,7 @@ public: Rationalizer(Compiler* comp); #ifdef DEBUG - static void ValidateStatement(GenTree* tree, BasicBlock* block); + static void ValidateStatement(GenTreeStmt* stmt, BasicBlock* block); // general purpose sanity checking of de facto standard GenTree void SanityCheck(); diff --git a/src/jit/simd.cpp b/src/jit/simd.cpp index af3c568b9a..b4cecb3e20 100644 --- a/src/jit/simd.cpp +++ b/src/jit/simd.cpp @@ -2274,13 +2274,13 @@ GenTree* Compiler::createAddressNodeForSIMDInit(GenTree* tree, unsigned simdSize // Arguments: // stmt - GenTree*. Input statement node. -void Compiler::impMarkContiguousSIMDFieldAssignments(GenTree* stmt) +void Compiler::impMarkContiguousSIMDFieldAssignments(GenTreeStmt* stmt) { if (!featureSIMD || opts.OptimizationDisabled()) { return; } - GenTree* expr = stmt->gtStmt.gtStmtExpr; + GenTree* expr = stmt->gtStmtExpr; if (expr->OperGet() == GT_ASG && expr->TypeGet() == TYP_FLOAT) { GenTree* curDst = expr->gtOp.gtOp1; @@ -2300,7 +2300,7 @@ void Compiler::impMarkContiguousSIMDFieldAssignments(GenTree* stmt) else if (fgPreviousCandidateSIMDFieldAsgStmt != nullptr) { assert(index > 0); - GenTree* prevAsgExpr = fgPreviousCandidateSIMDFieldAsgStmt->gtStmt.gtStmtExpr; + GenTree* prevAsgExpr = fgPreviousCandidateSIMDFieldAsgStmt->gtStmtExpr; GenTree* prevDst = prevAsgExpr->gtOp.gtOp1; GenTree* prevSrc = prevAsgExpr->gtOp.gtOp2; if (!areArgumentsContiguous(prevDst, curDst) || !areArgumentsContiguous(prevSrc, curSrc)) diff --git a/src/jit/ssabuilder.cpp b/src/jit/ssabuilder.cpp index 594e99dbe1..7ad1651449 100644 --- a/src/jit/ssabuilder.cpp +++ b/src/jit/ssabuilder.cpp @@ -113,7 +113,7 @@ void Compiler::fgResetForSsa() blk->bbPostOrderNum = 0; for (GenTreeStmt* stmt = blk->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree != nullptr; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { if (tree->IsLocal()) { @@ -652,7 +652,7 @@ void SsaBuilder::ComputeIteratedDominanceFrontier(BasicBlock* b, const BlkToBlkV static GenTree* GetPhiNode(BasicBlock* block, unsigned lclNum) { // Walk the statements for phi nodes. - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { // A prefix of the statements of the block are phi definition nodes. If we complete processing // that prefix, exit. @@ -661,7 +661,7 @@ static GenTree* GetPhiNode(BasicBlock* block, unsigned lclNum) break; } - GenTree* tree = stmt->gtStmt.gtStmtExpr; + GenTree* tree = stmt->gtStmtExpr; GenTree* phiLhs = tree->gtOp.gtOp1; assert(phiLhs->OperGet() == GT_LCL_VAR); @@ -756,7 +756,7 @@ void SsaBuilder::InsertPhiFunctions(BasicBlock** postOrder, int count) GenTree* phiAsg = m_pCompiler->gtNewAssignNode(phiLhs, phiRhs); - GenTree* stmt = m_pCompiler->fgInsertStmtAtBeg(bbInDomFront, phiAsg); + GenTreeStmt* stmt = m_pCompiler->fgInsertStmtAtBeg(bbInDomFront, phiAsg); m_pCompiler->gtSetStmtInfo(stmt); m_pCompiler->fgSetStmtSeq(stmt); } @@ -991,7 +991,7 @@ void SsaBuilder::AddDefToHandlerPhis(BasicBlock* block, unsigned lclNum, unsigne bool phiFound = false; #endif // A prefix of blocks statements will be SSA definitions. Search those for "lclNum". - for (GenTree* stmt = handler->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = handler->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { // If the tree is not an SSA def, break out of the loop: we're done. if (!stmt->IsPhiDefnStmt()) @@ -999,7 +999,7 @@ void SsaBuilder::AddDefToHandlerPhis(BasicBlock* block, unsigned lclNum, unsigne break; } - GenTree* tree = stmt->gtStmt.gtStmtExpr; + GenTree* tree = stmt->gtStmtExpr; assert(tree->IsPhiDefn()); @@ -1172,16 +1172,16 @@ void SsaBuilder::BlockRenameVariables(BasicBlock* block, SsaRenameState* pRename // We need to iterate over phi definitions, to give them SSA names, but we need // to know which are which, so we don't add phi definitions to handler phi arg lists. // Statements are phi defns until they aren't. - bool isPhiDefn = true; - GenTree* firstNonPhi = block->FirstNonPhiDef(); - for (GenTree* stmt = block->bbTreeList; stmt; stmt = stmt->gtNext) + bool isPhiDefn = true; + GenTreeStmt* firstNonPhi = block->FirstNonPhiDef(); + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { if (stmt == firstNonPhi) { isPhiDefn = false; } - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree; tree = tree->gtNext) { TreeRenameVariables(tree, block, pRenameState, isPhiDefn); } @@ -1239,9 +1239,10 @@ void SsaBuilder::AssignPhiNodeRhsVariables(BasicBlock* block, SsaRenameState* pR for (BasicBlock* succ : block->GetAllSuccs(m_pCompiler)) { // Walk the statements for phi nodes. - for (GenTree* stmt = succ->bbTreeList; stmt != nullptr && stmt->IsPhiDefnStmt(); stmt = stmt->gtNext) + for (GenTreeStmt* stmt = succ->firstStmt(); stmt != nullptr && stmt->IsPhiDefnStmt(); + stmt = stmt->getNextStmt()) { - GenTree* tree = stmt->gtStmt.gtStmtExpr; + GenTree* tree = stmt->gtStmtExpr; assert(tree->IsPhiDefn()); // Get the phi node from GT_ASG. @@ -1376,9 +1377,9 @@ void SsaBuilder::AssignPhiNodeRhsVariables(BasicBlock* block, SsaRenameState* pR // For a filter, we consider the filter to be the "real" handler. BasicBlock* handlerStart = succTry->ExFlowBlock(); - for (GenTree* stmt = handlerStart->bbTreeList; stmt; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = handlerStart->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - GenTree* tree = stmt->gtStmt.gtStmtExpr; + GenTree* tree = stmt->gtStmtExpr; // Check if the first n of the statements are phi nodes. If not, exit. if (tree->OperGet() != GT_ASG || tree->gtOp.gtOp2 == nullptr || diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp index 4280d872b0..88fbbcc3f0 100644 --- a/src/jit/valuenum.cpp +++ b/src/jit/valuenum.cpp @@ -5759,10 +5759,9 @@ void Compiler::fgValueNumber() for (BasicBlock* blk = fgFirstBB; blk != nullptr; blk = blk->bbNext) { // Now iterate over the block's statements, and their trees. - for (GenTree* stmts = blk->FirstNonPhiDef(); stmts != nullptr; stmts = stmts->gtNext) + for (GenTreeStmt* stmt = blk->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt()) { - assert(stmts->IsStatement()); - for (GenTree* tree = stmts->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { tree->gtVNPair.SetBoth(ValueNumStore::NoVN); } @@ -5925,12 +5924,12 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk) // First: visit phi's. If "newVNForPhis", give them new VN's. If not, // first check to see if all phi args have the same value. - GenTree* firstNonPhi = blk->FirstNonPhiDef(); - for (GenTree* phiDefs = blk->bbTreeList; phiDefs != firstNonPhi; phiDefs = phiDefs->gtNext) + GenTreeStmt* firstNonPhi = blk->FirstNonPhiDef(); + for (GenTreeStmt* phiDefStmt = blk->firstStmt(); phiDefStmt != firstNonPhi; phiDefStmt = phiDefStmt->getNextStmt()) { // TODO-Cleanup: It has been proposed that we should have an IsPhiDef predicate. We would use it // in Block::FirstNonPhiDef as well. - GenTree* phiDef = phiDefs->gtStmt.gtStmtExpr; + GenTree* phiDef = phiDefStmt->gtStmtExpr; assert(phiDef->OperGet() == GT_ASG); GenTreeLclVarCommon* newSsaVar = phiDef->gtOp.gtOp1->AsLclVarCommon(); @@ -6133,21 +6132,19 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk) } // Now iterate over the remaining statements, and their trees. - for (GenTree* stmt = firstNonPhi; stmt != nullptr; stmt = stmt->gtNext) + for (GenTreeStmt* stmt = firstNonPhi; stmt != nullptr; stmt = stmt->getNextStmt()) { - assert(stmt->IsStatement()); - #ifdef DEBUG compCurStmtNum++; if (verbose) { printf("\n***** " FMT_BB ", stmt %d (before)\n", blk->bbNum, compCurStmtNum); - gtDispTree(stmt->gtStmt.gtStmtExpr); + gtDispTree(stmt->gtStmtExpr); printf("\n"); } #endif - for (GenTree* tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext) + for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { fgValueNumberTree(tree); } @@ -6156,7 +6153,7 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk) if (verbose) { printf("\n***** " FMT_BB ", stmt %d (after)\n", blk->bbNum, compCurStmtNum); - gtDispTree(stmt->gtStmt.gtStmtExpr); + gtDispTree(stmt->gtStmtExpr); printf("\n"); if (stmt->gtNext) { -- cgit v1.2.3