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];
/* 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);
if (verbose)
{
printf("\nIntroducing a new copy for V%02u\n", lclNum);
- gtDispTree(stmt->gtStmt.gtStmtExpr);
+ gtDispTree(stmt->gtStmtExpr);
printf("\n");
}
#endif
// 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.
*/
GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion,
GenTree* tree,
- GenTree* stmt DEBUGARG(AssertionIndex index))
+ GenTreeStmt* stmt DEBUGARG(AssertionIndex index))
{
unsigned lclNum = tree->gtLclVarCommon.gtLclNum;
*/
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;
* 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
* 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);
* 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;
* 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);
*
* 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);
* 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.
*
*/
-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());
* 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)
{
*
*/
-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);
}
* 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)
{
*
*/
-GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenTree* stmt)
+GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenTreeStmt* stmt)
{
noway_assert(newTree != nullptr);
* 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)
{
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);
{
ASSERT_TP* jumpDestGen = fgAllocateTypeForEachBlk<ASSERT_TP>();
- 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)
{
// 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)
{
}
//
// 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".
// 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();
// 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());
}
// 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;
// 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)
}
// Perform the constant propagation
- GenTree* newTree = optVNConstantPropOnTree(block, stmt, tree);
+ GenTree* newTree = optVNConstantPropOnTree(block, tree);
if (newTree == nullptr)
{
// Not propagated, keep going.
// 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())
{
* 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
}
// 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;
}
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;
}
}
// 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();
}
}
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))
{
}
#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.
}
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.
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;
}
// 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())
{
//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)
// 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())
{
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();
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;
GenTree* args;
GenTree* argx;
- BasicBlock* block;
- GenTree* stmt;
- GenTree* call;
-
unsigned argNum;
unsigned argDWordNum;
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;
if (comp->compRationalIRForm)
{
- GenTree* tree;
-
- foreach_treenode_execution_order(tree, stmt)
+ for (GenTree* tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext)
{
cNodeIR(comp, tree);
}
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
{
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,
// 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);
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);
static fgWalkPreFn gtMarkColonCond;
static fgWalkPreFn gtClearColonCond;
- GenTree** gtFindLink(GenTree* stmt, GenTree* node);
+ GenTree** gtFindLink(GenTreeStmt* stmt, GenTree* node);
bool gtHasCatchArg(GenTree* tree);
typedef ArrayStack<GenTree*> GenTreeStack;
void lvaAllocOutgoingArgSpaceVar(); // Set up lvaOutgoingArgSpaceVar
- VARSET_VALRET_TP lvaStmtLclMask(GenTree* stmt);
+ VARSET_VALRET_TP lvaStmtLclMask(GenTreeStmt* stmt);
#ifdef DEBUG
struct lvaStressLclFldArgs
//----------------- 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
};
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);
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
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);
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();
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);
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);
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);
#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:
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.
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 --------------------------------------
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);
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);
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);
public:
void optInit();
- void optRemoveRangeCheck(GenTree* tree, GenTree* stmt);
+ void optRemoveRangeCheck(GenTree* tree, GenTreeStmt* stmt);
bool optIsRangeCheckRemovable(GenTree* tree);
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);
{
treeStmtLst* tslNext;
GenTree* tslTree; // tree node
- GenTree* tslStmt; // statement containing the tree
+ GenTreeStmt* tslStmt; // statement containing the tree
BasicBlock* tslBlock; // block containing the statement
};
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
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();
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);
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()
#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();
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);
{
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)
{
}
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);
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
/*****************************************************************************/
/*****************************************************************************/
-// 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.
* 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 */
* 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)
{
*/
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())
{
// 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)
// 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);
}
// 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))
{
// 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)
// * stmtExpr void (top level)
// \--* indir int
// \--* lclVar ref V02 loc0
- if (compCurStmt->gtStmt.gtStmtExpr == tree)
+ if (compCurStmt->gtStmtExpr == tree)
{
return nullptr;
}
HRESULT res = info.compCompHnd->allocBBProfileBuffer(countOfBlocks, &bbProfileBufferStart);
- GenTree* stmt;
+ GenTreeStmt* stmt;
if (!SUCCEEDED(res))
{
// 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)
//
// 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.
// 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);
* 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));
// 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));
* 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;
//
// 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;
}
}
// 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);
}
}
// 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)
*
*/
-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 &&
* 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();
}
// 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 */
}
else
{
- GenTree* nopStmt = fgInsertStmtAtEnd(block, nop);
+ GenTreeStmt* nopStmt = fgInsertStmtAtEnd(block, nop);
fgSetStmtSeq(nopStmt);
gtSetStmtInfo(nopStmt);
}
GenTree* cloned = gtCloneExpr(stmt->gtStmtExpr);
noway_assert(cloned);
- GenTree* jmpStmt = gtNewStmt(cloned);
+ GenTreeStmt* jmpStmt = gtNewStmt(cloned);
block->bbJumpKind = BBJ_COND;
block->bbJumpDest = target->bbJumpDest;
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;
/* 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;
}
//
{
// 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);
}
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);
/*****************************************************************************/
-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
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)
{
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);
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;
}
}
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;
/*****************************************************************************/
// 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
}
else
{
- gtDispTree(stmt->gtStmt.gtStmtExpr);
+ gtDispTree(stmt->gtStmtExpr);
}
}
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
}
// 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())
// TODO: return?
}
- GenTreeStmt* stmt = node->AsStmt();
-
assert(fgStmtListThreaded);
noway_assert(stmt->gtStmtList);
#ifdef DEBUG
- GenTree* currentDumpStmt = nullptr;
+ GenTreeStmt* currentDumpStmt = nullptr;
if (verbose)
{
}
// Prepend statements
- GenTree* stmtAfter = fgInlinePrependStatements(pInlineInfo);
+ GenTreeStmt* stmtAfter = fgInlinePrependStatements(pInlineInfo);
#ifdef DEBUG
if (verbose)
// 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;
{
do
{
- currentDumpStmt = currentDumpStmt->gtNext;
+ currentDumpStmt = currentDumpStmt->getNextStmt();
printf("\n");
- noway_assert(currentDumpStmt->gtOper == GT_STMT);
-
gtDispTree(currentDumpStmt);
printf("\n");
// 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);
// 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
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;
}
// 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)
{
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);
}
}
}
// 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)))
{
// 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);
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
{
// 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)
// 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)
{
// 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);
}
//------------------------------------------------------------------------
{
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)
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",
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));
}
// 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.
// 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
// 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)
{
}
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())
}
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.
// 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)
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)
{
}
// 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)
//-----------------------------------------------------------------------------
// 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
void Compiler::impInit()
{
-
+ impStmtList = impLastStmt = nullptr;
#ifdef DEBUG
- impTreeList = nullptr;
- impTreeLast = nullptr;
impInlinedCodeSize = 0;
-#endif
+#endif // DEBUG
}
/*****************************************************************************
}
}
-/*****************************************************************************
- *
- * 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);
}
/*****************************************************************************
* 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;
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;
}
/*****************************************************************************
* 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)
{
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
* 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;
/* 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
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);
/* 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);
}
#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;
}
/*****************************************************************************
* 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;
}
/*****************************************************************************
* 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);
}
/*****************************************************************************
* 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);
{
if (pAfterStmt)
{
- GenTree* asgStmt = gtNewStmt(asg, ilOffset);
- *pAfterStmt = fgInsertStmtAfter(block, *pAfterStmt, asgStmt);
+ GenTreeStmt* asgStmt = gtNewStmt(asg, ilOffset);
+ *pAfterStmt = fgInsertStmtAfter(block, *pAfterStmt, asgStmt);
}
else
{
GenTree* val,
CORINFO_CLASS_HANDLE structType,
unsigned curLevel,
- GenTree** pAfterStmt, /* = NULL */
+ GenTreeStmt** pAfterStmt, /* = NULL */
IL_OFFSETX ilOffset, /* = BAD_IL_OFFSET */
BasicBlock* block /* = NULL */
)
{
if (pAfterStmt)
{
- GenTree* asgStmt = gtNewStmt(asg, ilOffset);
- *pAfterStmt = fgInsertStmtAfter(block, *pAfterStmt, asgStmt);
+ GenTreeStmt* asgStmt = gtNewStmt(asg, ilOffset);
+ *pAfterStmt = fgInsertStmtAfter(block, *pAfterStmt, asgStmt);
}
else
{
// 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 */
)
// 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 */
)
// 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);
{
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();
}
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))
{
{
if (compIsForInlining())
{
- GenTree* callStmt = impInlineInfo->iciStmt;
- assert(callStmt->gtOper == GT_STMT);
- impCurStmtOffs = callStmt->gtStmt.gtStmtILoffsx;
+ GenTreeStmt* callStmt = impInlineInfo->iciStmt;
+ impCurStmtOffs = callStmt->gtStmtILoffsx;
}
else
{
// 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;
}
}
// 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;
}
// 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))
#ifdef DEBUG
// we need this since BeginTreeList asserts otherwise
- impTreeList = impTreeLast = nullptr;
+ impStmtList = impLastStmt = nullptr;
block->bbFlags &= ~BBF_IMPORTED;
if (logMsg)
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);
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);
}
#endif
- GenTree* lastStmt;
+ GenTreeStmt* lastStmt;
if (endCatches)
{
}
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);
}
#endif
- GenTree* lastStmt;
+ GenTreeStmt* lastStmt;
if (endCatches)
{
}
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
// 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
{
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 */
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;
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)
{
/* Put back the 'jtrue'/'switch' if we removed it earlier */
- if (addStmt)
+ if (addStmt != nullptr)
{
impAppendStmt(addStmt, (unsigned)CHECK_SPILL_NONE);
}
BasicBlock* block = compCurBB;
- GenTree* stmt;
- GenTree* expr;
-
if (block != fgFirstBB)
{
return FALSE;
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;
//
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);
}
//
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);
}
{
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);
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);
}
}
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)
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);
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!
/* 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 */
/* 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
{
/* Get the first statement in the block */
- GenTree* firstStmt = block->FirstNonPhiDef();
+ GenTreeStmt* firstStmt = block->FirstNonPhiDef();
if (firstStmt == nullptr)
{
/* 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)
{
if (verbose && treeModf)
{
printf("\nfgComputeLife modified tree:\n");
- gtDispTree(compCurStmt->gtStmt.gtStmtExpr);
+ gtDispTree(compCurStmt->gtStmtExpr);
printf("\n");
}
#endif // DEBUG
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"));
}
//--------------------------------------------------------------------------------------------------
*/
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)
{
}
#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();
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);
}
// [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
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;
// 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;
// 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);
}
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
// 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.
// 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)
// 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);
}
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.
{
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);
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)
{
/* 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
{
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);
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)
{
/* 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 */
GenTree* prev = nullptr;
for (; stmt != nullptr; prev = stmt->gtStmtExpr, stmt = stmt->gtNextStmt)
{
- assert(stmt->gtOper == GT_STMT);
-
if (fgRemoveRestOfBlock)
{
fgRemoveStmt(block, stmt);
{
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)
{
op1->gtFlags &= ~GTF_RELOP_JMP_USED;
}
- last->gtStmt.gtStmtExpr = fgMorphTree(op1);
+ lastStmt->gtStmtExpr = fgMorphTree(op1);
}
}
//
// 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))
{
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
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)
* tmp has the result.
*
*/
-void Compiler::fgExpandQmarkForCastInstOf(BasicBlock* block, GenTree* stmt)
+void Compiler::fgExpandQmarkForCastInstOf(BasicBlock* block, GenTreeStmt* stmt)
{
#ifdef DEBUG
if (verbose)
}
#endif // DEBUG
- GenTree* expr = stmt->gtStmt.gtStmtExpr;
+ GenTree* expr = stmt->gtStmtExpr;
GenTree* dst = nullptr;
GenTree* qmark = fgGetTopLevelQmark(expr, &dst);
// 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.
* 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;
}
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.
{
trueExpr = gtNewTempAssign(lclNum, trueExpr);
}
- GenTree* trueStmt = fgNewStmtFromTree(trueExpr, stmt->gtStmt.gtStmtILoffsx);
+ GenTreeStmt* trueStmt = fgNewStmtFromTree(trueExpr, stmt->gtStmtILoffsx);
fgInsertStmtAtEnd(thenBlock, trueStmt);
}
{
falseExpr = gtNewTempAssign(lclNum, falseExpr);
}
- GenTree* falseStmt = fgNewStmtFromTree(falseExpr, stmt->gtStmt.gtStmtILoffsx);
+ GenTreeStmt* falseStmt = fgNewStmtFromTree(falseExpr, stmt->gtStmtILoffsx);
fgInsertStmtAtEnd(elseBlock, falseStmt);
}
{
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
*/
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);
}
}
// 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);
}
}
}
// 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;
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;
prevRHS = curRHS;
lastStmt = curStmt;
- curStmt = curStmt->gtNext;
+ curStmt = curStmt->getNextStmt();
}
if (remainingAssignments > 0)
for (int i = 0; i < assignmentsCount; i++)
{
- fgRemoveStmt(block, stmt->gtNext);
+ fgRemoveStmt(block, stmt->getNextStmt());
}
GenTree* copyBlkDst = createAddressNodeForSIMDInit(originalLHS, simdSize);
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)
// 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;
{
// 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;
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)
{
#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;
// 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))
{
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;
// 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);
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);
}
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;
}
{
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);
}
// 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:
// 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)
{
{
// 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;
{
if (rhs->OperIsCompare())
{
- *newTest = prevStmt;
+ *newTestStmt = prevStmt;
return true;
}
}
// 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)
{
}
// 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
{
}
}
- 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
{
// 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;
}
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);
}
// 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);
}
else
{
- testCopyStmt->gtStmt.gtStmtExpr = sideEffList;
+ testCopyStmt->gtStmtExpr = sideEffList;
}
newBlock->bbJumpKind = BBJ_NONE;
* 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;
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
/* 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;
/* 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
//
// 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
for (GenTreeStmt* stmt = beg->firstStmt(); stmt; stmt = stmt->gtNextStmt)
{
- noway_assert(stmt->gtOper == GT_STMT);
if (fgWalkTreePre(&stmt->gtStmtExpr, optIsVarAssgCB, &desc))
{
result = true;
{
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)
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 */
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;
// 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;
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();
// 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;
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);
}
}
}
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()))
{
/* 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)
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)
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)
{
}
};
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;
// 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())
{
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)
{
}
// 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.
#ifdef DEBUG
-void Rationalizer::ValidateStatement(GenTree* tree, BasicBlock* block)
+void Rationalizer::ValidateStatement(GenTreeStmt* stmt, BasicBlock* block)
{
- assert(tree->gtOper == 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
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);
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();
// 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;
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))
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())
{
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.
break;
}
- GenTree* tree = stmt->gtStmt.gtStmtExpr;
+ GenTree* tree = stmt->gtStmtExpr;
GenTree* phiLhs = tree->gtOp.gtOp1;
assert(phiLhs->OperGet() == GT_LCL_VAR);
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);
}
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())
break;
}
- GenTree* tree = stmt->gtStmt.gtStmtExpr;
+ GenTree* tree = stmt->gtStmtExpr;
assert(tree->IsPhiDefn());
// 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);
}
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.
// 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 ||
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);
}
// 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();
}
// 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);
}
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)
{