1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-10 18:11:04 +09:00

Clean up GT_NOP (#95353)

---------

Co-authored-by: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com>
This commit is contained in:
Egor Bogatov 2023-11-30 12:04:07 +01:00 committed by GitHub
parent ff6b26f047
commit 3805c174d0
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 85 additions and 103 deletions

View file

@ -1121,7 +1121,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1,
//
// Set op1 to the instance pointer of the indirection
//
op1 = op1->gtEffectiveVal(/* commaOnly */ true);
op1 = op1->gtEffectiveVal();
ssize_t offset = 0;
while ((op1->gtOper == GT_ADD) && (op1->gtType == TYP_BYREF))
@ -1129,12 +1129,12 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1,
if (op1->gtGetOp2()->IsCnsIntOrI())
{
offset += op1->gtGetOp2()->AsIntCon()->gtIconVal;
op1 = op1->gtGetOp1()->gtEffectiveVal(/* commaOnly */ true);
op1 = op1->gtGetOp1()->gtEffectiveVal();
}
else if (op1->gtGetOp1()->IsCnsIntOrI())
{
offset += op1->gtGetOp1()->AsIntCon()->gtIconVal;
op1 = op1->gtGetOp2()->gtEffectiveVal(/* commaOnly */ true);
op1 = op1->gtGetOp2()->gtEffectiveVal();
}
else
{
@ -4532,7 +4532,7 @@ bool Compiler::optAssertionIsNonNull(GenTree* op,
return true;
}
op = op->gtEffectiveVal(/* commaOnly */ true);
op = op->gtEffectiveVal();
if (!op->OperIs(GT_LCL_VAR))
{

View file

@ -1262,11 +1262,6 @@ AGAIN:
break;
#endif // !TARGET_ARMARCH && !TARGET_LOONGARCH64 && !TARGET_RISCV64
case GT_NOP:
op1 = op1->AsOp()->gtOp1;
goto AGAIN;
case GT_COMMA:
op1 = op1->AsOp()->gtOp2;
@ -1341,11 +1336,6 @@ AGAIN:
break;
#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64
case GT_NOP:
op2 = op2->AsOp()->gtOp1;
goto AGAIN;
case GT_COMMA:
op2 = op2->AsOp()->gtOp2;

View file

@ -11391,6 +11391,7 @@ public:
case GT_PINVOKE_PROLOG:
case GT_PINVOKE_EPILOG:
case GT_IL_OFFSET:
case GT_NOP:
break;
// Lclvar unary operators
@ -11431,7 +11432,6 @@ public:
case GT_PUTARG_REG:
case GT_PUTARG_STK:
case GT_RETURNTRAP:
case GT_NOP:
case GT_FIELD_ADDR:
case GT_RETURN:
case GT_RETFILT:

View file

@ -1242,7 +1242,7 @@ inline GenTree* Compiler::gtNewOperNode(genTreeOps oper, var_types type, GenTree
assert((GenTree::OperKind(oper) & (GTK_UNOP | GTK_BINOP)) != 0);
assert((GenTree::OperKind(oper) & GTK_EXOP) ==
0); // Can't use this to construct any types that extend unary/binary operator.
assert(op1 != nullptr || oper == GT_RETFILT || oper == GT_NOP || (oper == GT_RETURN && type == TYP_VOID));
assert(op1 != nullptr || oper == GT_RETFILT || (oper == GT_RETURN && type == TYP_VOID));
GenTree* node = new (this, oper) GenTreeOp(oper, type, op1, nullptr);
@ -1602,7 +1602,7 @@ inline GenTree* Compiler::gtNewNullCheck(GenTree* addr, BasicBlock* basicBlock)
inline GenTree* Compiler::gtNewNothingNode()
{
return new (this, GT_NOP) GenTreeOp(GT_NOP, TYP_VOID);
return new (this, GT_NOP) GenTree(GT_NOP, TYP_VOID);
}
/*****************************************************************************/
@ -1620,10 +1620,7 @@ inline bool GenTree::IsNothingNode() const
inline void GenTree::gtBashToNOP()
{
ChangeOper(GT_NOP);
gtType = TYP_VOID;
AsOp()->gtOp1 = AsOp()->gtOp2 = nullptr;
gtType = TYP_VOID;
gtFlags &= ~(GTF_ALL_EFFECT | GTF_REVERSE_OPS);
}
@ -4415,10 +4412,10 @@ void GenTree::VisitOperands(TVisitor visitor)
case GT_PINVOKE_PROLOG:
case GT_PINVOKE_EPILOG:
case GT_IL_OFFSET:
case GT_NOP:
return;
// Unary operators with an optional operand
case GT_NOP:
case GT_FIELD_ADDR:
case GT_RETURN:
case GT_RETFILT:

View file

@ -577,8 +577,7 @@ GenTree* Compiler::optFindNullCheckToFold(GenTree* tree, LocalNumberToNullCheckT
return nullptr;
}
const bool commaOnly = true;
GenTree* commaOp1EffectiveValue = defValue->gtGetOp1()->gtEffectiveVal(commaOnly);
GenTree* commaOp1EffectiveValue = defValue->gtGetOp1()->gtEffectiveVal();
if (commaOp1EffectiveValue->OperGet() != GT_NULLCHECK)
{

View file

@ -2567,19 +2567,20 @@ Compiler::fgWalkResult Compiler::fgStress64RsltMulCB(GenTree** pTree, fgWalkData
return WALK_CONTINUE;
}
JITDUMP("STRESS_64RSLT_MUL before:\n");
DISPTREE(tree);
JITDUMP("STRESS_64RSLT_MUL before:\n")
DISPTREE(tree)
// To ensure optNarrowTree() doesn't fold back to the original tree.
tree->AsOp()->gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->AsOp()->gtOp1, false, TYP_LONG);
tree->AsOp()->gtOp1 = pComp->gtNewOperNode(GT_NOP, TYP_LONG, tree->AsOp()->gtOp1);
tree->AsOp()->gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->AsOp()->gtOp1, false, TYP_LONG);
tree->AsOp()->gtOp2 = pComp->gtNewCastNode(TYP_LONG, tree->AsOp()->gtOp2, false, TYP_LONG);
tree->AsOp()->gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtGetOp1(), false, TYP_LONG);
tree->AsOp()->gtOp2 = pComp->gtNewCastNode(TYP_LONG, tree->gtGetOp2(), false, TYP_LONG);
tree->gtType = TYP_LONG;
*pTree = pComp->gtNewCastNode(TYP_INT, tree, false, TYP_INT);
JITDUMP("STRESS_64RSLT_MUL after:\n");
DISPTREE(*pTree);
// To ensure optNarrowTree() doesn't fold back to the original tree.
tree->gtGetOp1()->gtDebugFlags |= GTF_DEBUG_CAST_DONT_FOLD;
tree->gtGetOp2()->gtDebugFlags |= GTF_DEBUG_CAST_DONT_FOLD;
JITDUMP("STRESS_64RSLT_MUL after:\n")
DISPTREE(*pTree)
return WALK_SKIP_SUBTREES;
}
@ -3246,6 +3247,11 @@ void Compiler::fgDebugCheckTypes(GenTree* tree)
assert(!"TYP_ULONG and TYP_UINT are not legal in IR");
}
if (node->OperIs(GT_NOP))
{
assert(node->TypeIs(TYP_VOID) && "GT_NOP should be TYP_VOID.");
}
if (varTypeIsSmall(node))
{
if (node->OperIs(GT_COMMA))

View file

@ -259,7 +259,7 @@ public:
if (value->OperGet() == GT_COMMA)
{
GenTree* effectiveValue = value->gtEffectiveVal(/*commaOnly*/ true);
GenTree* effectiveValue = value->gtEffectiveVal();
noway_assert(
!varTypeIsStruct(effectiveValue) || (effectiveValue->OperGet() != GT_RET_EXPR) ||

View file

@ -2763,6 +2763,7 @@ AGAIN:
}
return true;
case GT_NOP:
case GT_LABEL:
return true;
@ -4512,7 +4513,7 @@ bool Compiler::gtCanSwapOrder(GenTree* firstNode, GenTree* secondNode)
bool Compiler::gtMarkAddrMode(GenTree* addr, int* pCostEx, int* pCostSz, var_types type)
{
GenTree* addrComma = addr;
addr = addr->gtEffectiveVal(/* commaOnly */ true);
addr = addr->gtEffectiveVal();
// These are "out" parameters on the call to genCreateAddrMode():
bool rev; // This will be true if the operands will need to be reversed. At this point we
@ -5334,6 +5335,12 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
costSz = 0;
break;
case GT_NOP:
level = 0;
costEx = 0;
costSz = 0;
break;
default:
level = 1;
costEx = 1;
@ -5449,11 +5456,6 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
break;
case GT_NOP:
costEx = 0;
costSz = 0;
break;
case GT_INTRINSIC:
intrinsic = tree->AsIntrinsic();
// named intrinsic
@ -6444,6 +6446,7 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse)
case GT_PINVOKE_PROLOG:
case GT_PINVOKE_EPILOG:
case GT_IL_OFFSET:
case GT_NOP:
return false;
// Standard unary operators
@ -6473,7 +6476,6 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse)
case GT_PUTARG_REG:
case GT_PUTARG_STK:
case GT_RETURNTRAP:
case GT_NOP:
case GT_RETURN:
case GT_RETFILT:
case GT_BSWAP:
@ -8641,8 +8643,8 @@ bool GenTreeOp::UsesDivideByConstOptimized(Compiler* comp)
#endif // TARGET_ARM64
bool isSignedDivide = OperIs(GT_DIV, GT_MOD);
GenTree* dividend = gtGetOp1()->gtEffectiveVal(/*commaOnly*/ true);
GenTree* divisor = gtGetOp2()->gtEffectiveVal(/*commaOnly*/ true);
GenTree* dividend = gtGetOp1()->gtEffectiveVal();
GenTree* divisor = gtGetOp2()->gtEffectiveVal();
#if !defined(TARGET_64BIT)
if (dividend->OperIs(GT_LONG))
@ -8764,7 +8766,7 @@ void GenTreeOp::CheckDivideByConstOptimized(Compiler* comp)
{
// Now set DONT_CSE on the GT_CNS_INT divisor, note that
// with ValueNumbering we can have a non GT_CNS_INT divisor
GenTree* divisor = gtGetOp2()->gtEffectiveVal(/*commaOnly*/ true);
GenTree* divisor = gtGetOp2()->gtEffectiveVal();
if (divisor->OperIs(GT_CNS_INT))
{
divisor->gtFlags |= GTF_DONT_CSE;
@ -9211,6 +9213,7 @@ GenTree* Compiler::gtCloneExpr(
case GT_CATCH_ARG:
case GT_NO_OP:
case GT_NOP:
case GT_LABEL:
copy = new (this, oper) GenTree(oper, tree->gtType);
goto DONE;
@ -10099,6 +10102,7 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node)
case GT_PINVOKE_PROLOG:
case GT_PINVOKE_EPILOG:
case GT_IL_OFFSET:
case GT_NOP:
m_state = -1;
return;
@ -10142,7 +10146,6 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node)
return;
// Unary operators with an optional operand
case GT_NOP:
case GT_FIELD_ADDR:
case GT_RETURN:
case GT_RETFILT:
@ -12126,6 +12129,7 @@ void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack)
// Vanilla leaves. No qualifying information available. So do nothing
case GT_NOP:
case GT_NO_OP:
case GT_START_NONGC:
case GT_START_PREEMPTGC:
@ -14012,12 +14016,6 @@ CORINFO_CLASS_HANDLE Compiler::gtGetHelperArgClassHandle(GenTree* tree)
{
CORINFO_CLASS_HANDLE result = NO_CLASS_HANDLE;
// Walk through any wrapping nop.
if ((tree->gtOper == GT_NOP) && (tree->gtType == TYP_I_IMPL))
{
tree = tree->AsOp()->gtOp1;
}
// The handle could be a literal constant
if ((tree->OperGet() == GT_CNS_INT) && (tree->TypeGet() == TYP_I_IMPL))
{
@ -18239,7 +18237,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b
}
// Tunnel through commas.
GenTree* obj = tree->gtEffectiveVal(false);
GenTree* obj = tree->gtEffectiveVal();
const genTreeOps objOp = obj->OperGet();
switch (objOp)

View file

@ -618,6 +618,7 @@ enum GenTreeDebugFlags : unsigned int
GTF_DEBUG_NODE_MASK = 0x0000003F, // These flags are all node (rather than operation) properties.
GTF_DEBUG_VAR_CSE_REF = 0x00800000, // GT_LCL_VAR -- This is a CSE LCL_VAR node
GTF_DEBUG_CAST_DONT_FOLD = 0x00400000, // GT_CAST -- Try to prevent this cast from being folded
};
inline constexpr GenTreeDebugFlags operator ~(GenTreeDebugFlags a)
@ -1723,7 +1724,6 @@ public:
{
case GT_LEA:
case GT_RETFILT:
case GT_NOP:
case GT_FIELD_ADDR:
return true;
case GT_RETURN:
@ -1816,7 +1816,7 @@ public:
void ReplaceOperand(GenTree** useEdge, GenTree* replacement);
inline GenTree* gtEffectiveVal(bool commaOnly = false);
inline GenTree* gtEffectiveVal();
inline GenTree* gtCommaStoreVal();
@ -2995,7 +2995,7 @@ struct GenTreeOp : public GenTreeUnOp
: GenTreeUnOp(oper, type DEBUGARG(largeNode)), gtOp2(nullptr)
{
// Unary operators with optional arguments:
assert(oper == GT_NOP || oper == GT_RETURN || oper == GT_RETFILT || OperIsBlk(oper));
assert(oper == GT_RETURN || oper == GT_RETFILT || OperIsBlk(oper));
}
// returns true if we will use the division by constant optimization for this node.
@ -9239,18 +9239,14 @@ inline GenTree*& GenTree::Data()
return OperIsLocalStore() ? AsLclVarCommon()->Data() : AsIndir()->Data();
}
inline GenTree* GenTree::gtEffectiveVal(bool commaOnly /* = false */)
inline GenTree* GenTree::gtEffectiveVal()
{
GenTree* effectiveVal = this;
while (true)
{
if (effectiveVal->gtOper == GT_COMMA)
if (effectiveVal->OperIs(GT_COMMA))
{
effectiveVal = effectiveVal->AsOp()->gtGetOp2();
}
else if (!commaOnly && (effectiveVal->gtOper == GT_NOP) && (effectiveVal->AsOp()->gtOp1 != nullptr))
{
effectiveVal = effectiveVal->AsOp()->gtOp1;
effectiveVal = effectiveVal->gtGetOp2();
}
else
{

View file

@ -53,7 +53,7 @@ GTNODE(CNS_VEC , GenTreeVecCon ,0,0,GTK_LEAF)
//-----------------------------------------------------------------------------
GTNODE(NOT , GenTreeOp ,0,0,GTK_UNOP)
GTNODE(NOP , GenTree ,0,0,GTK_UNOP|DBK_NOCONTAIN)
GTNODE(NOP , GenTree ,0,1,GTK_LEAF|DBK_NOCONTAIN)
GTNODE(NEG , GenTreeOp ,0,0,GTK_UNOP)
GTNODE(INTRINSIC , GenTreeIntrinsic ,0,0,GTK_BINOP|GTK_EXOP)

View file

@ -340,10 +340,6 @@ bool OptIfConversionDsc::IfConvertCheckStmts(BasicBlock* fromBlock, IfConvertOpe
// These do not need conditional execution.
case GT_NOP:
if (tree->gtGetOp1() != nullptr || (tree->gtFlags & (GTF_SIDE_EFFECT | GTF_ORDER_SIDEEFF)) != 0)
{
return false;
}
break;
// Cannot optimise this block.

View file

@ -6875,7 +6875,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
// See what we know about the type of 'this' in the call.
assert(call->gtArgs.HasThisPointer());
CallArg* thisArg = call->gtArgs.GetThisArg();
GenTree* thisObj = thisArg->GetEarlyNode()->gtEffectiveVal(false);
GenTree* thisObj = thisArg->GetEarlyNode()->gtEffectiveVal();
bool isExact = false;
bool objIsNonNull = false;
CORINFO_CLASS_HANDLE objClass = gtGetClassHandle(thisObj, &isExact, &objIsNonNull);

View file

@ -2351,7 +2351,7 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call
if (isStructArg)
{
GenTree* actualArg = argx->gtEffectiveVal(true /* Commas only */);
GenTree* actualArg = argx->gtEffectiveVal();
// Here we look at "actualArg" to avoid calling "getClassSize".
structSize = actualArg->TypeIs(TYP_STRUCT) ? actualArg->GetLayout(comp)->GetSize() : genTypeSize(actualArg);
@ -3188,7 +3188,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
}
bool isStructArg = varTypeIsStruct(arg.GetSignatureType());
GenTree* argObj = argx->gtEffectiveVal(true /*commaOnly*/);
GenTree* argObj = argx->gtEffectiveVal();
bool makeOutArgCopy = false;
if (isStructArg && !reMorphing && !argObj->OperIs(GT_MKREFANY))
@ -6384,10 +6384,10 @@ void Compiler::fgValidateIRForTailCall(GenTreeCall* call)
return WALK_ABORT;
}
// GT_NOP might appear due to stores that end up as
// self-stores, which get morphed to GT_NOP.
if (tree->OperIs(GT_NOP))
{
// GT_NOP might appear due to stores that end up as
// self-stores, which get morphed to GT_NOP.
}
// We might see arbitrary chains of stores that trivially
// propagate the result. Example:
@ -8225,7 +8225,7 @@ GenTreeOp* Compiler::fgMorphCommutative(GenTreeOp* tree)
// op1 can be GT_COMMA, in this case we're going to fold
// "(op (COMMA(... (op X C1))) C2)" to "(COMMA(... (op X C3)))"
GenTree* op1 = tree->gtGetOp1()->gtEffectiveVal(true);
GenTree* op1 = tree->gtGetOp1()->gtEffectiveVal();
genTreeOps oper = tree->OperGet();
if (!op1->OperIs(oper) || !tree->gtGetOp2()->IsCnsIntOrI() || !op1->gtGetOp2()->IsCnsIntOrI() ||
@ -9041,6 +9041,10 @@ DONE_MORPHING_CHILDREN:
{
return tree;
}
else if (tree->IsNothingNode())
{
return tree;
}
/* gtFoldExpr could have used setOper to change the oper */
oper = tree->OperGet();
@ -9775,7 +9779,7 @@ GenTree* Compiler::fgMorphFinalizeIndir(GenTreeIndir* indir)
if (varTypeIsFloating(indir))
{
// Check for a misaligned floating point indirection.
GenTree* effAddr = addr->gtEffectiveVal(true);
GenTree* effAddr = addr->gtEffectiveVal();
target_ssize_t offset;
gtPeelOffsets(&effAddr, &offset);
@ -13146,7 +13150,7 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block)
GenTree* condTree;
condTree = lastStmt->GetRootNode()->AsOp()->gtOp1;
GenTree* cond;
cond = condTree->gtEffectiveVal(true);
cond = condTree->gtEffectiveVal();
if (cond->OperIsConst())
{
@ -13370,7 +13374,7 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block)
noway_assert(lastStmt->GetRootNode()->AsOp()->gtOp1);
GenTree* condTree = lastStmt->GetRootNode()->AsOp()->gtOp1;
GenTree* cond = condTree->gtEffectiveVal(true);
GenTree* cond = condTree->gtEffectiveVal();
if (cond->OperIsConst())
{

View file

@ -3150,7 +3150,7 @@ public:
{
// This can only be the case for a struct in which the 'val' was a COMMA, so
// the assignment is sunk below it.
store = store->gtEffectiveVal(true);
store = store->gtEffectiveVal();
noway_assert(origStore->OperIs(GT_COMMA) && (origStore == val));
}
else

View file

@ -5909,6 +5909,13 @@ bool Compiler::optNarrowTree(GenTree* tree, var_types srct, var_types dstt, Valu
case GT_CAST:
{
#ifdef DEBUG
if ((tree->gtDebugFlags & GTF_DEBUG_CAST_DONT_FOLD) != 0)
{
return false;
}
#endif
if ((tree->CastToType() != srct) || tree->gtOverflow())
{
return false;
@ -8471,7 +8478,7 @@ bool Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk)
continue;
}
GenTree* addr = tree->AsIndir()->Addr()->gtEffectiveVal(/*commaOnly*/ true);
GenTree* addr = tree->AsIndir()->Addr()->gtEffectiveVal();
if (addr->TypeGet() == TYP_BYREF && addr->OperGet() == GT_LCL_VAR)
{

View file

@ -9401,6 +9401,7 @@ static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memo
GT_MDARR_LENGTH,
GT_MDARR_LOWER_BOUND, // 'dim' value must be considered
GT_BITCAST, // Needs to encode the target type.
GT_NOP,
// These control-flow operations need no values.
GT_JTRUE, GT_RETURN, GT_SWITCH, GT_RETFILT, GT_CKFINITE};
@ -11165,6 +11166,7 @@ void Compiler::fgValueNumberTree(GenTree* tree)
// These do not represent values.
case GT_NO_OP:
case GT_NOP:
case GT_JMP: // Control flow
case GT_LABEL: // Control flow
#if !defined(FEATURE_EH_FUNCLETS)
@ -11367,34 +11369,21 @@ void Compiler::fgValueNumberTree(GenTree* tree)
{
if (GenTree::OperIsUnary(oper))
{
if (tree->AsOp()->gtOp1 != nullptr)
{
ValueNumPair op1VNP;
ValueNumPair op1VNPx;
vnStore->VNPUnpackExc(tree->AsOp()->gtOp1->gtVNPair, &op1VNP, &op1VNPx);
assert(tree->gtGetOp1() != nullptr);
ValueNumPair op1VNP;
ValueNumPair op1VNPx;
vnStore->VNPUnpackExc(tree->AsOp()->gtOp1->gtVNPair, &op1VNP, &op1VNPx);
// If we are fetching the array length for an array ref that came from global memory
// then for CSE safety we must use the conservative value number for both
//
if (tree->OperIsArrLength() && ((tree->AsOp()->gtOp1->gtFlags & GTF_GLOB_REF) != 0))
{
// use the conservative value number for both when computing the VN for the ARR_LENGTH
op1VNP.SetBoth(op1VNP.GetConservative());
}
tree->gtVNPair =
vnStore->VNPWithExc(vnStore->VNPairForFunc(tree->TypeGet(), vnf, op1VNP), op1VNPx);
}
else // Is actually nullary.
// If we are fetching the array length for an array ref that came from global memory
// then for CSE safety we must use the conservative value number for both
//
if (tree->OperIsArrLength() && ((tree->AsOp()->gtOp1->gtFlags & GTF_GLOB_REF) != 0))
{
// Mostly we'll leave these without a value number, assuming we'll detect these as VN failures
// if they actually need to have values. With the exception of NOPs, which can sometimes have
// meaning.
if (tree->OperGet() == GT_NOP)
{
tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
}
// use the conservative value number for both when computing the VN for the ARR_LENGTH
op1VNP.SetBoth(op1VNP.GetConservative());
}
tree->gtVNPair = vnStore->VNPWithExc(vnStore->VNPairForFunc(tree->TypeGet(), vnf, op1VNP), op1VNPx);
}
else // we have a binary oper
{