if (tree->gtOp.gtOp1)
regMask |= genRestoreAddrMode(addr, tree->gtOp.gtOp1, lockPhase);
- if (tree->gtGetOp2())
+ if (tree->gtGetOp2IfPresent())
regMask |= genRestoreAddrMode(addr, tree->gtOp.gtOp2, lockPhase);
}
else if (tree->gtOper == GT_ARR_ELEM)
noway_assert(kind & GTK_SMPOP);
- if (tree->gtGetOp2())
+ if (tree->gtGetOp2IfPresent())
{
genEvalSideEffects(tree->gtOp.gtOp1);
const genTreeOps oper = tree->OperGet();
const var_types treeType = tree->TypeGet();
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
regNumber reg = DUMMY_INIT(REG_CORRUPT);
regMaskTP regs = regSet.rsMaskUsed;
regMaskTP needReg = destReg;
int helper;
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
switch (oper)
{
assert(to->gtOp.gtOp1 == nullptr);
}
- if (from->gtGetOp2() != nullptr)
+ if (from->gtGetOp2IfPresent() != nullptr)
{
- assert(to->gtGetOp2() != nullptr);
+ assert(to->gtGetOp2IfPresent() != nullptr);
CopyTestDataToCloneTree(from->gtGetOp2(), to->gtGetOp2());
}
else
{
- assert(to->gtGetOp2() == nullptr);
+ assert(to->gtGetOp2IfPresent() == nullptr);
}
return;
if (kind & GTK_SMPOP)
{
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
// Special handling for GT_LIST
if (tree->OperGet() == GT_LIST)
else if (kind & GTK_SMPOP)
{
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
// During GS work, we make shadow copies for params.
// In gsParamsToShadows(), we create a shadow var of TYP_INT for every small type param.
if (kind & GTK_SMPOP)
{
- if (tree->gtGetOp2())
+ if (tree->gtGetOp2IfPresent())
{
if (tree->gtOp.gtOp1 != nullptr)
{
}
}
- if (tree->gtGetOp2())
+ if (tree->gtGetOp2IfPresent())
{
result = fgWalkTreeRec<doPreOrder, doPostOrder>(&tree->gtOp.gtOp2, fgWalkData);
if (result == WALK_ABORT)
if (kind & GTK_SMPOP)
{
- if (tree->gtGetOp2())
+ if (tree->gtGetOp2IfPresent())
{
if (gtHasRef(tree->gtOp.gtOp1, lclNum, defOnly))
{
}
}
- if (tree->gtGetOp2())
+ if (tree->gtGetOp2IfPresent())
{
/* It's a binary operator */
if (!lvaLclVarRefsAccum(tree->gtOp.gtOp1, findPtr, refsPtr, &allVars, &trkdVars))
unsigned lvl2; // scratch variable
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
costEx = 0;
costSz = 0;
if (kind & GTK_SMPOP)
{
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
/* Check for some special cases */
case GT_SIMD:
{
GenTreeSIMD* simdOp = tree->AsSIMD();
- copy = gtNewSIMDNode(simdOp->TypeGet(), simdOp->gtGetOp1(), simdOp->gtGetOp2(),
+ copy = gtNewSIMDNode(simdOp->TypeGet(), simdOp->gtGetOp1(), simdOp->gtGetOp2IfPresent(),
simdOp->gtSIMDIntrinsicID, simdOp->gtSIMDBaseType, simdOp->gtSIMDSize);
}
break;
}
}
- if (tree->gtGetOp2())
+ if (tree->gtGetOp2IfPresent())
{
copy->gtOp.gtOp2 = gtCloneExpr(tree->gtOp.gtOp2, addFlags, deepVarNum, deepVarVal);
}
{
copy->gtFlags |= (copy->gtOp.gtOp1->gtFlags & GTF_ALL_EFFECT);
}
- if (copy->gtGetOp2() != nullptr)
+ if (copy->gtGetOp2IfPresent() != nullptr)
{
copy->gtFlags |= (copy->gtGetOp2()->gtFlags & GTF_ALL_EFFECT);
}
{
if (!topOnly)
{
- if (tree->gtGetOp2())
+ if (tree->gtGetOp2IfPresent())
{
// Label the childMsgs of the GT_COLON operator
// op2 is the then part
assert(kind & (GTK_UNOP | GTK_BINOP));
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
if (!opts.OptEnabled(CLFLG_CONSTANTFOLD))
{
if (kind & GTK_SMPOP)
{
GenTreePtr op1 = expr->gtOp.gtOp1;
- GenTreePtr op2 = expr->gtGetOp2();
+ GenTreePtr op2 = expr->gtGetOp2IfPresent();
if (flags & GTF_EXCEPT)
{
inline GenTreePtr gtGetOp1();
+ // Directly return op2. Asserts the node is binary. Might return nullptr if the binary node allows
+ // a nullptr op2, such as GT_LIST. This is more efficient than gtGetOp2IfPresent() if you know what
+ // node type you have.
inline GenTreePtr gtGetOp2();
+ // The returned pointer might be nullptr if the node is not binary, or if non-null op2 is not required.
+ inline GenTreePtr gtGetOp2IfPresent();
+
// Given a tree node, if this is a child of that node, return the pointer to the child node so that it
// can be modified; otherwise, return null.
GenTreePtr* gtGetChildPointer(GenTreePtr parent);
if ((gtOper == GT_SIMD) && (gtSIMD.gtSIMDIntrinsicID == SIMDIntrinsicInit) && gtGetOp1()->IsIntegralConst(constVal))
{
assert(varTypeIsIntegral(gtSIMD.gtSIMDBaseType));
- assert(gtGetOp2() == nullptr);
+ assert(gtGetOp2IfPresent() == nullptr);
return true;
}
#endif
inline GenTreePtr GenTree::gtGetOp2()
{
+ assert(OperIsBinary());
+
+ GenTreePtr op2 = gtOp.gtOp2;
+
+ // Only allow null op2 if the node type allows it, e.g. GT_LIST.
+ assert((op2 != nullptr) || !RequiresNonNullOp2(gtOper));
+
+ return op2;
+}
+
+inline GenTreePtr GenTree::gtGetOp2IfPresent()
+{
/* gtOp.gtOp2 is only valid for GTK_BINOP nodes. */
GenTreePtr op2 = OperIsBinary() ? gtOp.gtOp2 : nullptr;
// This documents the genTreeOps for which gtOp.gtOp2 cannot be nullptr.
- // This helps prefix in its analyis of code which calls gtGetOp2()
+ // This helps prefix in its analysis of code which calls gtGetOp2()
assert((op2 != nullptr) || !RequiresNonNullOp2(gtOper));
// operands.
//
// Arguments:
- // tree - Gentree of a bininary operation.
+ // tree - Gentree of a binary operation.
//
// Returns
// None.
}
else if (kind & (GTK_SMPOP))
{
- if (tree->gtGetOp2() != nullptr)
+ if (tree->gtGetOp2IfPresent() != nullptr)
{
info->srcCount = 2;
}
}
else if (kind & (GTK_SMPOP))
{
- if (tree->gtGetOp2() != nullptr)
+ if (tree->gtGetOp2IfPresent() != nullptr)
{
info->srcCount = 2;
}
// The result is baseType of SIMD struct.
info->srcCount = 2;
- op2 = tree->gtGetOp2()
- // If the index is a constant, mark it as contained.
- if (CheckImmedAndMakeContained(tree, op2))
+ op2 = tree->gtGetOp2();
+
+ // If the index is a constant, mark it as contained.
+ if (CheckImmedAndMakeContained(tree, op2))
{
info->srcCount = 1;
}
}
else if (kind & (GTK_SMPOP))
{
- if (tree->gtGetOp2() != nullptr)
+ if (tree->gtGetOp2IfPresent() != nullptr)
{
info->srcCount = 2;
}
// Therefore, we insert a GT_ADDR just above the node, and wrap it in an obj or ind.
// TODO-1stClassStructs: Consider whether this can be improved.
// Also consider whether some of this can be included in gtNewBlockVal (though note
- // that doing so may cause us to query the type system before we otherwise would.
+ // that doing so may cause us to query the type system before we otherwise would).
GenTree* lastComma = nullptr;
for (GenTree* next = tree; next != nullptr && next->gtOper == GT_COMMA; next = next->gtGetOp2())
{
// FP architectures
GenTree* Compiler::fgMorphForRegisterFP(GenTree* tree)
{
- GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
-
- if (tree->OperIsArithmetic() && varTypeIsFloating(tree))
+ if (tree->OperIsArithmetic())
{
- if (op1->TypeGet() != tree->TypeGet())
+ if (varTypeIsFloating(tree))
{
- tree->gtOp.gtOp1 = gtNewCastNode(tree->TypeGet(), tree->gtOp.gtOp1, tree->TypeGet());
- }
- if (op2->TypeGet() != tree->TypeGet())
- {
- tree->gtOp.gtOp2 = gtNewCastNode(tree->TypeGet(), tree->gtOp.gtOp2, tree->TypeGet());
+ GenTreePtr op1 = tree->gtOp.gtOp1;
+ GenTreePtr op2 = tree->gtGetOp2();
+
+ if (op1->TypeGet() != tree->TypeGet())
+ {
+ tree->gtOp.gtOp1 = gtNewCastNode(tree->TypeGet(), op1, tree->TypeGet());
+ }
+ if (op2->TypeGet() != tree->TypeGet())
+ {
+ tree->gtOp.gtOp2 = gtNewCastNode(tree->TypeGet(), op2, tree->TypeGet());
+ }
}
}
- else if (tree->OperIsCompare() && varTypeIsFloating(op1) && op1->TypeGet() != op2->TypeGet())
+ else if (tree->OperIsCompare())
{
- // both had better be floating, just one bigger than other
- assert(varTypeIsFloating(op2));
- if (op1->TypeGet() == TYP_FLOAT)
- {
- tree->gtOp.gtOp1 = gtNewCastNode(TYP_DOUBLE, tree->gtOp.gtOp1, TYP_DOUBLE);
- }
- else if (op2->TypeGet() == TYP_FLOAT)
+ GenTreePtr op1 = tree->gtOp.gtOp1;
+
+ if (varTypeIsFloating(op1))
{
- tree->gtOp.gtOp2 = gtNewCastNode(TYP_DOUBLE, tree->gtOp.gtOp2, TYP_DOUBLE);
+ GenTreePtr op2 = tree->gtGetOp2();
+ assert(varTypeIsFloating(op2));
+
+ if (op1->TypeGet() != op2->TypeGet())
+ {
+ // both had better be floating, just one bigger than other
+ if (op1->TypeGet() == TYP_FLOAT)
+ {
+ assert(op2->TypeGet() == TYP_DOUBLE);
+ tree->gtOp.gtOp1 = gtNewCastNode(TYP_DOUBLE, op1, TYP_DOUBLE);
+ }
+ else if (op2->TypeGet() == TYP_FLOAT)
+ {
+ assert(op1->TypeGet() == TYP_DOUBLE);
+ tree->gtOp.gtOp2 = gtNewCastNode(TYP_DOUBLE, op2, TYP_DOUBLE);
+ }
+ }
}
}
genTreeOps oper = tree->OperGet();
var_types typ = tree->TypeGet();
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
/*-------------------------------------------------------------------------
* First do any PRE-ORDER processing
}
fgMorphRecognizeBoxNullable(tree);
op1 = tree->gtOp.gtOp1;
- op2 = tree->gtGetOp2();
+ op2 = tree->gtGetOp2IfPresent();
break;
/* gtFoldExpr could have changed op1 and op2 */
op1 = tree->gtOp.gtOp1;
- op2 = tree->gtGetOp2();
+ op2 = tree->gtGetOp2IfPresent();
// Do we have an integer compare operation?
//
genTreeOps oper = tree->OperGet();
var_types typ = tree->TypeGet();
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
/*
We have to use helper calls for all FP operations:
// genReturnLocal
noway_assert(ret->OperGet() == GT_RETURN);
noway_assert(ret->gtGetOp1() != nullptr);
- noway_assert(ret->gtGetOp2() == nullptr);
GenTreePtr tree = gtNewTempAssign(genReturnLocal, ret->gtGetOp1());
// 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);
- noway_assert(ret->gtGetOp2() == nullptr);
fgRemoveStmt(block, last);
}
op1->gtType = simdType;
}
- GenTree* op2 = simdNode->gtGetOp2();
+ GenTree* op2 = simdNode->gtGetOp2IfPresent();
if (op2 != nullptr && op2->gtType == TYP_STRUCT)
{
op2->gtType = simdType;
bool useBarriers = false;
GenTreeBlk* dst = tree->gtGetOp1()->AsBlk();
GenTreePtr dstAddr = dst->Addr();
- GenTreePtr srcAddrOrFill = tree->gtGetOp2();
+ GenTreePtr srcAddrOrFill = tree->gtGetOp2IfPresent();
size_t blkSize = dst->gtBlkSize;
if (kind & GTK_SMPOP)
{
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
GenTreePtr opsPtr[3];
regMaskTP regsPtr[3];
case GT_COMMA:
{
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
if (tree->gtFlags & GTF_REVERSE_OPS)
{
{
var_types type = tree->TypeGet();
GenTreePtr op1 = tree->gtGetOp1();
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
regMaskTP needRegOp1 = RBM_ALLINT;
regMaskTP addrReg = RBM_NONE;
var_types type = tree->TypeGet();
genTreeOps oper = tree->OperGet();
GenTreePtr op1 = tree->gtGetOp1();
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
regNumber tgtReg;
unsigned varNum;
emitAttr size;
unsigned offs;
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
assert(tree->OperGet() == GT_ASG);
if (tree->gtFlags & GTF_REVERSE_OPS)
{
bReverse = true;
- op1 = tree->gtGetOp2();
+ op1 = tree->gtGetOp2IfPresent();
op2 = tree->gtOp.gtOp1;
}
else
{
bReverse = false;
op1 = tree->gtOp.gtOp1;
- op2 = tree->gtGetOp2();
+ op2 = tree->gtGetOp2IfPresent();
}
regNumber result;
GenTreePtr op1, op2;
op1 = tree->gtOp.gtOp1;
- op2 = tree->gtGetOp2();
+ op2 = tree->gtGetOp2IfPresent();
genSetupForOpStackFP(op1, op2, (tree->gtFlags & GTF_REVERSE_OPS) ? true : false, true, false, true);
case GT_COMMA:
{
GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
+ GenTreePtr op2 = tree->gtGetOp2IfPresent();
if (tree->gtFlags & GTF_REVERSE_OPS)
{