Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
/coreclrPublic archive

Commit 8a33888

Browse files
authored
Enable checking of GTF_EXCEPT and GTF_ASG flags. (#13668)
* Enable checking of GTF_EXCEPT and GTF_ASG flags. fgDebugCheckFlags is modified to check that GTF_EXCEPT and GTF_ASG are set precisely when needed. It's also modified to handle several special operators correctly. fgAddrCouldBeNull is updated to check for handles, implicit byref locals, and stack byrefs. OperMayThrow is modified to handle several operators correctly. GTF_IND_NONFAULTING is reused on operations for which OperIsIndir() is true and on GT_ARR_LENGTH. Various places in morph are updated to set side effect flags correctly. gtUpdateSideEffects is re-written so that it's precise for GTF_ASG and GTF_EXCEPT and conservatively correct for the other side effects. It's now called from more places to keep the flags up-to-date after transformations. NoThrow in HelperCallProperties is updated and GTF_EXCEPT flag is set on helper calls according to that property. optRemoveRangeCheck is cleaned up and simplified.
1 parent 8a036ea commit 8a33888

19 files changed

+676
-332
lines changed

src/jit/assertionprop.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -3421,7 +3421,7 @@ GenTreePtr Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, const G
34213421
if ((tree->gtGetOp1()->OperGet() == GT_ARR_BOUNDS_CHECK) &&
34223422
((tree->gtGetOp1()->gtFlags & GTF_ARR_BOUND_INBND) != 0))
34233423
{
3424-
optRemoveRangeCheck(tree, stmt, true, GTF_ASG, true/* force remove */);
3424+
optRemoveRangeCheck(tree, stmt);
34253425
returnoptAssertionProp_Update(tree, tree, stmt);
34263426
}
34273427
returnnullptr;
@@ -3475,6 +3475,7 @@ GenTreePtr Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, const Gen
34753475
}
34763476
#endif
34773477
tree->gtFlags &= ~GTF_EXCEPT;
3478+
tree->gtFlags |= GTF_IND_NONFAULTING;
34783479

34793480
// Set this flag to prevent reordering
34803481
tree->gtFlags |= GTF_ORDER_SIDEEFF;

src/jit/compiler.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9765,7 +9765,7 @@ int cTreeFlagsIR(Compiler* comp, GenTree* tree)
97659765
#endif
97669766
if (tree->gtFlags & GTF_IND_NONFAULTING)
97679767
{
9768-
if ((op == GT_IND) || (op == GT_STOREIND))
9768+
if (tree->OperIsIndirOrArrLength())
97699769
{
97709770
chars += printf("[IND_NONFAULTING]");
97719771
}

src/jit/compiler.h

+20-7
Original file line numberDiff line numberDiff line change
@@ -2056,10 +2056,7 @@ class Compiler
20562056
GenTreeArgList* args,
20572057
IL_OFFSETX ilOffset = BAD_IL_OFFSET);
20582058

2059-
GenTreeCall* gtNewHelperCallNode(unsigned helper,
2060-
var_types type,
2061-
unsigned flags = 0,
2062-
GenTreeArgList* args = nullptr);
2059+
GenTreeCall* gtNewHelperCallNode(unsigned helper, var_types type, GenTreeArgList* args = nullptr);
20632060

20642061
GenTreePtr gtNewLclvNode(unsigned lnum, var_types type, IL_OFFSETX ILoffs = BAD_IL_OFFSET);
20652062

@@ -2086,6 +2083,10 @@ class Compiler
20862083

20872084
GenTreePtr gtNewIndexRef(var_types typ, GenTreePtr arrayOp, GenTreePtr indexOp);
20882085

2086+
GenTreeArrLen* gtNewArrLen(var_types typ, GenTree* arrayOp, int lenOffset);
2087+
2088+
GenTree* gtNewIndir(var_types typ, GenTree* addr);
2089+
20892090
GenTreeArgList* gtNewArgList(GenTreePtr op);
20902091
GenTreeArgList* gtNewArgList(GenTreePtr op1, GenTreePtr op2);
20912092
GenTreeArgList* gtNewArgList(GenTreePtr op1, GenTreePtr op2, GenTreePtr op3);
@@ -2139,7 +2140,13 @@ class Compiler
21392140

