@@ -103,8 +103,8 @@ void RangeAnalysis::CollectValues() {
103103 }
104104 }
105105 }
106- if (current-> IsCheckArrayBound () || current->IsGenericCheckBound ()) {
107- bounds_checks_.Add (current );
106+ if (auto check = current->AsCheckBoundBase ()) {
107+ bounds_checks_.Add (check );
108108 }
109109 }
110110 }
@@ -723,8 +723,7 @@ class BoundsCheckGeneralizer {
723723 flow_graph_ (flow_graph),
724724 scheduler_(flow_graph) {}
725725
726- void TryGeneralize (CheckArrayBoundInstr* check,
727- const RangeBoundary& array_length) {
726+ void TryGeneralize (CheckArrayBoundInstr* check) {
728727 Definition* upper_bound =
729728 ConstructUpperBound (check->index ()->definition (), check);
730729 if (upper_bound == UnwrapConstraint (check->index ()->definition ())) {
@@ -837,7 +836,7 @@ class BoundsCheckGeneralizer {
837836 new Value (UnwrapConstraint (check->length ()->definition ())),
838837 new Value (upper_bound), DeoptId::kNone );
839838 new_check->mark_generalized ();
840- if (new_check->IsRedundant (array_length )) {
839+ if (new_check->IsRedundant ()) {
841840 if (FLAG_trace_range_analysis) {
842841 THR_Print (" => generalized check is redundant\n " );
843842 }
@@ -1307,38 +1306,20 @@ void RangeAnalysis::EliminateRedundantBoundsChecks() {
13071306 if (FLAG_array_bounds_check_elimination) {
13081307 const Function& function = flow_graph_->function ();
13091308 // Generalization only if we have not deoptimized on a generalized
1310- // check earlier, or we're compiling precompiled code (no
1311- // optimistic hoisting of checks possible)
1309+ // check earlier and we are not compiling precompiled code
1310+ // (no optimistic hoisting of checks possible)
13121311 const bool try_generalization =
1313- !function.ProhibitsBoundsCheckGeneralization () &&
1314- !FLAG_precompiled_mode;
1315-
1312+ !FLAG_precompiled_mode &&
1313+ !function.ProhibitsBoundsCheckGeneralization ();
13161314 BoundsCheckGeneralizer generalizer (this , flow_graph_);
1317-
1318- for (intptr_t i = 0 ; i < bounds_checks_.length (); i++) {
1319- // Is this a non-speculative check bound?
1320- auto aot_check = bounds_checks_[i]->AsGenericCheckBound ();
1321- if (aot_check != nullptr ) {
1322- auto length = aot_check->length ()
1323- ->definition ()
1324- ->OriginalDefinitionIgnoreBoxingAndConstraints ();
1325- auto array_length = RangeBoundary::FromDefinition (length);
1326- if (aot_check->IsRedundant (array_length)) {
1327- aot_check->ReplaceUsesWith (aot_check->index ()->definition ());
1328- aot_check->RemoveFromGraph ();
1329- }
1330- continue ;
1331- }
1332- // Must be a speculative check bound.
1333- CheckArrayBoundInstr* check = bounds_checks_[i]->AsCheckArrayBound ();
1334- ASSERT (check != nullptr );
1335- RangeBoundary array_length =
1336- RangeBoundary::FromDefinition (check->length ()->definition ());
1337- if (check->IsRedundant (array_length)) {
1315+ for (CheckBoundBase* check : bounds_checks_) {
1316+ if (check->IsRedundant ()) {
13381317 check->ReplaceUsesWith (check->index ()->definition ());
13391318 check->RemoveFromGraph ();
13401319 } else if (try_generalization) {
1341- generalizer.TryGeneralize (check, array_length);
1320+ if (auto jit_check = check->AsCheckArrayBound ()) {
1321+ generalizer.TryGeneralize (jit_check);
1322+ }
13421323 }
13431324 }
13441325 }
@@ -2931,33 +2912,31 @@ void IntConverterInstr::InferRange(RangeAnalysis* analysis, Range* range) {
29312912 }
29322913}
29332914
2934- bool CheckArrayBoundInstr::IsRedundant (const RangeBoundary& length) {
2935- Range* index_range = index ()->definition ()->range ();
2936-
2915+ static bool IsRedundantBasedOnRangeInformation (Value* index, Value* length) {
29372916 // Range of the index is unknown can't decide if the check is redundant.
2938- if (index_range == NULL ) {
2939- if (!(index ()->BindsToConstant () &&
2940- compiler::target::IsSmi (index ()->BoundConstant ()))) {
2917+ Range* index_range = index->definition ()->range ();
2918+ if (index_range == nullptr ) {
2919+ if (!(index->BindsToConstant () &&
2920+ compiler::target::IsSmi (index->BoundConstant ()))) {
29412921 return false ;
29422922 }
2943-
29442923 Range range;
2945- index () ->definition ()->InferRange (NULL , &range);
2924+ index->definition ()->InferRange (nullptr , &range);
29462925 ASSERT (!Range::IsUnknown (&range));
2947- index () ->definition ()->set_range (range);
2948- index_range = index () ->definition ()->range ();
2926+ index->definition ()->set_range (range);
2927+ index_range = index->definition ()->range ();
29492928 }
29502929
29512930 // Range of the index is not positive. Check can't be redundant.
29522931 if (Range::ConstantMinSmi (index_range).ConstantValue () < 0 ) {
29532932 return false ;
29542933 }
29552934
2956- RangeBoundary max = RangeBoundary::FromDefinition (index ()->definition ());
2957-
2935+ RangeBoundary max = RangeBoundary::FromDefinition (index->definition ());
29582936 RangeBoundary max_upper = max.UpperBound ();
2959- RangeBoundary length_lower = length.LowerBound ();
2960-
2937+ RangeBoundary array_length =
2938+ RangeBoundary::FromDefinition (length->definition ());
2939+ RangeBoundary length_lower = array_length.LowerBound ();
29612940 if (max_upper.OverflowedSmi () || length_lower.OverflowedSmi ()) {
29622941 return false ;
29632942 }
@@ -2968,7 +2947,7 @@ bool CheckArrayBoundInstr::IsRedundant(const RangeBoundary& length) {
29682947 }
29692948
29702949 RangeBoundary canonical_length =
2971- CanonicalizeBoundary (length , RangeBoundary::PositiveInfinity ());
2950+ CanonicalizeBoundary (array_length , RangeBoundary::PositiveInfinity ());
29722951 if (canonical_length.OverflowedSmi ()) {
29732952 return false ;
29742953 }
@@ -3000,30 +2979,41 @@ static bool IsSameBound(const RangeBoundary& a, InductionVar* b) {
30002979 return false ;
30012980}
30022981
3003- bool GenericCheckBoundInstr::IsRedundant (const RangeBoundary& length) {
3004- // In loop, with index as induction?
3005- LoopInfo* loop = GetBlock ()->loop_info ();
3006- if (loop == nullptr ) {
3007- return false ;
3008- }
3009- InductionVar* induc = loop->LookupInduction (index ()->definition ());
3010- if (induc == nullptr ) {
3011- return false ;
2982+ bool CheckBoundBase::IsRedundant () {
2983+ // First, try to prove redundancy with the results of range analysis.
2984+ if (IsRedundantBasedOnRangeInformation (index (), length ())) {
2985+ return true ;
2986+ } else if (previous () == nullptr ) {
2987+ return false ; // check is not in flow graph yet
30122988 }
2989+ // Next, try to prove redundancy with the results of induction analysis.
30132990 // Under 64-bit wrap-around arithmetic, it is always safe to remove the
3014- // bounds check from the following, if initial >= 0 and the corresponding
2991+ // bounds check from the following loop , if initial >= 0 and the loop
30152992 // exit branch dominates the bounds check:
2993+ //
30162994 // for (int i = initial; i < length; i++)
30172995 // .... a[i] ....
3018- int64_t stride = 0 ;
3019- int64_t initial = 0 ;
3020- if (InductionVar::IsLinear (induc, &stride) &&
3021- InductionVar::IsConstant (induc->initial (), &initial)) {
3022- if (stride == 1 && initial >= 0 ) {
3023- for (auto bound : induc->bounds ()) {
3024- if (IsSameBound (length, bound.limit_ ) &&
3025- this ->IsDominatedBy (bound.branch_ )) {
3026- return true ;
2996+ //
2997+ LoopInfo* loop = GetBlock ()->loop_info ();
2998+ if (loop != nullptr ) {
2999+ InductionVar* induc = loop->LookupInduction (index ()->definition ());
3000+ if (induc != nullptr ) {
3001+ int64_t stride = 0 ;
3002+ int64_t initial = 0 ;
3003+ if (InductionVar::IsLinear (induc, &stride) &&
3004+ InductionVar::IsConstant (induc->initial (), &initial)) {
3005+ if (stride == 1 && initial >= 0 ) {
3006+ // Deeply trace back the range of the array length.
3007+ RangeBoundary deep_length = RangeBoundary::FromDefinition (
3008+ length ()
3009+ ->definition ()
3010+ ->OriginalDefinitionIgnoreBoxingAndConstraints ());
3011+ for (auto bound : induc->bounds ()) {
3012+ if (IsSameBound (deep_length, bound.limit_ ) &&
3013+ this ->IsDominatedBy (bound.branch_ )) {
3014+ return true ;
3015+ }
3016+ }
30273017 }
30283018 }
30293019 }
0 commit comments