@@ -5975,7 +5975,7 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree)
5975
5975
if (cnsOff == nullptr) // It must have folded into a zero offset
5976
5976
{
5977
5977
// Record in the general zero-offset map.
5978
- GetZeroOffsetFieldMap()->Set (addr, fieldSeq);
5978
+ fgAddFieldSeqForZeroOffset (addr, fieldSeq);
5979
5979
}
5980
5980
else
5981
5981
{
@@ -6398,14 +6398,6 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac)
6398
6398
6399
6399
addr = gtNewLclvNode(lclNum, objRefType); // Use "tmpLcl" to create "addr" node.
6400
6400
}
6401
- else if (fldOffset == 0)
6402
- {
6403
- // Generate the "addr" node.
6404
- addr = objRef;
6405
- FieldSeqNode* fieldSeq =
6406
- fieldMayOverlap ? FieldSeqStore::NotAField() : GetFieldSeqStore()->CreateSingleton(symHnd);
6407
- GetZeroOffsetFieldMap()->Set(addr, fieldSeq);
6408
- }
6409
6401
else
6410
6402
{
6411
6403
addr = objRef;
@@ -6647,19 +6639,55 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac)
6647
6639
}
6648
6640
noway_assert(tree->gtOper == GT_IND);
6649
6641
6650
- // Pass down the current mac; if non null we are computing an address
6651
- GenTree* res = fgMorphSmpOp(tree, mac);
6652
-
6653
- if (fldOffset == 0 && res->OperGet() == GT_IND)
6642
+ if (fldOffset == 0)
6654
6643
{
6655
- GenTree* addr = res->gtOp.gtOp1;
6644
+ GenTree* addr = tree->gtOp.gtOp1;
6645
+
6646
+ // 'addr' may be a GT_COMMA. Skip over any comma nodes
6647
+ addr = addr->gtEffectiveVal();
6648
+
6649
+ #ifdef DEBUG
6650
+ if (verbose)
6651
+ {
6652
+ printf("\nBefore calling fgAddFieldSeqForZeroOffset:\n");
6653
+ gtDispTree(tree);
6654
+ }
6655
+ #endif
6656
+
6657
+ // We expect 'addr' to be an address at this point.
6658
+ // But there are also cases where we can see a GT_LCL_FLD or a GT_LCL_VAR:
6659
+ //
6660
+ // [001076] ----G------- /--* FIELD long m_constArray
6661
+ // [001072] ----G------- | \--* ADDR byref
6662
+ // [001073] ----G------- | \--* FIELD struct blob
6663
+ // [001074] ------------ | \--* ADDR byref
6664
+ // [001075] ------------ | \--* LCL_VAR struct V18 loc11
6665
+ //
6666
+ //
6667
+ assert((addr->TypeGet() == TYP_BYREF) || (addr->TypeGet() == TYP_I_IMPL) || (addr->OperGet() == GT_LCL_FLD) ||
6668
+ (addr->OperGet() == GT_LCL_VAR));
6669
+
6656
6670
// Since we don't make a constant zero to attach the field sequence to, associate it with the "addr" node.
6657
6671
FieldSeqNode* fieldSeq =
6658
6672
fieldMayOverlap ? FieldSeqStore::NotAField() : GetFieldSeqStore()->CreateSingleton(symHnd);
6659
6673
fgAddFieldSeqForZeroOffset(addr, fieldSeq);
6660
6674
}
6661
6675
6662
- return res;
6676
+ // Pass down the current mac; if non null we are computing an address
6677
+ GenTree* result = fgMorphSmpOp(tree, mac);
6678
+
6679
+ #ifdef DEBUG
6680
+ if (fldOffset == 0)
6681
+ {
6682
+ if (verbose)
6683
+ {
6684
+ printf("\nAfter calling fgMorphSmpOp (zero fldOffset case):\n");
6685
+ gtDispTree(result);
6686
+ }
6687
+ }
6688
+ #endif
6689
+
6690
+ return result;
6663
6691
}
6664
6692
6665
6693
//------------------------------------------------------------------------------
@@ -12897,7 +12925,8 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
12897
12925
/* Negate the constant and change the node to be "+" */
12898
12926
12899
12927
op2->gtIntConCommon.SetIconValue(-op2->gtIntConCommon.IconValue());
12900
- oper = GT_ADD;
12928
+ op2->gtIntCon.gtFieldSeq = FieldSeqStore::NotAField();
12929
+ oper = GT_ADD;
12901
12930
tree->ChangeOper(oper);
12902
12931
goto CM_ADD_OP;
12903
12932
}
@@ -13472,13 +13501,25 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
13472
13501
temp->AsLclFld()->gtFieldSeq =
13473
13502
GetFieldSeqStore()->Append(temp->AsLclFld()->gtFieldSeq, fieldSeq);
13474
13503
}
13475
- else
13504
+ else // we have a GT_LCL_VAR
13476
13505
{
13477
- temp->ChangeOper(GT_LCL_FLD); // Note that this makes the gtFieldSeq "NotAField"...
13506
+ assert(temp->OperGet() == GT_LCL_VAR);
13507
+ temp->ChangeOper(GT_LCL_FLD); // Note that this typically makes the gtFieldSeq "NotAField"...
13478
13508
temp->AsLclFld()->gtLclOffs = (unsigned short)ival1;
13479
- if (fieldSeq != nullptr)
13480
- { // If it does represent a field, note that.
13481
- temp->AsLclFld()->gtFieldSeq = fieldSeq;
13509
+
13510
+ if (temp->AsLclFld()->gtFieldSeq == FieldSeqStore::NotAField())
13511
+ {
13512
+ if (fieldSeq != nullptr)
13513
+ {
13514
+ // If it does represent a field, note that.
13515
+ temp->AsLclFld()->gtFieldSeq = fieldSeq;
13516
+ }
13517
+ }
13518
+ else
13519
+ {
13520
+ // Append 'fieldSeq' to the exsisting one
13521
+ temp->AsLclFld()->gtFieldSeq =
13522
+ GetFieldSeqStore()->Append(temp->AsLclFld()->gtFieldSeq, fieldSeq);
13482
13523
}
13483
13524
}
13484
13525
temp->gtType = tree->gtType;
@@ -13689,7 +13730,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
13689
13730
zeroFieldSeq = GetFieldSeqStore()->Append(existingZeroOffsetFldSeq, zeroFieldSeq);
13690
13731
}
13691
13732
// Transfer the annotation to the new GT_ADDR node.
13692
- GetZeroOffsetFieldMap()->Set( op1, zeroFieldSeq, NodeToFieldSeqMap::Overwrite );
13733
+ fgAddFieldSeqForZeroOffset( op1, zeroFieldSeq);
13693
13734
}
13694
13735
commaNode->gtOp.gtOp2 = op1;
13695
13736
// Originally, I gave all the comma nodes type "byref". But the ADDR(IND(x)) == x transform
@@ -18703,66 +18744,132 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
18703
18744
}
18704
18745
};
18705
18746
18706
- void Compiler::fgAddFieldSeqForZeroOffset(GenTree* op1, FieldSeqNode* fieldSeq)
18747
+ //------------------------------------------------------------------------
18748
+ // fgAddFieldSeqForZeroOffset:
18749
+ // Associate a fieldSeq (with a zero offset) with the GenTree node 'addr'
18750
+ //
18751
+ // Arguments:
18752
+ // addr - A GenTree node
18753
+ // fieldSeqZero - a fieldSeq (with a zero offset)
18754
+ //
18755
+ // Notes:
18756
+ // Some GenTree nodes have internal fields that record the field sequence.
18757
+ // If we have one of these nodes: GT_CNS_INT, GT_LCL_FLD
18758
+ // we can append the field sequence using the gtFieldSeq
18759
+ // If we have a GT_ADD of a GT_CNS_INT we can use the
18760
+ // fieldSeq from child node.
18761
+ // Otherwise we record 'fieldSeqZero' in the GenTree node using
18762
+ // a Map: GetFieldSeqStore()
18763
+ // When doing so we take care to preserve any existing zero field sequence
18764
+ //
18765
+ void Compiler::fgAddFieldSeqForZeroOffset(GenTree* addr, FieldSeqNode* fieldSeqZero)
18707
18766
{
18708
- assert(op1->TypeGet() == TYP_BYREF || op1->TypeGet() == TYP_I_IMPL || op1->TypeGet() == TYP_REF);
18767
+ // We expect 'addr' to be an address at this point.
18768
+ // But there are also cases where we can see a GT_LCL_FLD or a GT_LCL_VAR:
18769
+ //
18770
+ // [001076] ----G------- /--* FIELD long m_constArray
18771
+ // [001072] ----G------- | \--* ADDR byref
18772
+ // [001073] ----G------- | \--* FIELD struct blob
18773
+ // [001074] ------------ | \--* ADDR byref
18774
+ // [001075] ------------ | \--* LCL_VAR struct V18 loc11
18775
+ //
18776
+ //
18777
+ assert(addr->TypeGet() == TYP_BYREF || addr->TypeGet() == TYP_I_IMPL || addr->OperGet() == GT_LCL_FLD ||
18778
+ addr->OperGet() == GT_LCL_VAR);
18779
+
18780
+ FieldSeqNode* fieldSeqUpdate = fieldSeqZero;
18781
+ GenTree* fieldSeqNode = addr;
18782
+ bool fieldSeqRecorded = false;
18783
+ bool isMapAnnotation = false;
18784
+
18785
+ #ifdef DEBUG
18786
+ if (verbose)
18787
+ {
18788
+ printf("\nfgAddFieldSeqForZeroOffset for");
18789
+ gtDispFieldSeq(fieldSeqZero);
18790
+
18791
+ printf("\naddr (Before)\n");
18792
+ gtDispNode(addr, nullptr, nullptr, false);
18793
+ gtDispCommonEndLine(addr);
18794
+ }
18795
+ #endif // DEBUG
18709
18796
18710
- switch (op1 ->OperGet())
18797
+ switch (addr ->OperGet())
18711
18798
{
18799
+ case GT_CNS_INT:
18800
+ fieldSeqUpdate = GetFieldSeqStore()->Append(addr->gtIntCon.gtFieldSeq, fieldSeqZero);
18801
+ addr->gtIntCon.gtFieldSeq = fieldSeqUpdate;
18802
+ fieldSeqRecorded = true;
18803
+ break;
18804
+
18805
+ case GT_LCL_FLD:
18806
+ {
18807
+ GenTreeLclFld* lclFld = addr->AsLclFld();
18808
+ fieldSeqUpdate = GetFieldSeqStore()->Append(lclFld->gtFieldSeq, fieldSeqZero);
18809
+ lclFld->gtFieldSeq = fieldSeqUpdate;
18810
+ fieldSeqRecorded = true;
18811
+ break;
18812
+ }
18813
+
18712
18814
case GT_ADDR:
18713
- if (op1 ->gtOp.gtOp1->OperGet() == GT_LCL_FLD)
18815
+ if (addr ->gtOp.gtOp1->OperGet() == GT_LCL_FLD)
18714
18816
{
18715
- GenTreeLclFld* lclFld = op1->gtOp.gtOp1->AsLclFld();
18716
- lclFld->gtFieldSeq = GetFieldSeqStore()->Append(lclFld->gtFieldSeq, fieldSeq);
18817
+ fieldSeqNode = addr->gtOp.gtOp1;
18818
+
18819
+ GenTreeLclFld* lclFld = addr->gtOp.gtOp1->AsLclFld();
18820
+ fieldSeqUpdate = GetFieldSeqStore()->Append(lclFld->gtFieldSeq, fieldSeqZero);
18821
+ lclFld->gtFieldSeq = fieldSeqUpdate;
18822
+ fieldSeqRecorded = true;
18717
18823
}
18718
18824
break;
18719
18825
18720
18826
case GT_ADD:
18721
- if (op1 ->gtOp.gtOp1->OperGet() == GT_CNS_INT)
18827
+ if (addr ->gtOp.gtOp1->OperGet() == GT_CNS_INT)
18722
18828
{
18723
- FieldSeqNode* op1Fs = op1->gtOp.gtOp1->gtIntCon.gtFieldSeq;
18724
- if (op1Fs != nullptr)
18725
- {
18726
- op1Fs = GetFieldSeqStore()->Append(op1Fs, fieldSeq);
18727
- op1->gtOp.gtOp1->gtIntCon.gtFieldSeq = op1Fs;
18728
- }
18829
+ fieldSeqNode = addr->gtOp.gtOp1;
18830
+
18831
+ fieldSeqUpdate = GetFieldSeqStore()->Append(addr->gtOp.gtOp1->gtIntCon.gtFieldSeq, fieldSeqZero);
18832
+ addr->gtOp.gtOp1->gtIntCon.gtFieldSeq = fieldSeqUpdate;
18833
+ fieldSeqRecorded = true;
18729
18834
}
18730
- else if (op1 ->gtOp.gtOp2->OperGet() == GT_CNS_INT)
18835
+ else if (addr ->gtOp.gtOp2->OperGet() == GT_CNS_INT)
18731
18836
{
18732
- FieldSeqNode* op2Fs = op1->gtOp.gtOp2->gtIntCon.gtFieldSeq;
18733
- if (op2Fs != nullptr)
18734
- {
18735
- op2Fs = GetFieldSeqStore()->Append(op2Fs, fieldSeq);
18736
- op1->gtOp.gtOp2->gtIntCon.gtFieldSeq = op2Fs;
18737
- }
18837
+ fieldSeqNode = addr->gtOp.gtOp2;
18838
+
18839
+ fieldSeqUpdate = GetFieldSeqStore()->Append(addr->gtOp.gtOp2->gtIntCon.gtFieldSeq, fieldSeqZero);
18840
+ addr->gtOp.gtOp2->gtIntCon.gtFieldSeq = fieldSeqUpdate;
18841
+ fieldSeqRecorded = true;
18738
18842
}
18739
18843
break;
18740
18844
18741
- case GT_CNS_INT:
18845
+ default:
18846
+ break;
18847
+ }
18848
+
18849
+ if (fieldSeqRecorded == false)
18850
+ {
18851
+ // Record in the general zero-offset map.
18852
+
18853
+ // The "addr" node might already be annotated with a zero-offset field sequence.
18854
+ FieldSeqNode* existingFieldSeq = nullptr;
18855
+ if (GetZeroOffsetFieldMap()->Lookup(addr, &existingFieldSeq))
18742
18856
{
18743
- FieldSeqNode* op1Fs = op1->gtIntCon.gtFieldSeq;
18744
- if (op1Fs != nullptr)
18745
- {
18746
- op1Fs = GetFieldSeqStore()->Append(op1Fs, fieldSeq);
18747
- op1->gtIntCon.gtFieldSeq = op1Fs;
18748
- }
18857
+ // Append the zero field sequences
18858
+ fieldSeqUpdate = GetFieldSeqStore()->Append(existingFieldSeq, fieldSeqZero);
18749
18859
}
18750
- break;
18751
-
18752
- default:
18753
- // Record in the general zero-offset map.
18860
+ // Overwrite the field sequence annotation for op1
18861
+ GetZeroOffsetFieldMap()->Set(addr, fieldSeqUpdate, NodeToFieldSeqMap::Overwrite);
18862
+ fieldSeqRecorded = true;
18863
+ }
18754
18864
18755
- // The "op1" node might already be annotated with a zero-offset field sequence.
18756
- FieldSeqNode* existingZeroOffsetFldSeq = nullptr;
18757
- if (GetZeroOffsetFieldMap()->Lookup(op1, &existingZeroOffsetFldSeq))
18758
- {
18759
- // Append the zero field sequences
18760
- fieldSeq = GetFieldSeqStore()->Append(existingZeroOffsetFldSeq, fieldSeq);
18761
- }
18762
- // Set the new field sequence annotation for op1
18763
- GetZeroOffsetFieldMap()->Set(op1, fieldSeq, NodeToFieldSeqMap::Overwrite);
18764
- break;
18865
+ #ifdef DEBUG
18866
+ if (verbose)
18867
+ {
18868
+ printf(" (After)\n");
18869
+ gtDispNode(fieldSeqNode, nullptr, nullptr, false);
18870
+ gtDispCommonEndLine(fieldSeqNode);
18765
18871
}
18872
+ #endif // DEBUG
18766
18873
}
18767
18874
18768
18875
//------------------------------------------------------------------------
0 commit comments