GenTreeBoundsChk* arrBndsChk = op1->AsBoundsChk();
assertion->assertionKind = assertionKind;
assertion->op1.kind = O1K_ARR_BND;
- assertion->op1.bnd.vnIdx = arrBndsChk->gtIndex->gtVNPair.GetConservative();
- assertion->op1.bnd.vnLen = arrBndsChk->gtArrLen->gtVNPair.GetConservative();
+ assertion->op1.bnd.vnIdx = vnStore->VNNormalValue(arrBndsChk->gtIndex->gtVNPair, VNK_Conservative);
+ assertion->op1.bnd.vnLen = vnStore->VNNormalValue(arrBndsChk->gtArrLen->gtVNPair, VNK_Conservative);
goto DONE_ASSERTION;
}
}
goto DONE_ASSERTION; // Don't make an assertion
}
- vn = op1->gtVNPair.GetConservative();
+ vn = vnStore->VNNormalValue(op1->gtVNPair, VNK_Conservative);
VNFuncApp funcAttr;
// Try to get value number corresponding to the GC ref of the indirection
assertion->op1.kind = O1K_LCLVAR;
assertion->op1.lcl.lclNum = lclNum;
assertion->op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum();
- vn = op1->gtVNPair.GetConservative();
+ vn = vnStore->VNNormalValue(op1->gtVNPair, VNK_Conservative);
}
assertion->op1.vn = vn;
//
assertion->op1.kind = O1K_SUBTYPE;
assertion->op1.lcl.lclNum = lclNum;
- assertion->op1.vn = op1->gtVNPair.GetConservative();
+ assertion->op1.vn = vnStore->VNNormalValue(op1->gtVNPair, VNK_Conservative);
assertion->op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum();
assertion->op2.u1.iconVal = op2->gtIntCon.gtIconVal;
- assertion->op2.vn = op2->gtVNPair.GetConservative();
+ assertion->op2.vn = vnStore->VNNormalValue(op2->gtVNPair, VNK_Conservative);
assertion->op2.u1.iconFlags = op2->GetIconHandleFlag();
//
assertion->op1.kind = O1K_LCLVAR;
assertion->op1.lcl.lclNum = lclNum;
- assertion->op1.vn = op1->gtVNPair.GetConservative();
+ assertion->op1.vn = vnStore->VNNormalValue(op1->gtVNPair, VNK_Conservative);
assertion->op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum();
switch (op2->gtOper)
assertion->op2.kind = op2Kind;
assertion->op2.lconVal = 0;
- assertion->op2.vn = op2->gtVNPair.GetConservative();
+ assertion->op2.vn = vnStore->VNNormalValue(op2->gtVNPair, VNK_Conservative);
if (op2->gtOper == GT_CNS_INT)
{
assertion->op2.kind = O2K_LCLVAR_COPY;
assertion->op2.lcl.lclNum = lclNum2;
- assertion->op2.vn = op2->gtVNPair.GetConservative();
+ assertion->op2.vn = vnStore->VNNormalValue(op2->gtVNPair, VNK_Conservative);
assertion->op2.lcl.ssaNum = op2->AsLclVarCommon()->GetSsaNum();
//
assertion->op1.kind = O1K_EXACT_TYPE;
assertion->op1.lcl.lclNum = lclNum;
- assertion->op1.vn = op1->gtVNPair.GetConservative();
+ assertion->op1.vn = vnStore->VNNormalValue(op1->gtVNPair, VNK_Conservative);
assertion->op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum();
+
assert(assertion->op1.lcl.ssaNum == SsaConfig::RESERVED_SSA_NUM ||
assertion->op1.vn ==
- lvaTable[lclNum].GetPerSsaData(assertion->op1.lcl.ssaNum)->m_vnPair.GetConservative());
+ vnStore->VNNormalValue(lvaTable[lclNum].GetPerSsaData(assertion->op1.lcl.ssaNum)->m_vnPair,
+ VNK_Conservative));
ssize_t cnsValue = 0;
unsigned iconFlags = 0;
assertion->assertionKind = assertionKind;
assertion->op2.kind = O2K_IND_CNS_INT;
assertion->op2.u1.iconVal = cnsValue;
- assertion->op2.vn = op2->gtOp.gtOp1->gtVNPair.GetConservative();
+ assertion->op2.vn = vnStore->VNNormalValue(op2->gtOp.gtOp1->gtVNPair, VNK_Conservative);
+
/* iconFlags should only contain bits in GTF_ICON_HDL_MASK */
assert((iconFlags & ~GTF_ICON_HDL_MASK) == 0);
assertion->op2.u1.iconFlags = iconFlags;
assertion->assertionKind = assertionKind;
assertion->op2.kind = O2K_IND_CNS_INT;
assertion->op2.u1.iconVal = cnsValue;
- assertion->op2.vn = op2->gtVNPair.GetConservative();
+ assertion->op2.vn = vnStore->VNNormalValue(op2->gtVNPair, VNK_Conservative);
+
/* iconFlags should only contain bits in GTF_ICON_HDL_MASK */
assert((iconFlags & ~GTF_ICON_HDL_MASK) == 0);
assertion->op2.u1.iconFlags = iconFlags;
}
// Global assertion prop
- if (!vnStore->IsVNConstant(tree->gtVNPair.GetConservative()))
+ ValueNum vn = vnStore->VNNormalValue(tree->gtVNPair, VNK_Conservative);
+ if (!vnStore->IsVNConstant(vn))
{
return false;
}
- ValueNum vn = tree->gtVNPair.GetConservative();
+ // ValueNumber 'vn' indicates that this node evaluates to a constant
+
var_types vnType = vnStore->TypeOfVN(vn);
if (vnType == TYP_INT)
{
GenTree* op1 = relop->gtGetOp1();
GenTree* op2 = relop->gtGetOp2();
- ValueNum vn = op1->gtVNPair.GetConservative();
+ ValueNum op1VN = vnStore->VNNormalValue(op1->gtVNPair, VNK_Conservative);
+ ValueNum op2VN = vnStore->VNNormalValue(op2->gtVNPair, VNK_Conservative);
+ ValueNum relopVN = vnStore->VNNormalValue(relop->gtVNPair, VNK_Conservative);
+
+ bool hasTestAgainstZero =
+ (relop->gtOper == GT_EQ || relop->gtOper == GT_NE) && (op2VN == vnStore->VNZeroForType(op2->TypeGet()));
ValueNumStore::UnsignedCompareCheckedBoundInfo unsignedCompareBnd;
// Cases where op1 holds the upper bound arithmetic and op2 is 0.
// Loop condition like: "i < bnd +/-k == 0"
// Assertion: "i < bnd +/- k == 0"
- if (vnStore->IsVNCompareCheckedBoundArith(vn) &&
- op2->gtVNPair.GetConservative() == vnStore->VNZeroForType(op2->TypeGet()) &&
- (relop->gtOper == GT_EQ || relop->gtOper == GT_NE))
+ if (hasTestAgainstZero && vnStore->IsVNCompareCheckedBoundArith(op1VN))
{
AssertionDsc dsc;
dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL;
dsc.op1.kind = O1K_BOUND_OPER_BND;
- dsc.op1.vn = vn;
+ dsc.op1.vn = op1VN;
dsc.op2.kind = O2K_CONST_INT;
dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet());
dsc.op2.u1.iconVal = 0;
// Cases where op1 holds the upper bound and op2 is 0.
// Loop condition like: "i < bnd == 0"
// Assertion: "i < bnd == false"
- else if (vnStore->IsVNCompareCheckedBound(vn) &&
- (op2->gtVNPair.GetConservative() == vnStore->VNZeroForType(op2->TypeGet())) &&
- (relop->gtOper == GT_EQ || relop->gtOper == GT_NE))
+ else if (hasTestAgainstZero && vnStore->IsVNCompareCheckedBound(op1VN))
{
AssertionDsc dsc;
dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL;
dsc.op1.kind = O1K_BOUND_LOOP_BND;
- dsc.op1.vn = vn;
+ dsc.op1.vn = op1VN;
dsc.op2.kind = O2K_CONST_INT;
dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet());
dsc.op2.u1.iconVal = 0;
// Cases where op1 holds the lhs of the condition op2 holds the bound.
// Loop condition like "i < bnd"
// Assertion: "i < bnd != 0"
- else if (vnStore->IsVNCompareCheckedBound(relop->gtVNPair.GetConservative()))
+ else if (vnStore->IsVNCompareCheckedBound(relopVN))
{
AssertionDsc dsc;
dsc.assertionKind = OAK_NOT_EQUAL;
dsc.op1.kind = O1K_BOUND_LOOP_BND;
- dsc.op1.vn = relop->gtVNPair.GetConservative();
+ dsc.op1.vn = relopVN;
dsc.op2.kind = O2K_CONST_INT;
dsc.op2.vn = vnStore->VNZeroForType(TYP_INT);
dsc.op2.u1.iconVal = 0;
}
// Loop condition like "(uint)i < (uint)bnd" or equivalent
// Assertion: "no throw" since this condition guarantees that i is both >= 0 and < bnd (on the appropiate edge)
- else if (vnStore->IsVNUnsignedCompareCheckedBound(relop->gtVNPair.GetConservative(), &unsignedCompareBnd))
+ else if (vnStore->IsVNUnsignedCompareCheckedBound(relopVN, &unsignedCompareBnd))
{
assert(unsignedCompareBnd.vnIdx != ValueNumStore::NoVN);
assert((unsignedCompareBnd.cmpOper == VNF_LT_UN) || (unsignedCompareBnd.cmpOper == VNF_GE_UN));
AssertionDsc dsc;
dsc.assertionKind = OAK_NO_THROW;
dsc.op1.kind = O1K_ARR_BND;
- dsc.op1.vn = relop->gtVNPair.GetConservative();
+ dsc.op1.vn = relopVN;
dsc.op1.bnd.vnIdx = unsignedCompareBnd.vnIdx;
- dsc.op1.bnd.vnLen = unsignedCompareBnd.vnBound;
+ dsc.op1.bnd.vnLen = vnStore->VNNormalValue(unsignedCompareBnd.vnBound);
dsc.op2.kind = O2K_INVALID;
dsc.op2.vn = ValueNumStore::NoVN;
// Cases where op1 holds the condition bound check and op2 is 0.
// Loop condition like: "i < 100 == 0"
// Assertion: "i < 100 == false"
- else if (vnStore->IsVNConstantBound(vn) &&
- (op2->gtVNPair.GetConservative() == vnStore->VNZeroForType(op2->TypeGet())) &&
- (relop->gtOper == GT_EQ || relop->gtOper == GT_NE))
+ else if (hasTestAgainstZero && vnStore->IsVNConstantBound(op1VN))
{
AssertionDsc dsc;
dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL;
dsc.op1.kind = O1K_CONSTANT_LOOP_BND;
- dsc.op1.vn = vn;
+ dsc.op1.vn = op1VN;
dsc.op2.kind = O2K_CONST_INT;
dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet());
dsc.op2.u1.iconVal = 0;
// Cases where op1 holds the lhs of the condition op2 holds rhs.
// Loop condition like "i < 100"
// Assertion: "i < 100 != 0"
- else if (vnStore->IsVNConstantBound(relop->gtVNPair.GetConservative()))
+ else if (vnStore->IsVNConstantBound(relopVN))
{
AssertionDsc dsc;
dsc.assertionKind = OAK_NOT_EQUAL;
dsc.op1.kind = O1K_CONSTANT_LOOP_BND;
- dsc.op1.vn = relop->gtVNPair.GetConservative();
+ dsc.op1.vn = relopVN;
dsc.op2.kind = O2K_CONST_INT;
dsc.op2.vn = vnStore->VNZeroForType(TYP_INT);
dsc.op2.u1.iconVal = 0;
(curAssertion->op1.kind == O1K_LCLVAR))
{
// For local assertion prop use comparison on locals, and use comparison on vns for global prop.
- bool isEqual = optLocalAssertionProp ? (curAssertion->op1.lcl.lclNum == tree->AsLclVarCommon()->GetLclNum())
- : (curAssertion->op1.vn == tree->gtVNPair.GetConservative());
+ bool isEqual = optLocalAssertionProp
+ ? (curAssertion->op1.lcl.lclNum == tree->AsLclVarCommon()->GetLclNum())
+ : (curAssertion->op1.vn == vnStore->VNNormalValue(tree->gtVNPair, VNK_Conservative));
if (!isEqual)
{
continue;
}
// If local assertion prop use "lcl" based comparison, if global assertion prop use vn based comparison.
- if ((optLocalAssertionProp) ? (curAssertion->op1.lcl.lclNum != tree->AsLclVarCommon()->GetLclNum())
- : (curAssertion->op1.vn != tree->gtVNPair.GetConservative()))
+ if ((optLocalAssertionProp)
+ ? (curAssertion->op1.lcl.lclNum != tree->AsLclVarCommon()->GetLclNum())
+ : (curAssertion->op1.vn != vnStore->VNNormalValue(tree->gtVNPair, VNK_Conservative)))
{
continue;
}
return nullptr;
}
- ValueNum vnCns = tree->gtVNPair.GetConservative();
- ValueNum vnLib = tree->gtVNPair.GetLiberal();
+ // We want to use the Normal ValueNumber when checking for constants.
+ ValueNum vnCns = vnStore->VNNormalValue(tree->gtVNPair, VNK_Conservative);
+ ValueNum vnLib = vnStore->VNNormalValue(tree->gtVNPair, VNK_Liberal);
// Check if node evaluates to a constant.
if (!vnStore->IsVNConstant(vnCns))
return optConstantAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex));
}
// If global assertion, perform constant propagation only if the VN's match and the lcl is non-CSE.
- else if (curAssertion->op1.vn == tree->gtVNPair.GetConservative())
+ else if (curAssertion->op1.vn == vnStore->VNNormalValue(tree->gtVNPair, VNK_Conservative))
{
#if FEATURE_ANYCSE
// Don't perform constant prop for CSE LclVars
continue;
}
- if (curAssertion->op1.vn == op1->gtVNPair.GetConservative() &&
- curAssertion->op2.vn == op2->gtVNPair.GetConservative())
+ if ((curAssertion->op1.vn == vnStore->VNNormalValue(op1->gtVNPair, VNK_Conservative)) &&
+ (curAssertion->op2.vn == vnStore->VNNormalValue(op2->gtVNPair, VNK_Conservative)))
{
return assertionIndex;
}
bool allowReverse = true;
// If the assertion involves "op2" and it is a constant, then check if "op1" also has a constant value.
- if (vnStore->IsVNConstant(op2->gtVNPair.GetConservative()))
+ ValueNum vnCns = vnStore->VNNormalValue(op2->gtVNPair, VNK_Conservative);
+ if (vnStore->IsVNConstant(vnCns))
{
- ValueNum vnCns = op2->gtVNPair.GetConservative();
#ifdef DEBUG
if (verbose)
{
#endif
// Do we have a previous range check involving the same 'vnLen' upper bound?
- if (curAssertion->op1.bnd.vnLen == arrBndsChk->gtArrLen->gtVNPair.GetConservative())
+ if (curAssertion->op1.bnd.vnLen == vnStore->VNNormalValue(arrBndsChk->gtArrLen->gtVNPair, VNK_Conservative))
{
- ValueNum vnCurIdx = arrBndsChk->gtIndex->gtVNPair.GetConservative();
+ ValueNum vnCurIdx = vnStore->VNNormalValue(arrBndsChk->gtIndex->gtVNPair, VNK_Conservative);
// Do we have the exact same lower bound 'vnIdx'?
// a[i] followed by a[i]
// (e.g. VN may evaluate a DIV/MOD node to a constant and the node may still
// have GTF_EXCEPT set, even if it does not actually throw any exceptions).
assert(!gtNodeHasSideEffects(oldTree, GTF_EXCEPT) ||
- vnStore->IsVNConstant(oldTree->gtVNPair.GetConservative()));
+ vnStore->IsVNConstant(vnStore->VNNormalValue(oldTree->gtVNPair, VNK_Conservative)));
ignoreRoot = true;
}
//
assert((relop->gtFlags & GTF_RELOP_JMP_USED) != 0);
- if (!vnStore->IsVNConstant(relop->gtVNPair.GetConservative()))
+ ValueNum vnCns = relop->gtVNPair.GetConservative();
+ ValueNum vnLib = relop->gtVNPair.GetLiberal();
+ if (!vnStore->IsVNConstant(vnCns))
{
return nullptr;
}
relop->gtOp.gtOp2->gtVNPair = ValueNumPair(vnZero, vnZero);
// Update the oper and restore the value numbers.
- ValueNum vnCns = relop->gtVNPair.GetConservative();
- ValueNum vnLib = relop->gtVNPair.GetLiberal();
- bool evalsToTrue = (vnStore->CoercedConstantValue<INT64>(vnCns) != 0);
+ bool evalsToTrue = (vnStore->CoercedConstantValue<INT64>(vnCns) != 0);
relop->SetOper(evalsToTrue ? GT_EQ : GT_NE);
relop->gtVNPair = ValueNumPair(vnLib, vnCns);
ValueNumStore* vnStore = m_pCompiler->vnStore;
// Get the VN for the upper limit.
- ValueNum uLimitVN = upper->gtVNPair.GetConservative();
+ ValueNum uLimitVN = vnStore->VNNormalValue(upper->gtVNPair, VNK_Conservative);
#ifdef DEBUG
JITDUMP(FMT_VN " upper bound is: ", uLimitVN);
GenTree* treeIndex = bndsChk->gtIndex;
// Take care of constant index first, like a[2], for example.
- ValueNum idxVn = treeIndex->gtVNPair.GetConservative();
- ValueNum arrLenVn = bndsChk->gtArrLen->gtVNPair.GetConservative();
+ ValueNum idxVn = m_pCompiler->vnStore->VNNormalValue(treeIndex->gtVNPair, VNK_Conservative);
+ ValueNum arrLenVn = m_pCompiler->vnStore->VNNormalValue(bndsChk->gtArrLen->gtVNPair, VNK_Conservative);
int arrSize = 0;
if (m_pCompiler->vnStore->IsVNConstant(arrLenVn))
Limit limit(Limit::keUndef);
genTreeOps cmpOper = GT_NONE;
+ LclSsaVarDsc* ssaData = m_pCompiler->lvaTable[lcl->gtLclNum].GetPerSsaData(lcl->gtSsaNum);
+ ValueNum normalLclVN = m_pCompiler->vnStore->VNNormalValue(ssaData->m_vnPair, VNK_Conservative);
+
// Current assertion is of the form (i < len - cns) != 0
if (curAssertion->IsCheckedBoundArithBound())
{
// Get i, len, cns and < as "info."
m_pCompiler->vnStore->GetCompareCheckedBoundArithInfo(curAssertion->op1.vn, &info);
- if (m_pCompiler->lvaTable[lcl->gtLclNum].GetPerSsaData(lcl->gtSsaNum)->m_vnPair.GetConservative() !=
- info.cmpOp)
+ // If we don't have the same variable we are comparing against, bail.
+ if (normalLclVN != info.cmpOp)
{
continue;
}
// Get the info as "i", "<" and "len"
m_pCompiler->vnStore->GetCompareCheckedBound(curAssertion->op1.vn, &info);
- ValueNum lclVn =
- m_pCompiler->lvaTable[lcl->gtLclNum].GetPerSsaData(lcl->gtSsaNum)->m_vnPair.GetConservative();
// If we don't have the same variable we are comparing against, bail.
- if (lclVn != info.cmpOp)
+ if (normalLclVN != info.cmpOp)
{
continue;
}
+
limit = Limit(Limit::keBinOpArray, info.vnBound, 0);
cmpOper = (genTreeOps)info.cmpOper;
}
// Get the info as "i", "<" and "100"
m_pCompiler->vnStore->GetConstantBoundInfo(curAssertion->op1.vn, &info);
- ValueNum lclVn =
- m_pCompiler->lvaTable[lcl->gtLclNum].GetPerSsaData(lcl->gtSsaNum)->m_vnPair.GetConservative();
-
// If we don't have the same variable we are comparing against, bail.
- if (lclVn != info.cmpOpVN)
+ if (normalLclVN != info.cmpOpVN)
{
continue;
}
}
#endif
- ValueNum arrLenVN = m_pCurBndsChk->gtArrLen->gtVNPair.GetConservative();
+ ValueNum arrLenVN = m_pCompiler->vnStore->VNNormalValue(m_pCurBndsChk->gtArrLen->gtVNPair, VNK_Conservative);
if (m_pCompiler->vnStore->IsVNConstant(arrLenVN))
{
void RangeCheck::MergeAssertion(BasicBlock* block, GenTree* op, Range* pRange DEBUGARG(int indent))
{
JITDUMP("Merging assertions from pred edges of " FMT_BB " for op [%06d] " FMT_VN "\n", block->bbNum,
- Compiler::dspTreeID(op), op->gtVNPair.GetConservative());
+ Compiler::dspTreeID(op), m_pCompiler->vnStore->VNNormalValue(op->gtVNPair, VNK_Conservative));
ASSERT_TP assertions = BitVecOps::UninitVal();
// If we have a phi arg, we can get to the block from it and use its assertion out.
bool newlyAdded = !m_pSearchPath->Set(expr, block);
Range range = Limit(Limit::keUndef);
- ValueNum vn = expr->gtVNPair.GetConservative();
+ ValueNum vn = m_pCompiler->vnStore->VNNormalValue(expr->gtVNPair, VNK_Conservative);
// If newly added in the current search path, then reduce the budget.
if (newlyAdded)
{
//
template <typename T>
-T ValueNumStore::EvalOp(VNFunc vnf, T v0, T v1, ValueNum* pExcSet)
+T ValueNumStore::EvalOp(VNFunc vnf, T v0, T v1)
{
// Here we handle the binary ops that are the same for all types.
}
ValueNum result; // left uninitialized, we are required to initialize it on all paths below.
- ValueNum excSet = VNForEmptyExcSet();
// Are both args of the same type?
if (arg0VNtyp == arg1VNtyp)
else
{
assert(typ == TYP_INT);
- int resultVal = EvalOp<int>(func, arg0Val, arg1Val, &excSet);
+ int resultVal = EvalOp<int>(func, arg0Val, arg1Val);
// Bin op on a handle results in a handle.
ValueNum handleVN = IsVNHandle(arg0VN) ? arg0VN : IsVNHandle(arg1VN) ? arg1VN : NoVN;
if (handleVN != NoVN)
{
- assert(excSet == VNForEmptyExcSet()); // Handles aren't allowed to generate exceptions
result = VNForHandle(ssize_t(resultVal), GetHandleFlags(handleVN)); // Use VN for Handle
}
else
{
- result = VNWithExc(VNForIntCon(resultVal), excSet);
+ result = VNForIntCon(resultVal);
}
}
}
else
{
assert(typ == TYP_LONG);
- INT64 resultVal = EvalOp<INT64>(func, arg0Val, arg1Val, &excSet);
+ INT64 resultVal = EvalOp<INT64>(func, arg0Val, arg1Val);
ValueNum handleVN = IsVNHandle(arg0VN) ? arg0VN : IsVNHandle(arg1VN) ? arg1VN : NoVN;
- ValueNum resultVN = (handleVN != NoVN)
- ? VNForHandle(ssize_t(resultVal), GetHandleFlags(handleVN)) // Use VN for Handle
- : VNForLongCon(resultVal);
- result = VNWithExc(resultVN, excSet);
+
+ if (handleVN != NoVN)
+ {
+ result = VNForHandle(ssize_t(resultVal), GetHandleFlags(handleVN)); // Use VN for Handle
+ }
+ else
+ {
+ result = VNForLongCon(resultVal);
+ }
}
}
else // both args are TYP_REF or both args are TYP_BYREF
}
else if (typ == TYP_INT) // We could see GT_OR of a constant ByRef and Null
{
- int resultVal = (int)EvalOp<INT64>(func, arg0Val, arg1Val, &excSet);
- result = VNWithExc(VNForIntCon(resultVal), excSet);
+ int resultVal = (int)EvalOp<INT64>(func, arg0Val, arg1Val);
+ result = VNForIntCon(resultVal);
}
else // We could see GT_OR of a constant ByRef and Null
{
assert((typ == TYP_BYREF) || (typ == TYP_LONG));
- INT64 resultVal = EvalOp<INT64>(func, arg0Val, arg1Val, &excSet);
- result = VNWithExc(VNForByrefCon(resultVal), excSet);
+ INT64 resultVal = EvalOp<INT64>(func, arg0Val, arg1Val);
+ result = VNForByrefCon(resultVal);
}
}
}
}
else if (typ == TYP_INT) // We could see GT_OR of an int and constant ByRef or Null
{
- int resultVal = (int)EvalOp<INT64>(func, arg0Val, arg1Val, &excSet);
- result = VNWithExc(VNForIntCon(resultVal), excSet);
+ int resultVal = (int)EvalOp<INT64>(func, arg0Val, arg1Val);
+ result = VNForIntCon(resultVal);
}
else
{
assert(typ != TYP_INT);
- ValueNum resultValx = VNForEmptyExcSet();
- INT64 resultVal = EvalOp<INT64>(func, arg0Val, arg1Val, &resultValx);
+ INT64 resultVal = EvalOp<INT64>(func, arg0Val, arg1Val);
- // check for the Exception case
- if (resultValx != VNForEmptyExcSet())
- {
- result = VNWithExc(VNForVoid(), resultValx);
- }
- else
+ switch (typ)
{
- switch (typ)
- {
- case TYP_BYREF:
- result = VNForByrefCon(resultVal);
- break;
- case TYP_LONG:
- result = VNForLongCon(resultVal);
- break;
- case TYP_REF:
- assert(resultVal == 0); // Only valid REF constant
- result = VNForNull();
- break;
- default:
- unreached();
- }
+ case TYP_BYREF:
+ result = VNForByrefCon(resultVal);
+ break;
+ case TYP_LONG:
+ result = VNForLongCon(resultVal);
+ break;
+ case TYP_REF:
+ assert(resultVal == 0); // Only valid REF constant
+ result = VNForNull();
+ break;
+ default:
+ unreached();
}
}
}
assert(varTypeIsFloating(typ));
assert(arg0VNtyp == typ);
- ValueNum exception = VNForEmptyExcSet();
-
if (typ == TYP_FLOAT)
{
- float floatResultVal =
- EvalOp<float>(func, GetConstantSingle(arg0VN), GetConstantSingle(arg1VN), &exception);
- assert(exception == VNForEmptyExcSet()); // Floating point ops don't throw.
- result = VNForFloatCon(floatResultVal);
+ float floatResultVal = EvalOp<float>(func, GetConstantSingle(arg0VN), GetConstantSingle(arg1VN));
+ result = VNForFloatCon(floatResultVal);
}
else
{
assert(typ == TYP_DOUBLE);
- double doubleResultVal =
- EvalOp<double>(func, GetConstantDouble(arg0VN), GetConstantDouble(arg1VN), &exception);
- assert(exception == VNForEmptyExcSet()); // Floating point ops don't throw.
- result = VNForDoubleCon(doubleResultVal);
+ double doubleResultVal = EvalOp<double>(func, GetConstantDouble(arg0VN), GetConstantDouble(arg1VN));
+ result = VNForDoubleCon(doubleResultVal);
}
}
ValueNumPair castArgxVNP = ValueNumStore::VNPForEmptyExcSet();
VNPUnpackExc(srcVNPair, &castArgVNP, &castArgxVNP);
- // When we're considering actual value returned by a non-checking cast (or a checking cast that succeeds),
+ // When we're considering actual value returned by a non-checking cast, (hasOverflowCheck is false)
// whether or not the source is unsigned does *not* matter for non-widening casts.
// That is, if we cast an int or a uint to short, we just extract the first two bytes from the source
// bit pattern, not worrying about the interpretation. The same is true in casting between signed/unsigned
// Important: Casts to floating point cannot be optimized in this fashion. (bug 946768)
//
bool srcIsUnsignedNorm = srcIsUnsigned;
- if (genTypeSize(castToType) <= genTypeSize(castFromType) && !varTypeIsFloating(castToType))
+ if (!hasOverflowCheck && !varTypeIsFloating(castToType) && (genTypeSize(castToType) <= genTypeSize(castFromType)))
{
srcIsUnsignedNorm = false;
}
+ VNFunc vnFunc = hasOverflowCheck ? VNF_CastOvf : VNF_Cast;
ValueNum castTypeVN = VNForCastOper(castToType, srcIsUnsignedNorm);
ValueNumPair castTypeVNPair(castTypeVN, castTypeVN);
- ValueNumPair castNormRes = VNPairForFunc(resultType, VNF_Cast, castArgVNP, castTypeVNPair);
+ ValueNumPair castNormRes = VNPairForFunc(resultType, vnFunc, castArgVNP, castTypeVNPair);
ValueNumPair resultVNP = VNPWithExc(castNormRes, castArgxVNP);
// If we have a check for overflow, add the exception information.
if (hasOverflowCheck)
{
- // For overflow checking, we always need to know whether the source is unsigned.
- castTypeVNPair.SetBoth(VNForCastOper(castToType, srcIsUnsigned));
- ValueNumPair excSet =
- VNPExcSetSingleton(VNPairForFunc(TYP_REF, VNF_ConvOverflowExc, castArgVNP, castTypeVNPair));
- excSet = VNPExcSetUnion(excSet, castArgxVNP);
- resultVNP = VNPWithExc(castNormRes, excSet);
+ ValueNumPair ovfChk = VNPairForFunc(TYP_REF, VNF_ConvOverflowExc, castArgVNP, castTypeVNPair);
+ ValueNumPair excSet = VNPExcSetSingleton(ovfChk);
+ excSet = VNPExcSetUnion(excSet, castArgxVNP);
+ resultVNP = VNPWithExc(castNormRes, excSet);
}
return resultVNP;