@@ -251,7 +251,7 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree*
251
251
{
252
252
JITDUMP (" Looking for array size assertions for: " FMT_VN " \n " , arrLenVn);
253
253
Range arrLength = Range (Limit (Limit::keDependent));
254
- MergeEdgeAssertions (arrLenVn, block->bbAssertionIn , &arrLength);
254
+ MergeEdgeAssertions (m_pCompiler, arrLenVn, arrLenVn, block->bbAssertionIn , &arrLength);
255
255
if (arrLength.lLimit .IsConstant ())
256
256
{
257
257
arrSize = arrLength.lLimit .GetConstant ();
@@ -640,20 +640,28 @@ void RangeCheck::MergeEdgeAssertions(GenTreeLclVarCommon* lcl, ASSERT_VALARG_TP
640
640
641
641
LclSsaVarDsc* ssaData = m_pCompiler->lvaGetDesc (lcl)->GetPerSsaData (lcl->GetSsaNum ());
642
642
ValueNum normalLclVN = m_pCompiler->vnStore ->VNConservativeNormalValue (ssaData->m_vnPair );
643
- MergeEdgeAssertions (normalLclVN, assertions, pRange);
643
+ ValueNum arrLenVN = m_pCompiler->vnStore ->VNConservativeNormalValue (m_pCurBndsChk->GetArrayLength ()->gtVNPair );
644
+ MergeEdgeAssertions (m_pCompiler, normalLclVN, arrLenVN, assertions, pRange);
644
645
}
645
646
646
647
// ------------------------------------------------------------------------
647
648
// MergeEdgeAssertions: Merge assertions on the edge flowing into the block about a variable
648
649
//
649
650
// Arguments:
650
- // normalLclVN - the value number to look for assertions for
651
- // assertions - the assertions to use
652
- // pRange - the range to tighten with assertions
651
+ // comp - the compiler instance
652
+ // normalLclVN - the value number to look for assertions for
653
+ // preferredBoundVN - when this VN is set, it will be given preference over constant limits
654
+ // assertions - the assertions to use
655
+ // pRange - the range to tighten with assertions
653
656
//
654
- void RangeCheck::MergeEdgeAssertions (ValueNum normalLclVN, ASSERT_VALARG_TP assertions, Range* pRange)
657
+ void RangeCheck::MergeEdgeAssertions (Compiler* comp,
658
+ ValueNum normalLclVN,
659
+ ValueNum preferredBoundVN,
660
+ ASSERT_VALARG_TP assertions,
661
+ Range* pRange,
662
+ bool log)
655
663
{
656
- if (BitVecOps::IsEmpty (m_pCompiler ->apTraits , assertions))
664
+ if (BitVecOps::IsEmpty (comp ->apTraits , assertions))
657
665
{
658
666
return ;
659
667
}
@@ -663,14 +671,14 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
663
671
return ;
664
672
}
665
673
666
- // Walk through the "assertions" to check if the apply.
667
- BitVecOps::Iter iter (m_pCompiler ->apTraits , assertions);
674
+ // Walk through the "assertions" to check if they apply.
675
+ BitVecOps::Iter iter (comp ->apTraits , assertions);
668
676
unsigned index = 0 ;
669
677
while (iter.NextElem (&index ))
670
678
{
671
679
AssertionIndex assertionIndex = GetAssertionIndex (index );
672
680
673
- Compiler::AssertionDsc* curAssertion = m_pCompiler ->optGetAssertion (assertionIndex);
681
+ Compiler::AssertionDsc* curAssertion = comp ->optGetAssertion (assertionIndex);
674
682
675
683
Limit limit (Limit::keUndef);
676
684
genTreeOps cmpOper = GT_NONE;
@@ -683,7 +691,7 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
683
691
ValueNumStore::CompareCheckedBoundArithInfo info;
684
692
685
693
// Get i, len, cns and < as "info."
686
- m_pCompiler ->vnStore ->GetCompareCheckedBoundArithInfo (curAssertion->op1 .vn , &info);
694
+ comp ->vnStore ->GetCompareCheckedBoundArithInfo (curAssertion->op1 .vn , &info);
687
695
688
696
// If we don't have the same variable we are comparing against, bail.
689
697
if (normalLclVN != info.cmpOp )
@@ -697,12 +705,12 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
697
705
}
698
706
699
707
// If the operand that operates on the bound is not constant, then done.
700
- if (!m_pCompiler ->vnStore ->IsVNInt32Constant (info.arrOp ))
708
+ if (!comp ->vnStore ->IsVNInt32Constant (info.arrOp ))
701
709
{
702
710
continue ;
703
711
}
704
712
705
- int cons = m_pCompiler ->vnStore ->ConstantValue <int >(info.arrOp );
713
+ int cons = comp ->vnStore ->ConstantValue <int >(info.arrOp );
706
714
limit = Limit (Limit::keBinOpArray, info.vnBound , info.arrOper == GT_SUB ? -cons : cons);
707
715
cmpOper = (genTreeOps)info.cmpOper ;
708
716
}
@@ -712,7 +720,7 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
712
720
ValueNumStore::CompareCheckedBoundArithInfo info;
713
721
714
722
// Get the info as "i", "<" and "len"
715
- m_pCompiler ->vnStore ->GetCompareCheckedBound (curAssertion->op1 .vn , &info);
723
+ comp ->vnStore ->GetCompareCheckedBound (curAssertion->op1 .vn , &info);
716
724
717
725
// If we don't have the same variable we are comparing against, bail.
718
726
if (normalLclVN == info.cmpOp )
@@ -736,7 +744,7 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
736
744
ValueNumStore::ConstantBoundInfo info;
737
745
738
746
// Get the info as "i", "<" and "100"
739
- m_pCompiler ->vnStore ->GetConstantBoundInfo (curAssertion->op1 .vn , &info);
747
+ comp ->vnStore ->GetConstantBoundInfo (curAssertion->op1 .vn , &info);
740
748
741
749
// If we don't have the same variable we are comparing against, bail.
742
750
if (normalLclVN != info.cmpOpVN )
@@ -757,10 +765,10 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
757
765
}
758
766
759
767
int cnstLimit = (int )curAssertion->op2 .u1 .iconVal ;
760
- assert (cnstLimit == m_pCompiler ->vnStore ->CoercedConstantValue <int >(curAssertion->op2 .vn ));
768
+ assert (cnstLimit == comp ->vnStore ->CoercedConstantValue <int >(curAssertion->op2 .vn ));
761
769
762
770
if ((cnstLimit == 0 ) && (curAssertion->assertionKind == Compiler::OAK_NOT_EQUAL) &&
763
- m_pCompiler ->vnStore ->IsVNCheckedBound (curAssertion->op1 .vn ))
771
+ comp ->vnStore ->IsVNCheckedBound (curAssertion->op1 .vn ))
764
772
{
765
773
// we have arr.Len != 0, so the length must be atleast one
766
774
limit = Limit (Limit::keConstant, 1 );
@@ -805,31 +813,31 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
805
813
806
814
// Make sure the assertion is of the form != 0 or == 0 if it isn't a constant assertion.
807
815
if (!isConstantAssertion && (curAssertion->assertionKind != Compiler::OAK_NO_THROW) &&
808
- (curAssertion->op2 .vn != m_pCompiler ->vnStore ->VNZeroForType (TYP_INT)))
816
+ (curAssertion->op2 .vn != comp ->vnStore ->VNZeroForType (TYP_INT)))
809
817
{
810
818
continue ;
811
819
}
812
820
#ifdef DEBUG
813
- if (m_pCompiler ->verbose )
821
+ if (comp ->verbose )
814
822
{
815
- m_pCompiler ->optPrintAssertion (curAssertion, assertionIndex);
823
+ comp ->optPrintAssertion (curAssertion, assertionIndex);
816
824
}
817
825
#endif
818
826
819
827
// Limits are sometimes made with the form vn + constant, where vn is a known constant
820
828
// see if we can simplify this to just a constant
821
- if (limit.IsBinOpArray () && m_pCompiler ->vnStore ->IsVNInt32Constant (limit.vn ))
829
+ if (limit.IsBinOpArray () && comp ->vnStore ->IsVNInt32Constant (limit.vn ))
822
830
{
823
- Limit tempLimit = Limit (Limit::keConstant, m_pCompiler ->vnStore ->ConstantValue <int >(limit.vn ));
831
+ Limit tempLimit = Limit (Limit::keConstant, comp ->vnStore ->ConstantValue <int >(limit.vn ));
824
832
if (tempLimit.AddConstant (limit.cns ))
825
833
{
826
834
limit = tempLimit;
827
835
}
828
836
}
829
837
830
- ValueNum arrLenVN = m_pCompiler-> vnStore -> VNConservativeNormalValue (m_pCurBndsChk-> GetArrayLength ()-> gtVNPair ) ;
838
+ ValueNum arrLenVN = preferredBoundVN ;
831
839
832
- if (m_pCompiler ->vnStore ->IsVNConstant (arrLenVN))
840
+ if (comp ->vnStore ->IsVNConstant (arrLenVN))
833
841
{
834
842
// Set arrLenVN to NoVN; this will make it match the "vn" recorded on
835
843
// constant limits (where we explicitly track the constant and don't
@@ -918,7 +926,10 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
918
926
919
927
if (limit.vn != arrLenVN)
920
928
{
921
- JITDUMP (" Array length VN did not match arrLen=" FMT_VN " , limit=" FMT_VN " \n " , arrLenVN, limit.vn );
929
+ if (log )
930
+ {
931
+ JITDUMP (" Array length VN did not match arrLen=" FMT_VN " , limit=" FMT_VN " \n " , arrLenVN, limit.vn );
932
+ }
922
933
continue ;
923
934
}
924
935
@@ -928,7 +939,10 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
928
939
// Incoming limit doesn't tighten the existing upper limit.
929
940
if (limCns >= curCns)
930
941
{
931
- JITDUMP (" Bound limit %d doesn't tighten current bound %d\n " , limCns, curCns);
942
+ if (log )
943
+ {
944
+ JITDUMP (" Bound limit %d doesn't tighten current bound %d\n " , limCns, curCns);
945
+ }
932
946
continue ;
933
947
}
934
948
}
@@ -955,8 +969,12 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
955
969
956
970
case GT_GT:
957
971
case GT_GE:
958
- pRange->lLimit = limit;
959
- // it doesn't matter if it's isUnsigned or not here - it's not negative anyway.
972
+ // GT/GE being unsigned creates a non-contiguous range which we can't represent
973
+ // using single Range object.
974
+ if (!isUnsigned)
975
+ {
976
+ pRange->lLimit = limit;
977
+ }
960
978
break ;
961
979
962
980
case GT_EQ:
@@ -968,9 +986,13 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
968
986
// All other 'cmpOper' kinds leave lLimit/uLimit unchanged
969
987
break ;
970
988
}
971
- JITDUMP (" The range after edge merging:" );
972
- JITDUMP (pRange->ToString (m_pCompiler));
973
- JITDUMP (" \n " );
989
+
990
+ if (log )
991
+ {
992
+ JITDUMP (" The range after edge merging:" );
993
+ JITDUMP (pRange->ToString (comp));
994
+ JITDUMP (" \n " );
995
+ }
974
996
}
975
997
}
976
998
0 commit comments