//------------------------------------------------------------------------ // ContainCheckBoundsChk: determine whether any source of a bounds check node should be contained. // // Arguments: // node - pointer to the node // void Lowering::ContainCheckBoundsChk(GenTreeBoundsChk* node) { assert(node->OperIsBoundsCheck()); if (!CheckImmedAndMakeContained(node, node->gtIndex)) { CheckImmedAndMakeContained(node, node->gtArrLen); } }
//------------------------------------------------------------------------ // TreeNodeInfoInitStoreLoc: Set register requirements for a store of a lclVar // // Arguments: // storeLoc - the local store (GT_STORE_LCL_FLD or GT_STORE_LCL_VAR) // // Notes: // This involves: // - Setting the appropriate candidates for a store of a multi-reg call return value. // - Handling of contained immediates. // void Lowering::TreeNodeInfoInitStoreLoc(GenTreeLclVarCommon* storeLoc) { TreeNodeInfo* info = &(storeLoc->gtLsraInfo); // Is this the case of var = call where call is returning // a value in multiple return registers? GenTree* op1 = storeLoc->gtGetOp1(); if (op1->IsMultiRegCall()) { // backend expects to see this case only for store lclvar. assert(storeLoc->OperGet() == GT_STORE_LCL_VAR); // srcCount = number of registers in which the value is returned by call GenTreeCall* call = op1->AsCall(); ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); info->srcCount = retTypeDesc->GetReturnRegCount(); // Call node srcCandidates = Bitwise-OR(allregs(GetReturnRegType(i))) for all i=0..RetRegCount-1 regMaskTP srcCandidates = m_lsra->allMultiRegCallNodeRegs(call); op1->gtLsraInfo.setSrcCandidates(m_lsra, srcCandidates); } #if defined(_TARGET_ARM_) else if (op1->OperGet() == GT_LONG) { op1->SetContained(); } #endif // _TARGET_ARM_ else { CheckImmedAndMakeContained(storeLoc, op1); } }
//------------------------------------------------------------------------ // TreeNodeInfoInitCmp: Lower a GT comparison node. // // Arguments: // tree - the node to lower // // Return Value: // None. // void Lowering::TreeNodeInfoInitCmp(GenTreePtr tree) { TreeNodeInfo* info = &(tree->gtLsraInfo); info->srcCount = 2; info->dstCount = tree->OperIs(GT_CMP) ? 0 : 1; CheckImmedAndMakeContained(tree, tree->gtOp.gtOp2); }
//---------------------------------------------------------------------------------------------- // ContainCheckSIMD: Perform containment analysis for a SIMD intrinsic node. // // Arguments: // simdNode - The SIMD intrinsic node. // void Lowering::ContainCheckSIMD(GenTreeSIMD* simdNode) { switch (simdNode->gtSIMDIntrinsicID) { GenTree* op1; GenTree* op2; case SIMDIntrinsicInit: op1 = simdNode->gtOp.gtOp1; if (op1->IsIntegralConst(0)) { MakeSrcContained(simdNode, op1); } break; case SIMDIntrinsicInitArray: // We have an array and an index, which may be contained. CheckImmedAndMakeContained(simdNode, simdNode->gtGetOp2()); break; case SIMDIntrinsicOpEquality: case SIMDIntrinsicOpInEquality: // TODO-ARM64-CQ Support containing 0 break; case SIMDIntrinsicGetItem: { // This implements get_Item method. The sources are: // - the source SIMD struct // - index (which element to get) // The result is baseType of SIMD struct. op1 = simdNode->gtOp.gtOp1; op2 = simdNode->gtOp.gtOp2; // If the index is a constant, mark it as contained. if (op2->IsCnsIntOrI()) { MakeSrcContained(simdNode, op2); } if (IsContainableMemoryOp(op1)) { MakeSrcContained(simdNode, op1); if (op1->OperGet() == GT_IND) { op1->AsIndir()->Addr()->ClearContained(); } } break; } default: break; } }
//---------------------------------------------------------------------------------------------- // ContainCheckSIMD: Perform containment analysis for a SIMD intrinsic node. // // Arguments: // simdNode - The SIMD intrinsic node. // void Lowering::ContainCheckSIMD(GenTreeSIMD* simdNode) { switch (simdNode->gtSIMDIntrinsicID) { GenTree* op1; GenTree* op2; case SIMDIntrinsicInit: // TODO-ARM64-CQ Support containing 0 break; case SIMDIntrinsicInitArray: // We have an array and an index, which may be contained. CheckImmedAndMakeContained(simdNode, simdNode->gtGetOp2()); break; case SIMDIntrinsicOpEquality: case SIMDIntrinsicOpInEquality: // TODO-ARM64-CQ Support containing 0 break; case SIMDIntrinsicGetItem: { // TODO-ARM64-CQ Support containing op1 memory ops // This implements get_Item method. The sources are: // - the source SIMD struct // - index (which element to get) // The result is baseType of SIMD struct. op2 = simdNode->gtOp.gtOp2; // If the index is a constant, mark it as contained. CheckImmedAndMakeContained(simdNode, op2); break; } default: break; } }
//------------------------------------------------------------------------ // ContainCheckCompare: determine whether the sources of a compare node should be contained. // // Arguments: // node - pointer to the node // void Lowering::ContainCheckCompare(GenTreeOp* cmp) { CheckImmedAndMakeContained(cmp, cmp->gtOp2); }
//------------------------------------------------------------------------ // ContainCheckBinary: Determine whether a binary op's operands should be contained. // // Arguments: // node - the node we care about // void Lowering::ContainCheckBinary(GenTreeOp* node) { // Check and make op2 contained (if it is a containable immediate) CheckImmedAndMakeContained(node, node->gtOp2); }