@@ -4167,32 +4167,33 @@ ValueNum ValueNumStore::VNForFieldSeq(FieldSeqNode* fieldSeq)
41674167 {
41684168 return VNForNull ();
41694169 }
4170- else if (fieldSeq == FieldSeqStore::NotAField ())
4170+
4171+ ValueNum fieldSeqVN;
4172+ if (fieldSeq == FieldSeqStore::NotAField ())
41714173 {
41724174 // We always allocate a new, unique VN in this call.
41734175 Chunk* c = GetAllocChunk (TYP_REF, CEA_NotAField);
41744176 unsigned offsetWithinChunk = c->AllocVN ();
4175- ValueNum result = c->m_baseVN + offsetWithinChunk;
4176- return result;
4177+ fieldSeqVN = c->m_baseVN + offsetWithinChunk;
41774178 }
41784179 else
41794180 {
41804181 ssize_t fieldHndVal = ssize_t (fieldSeq->m_fieldHnd );
41814182 ValueNum fieldHndVN = VNForHandle (fieldHndVal, GTF_ICON_FIELD_HDL);
41824183 ValueNum seqNextVN = VNForFieldSeq (fieldSeq->m_next );
4183- ValueNum fieldSeqVN = VNForFunc (TYP_REF, VNF_FieldSeq, fieldHndVN, seqNextVN);
4184+ fieldSeqVN = VNForFunc (TYP_REF, VNF_FieldSeq, fieldHndVN, seqNextVN);
4185+ }
41844186
41854187#ifdef DEBUG
4186- if (m_pComp->verbose )
4187- {
4188- printf (" FieldSeq" );
4189- vnDump (m_pComp, fieldSeqVN);
4190- printf (" is " FMT_VN " \n " , fieldSeqVN);
4191- }
4188+ if (m_pComp->verbose )
4189+ {
4190+ printf (" FieldSeq" );
4191+ vnDump (m_pComp, fieldSeqVN);
4192+ printf (" is " FMT_VN " \n " , fieldSeqVN);
4193+ }
41924194#endif
41934195
4194- return fieldSeqVN;
4195- }
4196+ return fieldSeqVN;
41964197}
41974198
41984199FieldSeqNode* ValueNumStore::FieldSeqVNToFieldSeq (ValueNum vn)
@@ -5961,6 +5962,7 @@ void ValueNumStore::vnDump(Compiler* comp, ValueNum vn, bool isPtr)
59615962 switch (funcApp.m_func )
59625963 {
59635964 case VNF_FieldSeq:
5965+ case VNF_NotAField:
59645966 vnDumpFieldSeq (comp, &funcApp, true );
59655967 break ;
59665968 case VNF_MapSelect:
@@ -6068,6 +6070,12 @@ void ValueNumStore::vnDumpExcSeq(Compiler* comp, VNFuncApp* excSeq, bool isHead)
60686070
60696071void ValueNumStore::vnDumpFieldSeq (Compiler* comp, VNFuncApp* fieldSeq, bool isHead)
60706072{
6073+ if (fieldSeq->m_func == VNF_NotAField)
6074+ {
6075+ printf (" <NotAField>" );
6076+ return ;
6077+ }
6078+
60716079 assert (fieldSeq->m_func == VNF_FieldSeq); // Precondition.
60726080 // First arg is the field handle VN.
60736081 assert (IsVNConstant (fieldSeq->m_args [0 ]) && TypeOfVN (fieldSeq->m_args [0 ]) == TYP_I_IMPL);
@@ -8592,12 +8600,21 @@ void Compiler::fgValueNumberTree(GenTree* tree)
85928600 newVN = vnStore->VNForExpr (compCurBB, TYP_BYREF);
85938601 }
85948602 }
8603+
85958604 if (newVN == ValueNumStore::NoVN)
85968605 {
8606+ // We may have a zero-offset field sequence on this ADDR.
8607+ FieldSeqNode* zeroOffsetFieldSeq = nullptr ;
8608+ if (GetZeroOffsetFieldMap ()->Lookup (tree, &zeroOffsetFieldSeq))
8609+ {
8610+ fieldSeq = GetFieldSeqStore ()->Append (fieldSeq, zeroOffsetFieldSeq);
8611+ }
8612+
85978613 newVN = vnStore->VNForFunc (TYP_BYREF, VNF_PtrToLoc,
85988614 vnStore->VNForIntCon (arg->AsLclVarCommon ()->GetLclNum ()),
85998615 vnStore->VNForFieldSeq (fieldSeq));
86008616 }
8617+
86018618 tree->gtVNPair .SetBoth (newVN);
86028619 }
86038620 else if ((arg->gtOper == GT_IND) || arg->OperIsBlk ())
@@ -8608,8 +8625,7 @@ void Compiler::fgValueNumberTree(GenTree* tree)
86088625
86098626 ValueNumPair addrVNP = ValueNumPair ();
86108627 FieldSeqNode* zeroOffsetFieldSeq = nullptr ;
8611- if (GetZeroOffsetFieldMap ()->Lookup (tree, &zeroOffsetFieldSeq) &&
8612- (zeroOffsetFieldSeq != FieldSeqStore::NotAField ()))
8628+ if (GetZeroOffsetFieldMap ()->Lookup (tree, &zeroOffsetFieldSeq))
86138629 {
86148630 ValueNum addrExtended = vnStore->ExtendPtrVN (arg->AsIndir ()->Addr (), zeroOffsetFieldSeq);
86158631 if (addrExtended != ValueNumStore::NoVN)
@@ -9270,6 +9286,8 @@ void Compiler::fgValueNumberTree(GenTree* tree)
92709286 printf (" \n " );
92719287 }
92729288 }
9289+
9290+ fgDebugCheckValueNumberedTree (tree);
92739291#endif // DEBUG
92749292}
92759293
@@ -10965,6 +10983,72 @@ void Compiler::fgDebugCheckExceptionSets()
1096510983 }
1096610984}
1096710985
10986+ // ------------------------------------------------------------------------
10987+ // fgDebugCheckValueNumberedTree: Verify proper numbering for "tree".
10988+ //
10989+ // Currently only checks that we have not forgotten to add a zero-offset
10990+ // field sequence to "tree"'s value number.
10991+ //
10992+ // Arguments:
10993+ // tree - The tree, that has just been numbered, to check
10994+ //
10995+ void Compiler::fgDebugCheckValueNumberedTree (GenTree* tree)
10996+ {
10997+ FieldSeqNode* zeroOffsetFldSeq;
10998+ if (GetZeroOffsetFieldMap ()->Lookup (tree, &zeroOffsetFldSeq))
10999+ {
11000+ // Empty field sequences should never be recorded in the map.
11001+ assert (zeroOffsetFldSeq != nullptr );
11002+
11003+ ValueNum vns[] = {tree->GetVN (VNK_Liberal), tree->GetVN (VNK_Conservative)};
11004+ for (ValueNum vn : vns)
11005+ {
11006+ VNFuncApp vnFunc;
11007+ if (vnStore->GetVNFunc (vn, &vnFunc))
11008+ {
11009+ FieldSeqNode* fullFldSeq;
11010+ switch (vnFunc.m_func )
11011+ {
11012+ case VNF_PtrToLoc:
11013+ case VNF_PtrToStatic:
11014+ fullFldSeq = vnStore->FieldSeqVNToFieldSeq (vnFunc.m_args [1 ]);
11015+ break ;
11016+
11017+ case VNF_PtrToArrElem:
11018+ fullFldSeq = vnStore->FieldSeqVNToFieldSeq (vnFunc.m_args [3 ]);
11019+ break ;
11020+
11021+ default :
11022+ continue ;
11023+ }
11024+
11025+ // Verify that the "fullFldSeq" we have just collected is of the
11026+ // form "[outer fields, zeroOffsetFldSeq]", or is "NotAField".
11027+ if (fullFldSeq == FieldSeqStore::NotAField ())
11028+ {
11029+ continue ;
11030+ }
11031+
11032+ // This check relies on the canonicality of field sequences.
11033+ FieldSeqNode* fldSeq = fullFldSeq;
11034+ bool zeroOffsetFldSeqFound = false ;
11035+ while (fldSeq != nullptr )
11036+ {
11037+ if (fldSeq == zeroOffsetFldSeq)
11038+ {
11039+ zeroOffsetFldSeqFound = true ;
11040+ break ;
11041+ }
11042+
11043+ fldSeq = fldSeq->m_next ;
11044+ }
11045+
11046+ assert (zeroOffsetFldSeqFound);
11047+ }
11048+ }
11049+ }
11050+ }
11051+
1096811052// This method asserts that SSA name constraints specified are satisfied.
1096911053// Until we figure out otherwise, all VN's are assumed to be liberal.
1097011054// TODO-Cleanup: new JitTestLabels for lib vs cons vs both VN classes?
0 commit comments