21402141
GenTreePtr gtReplaceTree(GenTreePtr stmt, GenTreePtr tree, GenTreePtr replacementTree);
21412142

2142-
voidgtUpdateSideEffects(GenTreePtr tree, unsigned oldGtFlags, unsigned newGtFlags);
2143+
voidgtUpdateSideEffects(GenTree* stmt, GenTree* tree);
2144+
2145+
voidgtUpdateTreeAncestorsSideEffects(GenTree* tree);
2146+
2147+
voidgtUpdateStmtSideEffects(GenTree* stmt);
2148+
2149+
voidgtResetNodeSideEffects(GenTree* tree);
21432150

21442151
// Returns "true" iff the complexity (not formally defined, but first interpretation
21452152
// is #of nodes in subtree) of "tree" is greater than "limit".
@@ -4748,7 +4755,11 @@ class Compiler
47484755

47494756
voidfgFixupStructReturn(GenTreePtr call);
47504757
GenTreePtr fgMorphLocalVar(GenTreePtr tree, bool forceRemorph);
4758+
4759+
public:
47514760
boolfgAddrCouldBeNull(GenTreePtr addr);
4761+
4762+
private:
47524763
GenTreePtr fgMorphField(GenTreePtr tree, MorphAddrContext* mac);
47534764
boolfgCanFastTailCall(GenTreeCall* call);
47544765
voidfgMorphTailCall(GenTreeCall* call);
@@ -4913,6 +4924,9 @@ class Compiler
49134924
voidfgMarkAddressExposedLocals();
49144925
boolfgNodesMayInterfere(GenTree* store, GenTree* load);
49154926

4927+
static fgWalkPreFn fgUpdateSideEffectsPre;
4928+
static fgWalkPostFn fgUpdateSideEffectsPost;
4929+
49164930
// Returns true if the type of tree is of size at least "width", or if "tree" is not a
49174931
// local variable.
49184932
boolfgFitsInOrNotLoc(GenTreePtr tree, unsigned width);
@@ -4956,8 +4970,7 @@ class Compiler
49564970
LclVarDsc* optIsTrackedLocal(GenTreePtr tree);
49574971

49584972
public:
4959-
voidoptRemoveRangeCheck(
4960-
GenTreePtr tree, GenTreePtr stmt, bool updateCSEcounts, unsigned sideEffFlags = 0, bool forceRemove = false);
4973+
voidoptRemoveRangeCheck(GenTreePtr tree, GenTreePtr stmt);
49614974
booloptIsRangeCheckRemovable(GenTreePtr tree);
49624975

49634976
protected:

src/jit/compiler.hpp

