@@ -2860,6 +2860,81 @@ ValueNum ValueNumStore::VNForMapPhysicalSelect(
2860
2860
return result;
2861
2861
}
2862
2862
2863
+ typedef JitHashTable<ValueNum, JitSmallPrimitiveKeyFuncs<ValueNum>, bool> ValueNumSet;
2864
+
2865
+ class SmallValueNumSet
2866
+ {
2867
+ union {
2868
+ ValueNum m_inlineElements[4];
2869
+ ValueNumSet* m_set;
2870
+ };
2871
+ unsigned m_numElements = 0;
2872
+
2873
+ public:
2874
+ unsigned Count()
2875
+ {
2876
+ return m_numElements;
2877
+ }
2878
+
2879
+ template <typename Func>
2880
+ void ForEach(Func func)
2881
+ {
2882
+ if (m_numElements <= ArrLen(m_inlineElements))
2883
+ {
2884
+ for (unsigned i = 0; i < m_numElements; i++)
2885
+ {
2886
+ func(m_inlineElements[i]);
2887
+ }
2888
+ }
2889
+ else
2890
+ {
2891
+ for (ValueNum vn : ValueNumSet::KeyIteration(m_set))
2892
+ {
2893
+ func(vn);
2894
+ }
2895
+ }
2896
+ }
2897
+
2898
+ void Add(Compiler* comp, ValueNum vn)
2899
+ {
2900
+ if (m_numElements <= ArrLen(m_inlineElements))
2901
+ {
2902
+ for (unsigned i = 0; i < m_numElements; i++)
2903
+ {
2904
+ if (m_inlineElements[i] == vn)
2905
+ {
2906
+ return;
2907
+ }
2908
+ }
2909
+
2910
+ if (m_numElements < ArrLen(m_inlineElements))
2911
+ {
2912
+ m_inlineElements[m_numElements] = vn;
2913
+ m_numElements++;
2914
+ }
2915
+ else
2916
+ {
2917
+ ValueNumSet* set = new (comp, CMK_ValueNumber) ValueNumSet(comp->getAllocator(CMK_ValueNumber));
2918
+ for (ValueNum oldVn : m_inlineElements)
2919
+ {
2920
+ set->Set(oldVn, true);
2921
+ }
2922
+
2923
+ set->Set(vn, true);
2924
+
2925
+ m_set = set;
2926
+ m_numElements++;
2927
+ assert(m_numElements == set->GetCount());
2928
+ }
2929
+ }
2930
+ else
2931
+ {
2932
+ m_set->Set(vn, true, ValueNumSet::SetKind::Overwrite);
2933
+ m_numElements = m_set->GetCount();
2934
+ }
2935
+ }
2936
+ };
2937
+
2863
2938
//------------------------------------------------------------------------------
2864
2939
// VNForMapSelectInner: Select value from a map and record loop memory dependencies.
2865
2940
//
@@ -2874,10 +2949,10 @@ ValueNum ValueNumStore::VNForMapPhysicalSelect(
2874
2949
//
2875
2950
ValueNum ValueNumStore::VNForMapSelectInner(ValueNumKind vnk, var_types type, ValueNum map, ValueNum index)
2876
2951
{
2877
- int budget = m_mapSelectBudget;
2878
- bool usedRecursiveVN = false;
2879
- ArrayStack<ValueNum> memoryDependencies(m_alloc) ;
2880
- ValueNum result = VNForMapSelectWork(vnk, type, map, index, &budget, &usedRecursiveVN, & memoryDependencies);
2952
+ int budget = m_mapSelectBudget;
2953
+ bool usedRecursiveVN = false;
2954
+ SmallValueNumSet memoryDependencies;
2955
+ ValueNum result = VNForMapSelectWork(vnk, type, map, index, &budget, &usedRecursiveVN, memoryDependencies);
2881
2956
2882
2957
// The remaining budget should always be between [0..m_mapSelectBudget]
2883
2958
assert((budget >= 0) && (budget <= m_mapSelectBudget));
@@ -2888,11 +2963,9 @@ ValueNum ValueNumStore::VNForMapSelectInner(ValueNumKind vnk, var_types type, Va
2888
2963
if ((m_pComp->compCurBB != nullptr) && (m_pComp->compCurTree != nullptr) &&
2889
2964
m_pComp->compCurBB->bbNatLoopNum != BasicBlock::NOT_IN_LOOP)
2890
2965
{
2891
- for (int i = 0; i < memoryDependencies.Height(); i++)
2892
- {
2893
- m_pComp->optRecordLoopMemoryDependence(m_pComp->compCurTree, m_pComp->compCurBB,
2894
- memoryDependencies.Bottom(i));
2895
- }
2966
+ memoryDependencies.ForEach([this](ValueNum vn) {
2967
+ m_pComp->optRecordLoopMemoryDependence(m_pComp->compCurTree, m_pComp->compCurBB, vn);
2968
+ });
2896
2969
}
2897
2970
2898
2971
return result;
@@ -2903,19 +2976,16 @@ ValueNum ValueNumStore::VNForMapSelectInner(ValueNumKind vnk, var_types type, Va
2903
2976
// cache entry.
2904
2977
//
2905
2978
// Arguments:
2906
- // alloc - Allocator to use if memory is required.
2907
- // deps - Array stack containing the memory dependencies.
2908
- // startIndex - Start index into 'deps' of memory dependencies.
2979
+ // comp - Compiler instance
2980
+ // set - Set of memory dependencies to store in the entry.
2909
2981
//
2910
- void ValueNumStore::MapSelectWorkCacheEntry::SetMemoryDependencies(CompAllocator alloc,
2911
- ArrayStack<ValueNum>& deps,
2912
- unsigned startIndex)
2982
+ void ValueNumStore::MapSelectWorkCacheEntry::SetMemoryDependencies(Compiler* comp, SmallValueNumSet& set)
2913
2983
{
2914
- m_numMemoryDependencies = deps.Height() - startIndex ;
2984
+ m_numMemoryDependencies = set.Count() ;
2915
2985
ValueNum* arr;
2916
2986
if (m_numMemoryDependencies > ArrLen(m_inlineMemoryDependencies))
2917
2987
{
2918
- m_memoryDependencies = new (alloc ) ValueNum[m_numMemoryDependencies];
2988
+ m_memoryDependencies = new (comp, CMK_ValueNumber ) ValueNum[m_numMemoryDependencies];
2919
2989
2920
2990
arr = m_memoryDependencies;
2921
2991
}
@@ -2924,27 +2994,29 @@ void ValueNumStore::MapSelectWorkCacheEntry::SetMemoryDependencies(CompAllocator
2924
2994
arr = m_inlineMemoryDependencies;
2925
2995
}
2926
2996
2927
- for (unsigned i = 0; i < m_numMemoryDependencies; i++)
2928
- {
2929
- arr[i] = deps.Bottom(startIndex + i);
2930
- }
2997
+ size_t i = 0;
2998
+ set.ForEach([&i, arr](ValueNum vn) {
2999
+ arr[i] = vn;
3000
+ i++;
3001
+ });
2931
3002
}
2932
3003
2933
3004
//------------------------------------------------------------------------------
2934
3005
// GetMemoryDependencies: Push all of the memory dependencies cached in this
2935
- // entry into the specified array stack .
3006
+ // entry into the specified set .
2936
3007
//
2937
3008
// Arguments:
2938
- // result - Array stack to push memory dependencies into.
3009
+ // comp - Compiler instance
3010
+ // result - Set to add memory dependencies to.
2939
3011
//
2940
- void ValueNumStore::MapSelectWorkCacheEntry::GetMemoryDependencies(ArrayStack<ValueNum> & result)
3012
+ void ValueNumStore::MapSelectWorkCacheEntry::GetMemoryDependencies(Compiler* comp, SmallValueNumSet & result)
2941
3013
{
2942
3014
ValueNum* arr = m_numMemoryDependencies <= ArrLen(m_inlineMemoryDependencies) ? m_inlineMemoryDependencies
2943
3015
: m_memoryDependencies;
2944
3016
2945
3017
for (unsigned i = 0; i < m_numMemoryDependencies; i++)
2946
3018
{
2947
- result.Push( arr[i]);
3019
+ result.Add(comp, arr[i]);
2948
3020
}
2949
3021
}
2950
3022
@@ -2959,7 +3031,7 @@ void ValueNumStore::MapSelectWorkCacheEntry::GetMemoryDependencies(ArrayStack<Va
2959
3031
// pBudget - Remaining budget for the outer evaluation
2960
3032
// pUsedRecursiveVN - Out-parameter that is set to true iff RecursiveVN was returned from this method
2961
3033
// or from a method called during one of recursive invocations.
2962
- // memoryDependencies - Array stack that records VNs of memories that the result is dependent upon.
3034
+ // memoryDependencies - Set that records VNs of memories that the result is dependent upon.
2963
3035
//
2964
3036
// Return Value:
2965
3037
// Value number for the result of the evaluation.
@@ -2969,13 +3041,13 @@ void ValueNumStore::MapSelectWorkCacheEntry::GetMemoryDependencies(ArrayStack<Va
2969
3041
// "select(m1, ind)", ..., "select(mk, ind)" to see if they agree. It needs to know which kind of value number
2970
3042
// (liberal/conservative) to read from the SSA def referenced in the phi argument.
2971
3043
//
2972
- ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
2973
- var_types type,
2974
- ValueNum map,
2975
- ValueNum index,
2976
- int* pBudget,
2977
- bool* pUsedRecursiveVN,
2978
- ArrayStack<ValueNum>* memoryDependencies)
3044
+ ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
3045
+ var_types type,
3046
+ ValueNum map,
3047
+ ValueNum index,
3048
+ int* pBudget,
3049
+ bool* pUsedRecursiveVN,
3050
+ SmallValueNumSet& memoryDependencies)
2979
3051
{
2980
3052
TailCall:
2981
3053
// This label allows us to directly implement a tail call by setting up the arguments, and doing a goto to here.
@@ -2997,13 +3069,12 @@ ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
2997
3069
assert(selLim == 0 || m_numMapSels < selLim);
2998
3070
#endif
2999
3071
3000
- int firstMemoryDependency = memoryDependencies->Height();
3001
3072
MapSelectWorkCacheEntry entry;
3002
3073
3003
3074
VNDefFuncApp<2> fstruct(VNF_MapSelect, map, index);
3004
3075
if (GetMapSelectWorkCache()->Lookup(fstruct, &entry))
3005
3076
{
3006
- entry.GetMemoryDependencies(* memoryDependencies);
3077
+ entry.GetMemoryDependencies(m_pComp, memoryDependencies);
3007
3078
return entry.Result;
3008
3079
}
3009
3080
@@ -3029,6 +3100,8 @@ ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
3029
3100
return RecursiveVN;
3030
3101
}
3031
3102
3103
+ SmallValueNumSet recMemoryDependencies;
3104
+
3032
3105
VNFuncApp funcApp;
3033
3106
if (GetVNFunc(map, &funcApp))
3034
3107
{
@@ -3047,7 +3120,7 @@ ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
3047
3120
funcApp.m_args[0], map, funcApp.m_args[1], funcApp.m_args[2], index, funcApp.m_args[2]);
3048
3121
#endif
3049
3122
3050
- memoryDependencies->Push( funcApp.m_args[0]);
3123
+ memoryDependencies.Add(m_pComp, funcApp.m_args[0]);
3051
3124
3052
3125
return funcApp.m_args[2];
3053
3126
}
@@ -3191,7 +3264,7 @@ ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
3191
3264
bool allSame = true;
3192
3265
ValueNum argRest = phiFuncApp.m_args[1];
3193
3266
ValueNum sameSelResult = VNForMapSelectWork(vnk, type, phiArgVN, index, pBudget,
3194
- pUsedRecursiveVN, memoryDependencies );
3267
+ pUsedRecursiveVN, recMemoryDependencies );
3195
3268
3196
3269
// It is possible that we just now exceeded our budget, if so we need to force an early exit
3197
3270
// and stop calling VNForMapSelectWork
@@ -3233,7 +3306,7 @@ ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
3233
3306
{
3234
3307
bool usedRecursiveVN = false;
3235
3308
ValueNum curResult = VNForMapSelectWork(vnk, type, phiArgVN, index, pBudget,
3236
- &usedRecursiveVN, memoryDependencies );
3309
+ &usedRecursiveVN, recMemoryDependencies );
3237
3310
3238
3311
*pUsedRecursiveVN |= usedRecursiveVN;
3239
3312
if (sameSelResult == ValueNumStore::RecursiveVN)
@@ -3261,11 +3334,14 @@ ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
3261
3334
if (!*pUsedRecursiveVN)
3262
3335
{
3263
3336
entry.Result = sameSelResult;
3264
- entry.SetMemoryDependencies(m_alloc, *memoryDependencies, firstMemoryDependency );
3337
+ entry.SetMemoryDependencies(m_pComp, recMemoryDependencies );
3265
3338
3266
3339
GetMapSelectWorkCache()->Set(fstruct, entry);
3267
3340
}
3268
3341
3342
+ recMemoryDependencies.ForEach(
3343
+ [this, &memoryDependencies](ValueNum vn) { memoryDependencies.Add(m_pComp, vn); });
3344
+
3269
3345
return sameSelResult;
3270
3346
}
3271
3347
// Otherwise, fall through to creating the select(phi(m1, m2), x) function application.
@@ -3294,11 +3370,13 @@ ValueNum ValueNumStore::VNForMapSelectWork(ValueNumKind vnk,
3294
3370
fapp->m_args[1] = fstruct.m_args[1];
3295
3371
3296
3372
entry.Result = c->m_baseVN + offsetWithinChunk;
3297
- entry.SetMemoryDependencies(m_alloc, *memoryDependencies, firstMemoryDependency );
3373
+ entry.SetMemoryDependencies(m_pComp, recMemoryDependencies );
3298
3374
3299
3375
GetMapSelectWorkCache()->Set(fstruct, entry);
3300
3376
}
3301
3377
3378
+ recMemoryDependencies.ForEach([this, &memoryDependencies](ValueNum vn) { memoryDependencies.Add(m_pComp, vn); });
3379
+
3302
3380
return entry.Result;
3303
3381
}
3304
3382
0 commit comments