unsigned lclNum = lclVarTree->GetLclNum();
+ unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);
// Ignore vars that we excluded from SSA (for example, because they're address-exposed). They don't have
// SSA names in which to store VN's on defs. We'll yield unique VN's when we read from them.
- if (lvaInSsa(lclNum))
+ if (lvaInSsa(lclNum) && lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM)
{
// Should not have been recorded as updating ByrefExposed.
assert(!GetMemorySsaMap(ByrefExposed)->Lookup(tree));
- unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);
-
ValueNum initBlkVN = ValueNumStore::NoVN;
GenTree* initConst = rhs;
if (isEntire && initConst->OperGet() == GT_CNS_INT)
// Should not have been recorded as updating the GC heap.
assert(!GetMemorySsaMap(GcHeap)->Lookup(tree));
- unsigned lhsLclNum = lclVarTree->GetLclNum();
- FieldSeqNode* lhsFldSeq = nullptr;
+ unsigned lhsLclNum = lclVarTree->GetLclNum();
+ FieldSeqNode* lhsFldSeq = nullptr;
+ unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);
// If it's excluded from SSA, don't need to do anything.
- if (lvaInSsa(lhsLclNum))
+ if (lvaInSsa(lhsLclNum) && lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM)
{
// Should not have been recorded as updating ByrefExposed.
assert(!GetMemorySsaMap(ByrefExposed)->Lookup(tree));
- unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);
-
if (lhs->IsLocalExpr(this, &lclVarTree, &lhsFldSeq))
{
noway_assert(lclVarTree->GetLclNum() == lhsLclNum);
{
unsigned rhsLclNum = rhsLclVarTree->GetLclNum();
rhsVarDsc = &lvaTable[rhsLclNum];
- if (!lvaInSsa(rhsLclNum) || rhsFldSeq == FieldSeqStore::NotAField())
+ if (!lvaInSsa(rhsLclNum) || !rhsLclVarTree->HasSsaName() ||
+ rhsFldSeq == FieldSeqStore::NotAField())
{
rhsVNPair.SetBoth(vnStore->VNForExpr(compCurBB, rhsLclVarTree->TypeGet()));
isNewUniq = true;
{
unsigned rhsLclNum = rhsLclVarTree->GetLclNum();
rhsVarDsc = &lvaTable[rhsLclNum];
- if (!lvaInSsa(rhsLclNum) || rhsFldSeq == FieldSeqStore::NotAField())
+ if (!lvaInSsa(rhsLclNum) || !rhsLclVarTree->HasSsaName() ||
+ rhsFldSeq == FieldSeqStore::NotAField())
{
isNewUniq = true;
}
LclVarDsc* varDsc = &lvaTable[lclNum];
var_types indType = tree->TypeGet();
- if ((lclFld->GetFieldSeq() == FieldSeqStore::NotAField()) || !lvaInSsa(lclFld->GetLclNum()))
+ if ((lclFld->GetFieldSeq() == FieldSeqStore::NotAField()) || !lvaInSsa(lclFld->GetLclNum()) ||
+ !lclFld->HasSsaName())
{
// This doesn't represent a proper field access or it's a struct
// with overlapping fields that is hard to reason about; return a new unique VN.
wasLocal = true;
+ bool wasInSsa = false;
if (lvaInSsa(lclNum))
{
FieldSeqNode* fieldSeq = vnStore->FieldSeqVNToFieldSeq(funcApp.m_args[1]);
// Either "arg" is the address of (part of) a local itself, or else we have
// a "rogue" PtrToLoc, one that should have made the local in question
// address-exposed. Assert on that.
- GenTreeLclVarCommon* lclVarTree = nullptr;
- bool isEntire = false;
- unsigned lclDefSsaNum = SsaConfig::RESERVED_SSA_NUM;
- ValueNumPair newLhsVNPair;
+ GenTreeLclVarCommon* lclVarTree = nullptr;
+ bool isEntire = false;
- if (arg->DefinesLocalAddr(this, genTypeSize(lhs->TypeGet()), &lclVarTree, &isEntire))
+ if (arg->DefinesLocalAddr(this, genTypeSize(lhs->TypeGet()), &lclVarTree, &isEntire) &&
+ lclVarTree->HasSsaName())
{
// The local #'s should agree.
assert(lclNum == lclVarTree->GetLclNum());
rhsVNPair.SetBoth(vnStore->VNForExpr(compCurBB, lclVarTree->TypeGet()));
}
+ unsigned lclDefSsaNum;
+ ValueNumPair newLhsVNPair;
if (isEntire)
{
newLhsVNPair = rhsVNPair;
vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, fieldSeq, rhsVNPair,
lhs->TypeGet(), compCurBB);
}
- lvaTable[lclNum].GetPerSsaData(lclDefSsaNum)->m_vnPair = newLhsVNPair;
+
+ if (lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM)
+ {
+ lvaTable[lclNum].GetPerSsaData(lclDefSsaNum)->m_vnPair = newLhsVNPair;
+ wasInSsa = true;
+#ifdef DEBUG
+ if (verbose)
+ {
+ printf("Tree ");
+ Compiler::printTreeID(tree);
+ printf(" assigned VN to local var V%02u/%d: VN ", lclNum, lclDefSsaNum);
+ vnpPrint(newLhsVNPair, 1);
+ printf("\n");
+ }
+#endif // DEBUG
+ }
}
else
{
unreached(); // "Rogue" PtrToLoc, as discussed above.
}
-#ifdef DEBUG
- if (verbose)
- {
- printf("Tree ");
- Compiler::printTreeID(tree);
- printf(" assigned VN to local var V%02u/%d: VN ", lclNum, lclDefSsaNum);
- vnpPrint(newLhsVNPair, 1);
- printf("\n");
- }
-#endif // DEBUG
}
- else if (lvaVarAddrExposed(lclNum))
+
+ if (!wasInSsa && lvaVarAddrExposed(lclNum))
{
// Need to record the effect on ByrefExposed.
// We could use MapStore here and MapSelect on reads of address-exposed locals
{
FieldSeqNode* fieldSeq = nullptr;
ValueNum newVN = ValueNumStore::NoVN;
- if (!lvaInSsa(arg->AsLclVarCommon()->GetLclNum()))
+ if (!lvaInSsa(arg->AsLclVarCommon()->GetLclNum()) || !arg->AsLclVarCommon()->HasSsaName())
{
newVN = vnStore->VNForExpr(compCurBB, TYP_BYREF);
}
}
if (newVN == ValueNumStore::NoVN)
{
- assert(arg->AsLclVarCommon()->GetSsaNum() != ValueNumStore::NoVN);
newVN = vnStore->VNForFunc(TYP_BYREF, VNF_PtrToLoc,
vnStore->VNForIntCon(arg->AsLclVarCommon()->GetLclNum()),
vnStore->VNForFieldSeq(fieldSeq));
VNFuncApp funcApp;
// Is it a local or a heap address?
- if (addr->IsLocalAddrExpr(this, &lclVarTree, &localFldSeq) && lvaInSsa(lclVarTree->GetLclNum()))
+ if (addr->IsLocalAddrExpr(this, &lclVarTree, &localFldSeq) && lvaInSsa(lclVarTree->GetLclNum()) &&
+ lclVarTree->HasSsaName())
{
unsigned lclNum = lclVarTree->GetLclNum();
unsigned ssaNum = lclVarTree->GetSsaNum();
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+// Generated by Fuzzlyn v1.2 on 2021-08-16 22:20:52
+// Run on .NET 6.0.0-dev on X86 Windows
+// Seed: 15888848110967612195
+// Reduced from 235.4 KiB to 1.4 KiB in 00:22:05
+// Crashes the runtime
+using System.Runtime.CompilerServices;
+
+class C0
+{
+ public ushort F0;
+ public short F1;
+ public ulong F2;
+ public short F3;
+ public C0(ushort f0, ulong f2, short f3)
+ {
+ F0 = f0;
+ F2 = f2;
+ F3 = f3;
+ }
+}
+
+class C1
+{
+ public uint F1;
+}
+
+struct S0
+{
+ public byte F0;
+ public C0 F3;
+}
+
+public class Runtime_57061_3
+{
+ static long s_2;
+ static S0[][][] s_3;
+ static S0 s_4;
+ public static int Main()
+ {
+ C1 vr3 = default(C1);
+ for (int vr4 = 0; vr4 < Bound(); vr4++)
+ {
+ try
+ {
+ System.Console.WriteLine(vr3.F1);
+ }
+ finally
+ {
+ s_2 = s_2;
+ }
+
+ bool vr5 = false;
+ if (vr5)
+ {
+ try
+ {
+ vr5 &= 0 == s_4.F3.F1;
+ }
+ finally
+ {
+ var vr6 = new C0(1, 1, 0);
+ var vr7 = new C0(0, 0, 0);
+ S0 vr10 = s_3[0][0][0];
+ byte vr11 = s_4.F0++;
+ uint vr12 = default(uint);
+ var vr8 = (byte)vr12;
+ M4(ref s_3[0][0][0], vr8);
+ }
+ }
+ }
+
+ return 100;
+ }
+
+ static uint M4(ref S0 arg2, byte arg3)
+ {
+ return default(uint);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int Bound() => 0;
+}
\ No newline at end of file