@@ -436,6 +436,7 @@ ValueNumStore::ValueNumStore(Compiler* comp, CompAllocator alloc)
436
436
, m_longCnsMap(nullptr)
437
437
, m_handleMap(nullptr)
438
438
, m_embeddedToCompileTimeHandleMap(alloc)
439
+ , m_fieldAddressToFieldSeqMap(alloc)
439
440
, m_floatCnsMap(nullptr)
440
441
, m_doubleCnsMap(nullptr)
441
442
, m_byrefCnsMap(nullptr)
@@ -8254,12 +8255,20 @@ void Compiler::fgValueNumberTreeConst(GenTree* tree)
8254
8255
case TYP_BOOL:
8255
8256
if (tree->IsIconHandle())
8256
8257
{
8257
- const ssize_t embeddedHandle = tree->AsIntCon()->IconValue();
8258
- tree->gtVNPair.SetBoth(vnStore->VNForHandle(embeddedHandle, tree->GetIconHandleFlag()));
8259
- if (tree->GetIconHandleFlag() == GTF_ICON_CLASS_HDL)
8258
+ const GenTreeIntCon* cns = tree->AsIntCon();
8259
+ const GenTreeFlags handleFlags = tree->GetIconHandleFlag();
8260
+ tree->gtVNPair.SetBoth(vnStore->VNForHandle(cns->IconValue(), handleFlags));
8261
+ if (handleFlags == GTF_ICON_CLASS_HDL)
8260
8262
{
8261
- const ssize_t compileTimeHandle = tree->AsIntCon()->gtCompileTimeHandle;
8262
- vnStore->AddToEmbeddedHandleMap(embeddedHandle, compileTimeHandle);
8263
+ vnStore->AddToEmbeddedHandleMap(cns->IconValue(), cns->gtCompileTimeHandle);
8264
+ }
8265
+ else if ((handleFlags == GTF_ICON_STATIC_HDL) && (cns->gtFieldSeq != nullptr) &&
8266
+ (cns->gtFieldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress))
8267
+ {
8268
+ assert(cns->IconValue() == cns->gtFieldSeq->GetOffset());
8269
+
8270
+ // For now we're interested only in SimpleStaticKnownAddress
8271
+ vnStore->AddToFieldAddressToFieldSeqMap(cns->gtVNPair.GetLiberal(), cns->gtFieldSeq);
8263
8272
}
8264
8273
}
8265
8274
else if ((typ == TYP_LONG) || (typ == TYP_ULONG))
@@ -8570,13 +8579,13 @@ static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, s
8570
8579
ValueNum op1vn = op1->gtVNPair.GetLiberal();
8571
8580
ValueNum op2vn = op2->gtVNPair.GetLiberal();
8572
8581
8573
- if (! op1->IsIconHandle(GTF_ICON_STATIC_HDL ) && op1->gtVNPair.BothEqual( ) && vnStore->IsVNConstant (op1vn) &&
8582
+ if (op1->gtVNPair.BothEqual( ) && vnStore->IsVNConstant(op1vn ) && ! vnStore->IsVNHandle (op1vn) &&
8574
8583
varTypeIsIntegral(vnStore->TypeOfVN(op1vn)))
8575
8584
{
8576
8585
val += vnStore->CoercedConstantValue<ssize_t>(op1vn);
8577
8586
tree = op2;
8578
8587
}
8579
- else if (! op2->IsIconHandle(GTF_ICON_STATIC_HDL ) && op2->gtVNPair.BothEqual( ) && vnStore->IsVNConstant (op2vn) &&
8588
+ else if (op2->gtVNPair.BothEqual( ) && vnStore->IsVNConstant(op2vn ) && ! vnStore->IsVNHandle (op2vn) &&
8580
8589
varTypeIsIntegral(vnStore->TypeOfVN(op2vn)))
8581
8590
{
8582
8591
val += vnStore->CoercedConstantValue<ssize_t>(op2vn);
@@ -8590,12 +8599,20 @@ static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, s
8590
8599
}
8591
8600
8592
8601
// Base address is expected to be static field's address
8593
- if ((tree->IsCnsIntOrI()) && (tree->AsIntCon()->gtFieldSeq != nullptr) &&
8594
- (tree->AsIntCon()->gtFieldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress))
8602
+ ValueNum treeVN = tree->gtVNPair.GetLiberal();
8603
+ if (tree->gtVNPair.BothEqual() && vnStore->IsVNHandle(treeVN) &&
8604
+ (vnStore->GetHandleFlags(treeVN) == GTF_ICON_STATIC_HDL))
8595
8605
{
8596
- *pFseq = tree->AsIntCon()->gtFieldSeq;
8597
- *byteOffset = tree->AsIntCon()->IconValue() + val - tree->AsIntCon()->gtFieldSeq->GetOffset();
8598
- return true;
8606
+ FieldSeq* fldSeq = vnStore->GetFieldSeqFromAddress(treeVN);
8607
+ if (fldSeq != nullptr)
8608
+ {
8609
+ assert(fldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress);
8610
+ assert(fldSeq->GetOffset() == vnStore->CoercedConstantValue<ssize_t>(treeVN));
8611
+
8612
+ *pFseq = fldSeq;
8613
+ *byteOffset = val;
8614
+ return true;
8615
+ }
8599
8616
}
8600
8617
return false;
8601
8618
}
@@ -9769,6 +9786,13 @@ ValueNum ValueNumStore::VNForCast(ValueNum srcVN,
9769
9786
bool srcIsUnsigned, /* = false */
9770
9787
bool hasOverflowCheck) /* = false */
9771
9788
{
9789
+
9790
+ if ((castFromType == TYP_I_IMPL) && (castToType == TYP_BYREF) && IsVNHandle(srcVN))
9791
+ {
9792
+ // Omit cast for (h)CNS_INT [TYP_I_IMPL -> TYP_BYREF]
9793
+ return srcVN;
9794
+ }
9795
+
9772
9796
// The resulting type after performing the cast is always widened to a supported IL stack size
9773
9797
var_types resultType = genActualType(castToType);
9774
9798
@@ -9808,8 +9832,9 @@ ValueNumPair ValueNumStore::VNPairForCast(ValueNumPair srcVNPair,
9808
9832
bool srcIsUnsigned, /* = false */
9809
9833
bool hasOverflowCheck) /* = false */
9810
9834
{
9811
- ValueNum srcLibVN = srcVNPair.GetLiberal();
9812
- ValueNum srcConVN = srcVNPair.GetConservative();
9835
+ ValueNum srcLibVN = srcVNPair.GetLiberal();
9836
+ ValueNum srcConVN = srcVNPair.GetConservative();
9837
+
9813
9838
ValueNum castLibVN = VNForCast(srcLibVN, castToType, castFromType, srcIsUnsigned, hasOverflowCheck);
9814
9839
ValueNum castConVN;
9815
9840
0 commit comments