{
assert(MapIsPrecise(map));
- int budget = m_mapSelectBudget;
- bool usedRecursiveVN = false;
- ValueNum result = VNForMapSelectWork(vnk, type, map, index, &budget, &usedRecursiveVN);
-
- // The remaining budget should always be between [0..m_mapSelectBudget]
- assert((budget >= 0) && (budget <= m_mapSelectBudget));
+ ValueNum result = VNForMapSelectInner(vnk, type, map, index);
JITDUMP(" VNForMapSelect(" FMT_VN ", " FMT_VN "):%s returns ", map, index, VNMapTypeName(type));
JITDUMPEXEC(m_pComp->vnPrint(result, 1));
{
assert(MapIsPhysical(map));
- ValueNum selector = EncodePhysicalSelector(offset, size);
- int budget = m_mapSelectBudget;
- bool usedRecursiveVN = false;
- ValueNum result = VNForMapSelectWork(vnk, type, map, selector, &budget, &usedRecursiveVN);
-
- // The remaining budget should always be between [0..m_mapSelectBudget]
- assert((budget >= 0) && (budget <= m_mapSelectBudget));
+ ValueNum selector = EncodePhysicalSelector(offset, size);
+ ValueNum result = VNForMapSelectInner(vnk, type, map, selector);
JITDUMP(" VNForMapPhysicalSelect(" FMT_VN ", ", map);
JITDUMPEXEC(vnDumpPhysicalSelector(selector));
}
//------------------------------------------------------------------------------
+// VNForMapSelectInner: Select value from a map and record loop memory dependencies.
+//
+// Arguments:
+// vnk - Value number kind (see the notes for "VNForMapSelect")
+// type - The type to select
+// map - (VN of) the physical map
+// index - The selector
+//
+// Return Value:
+// Value number for the result of the evaluation.
+//
+ValueNum ValueNumStore::VNForMapSelectInner(ValueNumKind vnk, var_types type, ValueNum map, ValueNum index)
+{
+ int budget = m_mapSelectBudget;
+ bool usedRecursiveVN = false;
+ ArrayStack<ValueNum> memoryDependencies(m_alloc);
+ ValueNum result = VNForMapSelectWork(vnk, type, map, index, &budget, &usedRecursiveVN, &memoryDependencies);
+
+ // The remaining budget should always be between [0..m_mapSelectBudget]
+ assert((budget >= 0) && (budget <= m_mapSelectBudget));
+
+ // If the current tree is in a loop then record memory dependencies for
+ // hoisting. Note that this function may be called by other phases than VN
+ // (such as VN-based dead store removal).
+ if ((m_pComp->compCurBB != nullptr) && (m_pComp->compCurTree != nullptr) &&
+ m_pComp->compCurBB->bbNatLoopNum != BasicBlock::NOT_IN_LOOP)
+ {
+ for (int i = 0; i < memoryDependencies.Height(); i++)
+ {
+ m_pComp->optRecordLoopMemoryDependence(m_pComp->compCurTree, m_pComp->compCurBB,
+ memoryDependencies.Bottom(i));
+ }
+ }
+
+ return result;
+}
+
+//------------------------------------------------------------------------------
+// SetMemoryDependencies: Set the cached memory dependencies for a map-select
+// cache entry.
+//
+// Arguments:
+// alloc - Allocator to use if memory is required.
+// deps - Array stack containing the memory dependencies.
+// startIndex - Start index into 'deps' of memory dependencies.
+//
+void ValueNumStore::MapSelectWorkCacheEntry::SetMemoryDependencies(CompAllocator alloc,
+ ArrayStack<ValueNum>& deps,
+ unsigned startIndex)
+{
+ m_numMemoryDependencies = deps.Height() - startIndex;
+ ValueNum* arr;
+ if (m_numMemoryDependencies > ArrLen(m_inlineMemoryDependencies))
+ {
+ m_memoryDependencies = new (alloc) ValueNum[m_numMemoryDependencies];
+
+ arr = m_memoryDependencies;
+ }
+ else
+ {
+ arr = m_inlineMemoryDependencies;
+ }
+
+ for (unsigned i = 0; i < m_numMemoryDependencies; i++)
+ {
+ arr[i] = deps.Bottom(startIndex + i);
+ }
+}
+
+//------------------------------------------------------------------------------
+// GetMemoryDependencies: Push all of the memory dependencies cached in this
+// entry into the specified array stack.
+//
+// Arguments:
+// result - Array stack to push memory dependencies into.
+//
+void ValueNumStore::MapSelectWorkCacheEntry::GetMemoryDependencies(ArrayStack<ValueNum>& result)
+{
+ ValueNum* arr = m_numMemoryDependencies <= ArrLen(m_inlineMemoryDependencies) ? m_inlineMemoryDependencies
+ : m_memoryDependencies;
+
+ for (unsigned i = 0; i < m_numMemoryDependencies; i++)
+ {
+ result.Push(arr[i]);
+ }
+}
+
+//------------------------------------------------------------------------------
// VNForMapSelectWork : A method that does the work for VNForMapSelect and may call itself recursively.
//
// Arguments:
-// vnk - Value number kind
-// type - Value type
-// map - The map to select from
-// index - The selector
-// pBudget - Remaining budget for the outer evaluation
-// pUsedRecursiveVN - Out-parameter that is set to true iff RecursiveVN was returned from this method
-// or from a method called during one of recursive invocations.
+// vnk - Value number kind
+// type - Value type
+// map - The map to select from
+// index - The selector
+// pBudget - Remaining budget for the outer evaluation
+// pUsedRecursiveVN - Out-parameter that is set to true iff RecursiveVN was returned from this method
+// or from a method called during one of recursive invocations.
+// memoryDependencies - Array stack that records VNs of memories that the result is dependent upon.
//
// Return Value:
// Value number for the result of the evaluation.
// "select(m1, ind)", ..., "select(mk, ind)" to see if they agree. It needs to know which kind of value number
// (liberal/conservative) to read from the SSA def referenced in the phi argument.
//
-ValueNum ValueNumStore::VNForMapSelectWork(
- ValueNumKind vnk, var_types type, ValueNum map, ValueNum index, int* pBudget, bool* pUsedRecursiveVN)
+ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
+ var_types type,
+ ValueNum map,
+ ValueNum index,
+ int* pBudget,
+ bool* pUsedRecursiveVN,
+ ArrayStack<ValueNum>* memoryDependencies)
{
TailCall:
// This label allows us to directly implement a tail call by setting up the arguments, and doing a goto to here.
unsigned selLim = JitConfig.JitVNMapSelLimit();
assert(selLim == 0 || m_numMapSels < selLim);
#endif
- ValueNum res;
+
+ int firstMemoryDependency = memoryDependencies->Height();
+ MapSelectWorkCacheEntry entry;
VNDefFuncApp<2> fstruct(VNF_MapSelect, map, index);
- if (GetVNFunc2Map()->Lookup(fstruct, &res))
+ if (GetMapSelectWorkCache()->Lookup(fstruct, &entry))
{
- return res;
+ entry.GetMemoryDependencies(*memoryDependencies);
+ return entry.Result;
}
- else
+
+ // Give up if we've run out of budget.
+ if (*pBudget == 0)
{
- // Give up if we've run out of budget.
- if (*pBudget == 0)
- {
- // We have to use 'nullptr' for the basic block here, because subsequent expressions
- // in different blocks may find this result in the VNFunc2Map -- other expressions in
- // the IR may "evaluate" to this same VNForExpr, so it is not "unique" in the sense
- // that permits the BasicBlock attribution.
- res = VNForExpr(nullptr, type);
- GetVNFunc2Map()->Set(fstruct, res);
- return res;
- }
+ // We have to use 'nullptr' for the basic block here, because subsequent expressions
+ // in different blocks may find this result in the VNFunc2Map -- other expressions in
+ // the IR may "evaluate" to this same VNForExpr, so it is not "unique" in the sense
+ // that permits the BasicBlock attribution.
+ entry.Result = VNForExpr(nullptr, type);
+ GetMapSelectWorkCache()->Set(fstruct, entry);
+ return entry.Result;
+ }
- // Reduce our budget by one
- (*pBudget)--;
+ // Reduce our budget by one
+ (*pBudget)--;
- // If it's recursive, stop the recursion.
- if (SelectIsBeingEvaluatedRecursively(map, index))
- {
- *pUsedRecursiveVN = true;
- return RecursiveVN;
- }
+ // If it's recursive, stop the recursion.
+ if (SelectIsBeingEvaluatedRecursively(map, index))
+ {
+ *pUsedRecursiveVN = true;
+ return RecursiveVN;
+ }
- VNFuncApp funcApp;
- if (GetVNFunc(map, &funcApp))
+ VNFuncApp funcApp;
+ if (GetVNFunc(map, &funcApp))
+ {
+ switch (funcApp.m_func)
{
- switch (funcApp.m_func)
+ case VNF_MapStore:
{
- case VNF_MapStore:
- {
- assert(MapIsPrecise(map));
+ assert(MapIsPrecise(map));
- // select(store(m, i, v), i) == v
- if (funcApp.m_args[1] == index)
- {
+ // select(store(m, i, v), i) == v
+ if (funcApp.m_args[1] == index)
+ {
#if FEATURE_VN_TRACE_APPLY_SELECTORS
- JITDUMP(" AX1: select([" FMT_VN "]store(" FMT_VN ", " FMT_VN ", " FMT_VN "), " FMT_VN
- ") ==> " FMT_VN ".\n",
- funcApp.m_args[0], map, funcApp.m_args[1], funcApp.m_args[2], index, funcApp.m_args[2]);
+ JITDUMP(" AX1: select([" FMT_VN "]store(" FMT_VN ", " FMT_VN ", " FMT_VN "), " FMT_VN
+ ") ==> " FMT_VN ".\n",
+ funcApp.m_args[0], map, funcApp.m_args[1], funcApp.m_args[2], index, funcApp.m_args[2]);
#endif
- m_pComp->optRecordLoopMemoryDependence(m_pComp->compCurTree, m_pComp->compCurBB,
- funcApp.m_args[0]);
- return funcApp.m_args[2];
- }
- // i # j ==> select(store(m, i, v), j) == select(m, j)
- // Currently the only source of distinctions is when both indices are constants.
- else if (IsVNConstant(index) && IsVNConstant(funcApp.m_args[1]))
- {
- assert(funcApp.m_args[1] != index); // we already checked this above.
+ memoryDependencies->Push(funcApp.m_args[0]);
+
+ return funcApp.m_args[2];
+ }
+ // i # j ==> select(store(m, i, v), j) == select(m, j)
+ // Currently the only source of distinctions is when both indices are constants.
+ else if (IsVNConstant(index) && IsVNConstant(funcApp.m_args[1]))
+ {
+ assert(funcApp.m_args[1] != index); // we already checked this above.
#if FEATURE_VN_TRACE_APPLY_SELECTORS
- JITDUMP(" AX2: " FMT_VN " != " FMT_VN " ==> select([" FMT_VN "]store(" FMT_VN ", " FMT_VN
- ", " FMT_VN "), " FMT_VN ") ==> select(" FMT_VN ", " FMT_VN
- ") remaining budget is %d.\n",
- index, funcApp.m_args[1], map, funcApp.m_args[0], funcApp.m_args[1], funcApp.m_args[2],
- index, funcApp.m_args[0], index, *pBudget);
+ JITDUMP(" AX2: " FMT_VN " != " FMT_VN " ==> select([" FMT_VN "]store(" FMT_VN ", " FMT_VN
+ ", " FMT_VN "), " FMT_VN ") ==> select(" FMT_VN ", " FMT_VN ") remaining budget is %d.\n",
+ index, funcApp.m_args[1], map, funcApp.m_args[0], funcApp.m_args[1], funcApp.m_args[2],
+ index, funcApp.m_args[0], index, *pBudget);
#endif
- // This is the equivalent of the recursive tail call:
- // return VNForMapSelect(vnk, typ, funcApp.m_args[0], index);
- // Make sure we capture any exceptions from the "i" and "v" of the store...
- map = funcApp.m_args[0];
- goto TailCall;
- }
+ // This is the equivalent of the recursive tail call:
+ // return VNForMapSelect(vnk, typ, funcApp.m_args[0], index);
+ // Make sure we capture any exceptions from the "i" and "v" of the store...
+ map = funcApp.m_args[0];
+ goto TailCall;
}
- break;
+ }
+ break;
- case VNF_MapPhysicalStore:
- {
- assert(MapIsPhysical(map));
+ case VNF_MapPhysicalStore:
+ {
+ assert(MapIsPhysical(map));
#if FEATURE_VN_TRACE_APPLY_SELECTORS
- JITDUMP(" select(");
- JITDUMPEXEC(m_pComp->vnPrint(map, 1));
- JITDUMP(", ");
- JITDUMPEXEC(vnDumpPhysicalSelector(index));
- JITDUMP(")");
+ JITDUMP(" select(");
+ JITDUMPEXEC(m_pComp->vnPrint(map, 1));
+ JITDUMP(", ");
+ JITDUMPEXEC(vnDumpPhysicalSelector(index));
+ JITDUMP(")");
#endif
- ValueNum storeSelector = funcApp.m_args[1];
+ ValueNum storeSelector = funcApp.m_args[1];
- if (index == storeSelector)
- {
+ if (index == storeSelector)
+ {
#if FEATURE_VN_TRACE_APPLY_SELECTORS
- JITDUMP(" ==> " FMT_VN "\n", funcApp.m_args[2]);
+ JITDUMP(" ==> " FMT_VN "\n", funcApp.m_args[2]);
#endif
- return funcApp.m_args[2];
- }
+ return funcApp.m_args[2];
+ }
- unsigned selectSize;
- unsigned selectOffset = DecodePhysicalSelector(index, &selectSize);
+ unsigned selectSize;
+ unsigned selectOffset = DecodePhysicalSelector(index, &selectSize);
- unsigned storeSize;
- unsigned storeOffset = DecodePhysicalSelector(storeSelector, &storeSize);
+ unsigned storeSize;
+ unsigned storeOffset = DecodePhysicalSelector(storeSelector, &storeSize);
- unsigned selectEndOffset = selectOffset + selectSize; // Exclusive.
- unsigned storeEndOffset = storeOffset + storeSize; // Exclusive.
+ unsigned selectEndOffset = selectOffset + selectSize; // Exclusive.
+ unsigned storeEndOffset = storeOffset + storeSize; // Exclusive.
- if ((storeOffset <= selectOffset) && (selectEndOffset <= storeEndOffset))
- {
+ if ((storeOffset <= selectOffset) && (selectEndOffset <= storeEndOffset))
+ {
#if FEATURE_VN_TRACE_APPLY_SELECTORS
- JITDUMP(" ==> enclosing, selecting inner, remaining budget is %d\n", *pBudget);
+ JITDUMP(" ==> enclosing, selecting inner, remaining budget is %d\n", *pBudget);
#endif
- map = funcApp.m_args[2];
- index = EncodePhysicalSelector(selectOffset - storeOffset, selectSize);
- goto TailCall;
- }
+ map = funcApp.m_args[2];
+ index = EncodePhysicalSelector(selectOffset - storeOffset, selectSize);
+ goto TailCall;
+ }
- // If it was disjoint with the location being selected, continue the linear search.
- if ((storeEndOffset <= selectOffset) || (selectEndOffset <= storeOffset))
- {
+ // If it was disjoint with the location being selected, continue the linear search.
+ if ((storeEndOffset <= selectOffset) || (selectEndOffset <= storeOffset))
+ {
#if FEATURE_VN_TRACE_APPLY_SELECTORS
- JITDUMP(" ==> disjoint, remaining budget is %d\n", *pBudget);
+ JITDUMP(" ==> disjoint, remaining budget is %d\n", *pBudget);
#endif
- map = funcApp.m_args[0];
- goto TailCall;
- }
- else
- {
+ map = funcApp.m_args[0];
+ goto TailCall;
+ }
+ else
+ {
#if FEATURE_VN_TRACE_APPLY_SELECTORS
- JITDUMP(" ==> aliasing!\n");
+ JITDUMP(" ==> aliasing!\n");
#endif
- }
}
- break;
+ }
+ break;
- case VNF_BitCast:
- assert(MapIsPhysical(map));
+ case VNF_BitCast:
+ assert(MapIsPhysical(map));
#if FEATURE_VN_TRACE_APPLY_SELECTORS
- JITDUMP(" select(bitcast<%s>(" FMT_VN ")) ==> select(" FMT_VN ")\n",
- varTypeName(TypeOfVN(funcApp.m_args[0])), funcApp.m_args[0], funcApp.m_args[0]);
+ JITDUMP(" select(bitcast<%s>(" FMT_VN ")) ==> select(" FMT_VN ")\n",
+ varTypeName(TypeOfVN(funcApp.m_args[0])), funcApp.m_args[0], funcApp.m_args[0]);
#endif // FEATURE_VN_TRACE_APPLY_SELECTORS
- map = funcApp.m_args[0];
- goto TailCall;
+ map = funcApp.m_args[0];
+ goto TailCall;
- case VNF_ZeroObj:
- assert(MapIsPhysical(map));
+ case VNF_ZeroObj:
+ assert(MapIsPhysical(map));
- // TODO-CQ: support selection of TYP_STRUCT here.
- if (type != TYP_STRUCT)
- {
- return VNZeroForType(type);
- }
- break;
+ // TODO-CQ: support selection of TYP_STRUCT here.
+ if (type != TYP_STRUCT)
+ {
+ return VNZeroForType(type);
+ }
+ break;
- case VNF_PhiDef:
- case VNF_PhiMemoryDef:
+ case VNF_PhiDef:
+ case VNF_PhiMemoryDef:
+ {
+ unsigned lclNum = BAD_VAR_NUM;
+ bool isMemory = false;
+ VNFuncApp phiFuncApp;
+ bool defArgIsFunc = false;
+ if (funcApp.m_func == VNF_PhiDef)
+ {
+ lclNum = unsigned(funcApp.m_args[0]);
+ defArgIsFunc = GetVNFunc(funcApp.m_args[2], &phiFuncApp);
+ }
+ else
+ {
+ assert(funcApp.m_func == VNF_PhiMemoryDef);
+ isMemory = true;
+ defArgIsFunc = GetVNFunc(funcApp.m_args[1], &phiFuncApp);
+ }
+ if (defArgIsFunc && phiFuncApp.m_func == VNF_Phi)
{
- unsigned lclNum = BAD_VAR_NUM;
- bool isMemory = false;
- VNFuncApp phiFuncApp;
- bool defArgIsFunc = false;
- if (funcApp.m_func == VNF_PhiDef)
+ // select(phi(m1, m2), x): if select(m1, x) == select(m2, x), return that, else new fresh.
+ // Get the first argument of the phi.
+
+ // We need to be careful about breaking infinite recursion. Record the outer select.
+ m_fixedPointMapSels.Push(VNDefFuncApp<2>(VNF_MapSelect, map, index));
+
+ assert(IsVNConstant(phiFuncApp.m_args[0]));
+ unsigned phiArgSsaNum = ConstantValue<unsigned>(phiFuncApp.m_args[0]);
+ ValueNum phiArgVN;
+ if (isMemory)
{
- lclNum = unsigned(funcApp.m_args[0]);
- defArgIsFunc = GetVNFunc(funcApp.m_args[2], &phiFuncApp);
+ phiArgVN = m_pComp->GetMemoryPerSsaData(phiArgSsaNum)->m_vnPair.Get(vnk);
}
else
{
- assert(funcApp.m_func == VNF_PhiMemoryDef);
- isMemory = true;
- defArgIsFunc = GetVNFunc(funcApp.m_args[1], &phiFuncApp);
+ phiArgVN = m_pComp->lvaTable[lclNum].GetPerSsaData(phiArgSsaNum)->m_vnPair.Get(vnk);
}
- if (defArgIsFunc && phiFuncApp.m_func == VNF_Phi)
+ if (phiArgVN != ValueNumStore::NoVN)
{
- // select(phi(m1, m2), x): if select(m1, x) == select(m2, x), return that, else new fresh.
- // Get the first argument of the phi.
-
- // We need to be careful about breaking infinite recursion. Record the outer select.
- m_fixedPointMapSels.Push(VNDefFuncApp<2>(VNF_MapSelect, map, index));
-
- assert(IsVNConstant(phiFuncApp.m_args[0]));
- unsigned phiArgSsaNum = ConstantValue<unsigned>(phiFuncApp.m_args[0]);
- ValueNum phiArgVN;
- if (isMemory)
- {
- phiArgVN = m_pComp->GetMemoryPerSsaData(phiArgSsaNum)->m_vnPair.Get(vnk);
- }
- else
+ bool allSame = true;
+ ValueNum argRest = phiFuncApp.m_args[1];
+ ValueNum sameSelResult = VNForMapSelectWork(vnk, type, phiArgVN, index, pBudget,
+ pUsedRecursiveVN, memoryDependencies);
+
+ // It is possible that we just now exceeded our budget, if so we need to force an early exit
+ // and stop calling VNForMapSelectWork
+ if (*pBudget <= 0)
{
- phiArgVN = m_pComp->lvaTable[lclNum].GetPerSsaData(phiArgSsaNum)->m_vnPair.Get(vnk);
+ // We don't have any budget remaining to verify that all phiArgs are the same
+ // so setup the default failure case now.
+ allSame = false;
}
- if (phiArgVN != ValueNumStore::NoVN)
+
+ while (allSame && argRest != ValueNumStore::NoVN)
{
- bool allSame = true;
- ValueNum argRest = phiFuncApp.m_args[1];
- ValueNum sameSelResult =
- VNForMapSelectWork(vnk, type, phiArgVN, index, pBudget, pUsedRecursiveVN);
-
- // It is possible that we just now exceeded our budget, if so we need to force an early exit
- // and stop calling VNForMapSelectWork
- if (*pBudget <= 0)
+ ValueNum cur = argRest;
+ VNFuncApp phiArgFuncApp;
+ if (GetVNFunc(argRest, &phiArgFuncApp) && phiArgFuncApp.m_func == VNF_Phi)
+ {
+ cur = phiArgFuncApp.m_args[0];
+ argRest = phiArgFuncApp.m_args[1];
+ }
+ else
+ {
+ argRest = ValueNumStore::NoVN; // Cause the loop to terminate.
+ }
+ assert(IsVNConstant(cur));
+ phiArgSsaNum = ConstantValue<unsigned>(cur);
+ if (isMemory)
+ {
+ phiArgVN = m_pComp->GetMemoryPerSsaData(phiArgSsaNum)->m_vnPair.Get(vnk);
+ }
+ else
+ {
+ phiArgVN = m_pComp->lvaTable[lclNum].GetPerSsaData(phiArgSsaNum)->m_vnPair.Get(vnk);
+ }
+ if (phiArgVN == ValueNumStore::NoVN)
{
- // We don't have any budget remaining to verify that all phiArgs are the same
- // so setup the default failure case now.
allSame = false;
}
-
- while (allSame && argRest != ValueNumStore::NoVN)
+ else
{
- ValueNum cur = argRest;
- VNFuncApp phiArgFuncApp;
- if (GetVNFunc(argRest, &phiArgFuncApp) && phiArgFuncApp.m_func == VNF_Phi)
- {
- cur = phiArgFuncApp.m_args[0];
- argRest = phiArgFuncApp.m_args[1];
- }
- else
- {
- argRest = ValueNumStore::NoVN; // Cause the loop to terminate.
- }
- assert(IsVNConstant(cur));
- phiArgSsaNum = ConstantValue<unsigned>(cur);
- if (isMemory)
- {
- phiArgVN = m_pComp->GetMemoryPerSsaData(phiArgSsaNum)->m_vnPair.Get(vnk);
- }
- else
+ bool usedRecursiveVN = false;
+ ValueNum curResult = VNForMapSelectWork(vnk, type, phiArgVN, index, pBudget,
+ &usedRecursiveVN, memoryDependencies);
+
+ *pUsedRecursiveVN |= usedRecursiveVN;
+ if (sameSelResult == ValueNumStore::RecursiveVN)
{
- phiArgVN = m_pComp->lvaTable[lclNum].GetPerSsaData(phiArgSsaNum)->m_vnPair.Get(vnk);
+ sameSelResult = curResult;
}
- if (phiArgVN == ValueNumStore::NoVN)
+ if (curResult != ValueNumStore::RecursiveVN && curResult != sameSelResult)
{
allSame = false;
}
- else
- {
- bool usedRecursiveVN = false;
- ValueNum curResult =
- VNForMapSelectWork(vnk, type, phiArgVN, index, pBudget, &usedRecursiveVN);
-
- *pUsedRecursiveVN |= usedRecursiveVN;
- if (sameSelResult == ValueNumStore::RecursiveVN)
- {
- sameSelResult = curResult;
- }
- if (curResult != ValueNumStore::RecursiveVN && curResult != sameSelResult)
- {
- allSame = false;
- }
- }
}
- if (allSame && sameSelResult != ValueNumStore::RecursiveVN)
+ }
+ if (allSame && sameSelResult != ValueNumStore::RecursiveVN)
+ {
+ // Make sure we're popping what we pushed.
+ assert(FixedPointMapSelsTopHasValue(map, index));
+ m_fixedPointMapSels.Pop();
+
+ // To avoid exponential searches, we make sure that this result is memo-ized.
+ // The result is always valid for memoization if we didn't rely on RecursiveVN to get
+ // it.
+ // If RecursiveVN was used, we are processing a loop and we can't memo-ize this
+ // intermediate
+ // result if, e.g., this block is in a multi-entry loop.
+ if (!*pUsedRecursiveVN)
{
- // Make sure we're popping what we pushed.
- assert(FixedPointMapSelsTopHasValue(map, index));
- m_fixedPointMapSels.Pop();
-
- // To avoid exponential searches, we make sure that this result is memo-ized.
- // The result is always valid for memoization if we didn't rely on RecursiveVN to get
- // it.
- // If RecursiveVN was used, we are processing a loop and we can't memo-ize this
- // intermediate
- // result if, e.g., this block is in a multi-entry loop.
- if (!*pUsedRecursiveVN)
- {
- GetVNFunc2Map()->Set(fstruct, sameSelResult);
- }
+ entry.Result = sameSelResult;
+ entry.SetMemoryDependencies(m_alloc, *memoryDependencies, firstMemoryDependency);
- return sameSelResult;
+ GetMapSelectWorkCache()->Set(fstruct, entry);
}
- // Otherwise, fall through to creating the select(phi(m1, m2), x) function application.
+
+ return sameSelResult;
}
- // Make sure we're popping what we pushed.
- assert(FixedPointMapSelsTopHasValue(map, index));
- m_fixedPointMapSels.Pop();
+ // Otherwise, fall through to creating the select(phi(m1, m2), x) function application.
}
+ // Make sure we're popping what we pushed.
+ assert(FixedPointMapSelsTopHasValue(map, index));
+ m_fixedPointMapSels.Pop();
}
- break;
-
- default:
- break;
}
+ break;
+
+ default:
+ break;
}
+ }
- // We may have run out of budget and already assigned a result
- if (!GetVNFunc2Map()->Lookup(fstruct, &res))
- {
- // Otherwise, assign a new VN for the function application.
- Chunk* const c = GetAllocChunk(type, CEA_Func2);
- unsigned const offsetWithinChunk = c->AllocVN();
- VNDefFuncAppFlexible* fapp = c->PointerToFuncApp(offsetWithinChunk, 2);
- fapp->m_func = fstruct.m_func;
- fapp->m_args[0] = fstruct.m_args[0];
- fapp->m_args[1] = fstruct.m_args[1];
- res = c->m_baseVN + offsetWithinChunk;
+ // We may have run out of budget and already assigned a result
+ if (!GetMapSelectWorkCache()->Lookup(fstruct, &entry))
+ {
+ // Otherwise, assign a new VN for the function application.
+ Chunk* const c = GetAllocChunk(type, CEA_Func2);
+ unsigned const offsetWithinChunk = c->AllocVN();
+ VNDefFuncAppFlexible* fapp = c->PointerToFuncApp(offsetWithinChunk, 2);
+ fapp->m_func = fstruct.m_func;
+ fapp->m_args[0] = fstruct.m_args[0];
+ fapp->m_args[1] = fstruct.m_args[1];
- GetVNFunc2Map()->Set(fstruct, res);
- }
- return res;
+ entry.Result = c->m_baseVN + offsetWithinChunk;
+ entry.SetMemoryDependencies(m_alloc, *memoryDependencies, firstMemoryDependency);
+
+ GetMapSelectWorkCache()->Set(fstruct, entry);
}
+
+ return entry.Result;
}
//------------------------------------------------------------------------