@@ -1635,7 +1635,20 @@ bool ValueNumStore::IsKnownNonNull(ValueNum vn)
1635
1635
}
1636
1636
1637
1637
VNFuncApp funcAttr;
1638
- return GetVNFunc(vn, &funcAttr) && (s_vnfOpAttribs[funcAttr.m_func] & VNFOA_KnownNonNull) != 0;
1638
+ if (!GetVNFunc(vn, &funcAttr))
1639
+ {
1640
+ return false;
1641
+ }
1642
+
1643
+ if ((s_vnfOpAttribs[funcAttr.m_func] & VNFOA_KnownNonNull) != 0)
1644
+ {
1645
+ return true;
1646
+ }
1647
+
1648
+ // TODO: we can recognize more non-null idioms here, e.g.
1649
+ // ADD(IsKnownNonNull(op1), smallCns), etc.
1650
+
1651
+ return false;
1639
1652
}
1640
1653
1641
1654
bool ValueNumStore::IsSharedStatic(ValueNum vn)
@@ -3191,81 +3204,81 @@ ValueNum ValueNumStore::VNForMapPhysicalSelect(
3191
3204
return result;
3192
3205
}
3193
3206
3194
- typedef JitHashTable<ValueNum, JitSmallPrimitiveKeyFuncs<ValueNum>, bool> ValueNumSet;
3195
-
3196
- class SmallValueNumSet
3207
+ bool ValueNumStore::SmallValueNumSet::Lookup(ValueNum vn)
3197
3208
{
3198
- union
3209
+ // O(N) lookup for inline elements
3210
+ if (m_numElements <= ArrLen(m_inlineElements))
3199
3211
{
3200
- ValueNum m_inlineElements[4];
3201
- ValueNumSet* m_set;
3202
- };
3203
- unsigned m_numElements = 0;
3204
-
3205
- public:
3206
- unsigned Count()
3207
- {
3208
- return m_numElements;
3209
- }
3210
-
3211
- template <typename Func>
3212
- void ForEach(Func func)
3213
- {
3214
- if (m_numElements <= ArrLen(m_inlineElements))
3212
+ for (unsigned i = 0; i < m_numElements; i++)
3215
3213
{
3216
- for (unsigned i = 0; i < m_numElements; i++ )
3214
+ if (m_inlineElements[i] == vn )
3217
3215
{
3218
- func(m_inlineElements[i]);
3219
- }
3220
- }
3221
- else
3222
- {
3223
- for (ValueNum vn : ValueNumSet::KeyIteration(m_set))
3224
- {
3225
- func(vn);
3216
+ return true;
3226
3217
}
3227
3218
}
3219
+
3220
+ // Not found
3221
+ return false;
3228
3222
}
3229
3223
3230
- void Add(Compiler* comp, ValueNum vn)
3224
+ return m_set->Lookup(vn);
3225
+ }
3226
+
3227
+ // Returns false if the value already exists
3228
+ bool ValueNumStore::SmallValueNumSet::Add(Compiler* comp, ValueNum vn)
3229
+ {
3230
+ if (m_numElements <= ArrLen(m_inlineElements))
3231
3231
{
3232
- if (m_numElements <= ArrLen(m_inlineElements) )
3232
+ for (unsigned i = 0; i < m_numElements; i++ )
3233
3233
{
3234
- for (unsigned i = 0; i < m_numElements; i++ )
3234
+ if (m_inlineElements[i] == vn )
3235
3235
{
3236
- if (m_inlineElements[i] == vn)
3237
- {
3238
- return;
3239
- }
3236
+ // Already exists
3237
+ return false;
3240
3238
}
3239
+ }
3241
3240
3242
- if (m_numElements < ArrLen(m_inlineElements))
3241
+ if (m_numElements < ArrLen(m_inlineElements))
3242
+ {
3243
+ m_inlineElements[m_numElements] = vn;
3244
+ m_numElements++;
3245
+ }
3246
+ else
3247
+ {
3248
+ ValueNumSet* set = new (comp, CMK_ValueNumber) ValueNumSet(comp->getAllocator(CMK_ValueNumber));
3249
+ for (ValueNum oldVn : m_inlineElements)
3243
3250
{
3244
- m_inlineElements[m_numElements] = vn;
3245
- m_numElements++;
3251
+ set->Set(oldVn, true);
3246
3252
}
3247
- else
3248
- {
3249
- ValueNumSet* set = new (comp, CMK_ValueNumber) ValueNumSet(comp->getAllocator(CMK_ValueNumber));
3250
- for (ValueNum oldVn : m_inlineElements)
3251
- {
3252
- set->Set(oldVn, true);
3253
- }
3254
3253
3255
- set->Set(vn, true);
3254
+ set->Set(vn, true);
3256
3255
3257
- m_set = set;
3258
- m_numElements++;
3259
- assert(m_numElements == set->GetCount());
3260
- }
3261
- }
3262
- else
3263
- {
3264
- m_set->Set(vn, true, ValueNumSet::SetKind::Overwrite);
3265
- m_numElements = m_set->GetCount();
3256
+ m_set = set;
3257
+ m_numElements++;
3258
+ assert(m_numElements == set->GetCount());
3266
3259
}
3260
+ return true;
3267
3261
}
3268
- };
3262
+
3263
+ bool exists = m_set->Set(vn, true, ValueNumSet::SetKind::Overwrite);
3264
+ m_numElements = m_set->GetCount();
3265
+ return !exists;
3266
+ }
3267
+
3268
+ //------------------------------------------------------------------------------
3269
+ // VNPhiDefToVN: Extracts the VN for a specific argument of a phi definition.
3270
+ //
3271
+ // Arguments:
3272
+ // phiDef - The phi definition
3273
+ // ssaArgNum - The argument number to extract
3274
+ //
3275
+ // Return Value:
3276
+ // The VN for the specified argument of the phi definition.
3277
+ //
3278
+ ValueNum ValueNumStore::VNPhiDefToVN(const VNPhiDef& phiDef, unsigned ssaArgNum)
3279
+ {
3280
+ return m_pComp->lvaGetDesc(phiDef.LclNum)->GetPerSsaData(phiDef.SsaArgs[ssaArgNum])->m_vnPair.Get(VNK_Conservative);
3281
+ }
3269
3282
3270
3283
//------------------------------------------------------------------------------
3271
3284
// VNForMapSelectInner: Select value from a map and record loop memory dependencies.
@@ -6513,68 +6526,75 @@ bool ValueNumStore::IsVNInt32Constant(ValueNum vn)
6513
6526
6514
6527
bool ValueNumStore::IsVNNeverNegative(ValueNum vn)
6515
6528
{
6516
- assert(varTypeIsIntegral(TypeOfVN(vn)));
6517
-
6518
- if (IsVNConstant(vn))
6519
- {
6520
- var_types vnTy = TypeOfVN(vn);
6521
- if (vnTy == TYP_INT)
6529
+ auto vnVisitor = [this](ValueNum vn) -> VNVisit {
6530
+ if ((vn == NoVN) || !varTypeIsIntegral(TypeOfVN(vn)))
6522
6531
{
6523
- return GetConstantInt32(vn) >= 0 ;
6532
+ return VNVisit::Abort ;
6524
6533
}
6525
- else if (vnTy == TYP_LONG)
6534
+
6535
+ if (IsVNConstant(vn))
6526
6536
{
6527
- return GetConstantInt64(vn) >= 0;
6537
+ var_types vnTy = TypeOfVN(vn);
6538
+ if (vnTy == TYP_INT)
6539
+ {
6540
+ return GetConstantInt32(vn) >= 0 ? VNVisit::Continue : VNVisit::Abort;
6541
+ }
6542
+ if (vnTy == TYP_LONG)
6543
+ {
6544
+ return GetConstantInt64(vn) >= 0 ? VNVisit::Continue : VNVisit::Abort;
6545
+ }
6546
+ return VNVisit::Abort;
6528
6547
}
6529
6548
6530
- return false;
6531
- }
6549
+ // Array length can never be negative.
6550
+ if (IsVNArrLen(vn))
6551
+ {
6552
+ return VNVisit::Continue;
6553
+ }
6532
6554
6533
- // Array length can never be negative.
6534
- if (IsVNArrLen(vn))
6535
- {
6536
- return true;
6537
- }
6555
+ // TODO-VN: Recognize Span.Length
6556
+ // Handle more intrinsics such as Math.Max(neverNegative1, neverNegative2)
6538
6557
6539
- VNFuncApp funcApp;
6540
- if (GetVNFunc(vn, &funcApp))
6541
- {
6542
- switch (funcApp.m_func)
6558
+ VNFuncApp funcApp;
6559
+ if (GetVNFunc(vn, &funcApp))
6543
6560
{
6544
- case VNF_GE_UN:
6545
- case VNF_GT_UN:
6546
- case VNF_LE_UN:
6547
- case VNF_LT_UN:
6548
- case VNF_COUNT:
6549
- case VNF_ADD_UN_OVF:
6550
- case VNF_SUB_UN_OVF:
6551
- case VNF_MUL_UN_OVF:
6561
+ switch (funcApp.m_func)
6562
+ {
6563
+ case VNF_GE_UN:
6564
+ case VNF_GT_UN:
6565
+ case VNF_LE_UN:
6566
+ case VNF_LT_UN:
6567
+ case VNF_COUNT:
6568
+ case VNF_ADD_UN_OVF:
6569
+ case VNF_SUB_UN_OVF:
6570
+ case VNF_MUL_UN_OVF:
6552
6571
#ifdef FEATURE_HW_INTRINSICS
6553
6572
#ifdef TARGET_XARCH
6554
- case VNF_HWI_POPCNT_PopCount:
6555
- case VNF_HWI_POPCNT_X64_PopCount:
6556
- case VNF_HWI_LZCNT_LeadingZeroCount:
6557
- case VNF_HWI_LZCNT_X64_LeadingZeroCount:
6558
- case VNF_HWI_BMI1_TrailingZeroCount:
6559
- case VNF_HWI_BMI1_X64_TrailingZeroCount:
6560
- return true ;
6573
+ case VNF_HWI_POPCNT_PopCount:
6574
+ case VNF_HWI_POPCNT_X64_PopCount:
6575
+ case VNF_HWI_LZCNT_LeadingZeroCount:
6576
+ case VNF_HWI_LZCNT_X64_LeadingZeroCount:
6577
+ case VNF_HWI_BMI1_TrailingZeroCount:
6578
+ case VNF_HWI_BMI1_X64_TrailingZeroCount:
6579
+ return VNVisit::Continue ;
6561
6580
#elif defined(TARGET_ARM64)
6562
- case VNF_HWI_AdvSimd_PopCount:
6563
- case VNF_HWI_AdvSimd_LeadingZeroCount:
6564
- case VNF_HWI_AdvSimd_LeadingSignCount:
6565
- case VNF_HWI_ArmBase_LeadingZeroCount:
6566
- case VNF_HWI_ArmBase_Arm64_LeadingZeroCount:
6567
- case VNF_HWI_ArmBase_Arm64_LeadingSignCount:
6568
- return true ;
6581
+ case VNF_HWI_AdvSimd_PopCount:
6582
+ case VNF_HWI_AdvSimd_LeadingZeroCount:
6583
+ case VNF_HWI_AdvSimd_LeadingSignCount:
6584
+ case VNF_HWI_ArmBase_LeadingZeroCount:
6585
+ case VNF_HWI_ArmBase_Arm64_LeadingZeroCount:
6586
+ case VNF_HWI_ArmBase_Arm64_LeadingSignCount:
6587
+ return VNVisit::Continue ;
6569
6588
#endif
6570
6589
#endif // FEATURE_HW_INTRINSICS
6571
6590
6572
- default:
6573
- break;
6591
+ default:
6592
+ break;
6593
+ }
6574
6594
}
6575
- }
6576
-
6577
- return false ;
6595
+ return VNVisit::Abort;
6596
+ };
6597
+ return VNVisitReachingVNs(vn, vnVisitor) == VNVisit::Continue ;
6578
6598
}
6579
6599
6580
6600
GenTreeFlags ValueNumStore::GetHandleFlags(ValueNum vn)
0 commit comments