+63-3
Original file line numberDiff line numberDiff line change
@@ -1121,8 +1121,21 @@ inline GenTreePtr Compiler::gtNewIconEmbFldHndNode(CORINFO_FIELD_HANDLE fldHnd,
11211121

11221122
/*****************************************************************************/
11231123

1124-
inline GenTreeCall* Compiler::gtNewHelperCallNode(unsigned helper, var_types type, unsigned flags, GenTreeArgList* args)
1124+
//------------------------------------------------------------------------------
1125+
// gtNewHelperCallNode : Helper to create a call helper node.
1126+
//
1127+
//
1128+
// Arguments:
1129+
// helper - Call helper
1130+
// type - Type of the node
1131+
// args - Call args
1132+
//
1133+
// Return Value:
1134+
// New CT_HELPER node
1135+
1136+
inline GenTreeCall* Compiler::gtNewHelperCallNode(unsigned helper, var_types type, GenTreeArgList* args)
11251137
{
1138+
unsigned flags = s_helperCallProperties.NoThrow((CorInfoHelpFunc)helper) ? 0 : GTF_EXCEPT;
11261139
GenTreeCall* result = gtNewCallNode(CT_HELPER, eeFindHelper(helper), type, args);
11271140
result->gtFlags |= flags;
11281141

@@ -1228,6 +1241,43 @@ inline GenTreePtr Compiler::gtNewIndexRef(var_types typ, GenTreePtr arrayOp, Gen
12281241
return gtIndx;
12291242
}
12301243

1244+
//------------------------------------------------------------------------------
1245+
// gtNewArrLen : Helper to create an array length node.
1246+
//
1247+
//
1248+
// Arguments:
1249+
// typ - Type of the node
1250+
// arrayOp - Array node
1251+
// lenOffset - Offset of the length field
1252+
//
1253+
// Return Value:
1254+
// New GT_ARR_LENGTH node
1255+
1256+
inline GenTreeArrLen* Compiler::gtNewArrLen(var_types typ, GenTree* arrayOp, int lenOffset)
1257+
{
1258+
GenTreeArrLen* arrLen = new (this, GT_ARR_LENGTH) GenTreeArrLen(typ, arrayOp, lenOffset);
1259+
static_assert_no_msg(GTF_ARRLEN_NONFAULTING == GTF_IND_NONFAULTING);
1260+
arrLen->SetIndirExceptionFlags(this);
1261+
return arrLen;
1262+
}
1263+
1264+
//------------------------------------------------------------------------------
1265+
// gtNewIndir : Helper to create an indirection node.
1266+
//
1267+
// Arguments:
1268+
// typ - Type of the node
1269+
// addr - Address of the indirection
1270+
//
1271+
// Return Value:
1272+
// New GT_IND node
1273+
1274+
inline GenTree* Compiler::gtNewIndir(var_types typ, GenTree* addr)
1275+
{
1276+
GenTree* indir = gtNewOperNode(GT_IND, typ, addr);
1277+
indir->SetIndirExceptionFlags(this);
1278+
return indir;
1279+
}
1280+
12311281
/*****************************************************************************
12321282
*
12331283
* Create (and check for) a "nothing" node, i.e. a node that doesn't produce
@@ -1512,8 +1562,13 @@ inline void GenTree::ChangeOper(genTreeOps oper, ValueNumberUpdate vnUpdate)
15121562
{
15131563
assert(!OperIsConst(oper)); // use ChangeOperLeaf() instead
15141564

1565+
unsigned mask = GTF_COMMON_MASK;
1566+
if (this->OperIsIndirOrArrLength() && OperIsIndirOrArrLength(oper))
1567+
{
1568+
mask |= GTF_IND_NONFAULTING;
1569+
}
15151570
SetOper(oper, vnUpdate);
1516-
gtFlags &= GTF_COMMON_MASK;
1571+
gtFlags &= mask;
15171572

15181573
// Do "oper"-specific initializations...
15191574
switch (oper)
@@ -1529,8 +1584,13 @@ inline void GenTree::ChangeOper(genTreeOps oper, ValueNumberUpdate vnUpdate)
15291584

15301585
inline void GenTree::ChangeOperUnchecked(genTreeOps oper)
15311586
{
1587+
unsigned mask = GTF_COMMON_MASK;
1588+
if (this->OperIsIndirOrArrLength() && OperIsIndirOrArrLength(oper))
1589+
{
1590+
mask |= GTF_IND_NONFAULTING;
1591+
}
15321592
SetOperRaw(oper); // Trust the caller and don't use SetOper()
1533-
gtFlags &= GTF_COMMON_MASK;
1593+
gtFlags &= mask;
15341594
}
15351595

15361596
/*****************************************************************************

src/jit/copyprop.cpp

+22-14
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,17 @@ int Compiler::optCopyProp_LclVarScore(LclVarDsc* lclVarDsc, LclVarDsc* copyVarDs
110110
return score + ((preferOp2) ? 1 : -1);
111111
}
112112

113-
/**************************************************************************************
114-
*
115-
* Perform copy propagation on a given tree as we walk the graph and if it is a local
116-
* variable, then look up all currently live definitions and check if any of those
117-
* definitions share the same value number. If so, then we can make the replacement.
118-
*
119-
*/
113+
//------------------------------------------------------------------------------
114+
// optCopyProp : Perform copy propagation on a given tree as we walk the graph and if it is a local
115+
// variable, then look up all currently live definitions and check if any of those
116+
// definitions share the same value number. If so, then we can make the replacement.
117+
//
118+
// Arguments:
119+
// block - Block the tree belongs to
120+
// stmt - Statement the tree belongs to
121+
// tree - The tree to perform copy propagation on
122+
// curSsaName - The map from lclNum to its recently live definitions as a stack
123+
120124
voidCompiler::optCopyProp(BasicBlock* block, GenTreePtr stmt, GenTreePtr tree, LclNumToGenTreePtrStack* curSsaName)
121125
{
122126
// TODO-Review: EH successor/predecessor iteration seems broken.
@@ -259,6 +263,7 @@ void Compiler::optCopyProp(BasicBlock* block, GenTreePtr stmt, GenTreePtr tree,
259263
lvaTable[newLclNum].incRefCnts(block->getBBWeight(this), this);
260264
tree->gtLclVarCommon.SetLclNum(newLclNum);
261265
tree->AsLclVarCommon()->SetSsaNum(newSsaNum);
266+
gtUpdateSideEffects(stmt, tree);
262267
#ifdef DEBUG
263268
if (verbose)
264269
{
@@ -280,13 +285,15 @@ bool Compiler::optIsSsaLocal(GenTreePtr tree)
280285
return tree->IsLocal() && !fgExcludeFromSsa(tree->AsLclVarCommon()->GetLclNum());
281286
}
282287

283-
/**************************************************************************************
284-
*
285-
* Perform copy propagation using currently live definitions on the current block's
286-
* variables. Also as new definitions are encountered update the "curSsaName" which
287-
* tracks the currently live definitions.
288-
*
289-
*/
288+
//------------------------------------------------------------------------------
289+
// optBlockCopyProp : Perform copy propagation using currently live definitions on the current block's
290+
// variables. Also as new definitions are encountered update the "curSsaName" which
291+
// tracks the currently live definitions.
292+
//
293+
// Arguments:
294+
// block - Block the tree belongs to
295+
// curSsaName - The map from lclNum to its recently live definitions as a stack
296+
290297
voidCompiler::optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName)
291298
{
292299
JITDUMP("Copy Assertion for BB%02u\n", block->bbNum);
@@ -302,6 +309,7 @@ void Compiler::optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curS
302309
for (GenTreePtr tree = stmt->gtStmt.gtStmtList; tree; tree = tree->gtNext)
303310
{
304311
compUpdateLife</*ForCodeGen*/false>(tree);
312+
305313
optCopyProp(block, stmt, tree, curSsaName);
306314

307315
// TODO-Review: Merge this loop with the following loop to correctly update the

src/jit/decomposelongs.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1429,7 +1429,7 @@ GenTree* DecomposeLongs::DecomposeShift(LIR::Use& use)
14291429

14301430
GenTreeArgList* argList = m_compiler->gtNewArgList(loOp1, hiOp1, shiftByOp);
14311431

1432-
GenTree* call = m_compiler->gtNewHelperCallNode(helper, TYP_LONG, 0, argList);
1432+
GenTree* call = m_compiler->gtNewHelperCallNode(helper, TYP_LONG, argList);
14331433
call->gtFlags |= shift->gtFlags & GTF_ALL_EFFECT;
14341434

14351435
if (shift->IsUnusedValue())

src/jit/earlyprop.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,12 @@ void Compiler::optEarlyProp()
196196
{
197197
if (optEarlyPropRewriteTree(tree))
198198
{
199+
gtUpdateSideEffects(stmt, tree);
199200
isRewritten = true;
200201
}
201202
}
202203

203-
// Morph the stmt and update the evaluation order if the stmt has been rewritten.
204+
// Update the evaluation order and the statement info if the stmt has been rewritten.
204205
if (isRewritten)
205206
{
206207
gtSetStmtInfo(stmt);
@@ -611,6 +612,7 @@ void Compiler::optFoldNullCheck(GenTreePtr tree)
611612

612613
// Set this flag to prevent reordering
613614
nullCheckTree->gtFlags |= GTF_ORDER_SIDEEFF;
615+
nullCheckTree->gtFlags |= GTF_IND_NONFAULTING;
614616

615617
defRHS->gtFlags &= ~(GTF_EXCEPT | GTF_DONT_CSE);
616618
defRHS->gtFlags |=

0 commit comments

Comments
 (0)
close