summaryrefslogtreecommitdiff
path: root/src/jit/valuenum.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/valuenum.cpp')
-rw-r--r--src/jit/valuenum.cpp246
1 files changed, 146 insertions, 100 deletions
diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp
index 5bc96ed4a9..f7cc0c9a23 100644
--- a/src/jit/valuenum.cpp
+++ b/src/jit/valuenum.cpp
@@ -76,7 +76,6 @@ ValueNumStore::ValueNumStore(Compiler* comp, IAllocator* alloc)
, m_VNFunc2Map(nullptr)
, m_VNFunc3Map(nullptr)
, m_VNFunc4Map(nullptr)
- , m_uPtrToLocNotAFieldCount(1)
{
// We have no current allocation chunks.
for (unsigned i = 0; i < TYP_COUNT; i++)
@@ -604,6 +603,7 @@ ValueNumStore::Chunk::Chunk(
switch (attribs)
{
case CEA_None:
+ case CEA_NotAField:
break; // Nothing to do.
case CEA_Const:
switch (typ)
@@ -911,6 +911,7 @@ class Object* ValueNumStore::s_specialRefConsts[] = {nullptr, nullptr, nullptr};
ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func)
{
assert(VNFuncArity(func) == 0);
+ assert(func != VNF_NotAField);
ValueNum res;
@@ -1029,9 +1030,9 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
{
if (typ != TYP_BYREF) // We don't want/need to optimize a zero byref
{
- genTreeOps oper = genTreeOps(func);
- ValueNum ZeroVN, OneVN; // We may need to create one of these in the switch below.
- switch (oper)
+ ValueNum resultVN = NoVN;
+ ValueNum ZeroVN, OneVN; // We may need to create one of these in the switch below.
+ switch (genTreeOps(func))
{
case GT_ADD:
// This identity does not apply for floating point (when x == -0.0)
@@ -1041,11 +1042,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
ZeroVN = VNZeroForType(typ);
if (arg0VN == ZeroVN)
{
- return arg1VN;
+ resultVN = arg1VN;
}
else if (arg1VN == ZeroVN)
{
- return arg0VN;
+ resultVN = arg0VN;
}
}
break;
@@ -1055,7 +1056,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
ZeroVN = VNZeroForType(typ);
if (arg1VN == ZeroVN)
{
- return arg0VN;
+ resultVN = arg0VN;
}
break;
@@ -1066,11 +1067,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
{
if (arg0VN == OneVN)
{
- return arg1VN;
+ resultVN = arg1VN;
}
else if (arg1VN == OneVN)
{
- return arg0VN;
+ resultVN = arg0VN;
}
}
@@ -1080,11 +1081,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
ZeroVN = VNZeroForType(typ);
if (arg0VN == ZeroVN)
{
- return ZeroVN;
+ resultVN = ZeroVN;
}
else if (arg1VN == ZeroVN)
{
- return ZeroVN;
+ resultVN = ZeroVN;
}
}
break;
@@ -1097,7 +1098,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
{
if (arg1VN == OneVN)
{
- return arg0VN;
+ resultVN = arg0VN;
}
}
break;
@@ -1109,11 +1110,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
ZeroVN = VNZeroForType(typ);
if (arg0VN == ZeroVN)
{
- return arg1VN;
+ resultVN = arg1VN;
}
else if (arg1VN == ZeroVN)
{
- return arg0VN;
+ resultVN = arg0VN;
}
break;
@@ -1122,11 +1123,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
ZeroVN = VNZeroForType(typ);
if (arg0VN == ZeroVN)
{
- return ZeroVN;
+ resultVN = ZeroVN;
}
else if (arg1VN == ZeroVN)
{
- return ZeroVN;
+ resultVN = ZeroVN;
}
break;
@@ -1142,7 +1143,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
ZeroVN = VNZeroForType(typ);
if (arg1VN == ZeroVN)
{
- return arg0VN;
+ resultVN = arg0VN;
}
break;
@@ -1150,30 +1151,35 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
// (x == x) => true (unless x is NaN)
if (!varTypeIsFloating(TypeOfVN(arg0VN)) && (arg0VN != NoVN) && (arg0VN == arg1VN))
{
- return VNOneForType(typ);
+ resultVN = VNOneForType(typ);
}
if ((arg0VN == VNForNull() && IsKnownNonNull(arg1VN)) ||
(arg1VN == VNForNull() && IsKnownNonNull(arg0VN)))
{
- return VNZeroForType(typ);
+ resultVN = VNZeroForType(typ);
}
break;
case GT_NE:
// (x != x) => false (unless x is NaN)
if (!varTypeIsFloating(TypeOfVN(arg0VN)) && (arg0VN != NoVN) && (arg0VN == arg1VN))
{
- return VNZeroForType(typ);
+ resultVN = VNZeroForType(typ);
}
if ((arg0VN == VNForNull() && IsKnownNonNull(arg1VN)) ||
(arg1VN == VNForNull() && IsKnownNonNull(arg0VN)))
{
- return VNOneForType(typ);
+ resultVN = VNOneForType(typ);
}
break;
default:
break;
}
+
+ if ((resultVN != NoVN) && (TypeOfVN(resultVN) == typ))
+ {
+ return resultVN;
+ }
}
}
else // must be a VNF_ function
@@ -2072,10 +2078,11 @@ bool ValueNumStore::CanEvalForConstantArgs(VNFunc vnf)
case GT_MKREFANY: // We can't evaluate these.
case GT_RETFILT:
case GT_LIST:
+ case GT_FIELD_LIST:
case GT_ARR_LENGTH:
return false;
case GT_MULHI:
- // should be rare, not worth the complexity and risk of getting it wrong
+ assert(false && "Unexpected GT_MULHI node encountered before lowering");
return false;
default:
return true;
@@ -2545,6 +2552,11 @@ ValueNumPair ValueNumStore::VNPairApplySelectors(ValueNumPair map, FieldSeqNode*
return ValueNumPair(liberalVN, conservVN);
}
+bool ValueNumStore::IsVNNotAField(ValueNum vn)
+{
+ return m_chunks.GetNoExpand(GetChunkNum(vn))->m_attribs == CEA_NotAField;
+}
+
ValueNum ValueNumStore::VNForFieldSeq(FieldSeqNode* fieldSeq)
{
if (fieldSeq == nullptr)
@@ -2553,7 +2565,11 @@ ValueNum ValueNumStore::VNForFieldSeq(FieldSeqNode* fieldSeq)
}
else if (fieldSeq == FieldSeqStore::NotAField())
{
- return VNForNotAField();
+ // We always allocate a new, unique VN in this call.
+ Chunk* c = GetAllocChunk(TYP_REF, CEA_NotAField);
+ unsigned offsetWithinChunk = c->AllocVN();
+ ValueNum result = c->m_baseVN + offsetWithinChunk;
+ return result;
}
else
{
@@ -2585,22 +2601,22 @@ FieldSeqNode* ValueNumStore::FieldSeqVNToFieldSeq(ValueNum vn)
{
return nullptr;
}
- else if (vn == VNForNotAField())
+
+ assert(IsVNFunc(vn));
+
+ VNFuncApp funcApp;
+ GetVNFunc(vn, &funcApp);
+ if (funcApp.m_func == VNF_NotAField)
{
return FieldSeqStore::NotAField();
}
- else
- {
- assert(IsVNFunc(vn));
- VNFuncApp funcApp;
- GetVNFunc(vn, &funcApp);
- assert(funcApp.m_func == VNF_FieldSeq);
- ssize_t fieldHndVal = ConstantValue<ssize_t>(funcApp.m_args[0]);
- FieldSeqNode* head =
- m_pComp->GetFieldSeqStore()->CreateSingleton(reinterpret_cast<CORINFO_FIELD_HANDLE>(fieldHndVal));
- FieldSeqNode* tail = FieldSeqVNToFieldSeq(funcApp.m_args[1]);
- return m_pComp->GetFieldSeqStore()->Append(head, tail);
- }
+
+ assert(funcApp.m_func == VNF_FieldSeq);
+ const ssize_t fieldHndVal = ConstantValue<ssize_t>(funcApp.m_args[0]);
+ FieldSeqNode* head =
+ m_pComp->GetFieldSeqStore()->CreateSingleton(reinterpret_cast<CORINFO_FIELD_HANDLE>(fieldHndVal));
+ FieldSeqNode* tail = FieldSeqVNToFieldSeq(funcApp.m_args[1]);
+ return m_pComp->GetFieldSeqStore()->Append(head, tail);
}
ValueNum ValueNumStore::FieldSeqVNAppend(ValueNum fsVN1, ValueNum fsVN2)
@@ -2609,40 +2625,31 @@ ValueNum ValueNumStore::FieldSeqVNAppend(ValueNum fsVN1, ValueNum fsVN2)
{
return fsVN2;
}
- else if (fsVN1 == VNForNotAField() || fsVN2 == VNForNotAField())
- {
- return VNForNotAField();
- }
- else
- {
- assert(IsVNFunc(fsVN1));
- VNFuncApp funcApp1;
- GetVNFunc(fsVN1, &funcApp1);
- assert(funcApp1.m_func == VNF_FieldSeq);
- ValueNum tailRes = FieldSeqVNAppend(funcApp1.m_args[1], fsVN2);
- ValueNum fieldSeqVN = VNForFunc(TYP_REF, VNF_FieldSeq, funcApp1.m_args[0], tailRes);
-#ifdef DEBUG
- if (m_pComp->verbose)
- {
- printf(" fieldSeq " STR_VN "%x is ", fieldSeqVN);
- vnDump(m_pComp, fieldSeqVN);
- printf("\n");
- }
-#endif
+ assert(IsVNFunc(fsVN1));
- return fieldSeqVN;
+ VNFuncApp funcApp1;
+ GetVNFunc(fsVN1, &funcApp1);
+
+ if ((funcApp1.m_func == VNF_NotAField) || IsVNNotAField(fsVN2))
+ {
+ return VNForFieldSeq(FieldSeqStore::NotAField());
}
-}
-ValueNum ValueNumStore::VNForPtrToLoc(var_types typ, ValueNum lclVarVN, ValueNum fieldSeqVN)
-{
- if (fieldSeqVN == VNForNotAField())
+ assert(funcApp1.m_func == VNF_FieldSeq);
+ ValueNum tailRes = FieldSeqVNAppend(funcApp1.m_args[1], fsVN2);
+ ValueNum fieldSeqVN = VNForFunc(TYP_REF, VNF_FieldSeq, funcApp1.m_args[0], tailRes);
+
+#ifdef DEBUG
+ if (m_pComp->verbose)
{
- // To distinguish two different not a fields, append a unique value.
- return VNForFunc(typ, VNF_PtrToLoc, lclVarVN, fieldSeqVN, VNForIntCon(++m_uPtrToLocNotAFieldCount));
+ printf(" fieldSeq " STR_VN "%x is ", fieldSeqVN);
+ vnDump(m_pComp, fieldSeqVN);
+ printf("\n");
}
- return VNForFunc(typ, VNF_PtrToLoc, lclVarVN, fieldSeqVN, VNForIntCon(0));
+#endif
+
+ return fieldSeqVN;
}
ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, GenTreePtr opB)
@@ -2650,7 +2657,7 @@ ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, GenTreePtr opB)
if (opB->OperGet() == GT_CNS_INT)
{
FieldSeqNode* fldSeq = opB->gtIntCon.gtFieldSeq;
- if ((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField()))
+ if (fldSeq != nullptr)
{
return ExtendPtrVN(opA, opB->gtIntCon.gtFieldSeq);
}
@@ -2660,8 +2667,9 @@ ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, GenTreePtr opB)
ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, FieldSeqNode* fldSeq)
{
+ assert(fldSeq != nullptr);
+
ValueNum res = NoVN;
- assert(fldSeq != FieldSeqStore::NotAField());
ValueNum opAvnWx = opA->gtVNPair.GetLiberal();
assert(VNIsValid(opAvnWx));
@@ -2684,7 +2692,7 @@ ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, FieldSeqNode* fldSeq)
assert(GetVNFunc(VNNormVal(opA->GetVN(VNK_Conservative)), &consFuncApp) && consFuncApp.Equals(funcApp));
#endif
ValueNum fldSeqVN = VNForFieldSeq(fldSeq);
- res = VNForPtrToLoc(TYP_BYREF, funcApp.m_args[0], FieldSeqVNAppend(funcApp.m_args[1], fldSeqVN));
+ res = VNForFunc(TYP_BYREF, VNF_PtrToLoc, funcApp.m_args[0], FieldSeqVNAppend(funcApp.m_args[1], fldSeqVN));
}
else if (funcApp.m_func == VNF_PtrToStatic)
{
@@ -2917,6 +2925,11 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTreePtr tree,
var_types ValueNumStore::TypeOfVN(ValueNum vn)
{
+ if (vn == NoVN)
+ {
+ return TYP_UNDEF;
+ }
+
Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn));
return c->m_typ;
}
@@ -2936,6 +2949,11 @@ var_types ValueNumStore::TypeOfVN(ValueNum vn)
BasicBlock::loopNumber ValueNumStore::LoopOfVN(ValueNum vn)
{
+ if (vn == NoVN)
+ {
+ return MAX_LOOP_NUM;
+ }
+
Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn));
return c->m_loopNum;
}
@@ -3388,6 +3406,7 @@ bool ValueNumStore::IsVNFunc(ValueNum vn)
Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn));
switch (c->m_attribs)
{
+ case CEA_NotAField:
case CEA_Func0:
case CEA_Func1:
case CEA_Func2:
@@ -3401,6 +3420,11 @@ bool ValueNumStore::IsVNFunc(ValueNum vn)
bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp)
{
+ if (vn == NoVN)
+ {
+ return false;
+ }
+
Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn));
unsigned offset = ChunkOffset(vn);
assert(offset < c->m_numUsed);
@@ -3415,8 +3439,8 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp)
funcApp->m_args[1] = farg4->m_arg1;
funcApp->m_args[2] = farg4->m_arg2;
funcApp->m_args[3] = farg4->m_arg3;
- }
return true;
+ }
case CEA_Func3:
{
VNDefFunc3Arg* farg3 = &reinterpret_cast<VNDefFunc3Arg*>(c->m_defs)[offset];
@@ -3425,8 +3449,8 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp)
funcApp->m_args[0] = farg3->m_arg0;
funcApp->m_args[1] = farg3->m_arg1;
funcApp->m_args[2] = farg3->m_arg2;
- }
return true;
+ }
case CEA_Func2:
{
VNDefFunc2Arg* farg2 = &reinterpret_cast<VNDefFunc2Arg*>(c->m_defs)[offset];
@@ -3434,23 +3458,29 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp)
funcApp->m_arity = 2;
funcApp->m_args[0] = farg2->m_arg0;
funcApp->m_args[1] = farg2->m_arg1;
- }
return true;
+ }
case CEA_Func1:
{
VNDefFunc1Arg* farg1 = &reinterpret_cast<VNDefFunc1Arg*>(c->m_defs)[offset];
funcApp->m_func = farg1->m_func;
funcApp->m_arity = 1;
funcApp->m_args[0] = farg1->m_arg0;
- }
return true;
+ }
case CEA_Func0:
{
VNDefFunc0Arg* farg0 = &reinterpret_cast<VNDefFunc0Arg*>(c->m_defs)[offset];
funcApp->m_func = farg0->m_func;
funcApp->m_arity = 0;
+ return true;
}
+ case CEA_NotAField:
+ {
+ funcApp->m_func = VNF_NotAField;
+ funcApp->m_arity = 0;
return true;
+ }
default:
return false;
}
@@ -3751,8 +3781,9 @@ static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memo
// These need special semantics:
GT_COMMA, // == second argument (but with exception(s) from first).
GT_ADDR, GT_ARR_BOUNDS_CHECK,
- GT_OBJ, // May reference heap memory.
- GT_BLK, // May reference heap memory.
+ GT_OBJ, // May reference heap memory.
+ GT_BLK, // May reference heap memory.
+ GT_INIT_VAL, // Not strictly a pass-through.
// These control-flow operations need no values.
GT_JTRUE, GT_RETURN, GT_SWITCH, GT_RETFILT, GT_CKFINITE};
@@ -3842,10 +3873,9 @@ static const char* s_reservedNameArr[] = {
"$VN.No", // -1 NoVN
"$VN.Null", // 0 VNForNull()
"$VN.ZeroMap", // 1 VNForZeroMap()
- "$VN.NotAField", // 2 VNForNotAField()
- "$VN.ReadOnlyHeap", // 3 VNForROH()
- "$VN.Void", // 4 VNForVoid()
- "$VN.EmptyExcSet" // 5 VNForEmptyExcSet()
+ "$VN.ReadOnlyHeap", // 2 VNForROH()
+ "$VN.Void", // 3 VNForVoid()
+ "$VN.EmptyExcSet" // 4 VNForEmptyExcSet()
};
// Returns the string name of "vn" when it is a reserved value number, nullptr otherwise
@@ -4804,8 +4834,16 @@ void Compiler::fgValueNumberTreeConst(GenTreePtr tree)
tree->gtVNPair.SetBoth(vnStore->VNForDoubleCon(tree->gtDblCon.gtDconVal));
break;
case TYP_REF:
- // Null is the only constant. (Except maybe for String?)
- tree->gtVNPair.SetBoth(ValueNumStore::VNForNull());
+ if (tree->gtIntConCommon.IconValue() == 0)
+ {
+ tree->gtVNPair.SetBoth(ValueNumStore::VNForNull());
+ }
+ else
+ {
+ assert(tree->gtFlags == GTF_ICON_STR_HDL); // Constant object can be only frozen string.
+ tree->gtVNPair.SetBoth(
+ vnStore->VNForHandle(ssize_t(tree->gtIntConCommon.IconValue()), tree->GetIconHandleFlag()));
+ }
break;
case TYP_BYREF:
@@ -4903,9 +4941,6 @@ void Compiler::fgValueNumberBlockAssignment(GenTreePtr tree, bool evalAsgLhsInd)
}
#endif // DEBUG
}
- // Initblock's are of type void. Give them the void "value" -- they may occur in argument lists, which we
- // want to be able to give VN's to.
- tree->gtVNPair.SetBoth(ValueNumStore::VNForVoid());
}
else
{
@@ -4913,6 +4948,9 @@ void Compiler::fgValueNumberBlockAssignment(GenTreePtr tree, bool evalAsgLhsInd)
// TODO-CQ: Why not be complete, and get this case right?
fgMutateHeap(tree DEBUGARG("INITBLK - non local"));
}
+ // Initblock's are of type void. Give them the void "value" -- they may occur in argument lists, which we
+ // want to be able to give VN's to.
+ tree->gtVNPair.SetBoth(ValueNumStore::VNForVoid());
}
else
{
@@ -4953,17 +4991,21 @@ void Compiler::fgValueNumberBlockAssignment(GenTreePtr tree, bool evalAsgLhsInd)
assert(lhs->OperGet() == GT_IND);
lhsAddr = lhs->gtOp.gtOp1;
}
+
// For addr-of-local expressions, lib/cons shouldn't matter.
assert(lhsAddr->gtVNPair.BothEqual());
ValueNum lhsAddrVN = lhsAddr->GetVN(VNK_Liberal);
// Unpack the PtrToLoc value number of the address.
assert(vnStore->IsVNFunc(lhsAddrVN));
+
VNFuncApp lhsAddrFuncApp;
vnStore->GetVNFunc(lhsAddrVN, &lhsAddrFuncApp);
+
assert(lhsAddrFuncApp.m_func == VNF_PtrToLoc);
assert(vnStore->IsVNConstant(lhsAddrFuncApp.m_args[0]) &&
vnStore->ConstantValue<unsigned>(lhsAddrFuncApp.m_args[0]) == lhsLclNum);
+
lhsFldSeq = vnStore->FieldSeqVNToFieldSeq(lhsAddrFuncApp.m_args[1]);
}
@@ -5598,10 +5640,9 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd)
// (we looked in a side table above for its "def" identity). Look up that value.
ValueNumPair oldLhsVNPair =
lvaTable[lclFld->GetLclNum()].GetPerSsaData(lclFld->GetSsaNum())->m_vnPair;
- newLhsVNPair =
- vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lclFld->gtFieldSeq,
- rhsVNPair, // Pre-value.
- lvaGetActualType(lclFld->gtLclNum), compCurBB);
+ newLhsVNPair = vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lclFld->gtFieldSeq,
+ rhsVNPair, // Pre-value.
+ lclFld->TypeGet(), compCurBB);
}
}
lvaTable[lclFld->GetLclNum()].GetPerSsaData(lclDefSsaNum)->m_vnPair = newLhsVNPair;
@@ -6034,8 +6075,9 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd)
if (newVN == ValueNumStore::NoVN)
{
assert(arg->gtLclVarCommon.GetSsaNum() != ValueNumStore::NoVN);
- newVN = vnStore->VNForPtrToLoc(TYP_BYREF, vnStore->VNForIntCon(arg->gtLclVarCommon.GetLclNum()),
- vnStore->VNForFieldSeq(fieldSeq));
+ newVN = vnStore->VNForFunc(TYP_BYREF, VNF_PtrToLoc,
+ vnStore->VNForIntCon(arg->gtLclVarCommon.GetLclNum()),
+ vnStore->VNForFieldSeq(fieldSeq));
}
tree->gtVNPair.SetBoth(newVN);
}
@@ -6240,17 +6282,12 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd)
}
tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, addrXvnp);
}
- else if (!varTypeIsStruct(tree) && vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp) &&
- (funcApp.m_func == VNF_PtrToArrElem))
+ else if (vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp) && (funcApp.m_func == VNF_PtrToArrElem))
{
- // TODO-1stClassStructs: The above condition need not exclude struct types, but it is
- // excluded for now to minimize diffs.
fgValueNumberArrIndexVal(tree, &funcApp, addrXvnp.GetLiberal());
}
- else if (!varTypeIsStruct(tree) && addr->IsFieldAddr(this, &obj, &staticOffset, &fldSeq2))
+ else if (addr->IsFieldAddr(this, &obj, &staticOffset, &fldSeq2))
{
- // TODO-1stClassStructs: The above condition need not exclude struct types, but it is
- // excluded for now to minimize diffs.
if (fldSeq2 == FieldSeqStore::NotAField())
{
tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
@@ -6522,6 +6559,9 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd)
case GT_JTRUE:
case GT_LIST:
+#ifndef LEGACY_BACKEND
+ case GT_FIELD_LIST:
+#endif // !LEGACY_BACKEND
// These nodes never need to have a ValueNumber
tree->gtVNPair.SetBoth(ValueNumStore::NoVN);
break;
@@ -6667,7 +6707,7 @@ void Compiler::fgValueNumberCastTree(GenTreePtr tree)
bool srcIsUnsigned = ((tree->gtFlags & GTF_UNSIGNED) != 0);
bool hasOverflowCheck = tree->gtOverflowEx();
- assert(genActualType(castToType) == tree->TypeGet()); // Insure that the resultType is correct
+ assert(genActualType(castToType) == genActualType(tree->TypeGet())); // Insure that the resultType is correct
tree->gtVNPair = vnStore->VNPairForCast(srcVNPair, castToType, castFromType, srcIsUnsigned, hasOverflowCheck);
}
@@ -6816,6 +6856,7 @@ void Compiler::fgValueNumberHelperCallFunc(GenTreeCall* call, VNFunc vnf, ValueN
break;
case VNF_ReadyToRunStaticBase:
+ case VNF_ReadyToRunGenericStaticBase:
case VNF_ReadyToRunIsInstanceOf:
case VNF_ReadyToRunCastClass:
{
@@ -7061,11 +7102,11 @@ VNFunc Compiler::fgValueNumberHelperMethVNFunc(CorInfoHelpFunc helpFunc)
vnf = VNFunc(GT_MOD);
break;
case CORINFO_HELP_ULDIV:
- vnf = VNFunc(GT_DIV);
- break; // Is this the right thing?
+ vnf = VNFunc(GT_UDIV);
+ break;
case CORINFO_HELP_ULMOD:
- vnf = VNFunc(GT_MOD);
- break; // Is this the right thing?
+ vnf = VNFunc(GT_UMOD);
+ break;
case CORINFO_HELP_LNG2DBL:
vnf = VNF_Lng2Dbl;
@@ -7155,6 +7196,11 @@ VNFunc Compiler::fgValueNumberHelperMethVNFunc(CorInfoHelpFunc helpFunc)
case CORINFO_HELP_READYTORUN_STATIC_BASE:
vnf = VNF_ReadyToRunStaticBase;
break;
+#if COR_JIT_EE_VERSION > 460
+ case CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE:
+ vnf = VNF_ReadyToRunGenericStaticBase;
+ break;
+#endif // COR_JIT_EE_VERSION > 460
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
vnf = VNF_GetsharedGcstaticBaseDynamicclass;
break;