}
}
-/*****************************************************************************
- *
- * A DEBUG routine to check the that the exception flags are correctly set.
- *
- ****************************************************************************/
-
+//------------------------------------------------------------------------
+// fgDebugCheckFlags: Validate various invariants related to the propagation
+// and setting of tree flags ("gtFlags").
+//
+// Arguments:
+// tree - the tree to (recursively) check the flags for
+//
void Compiler::fgDebugCheckFlags(GenTree* tree)
{
- const genTreeOps oper = tree->OperGet();
- const unsigned kind = tree->OperKind();
- GenTreeFlags treeFlags = tree->gtFlags & GTF_ALL_EFFECT;
- GenTreeFlags chkFlags = GTF_EMPTY;
+ GenTreeFlags actualFlags = tree->gtFlags & GTF_ALL_EFFECT;
+ GenTreeFlags expectedFlags = GTF_EMPTY;
if (tree->OperMayThrow(this))
{
- chkFlags |= GTF_EXCEPT;
+ expectedFlags |= GTF_EXCEPT;
}
if (tree->OperRequiresAsgFlag())
{
- chkFlags |= GTF_ASG;
+ expectedFlags |= GTF_ASG;
}
if (tree->OperRequiresCallFlag(this))
{
- chkFlags |= GTF_CALL;
+ expectedFlags |= GTF_CALL;
}
- /* Is this a leaf node? */
-
- if (kind & GTK_LEAF)
+ // We reuse GTF_REVERSE_OPS as GTF_VAR_ARR_INDEX for LCL_VAR nodes.
+ if (((tree->gtFlags & GTF_REVERSE_OPS) != 0) && !tree->OperIs(GT_LCL_VAR))
{
- switch (oper)
- {
- case GT_CLS_VAR:
- chkFlags |= GTF_GLOB_REF;
- break;
-
- case GT_CATCH_ARG:
- chkFlags |= GTF_ORDER_SIDEEFF;
- break;
-
- case GT_MEMORYBARRIER:
- chkFlags |= GTF_GLOB_REF | GTF_ASG;
- break;
-
- case GT_LCL_VAR:
- assert((tree->gtFlags & GTF_VAR_FOLDED_IND) == 0);
- break;
-
- default:
- break;
- }
+ assert(tree->OperSupportsReverseOps());
}
- /* Is it a 'simple' unary/binary operator? */
+ GenTree* op1 = tree->OperIsSimple() ? tree->gtGetOp1() : nullptr;
- else if (kind & GTK_SMPOP)
+ switch (tree->OperGet())
{
- GenTree* op1 = tree->AsOp()->gtOp1;
- GenTree* op2 = tree->gtGetOp2IfPresent();
+ case GT_CLS_VAR:
+ expectedFlags |= GTF_GLOB_REF;
+ break;
- // During GS work, we make shadow copies for params.
- // In gsParamsToShadows(), we create a shadow var of TYP_INT for every small type param.
- // Then in gsReplaceShadowParams(), we change the gtLclNum to the shadow var.
- // We also change the types of the local var tree and the assignment tree to TYP_INT if necessary.
- // However, since we don't morph the tree at this late stage. Manually propagating
- // TYP_INT up to the GT_ASG tree is only correct if we don't need to propagate the TYP_INT back up.
- // The following checks will ensure this.
+ case GT_CATCH_ARG:
+ expectedFlags |= GTF_ORDER_SIDEEFF;
+ break;
- // Is the left child of "tree" a GT_ASG?
- //
- // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
- // (or) If GT_ASG is the left child of a GT_COMMA, the type of the GT_COMMA node will
- // be determined by its right child. So we don't need to propagate TYP_INT up either. We are fine.
- if (op1 && op1->gtOper == GT_ASG)
- {
- assert(tree->gtType == TYP_VOID || tree->gtOper == GT_COMMA);
- }
+ case GT_MEMORYBARRIER:
+ expectedFlags |= (GTF_GLOB_REF | GTF_ASG);
+ break;
- // Is the right child of "tree" a GT_ASG?
- //
- // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
- if (op2 && op2->gtOper == GT_ASG)
- {
- // We can have ASGs on the RHS of COMMAs in setup arguments to a call.
- assert(tree->gtType == TYP_VOID || tree->gtOper == GT_COMMA);
- }
+ case GT_LCL_VAR:
+ assert((tree->gtFlags & GTF_VAR_FOLDED_IND) == 0);
+ break;
- switch (oper)
- {
- case GT_QMARK:
- if (op1->OperIsCompare())
+ case GT_QMARK:
+ assert(!op1->CanCSE());
+ assert(op1->OperIsCompare() || op1->IsIntegralConst(0) || op1->IsIntegralConst(1));
+ break;
+
+ case GT_ASG:
+ case GT_ADDR:
+ // Note that this is a weak check - the "op1" location node can be a COMMA.
+ assert(!op1->CanCSE());
+ break;
+
+ case GT_IND:
+ // Do we have a constant integer address as op1 that is also a handle?
+ if (op1->IsCnsIntOrI() && op1->IsIconHandle())
+ {
+ if ((tree->gtFlags & GTF_IND_INVARIANT) != 0)
{
- noway_assert(op1->gtFlags & GTF_DONT_CSE);
+ actualFlags |= GTF_IND_INVARIANT;
}
- else
+ if ((tree->gtFlags & GTF_IND_NONFAULTING) != 0)
{
- noway_assert((op1->gtOper == GT_CNS_INT) &&
- ((op1->AsIntCon()->gtIconVal == 0) || (op1->AsIntCon()->gtIconVal == 1)));
+ actualFlags |= GTF_IND_NONFAULTING;
}
- break;
- case GT_ADDR:
- assert(!op1->CanCSE());
- break;
+ GenTreeFlags handleKind = op1->GetIconHandleFlag();
- case GT_IND:
- // Do we have a constant integer address as op1?
- //
- if (op1->OperGet() == GT_CNS_INT)
+ // Some of these aren't handles to invariant data...
+ if ((handleKind == GTF_ICON_STATIC_HDL) || // Pointer to a mutable class Static variable
+ (handleKind == GTF_ICON_BBC_PTR) || // Pointer to a mutable basic block count value
+ (handleKind == GTF_ICON_GLOBAL_PTR)) // Pointer to mutable data from the VM state
{
- // Is this constant a handle of some kind?
- //
- GenTreeFlags handleKind = (op1->gtFlags & GTF_ICON_HDL_MASK);
- if (handleKind != 0)
- {
- // Is the GTF_IND_INVARIANT flag set or unset?
- //
- bool invariantFlag = (tree->gtFlags & GTF_IND_INVARIANT) != 0;
- if (invariantFlag)
- {
- // Record the state of the GTF_IND_INVARIANT flags into 'chkFlags'
- chkFlags |= GTF_IND_INVARIANT;
- }
-
- // Is the GTF_IND_NONFAULTING flag set or unset?
- //
- bool nonFaultingFlag = (tree->gtFlags & GTF_IND_NONFAULTING) != 0;
- if (nonFaultingFlag)
- {
- // Record the state of the GTF_IND_NONFAULTING flags into 'chkFlags'
- chkFlags |= GTF_IND_NONFAULTING;
- }
- assert(nonFaultingFlag); // Currently this should always be set for all handle kinds
-
- // Some of these aren't handles to invariant data...
- //
- if ((handleKind == GTF_ICON_STATIC_HDL) || // Pointer to a mutable class Static variable
- (handleKind == GTF_ICON_BBC_PTR) || // Pointer to a mutable basic block count value
- (handleKind == GTF_ICON_GLOBAL_PTR)) // Pointer to mutable data from the VM state
-
- {
- // We expect the Invariant flag to be unset for this handleKind
- // If it is set then we will assert with "unexpected GTF_IND_INVARIANT flag set ...
- //
- if (handleKind == GTF_ICON_STATIC_HDL)
- {
- // We expect the GTF_GLOB_REF flag to be set for this handleKind
- // If it is not set then we will assert with "Missing flags on tree"
- //
- treeFlags |= GTF_GLOB_REF;
- }
- }
- else // All the other handle indirections are considered invariant
- {
- // We expect the Invariant flag to be set for this handleKind
- // If it is not set then we will assert with "Missing flags on tree"
- //
- treeFlags |= GTF_IND_INVARIANT;
- }
-
- // We currently expect all handle kinds to be nonFaulting
- //
- treeFlags |= GTF_IND_NONFAULTING;
-
- // Matrix for GTF_IND_INVARIANT (treeFlags and chkFlags)
- //
- // chkFlags INVARIANT value
- // 0 1
- // +--------------+----------------+
- // treeFlags 0 | OK | Missing Flag |
- // INVARIANT +--------------+----------------+
- // value: 1 | Extra Flag | OK |
- // +--------------+----------------+
- }
+ // For statics, we expect the GTF_GLOB_REF to be set. However, we currently
+ // fail to set it in a number of situations, and so this check is disabled.
+ // TODO: enable checking of GTF_GLOB_REF.
+ // expectedFlags |= GTF_GLOB_REF;
+ }
+ else // All the other handle indirections are considered invariant
+ {
+ expectedFlags |= GTF_IND_INVARIANT;
}
- break;
- case GT_ASG:
- {
- // Can't CSE dst.
- assert((tree->gtGetOp1()->gtFlags & GTF_DONT_CSE) != 0);
- break;
+ // Currently we expect all indirections with constant addresses to be nonfaulting.
+ expectedFlags |= GTF_IND_NONFAULTING;
}
- default:
- break;
- }
-
- /* Recursively check the subtrees */
-
- if (op1)
- {
- fgDebugCheckFlags(op1);
- }
- if (op2)
- {
- fgDebugCheckFlags(op2);
- }
-
- if (op1)
- {
- chkFlags |= (op1->gtFlags & GTF_ALL_EFFECT);
- }
- if (op2)
- {
- chkFlags |= (op2->gtFlags & GTF_ALL_EFFECT);
- }
+ break;
- // We reuse the value of GTF_REVERSE_OPS for a GT_IND-specific flag,
- // so exempt that (unary) operator.
- if (tree->OperGet() != GT_IND && tree->gtFlags & GTF_REVERSE_OPS)
- {
- /* Must have two operands if GTF_REVERSE is set */
- noway_assert(op1 && op2);
+ case GT_CALL:
- /* Make sure that the order of side effects has not been swapped. */
+ GenTreeCall* call;
- /* However CSE may introduce an assignment after the reverse flag
- was set and thus GTF_ASG cannot be considered here. */
+ call = tree->AsCall();
- /* For a GT_ASG(GT_IND(x), y) we are interested in the side effects of x */
- GenTree* op1p;
- if ((oper == GT_ASG) && (op1->gtOper == GT_IND))
- {
- op1p = op1->AsOp()->gtOp1;
- }
- else
+ if ((call->gtCallThisArg != nullptr) && ((call->gtCallThisArg->GetNode()->gtFlags & GTF_ASG) != 0))
{
- op1p = op1;
+ // TODO-Cleanup: this is a patch for a violation in our GT_ASG propagation.
+ // see https://github.com/dotnet/runtime/issues/13758
+ actualFlags |= GTF_ASG;
}
- /* This isn't true any more with the sticky GTF_REVERSE */
- /*
- // if op1p has side effects, then op2 cannot have side effects
- if (op1p->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
+ for (GenTreeCall::Use& use : call->Args())
{
- if (op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
- gtDispTree(tree);
- noway_assert(!(op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG)));
- }
- */
- }
-
- if (oper == GT_ADDR && (op1->OperIsLocal() || op1->gtOper == GT_CLS_VAR ||
- (op1->gtOper == GT_IND && op1->AsOp()->gtOp1->gtOper == GT_CLS_VAR_ADDR)))
- {
- /* &aliasedVar doesn't need GTF_GLOB_REF, though alisasedVar does.
- Similarly for clsVar */
- treeFlags |= GTF_GLOB_REF;
- }
- }
-
- /* See what kind of a special operator we have here */
-
- else
- {
- switch (tree->OperGet())
- {
- case GT_CALL:
-
- GenTreeCall* call;
-
- call = tree->AsCall();
-
- if (call->gtCallThisArg != nullptr)
- {
- fgDebugCheckFlags(call->gtCallThisArg->GetNode());
- chkFlags |= (call->gtCallThisArg->GetNode()->gtFlags & GTF_SIDE_EFFECT);
-
- if ((call->gtCallThisArg->GetNode()->gtFlags & GTF_ASG) != 0)
- {
- // TODO-Cleanup: this is a patch for a violation in our GT_ASG propagation
- // see https://github.com/dotnet/runtime/issues/13758
- treeFlags |= GTF_ASG;
- }
- }
-
- for (GenTreeCall::Use& use : call->Args())
- {
- fgDebugCheckFlags(use.GetNode());
-
- chkFlags |= (use.GetNode()->gtFlags & GTF_SIDE_EFFECT);
-
- if ((use.GetNode()->gtFlags & GTF_ASG) != 0)
- {
- // TODO-Cleanup: this is a patch for a violation in our GT_ASG propagation
- // see https://github.com/dotnet/runtime/issues/13758
- treeFlags |= GTF_ASG;
- }
- }
-
- for (GenTreeCall::Use& use : call->LateArgs())
+ if ((use.GetNode()->gtFlags & GTF_ASG) != 0)
{
- fgDebugCheckFlags(use.GetNode());
-
- chkFlags |= (use.GetNode()->gtFlags & GTF_SIDE_EFFECT);
-
- if ((use.GetNode()->gtFlags & GTF_ASG) != 0)
- {
- treeFlags |= GTF_ASG;
- }
- }
-
- if ((call->gtCallType == CT_INDIRECT) && (call->gtCallCookie != nullptr))
- {
- fgDebugCheckFlags(call->gtCallCookie);
- chkFlags |= (call->gtCallCookie->gtFlags & GTF_SIDE_EFFECT);
- }
-
- if (call->gtCallType == CT_INDIRECT)
- {
- fgDebugCheckFlags(call->gtCallAddr);
- chkFlags |= (call->gtCallAddr->gtFlags & GTF_SIDE_EFFECT);
- }
-
- if ((call->gtControlExpr != nullptr) && call->IsExpandedEarly() && call->IsVirtualVtable())
- {
- fgDebugCheckFlags(call->gtControlExpr);
- chkFlags |= (call->gtControlExpr->gtFlags & GTF_SIDE_EFFECT);
+ // TODO-Cleanup: this is a patch for a violation in our GT_ASG propagation.
+ // see https://github.com/dotnet/runtime/issues/13758
+ actualFlags |= GTF_ASG;
}
+ }
- if (call->IsUnmanaged() && (call->gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL))
- {
- if (call->gtCallArgs->GetNode()->OperGet() == GT_NOP)
- {
- noway_assert(call->gtCallLateArgs->GetNode()->TypeGet() == TYP_I_IMPL ||
- call->gtCallLateArgs->GetNode()->TypeGet() == TYP_BYREF);
- }
- else
- {
- noway_assert(call->gtCallArgs->GetNode()->TypeGet() == TYP_I_IMPL ||
- call->gtCallArgs->GetNode()->TypeGet() == TYP_BYREF);
- }
- }
- break;
-
-#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
-#if defined(FEATURE_SIMD)
- case GT_SIMD:
-#endif
-#if defined(FEATURE_HW_INTRINSICS)
- case GT_HWINTRINSIC:
-#endif
- // TODO-List-Cleanup: consider using the general Operands() iterator
- // here for the "special" nodes to reduce code duplication.
- for (GenTree* operand : tree->AsMultiOp()->Operands())
+ for (GenTreeCall::Use& use : call->LateArgs())
+ {
+ if ((use.GetNode()->gtFlags & GTF_ASG) != 0)
{
- fgDebugCheckFlags(operand);
- chkFlags |= (operand->gtFlags & GTF_ALL_EFFECT);
+ // TODO-Cleanup: this is a patch for a violation in our GT_ASG propagation.
+ // see https://github.com/dotnet/runtime/issues/13758
+ actualFlags |= GTF_ASG;
}
- break;
-#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
-
- case GT_ARR_ELEM:
-
- GenTree* arrObj;
- unsigned dim;
-
- arrObj = tree->AsArrElem()->gtArrObj;
- fgDebugCheckFlags(arrObj);
- chkFlags |= (arrObj->gtFlags & GTF_ALL_EFFECT);
+ }
- for (dim = 0; dim < tree->AsArrElem()->gtArrRank; dim++)
+ if (call->IsUnmanaged() && ((call->gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL) != 0))
+ {
+ if (call->gtCallArgs->GetNode()->OperGet() == GT_NOP)
{
- fgDebugCheckFlags(tree->AsArrElem()->gtArrInds[dim]);
- chkFlags |= tree->AsArrElem()->gtArrInds[dim]->gtFlags & GTF_ALL_EFFECT;
+ assert(call->gtCallLateArgs->GetNode()->TypeIs(TYP_I_IMPL, TYP_BYREF));
}
- break;
-
- case GT_ARR_OFFSET:
-
- fgDebugCheckFlags(tree->AsArrOffs()->gtOffset);
- chkFlags |= (tree->AsArrOffs()->gtOffset->gtFlags & GTF_ALL_EFFECT);
- fgDebugCheckFlags(tree->AsArrOffs()->gtIndex);
- chkFlags |= (tree->AsArrOffs()->gtIndex->gtFlags & GTF_ALL_EFFECT);
- fgDebugCheckFlags(tree->AsArrOffs()->gtArrObj);
- chkFlags |= (tree->AsArrOffs()->gtArrObj->gtFlags & GTF_ALL_EFFECT);
- break;
-
- case GT_PHI:
- for (GenTreePhi::Use& use : tree->AsPhi()->Uses())
+ else
{
- fgDebugCheckFlags(use.GetNode());
- chkFlags |= (use.GetNode()->gtFlags & GTF_ALL_EFFECT);
+ assert(call->gtCallArgs->GetNode()->TypeIs(TYP_I_IMPL, TYP_BYREF));
}
- break;
+ }
+ break;
- case GT_FIELD_LIST:
- for (GenTreeFieldList::Use& use : tree->AsFieldList()->Uses())
- {
- fgDebugCheckFlags(use.GetNode());
- chkFlags |= (use.GetNode()->gtFlags & GTF_ALL_EFFECT);
- }
- break;
+ case GT_CMPXCHG:
+ expectedFlags |= (GTF_GLOB_REF | GTF_ASG);
+ break;
- case GT_CMPXCHG:
-
- chkFlags |= (GTF_GLOB_REF | GTF_ASG);
- GenTreeCmpXchg* cmpXchg;
- cmpXchg = tree->AsCmpXchg();
- fgDebugCheckFlags(cmpXchg->gtOpLocation);
- chkFlags |= (cmpXchg->gtOpLocation->gtFlags & GTF_ALL_EFFECT);
- fgDebugCheckFlags(cmpXchg->gtOpValue);
- chkFlags |= (cmpXchg->gtOpValue->gtFlags & GTF_ALL_EFFECT);
- fgDebugCheckFlags(cmpXchg->gtOpComparand);
- chkFlags |= (cmpXchg->gtOpComparand->gtFlags & GTF_ALL_EFFECT);
- break;
+ default:
+ break;
+ }
- case GT_STORE_DYN_BLK:
- case GT_DYN_BLK:
+ tree->VisitOperands([&](GenTree* operand) -> GenTree::VisitResult {
- GenTreeDynBlk* dynBlk;
- dynBlk = tree->AsDynBlk();
- fgDebugCheckFlags(dynBlk->gtDynamicSize);
- chkFlags |= (dynBlk->gtDynamicSize->gtFlags & GTF_ALL_EFFECT);
- fgDebugCheckFlags(dynBlk->Addr());
- chkFlags |= (dynBlk->Addr()->gtFlags & GTF_ALL_EFFECT);
- if (tree->OperGet() == GT_STORE_DYN_BLK)
- {
- fgDebugCheckFlags(dynBlk->Data());
- chkFlags |= (dynBlk->Data()->gtFlags & GTF_ALL_EFFECT);
- }
- break;
+ // ASGs are nodes that produce no value, but have a type (essentially, the type of the location).
+ // Validate that nodes that parent ASGs do not consume values. This check also ensures that code
+ // which updates location types ("gsParamsToShadows" replaces small LCL_VARs with TYP_INT ones)
+ // does not have to worry about propagating the new type "up the tree".
+ //
+ // Uncoditionally allowing COMMA here weakens the assert, but is necessary because the compiler
+ // ("gtExtractSideEffList") can create "typed" "comma lists" with ASGs as second operands.
+ //
+ if (operand->OperIs(GT_ASG))
+ {
+ assert(tree->IsCall() || tree->OperIs(GT_COMMA));
+ }
- default:
+ fgDebugCheckFlags(operand);
+ expectedFlags |= (operand->gtFlags & GTF_ALL_EFFECT);
-#ifdef DEBUG
- gtDispTree(tree);
-#endif
+ return GenTree::VisitResult::Continue;
+ });
- assert(!"Unknown operator for fgDebugCheckFlags");
- break;
- }
+ // ADDR nodes break the "parent flags >= operands flags" invariant for GTF_GLOB_REF.
+ if (tree->OperIs(GT_ADDR) && op1->OperIs(GT_LCL_VAR, GT_LCL_FLD, GT_CLS_VAR))
+ {
+ expectedFlags &= ~GTF_GLOB_REF;
}
- fgDebugCheckFlagsHelper(tree, treeFlags, chkFlags);
+ fgDebugCheckFlagsHelper(tree, actualFlags, expectedFlags);
}
//------------------------------------------------------------------------------
// fgDebugCheckFlagsHelper : Check if all bits that are set in chkFlags are also set in treeFlags.
//
// Arguments:
-// tree - Tree whose flags are being checked
-// treeFlags - Actual flags on the tree
-// chkFlags - Expected flags
-//
-// Note:
-// Checking that all bits that are set in treeFlags are also set in chkFlags is currently disabled.
+// tree - Tree whose flags are being checked
+// actualFlags - Actual flags on the tree
+// expectedFlags - Expected flags
//
-void Compiler::fgDebugCheckFlagsHelper(GenTree* tree, GenTreeFlags treeFlags, GenTreeFlags chkFlags)
+void Compiler::fgDebugCheckFlagsHelper(GenTree* tree, GenTreeFlags actualFlags, GenTreeFlags expectedFlags)
{
- if (chkFlags & ~treeFlags)
+ if (expectedFlags & ~actualFlags)
{
// Print the tree so we can see it in the log.
printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
- Compiler::fgDebugCheckDispFlags(tree, chkFlags & ~treeFlags, GTF_DEBUG_NONE);
+ Compiler::fgDebugCheckDispFlags(tree, expectedFlags & ~actualFlags, GTF_DEBUG_NONE);
printf("\n");
gtDispTree(tree);
// Print the tree again so we can see it right after we hook up the debugger.
printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
- Compiler::fgDebugCheckDispFlags(tree, chkFlags & ~treeFlags, GTF_DEBUG_NONE);
+ Compiler::fgDebugCheckDispFlags(tree, expectedFlags & ~actualFlags, GTF_DEBUG_NONE);
printf("\n");
gtDispTree(tree);
}
- else if (treeFlags & ~chkFlags)
+ else if (actualFlags & ~expectedFlags)
{
// We can't/don't consider these flags (GTF_GLOB_REF or GTF_ORDER_SIDEEFF) as being "extra" flags
//
GenTreeFlags flagsToCheck = ~GTF_GLOB_REF & ~GTF_ORDER_SIDEEFF;
- if ((treeFlags & ~chkFlags & flagsToCheck) != 0)
+ if ((actualFlags & ~expectedFlags & flagsToCheck) != 0)
{
// Print the tree so we can see it in the log.
printf("Extra flags on tree [%06d]: ", dspTreeID(tree));
- Compiler::fgDebugCheckDispFlags(tree, treeFlags & ~chkFlags, GTF_DEBUG_NONE);
+ Compiler::fgDebugCheckDispFlags(tree, actualFlags & ~expectedFlags, GTF_DEBUG_NONE);
printf("\n");
gtDispTree(tree);
// Print the tree again so we can see it right after we hook up the debugger.
printf("Extra flags on tree [%06d]: ", dspTreeID(tree));
- Compiler::fgDebugCheckDispFlags(tree, treeFlags & ~chkFlags, GTF_DEBUG_NONE);
+ Compiler::fgDebugCheckDispFlags(tree, actualFlags & ~expectedFlags, GTF_DEBUG_NONE);
printf("\n");
gtDispTree(tree);
}