From 0b5849be045c5683d4a6b6b6c306abadba5f0fcc Mon Sep 17 00:00:00 2001 From: Aart Bik Date: Mon, 19 Oct 2015 14:59:26 -0700 Subject: Dynamic BCE (based on induction range analysis) Rationale: A rewritten dynamic BCE that uses induction variable analysis to generate the run-time tests before a loop in order to eliminate bounds-checks from its body. This CL removes now obsoleted induction related code inside the BCE module. Also, the dynamic test generation is placed more strategically, since we missed a few cases where static analysis does better. Most significant performance improvements (after filtering noise) is about: Linpack +20% LU > +10% Change-Id: I4e7b8bab0288beff6f98a14856e3536103d32742 --- compiler/optimizing/induction_var_range.cc | 55 +++++++++++++++++++----------- 1 file changed, 36 insertions(+), 19 deletions(-) (limited to 'compiler/optimizing/induction_var_range.cc') diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc index b40ef5aa41..433c8f8362 100644 --- a/compiler/optimizing/induction_var_range.cc +++ b/compiler/optimizing/induction_var_range.cc @@ -425,9 +425,13 @@ bool InductionVarRange::GenerateCode(HInstruction* context, } HInductionVarAnalysis::InductionInfo* trip = induction_analysis_->LookupInfo(loop, header->GetLastInstruction()); - // Determine what tests are needed. + // Determine what tests are needed. A finite test is needed if the evaluation code uses the + // trip-count and the loop maybe unsafe (because in such cases, the index could "overshoot" + // the computed range). A taken test is needed for any unknown trip-count, even if evaluation + // code does not use the trip-count explicitly (since there could be an implicit relation + // between e.g. an invariant subscript and a not-taken condition). *needs_finite_test = NeedsTripCount(info) && IsUnsafeTripCount(trip); - *needs_taken_test = NeedsTripCount(info) && IsBodyTripCount(trip); + *needs_taken_test = IsBodyTripCount(trip); // Code generation for taken test: generate the code when requested or otherwise analyze // if code generation is feasible when taken test is needed. if (taken_test != nullptr) { @@ -545,29 +549,42 @@ bool InductionVarRange::GenerateCode(HInductionVarAnalysis::InductionInfo* info, } break; case HInductionVarAnalysis::kLinear: { - // Linear induction a * i + b, for normalized 0 <= i < TC. Restrict to unit stride only - // to avoid arithmetic wrap-around situations that are hard to guard against. - int32_t stride_value = 0; - if (GetConstant(info->op_a, &stride_value)) { - if (stride_value == 1 || stride_value == -1) { - const bool is_min_a = stride_value == 1 ? is_min : !is_min; - if (GenerateCode(trip, trip, graph, block, &opa, in_body, is_min_a) && - GenerateCode(info->op_b, trip, graph, block, &opb, in_body, is_min)) { - if (graph != nullptr) { - HInstruction* oper; - if (stride_value == 1) { - oper = new (graph->GetArena()) HAdd(type, opa, opb); - } else { - oper = new (graph->GetArena()) HSub(type, opb, opa); - } - *result = Insert(block, oper); + // Linear induction a * i + b, for normalized 0 <= i < TC. Restrict to unit stride only + // to avoid arithmetic wrap-around situations that are hard to guard against. + int32_t stride_value = 0; + if (GetConstant(info->op_a, &stride_value)) { + if (stride_value == 1 || stride_value == -1) { + const bool is_min_a = stride_value == 1 ? is_min : !is_min; + if (GenerateCode(trip, trip, graph, block, &opa, in_body, is_min_a) && + GenerateCode(info->op_b, trip, graph, block, &opb, in_body, is_min)) { + if (graph != nullptr) { + HInstruction* oper; + if (stride_value == 1) { + oper = new (graph->GetArena()) HAdd(type, opa, opb); + } else { + oper = new (graph->GetArena()) HSub(type, opb, opa); } - return true; + *result = Insert(block, oper); } + return true; } } } break; + } + case HInductionVarAnalysis::kWrapAround: + case HInductionVarAnalysis::kPeriodic: { + // Wrap-around and periodic inductions are restricted to constants only, so that extreme + // values are easy to test at runtime without complications of arithmetic wrap-around. + Value extreme = GetVal(info, trip, in_body, is_min); + if (extreme.is_known && extreme.a_constant == 0) { + if (graph != nullptr) { + *result = graph->GetIntConstant(extreme.b_constant); + } + return true; + } + break; + } default: break; } -- cgit v1.2.3-59-g8ed1b