1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_INDUCTION_VAR_ANALYSIS_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_INDUCTION_VAR_ANALYSIS_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <string> 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h" 23*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h" 24*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 25*795d594fSAndroid Build Coastguard Worker #include "base/scoped_arena_containers.h" 26*795d594fSAndroid Build Coastguard Worker #include "nodes.h" 27*795d594fSAndroid Build Coastguard Worker #include "optimization.h" 28*795d594fSAndroid Build Coastguard Worker 29*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker /** 32*795d594fSAndroid Build Coastguard Worker * Induction variable analysis. This class does not have a direct public API. 33*795d594fSAndroid Build Coastguard Worker * Instead, the results of induction variable analysis can be queried through 34*795d594fSAndroid Build Coastguard Worker * friend classes, such as InductionVarRange. 35*795d594fSAndroid Build Coastguard Worker * 36*795d594fSAndroid Build Coastguard Worker * The analysis implementation is based on the paper by M. Gerlek et al. 37*795d594fSAndroid Build Coastguard Worker * "Beyond Induction Variables: Detecting and Classifying Sequences Using a Demand-Driven SSA Form" 38*795d594fSAndroid Build Coastguard Worker * (ACM Transactions on Programming Languages and Systems, Volume 17 Issue 1, Jan. 1995). 39*795d594fSAndroid Build Coastguard Worker */ 40*795d594fSAndroid Build Coastguard Worker class HInductionVarAnalysis : public HOptimization { 41*795d594fSAndroid Build Coastguard Worker public: 42*795d594fSAndroid Build Coastguard Worker explicit HInductionVarAnalysis(HGraph* graph, 43*795d594fSAndroid Build Coastguard Worker OptimizingCompilerStats* stats = nullptr, 44*795d594fSAndroid Build Coastguard Worker const char* name = kInductionPassName); 45*795d594fSAndroid Build Coastguard Worker 46*795d594fSAndroid Build Coastguard Worker bool Run() override; 47*795d594fSAndroid Build Coastguard Worker 48*795d594fSAndroid Build Coastguard Worker static constexpr const char* kInductionPassName = "induction_var_analysis"; 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker private: 51*795d594fSAndroid Build Coastguard Worker struct NodeInfo; 52*795d594fSAndroid Build Coastguard Worker struct StackEntry; 53*795d594fSAndroid Build Coastguard Worker 54*795d594fSAndroid Build Coastguard Worker enum InductionClass { 55*795d594fSAndroid Build Coastguard Worker kInvariant, 56*795d594fSAndroid Build Coastguard Worker kLinear, 57*795d594fSAndroid Build Coastguard Worker kPolynomial, 58*795d594fSAndroid Build Coastguard Worker kGeometric, 59*795d594fSAndroid Build Coastguard Worker kWrapAround, 60*795d594fSAndroid Build Coastguard Worker kPeriodic 61*795d594fSAndroid Build Coastguard Worker }; 62*795d594fSAndroid Build Coastguard Worker 63*795d594fSAndroid Build Coastguard Worker enum InductionOp { 64*795d594fSAndroid Build Coastguard Worker // Operations. 65*795d594fSAndroid Build Coastguard Worker kNop, 66*795d594fSAndroid Build Coastguard Worker kAdd, 67*795d594fSAndroid Build Coastguard Worker kSub, 68*795d594fSAndroid Build Coastguard Worker kNeg, 69*795d594fSAndroid Build Coastguard Worker kMul, 70*795d594fSAndroid Build Coastguard Worker kDiv, 71*795d594fSAndroid Build Coastguard Worker kRem, 72*795d594fSAndroid Build Coastguard Worker kXor, 73*795d594fSAndroid Build Coastguard Worker kFetch, 74*795d594fSAndroid Build Coastguard Worker // Trip-counts. 75*795d594fSAndroid Build Coastguard Worker kTripCountInLoop, // valid in full loop; loop is finite 76*795d594fSAndroid Build Coastguard Worker kTripCountInBody, // valid in body only; loop is finite 77*795d594fSAndroid Build Coastguard Worker kTripCountInLoopUnsafe, // valid in full loop; loop may be infinite 78*795d594fSAndroid Build Coastguard Worker kTripCountInBodyUnsafe, // valid in body only; loop may be infinite 79*795d594fSAndroid Build Coastguard Worker // Comparisons for trip-count tests. 80*795d594fSAndroid Build Coastguard Worker kLT, 81*795d594fSAndroid Build Coastguard Worker kLE, 82*795d594fSAndroid Build Coastguard Worker kGT, 83*795d594fSAndroid Build Coastguard Worker kGE 84*795d594fSAndroid Build Coastguard Worker }; 85*795d594fSAndroid Build Coastguard Worker 86*795d594fSAndroid Build Coastguard Worker /** 87*795d594fSAndroid Build Coastguard Worker * Defines a detected induction as: 88*795d594fSAndroid Build Coastguard Worker * (1) invariant: 89*795d594fSAndroid Build Coastguard Worker * op: a + b, a - b, -b, a * b, a / b, a % b, a ^ b, fetch 90*795d594fSAndroid Build Coastguard Worker * (2) linear: 91*795d594fSAndroid Build Coastguard Worker * nop: a * i + b 92*795d594fSAndroid Build Coastguard Worker * (3) polynomial: 93*795d594fSAndroid Build Coastguard Worker * nop: sum_lt(a) + b, for linear a 94*795d594fSAndroid Build Coastguard Worker * (4) geometric: 95*795d594fSAndroid Build Coastguard Worker * op: a * fetch^i + b, a * fetch^-i + b 96*795d594fSAndroid Build Coastguard Worker * (5) wrap-around 97*795d594fSAndroid Build Coastguard Worker * nop: a, then defined by b 98*795d594fSAndroid Build Coastguard Worker * (6) periodic 99*795d594fSAndroid Build Coastguard Worker * nop: a, then defined by b (repeated when exhausted) 100*795d594fSAndroid Build Coastguard Worker * (7) trip-count: 101*795d594fSAndroid Build Coastguard Worker * tc: defined by a, taken-test in b 102*795d594fSAndroid Build Coastguard Worker */ 103*795d594fSAndroid Build Coastguard Worker struct InductionInfo : public ArenaObject<kArenaAllocInductionVarAnalysis> { InductionInfoInductionInfo104*795d594fSAndroid Build Coastguard Worker InductionInfo(InductionClass ic, 105*795d594fSAndroid Build Coastguard Worker InductionOp op, 106*795d594fSAndroid Build Coastguard Worker InductionInfo* a, 107*795d594fSAndroid Build Coastguard Worker InductionInfo* b, 108*795d594fSAndroid Build Coastguard Worker HInstruction* f, 109*795d594fSAndroid Build Coastguard Worker DataType::Type t) 110*795d594fSAndroid Build Coastguard Worker : induction_class(ic), 111*795d594fSAndroid Build Coastguard Worker operation(op), 112*795d594fSAndroid Build Coastguard Worker op_a(a), 113*795d594fSAndroid Build Coastguard Worker op_b(b), 114*795d594fSAndroid Build Coastguard Worker fetch(f), 115*795d594fSAndroid Build Coastguard Worker type(t) {} 116*795d594fSAndroid Build Coastguard Worker InductionClass induction_class; 117*795d594fSAndroid Build Coastguard Worker InductionOp operation; 118*795d594fSAndroid Build Coastguard Worker InductionInfo* op_a; 119*795d594fSAndroid Build Coastguard Worker InductionInfo* op_b; 120*795d594fSAndroid Build Coastguard Worker HInstruction* fetch; 121*795d594fSAndroid Build Coastguard Worker DataType::Type type; // precision of operation 122*795d594fSAndroid Build Coastguard Worker }; 123*795d594fSAndroid Build Coastguard Worker 124*795d594fSAndroid Build Coastguard Worker CreateInvariantOp(const HBasicBlock * context,const HLoopInformation * loop,InductionOp op,InductionInfo * a,InductionInfo * b)125*795d594fSAndroid Build Coastguard Worker InductionInfo* CreateInvariantOp(const HBasicBlock* context, 126*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 127*795d594fSAndroid Build Coastguard Worker InductionOp op, 128*795d594fSAndroid Build Coastguard Worker InductionInfo* a, 129*795d594fSAndroid Build Coastguard Worker InductionInfo* b) { 130*795d594fSAndroid Build Coastguard Worker DCHECK(((op != kNeg && a != nullptr) || (op == kNeg && a == nullptr)) && b != nullptr); 131*795d594fSAndroid Build Coastguard Worker return CreateSimplifiedInvariant(context, loop, op, a, b); 132*795d594fSAndroid Build Coastguard Worker } 133*795d594fSAndroid Build Coastguard Worker CreateInvariantFetch(HInstruction * f)134*795d594fSAndroid Build Coastguard Worker InductionInfo* CreateInvariantFetch(HInstruction* f) { 135*795d594fSAndroid Build Coastguard Worker DCHECK(f != nullptr); 136*795d594fSAndroid Build Coastguard Worker return new (graph_->GetAllocator()) 137*795d594fSAndroid Build Coastguard Worker InductionInfo(kInvariant, kFetch, nullptr, nullptr, f, f->GetType()); 138*795d594fSAndroid Build Coastguard Worker } 139*795d594fSAndroid Build Coastguard Worker CreateTripCount(InductionOp op,InductionInfo * a,InductionInfo * b,DataType::Type type)140*795d594fSAndroid Build Coastguard Worker InductionInfo* CreateTripCount(InductionOp op, 141*795d594fSAndroid Build Coastguard Worker InductionInfo* a, 142*795d594fSAndroid Build Coastguard Worker InductionInfo* b, 143*795d594fSAndroid Build Coastguard Worker DataType::Type type) { 144*795d594fSAndroid Build Coastguard Worker DCHECK(a != nullptr && b != nullptr); 145*795d594fSAndroid Build Coastguard Worker return new (graph_->GetAllocator()) InductionInfo(kInvariant, op, a, b, nullptr, type); 146*795d594fSAndroid Build Coastguard Worker } 147*795d594fSAndroid Build Coastguard Worker CreateInduction(InductionClass ic,InductionOp op,InductionInfo * a,InductionInfo * b,HInstruction * f,DataType::Type type)148*795d594fSAndroid Build Coastguard Worker InductionInfo* CreateInduction(InductionClass ic, 149*795d594fSAndroid Build Coastguard Worker InductionOp op, 150*795d594fSAndroid Build Coastguard Worker InductionInfo* a, 151*795d594fSAndroid Build Coastguard Worker InductionInfo* b, 152*795d594fSAndroid Build Coastguard Worker HInstruction* f, 153*795d594fSAndroid Build Coastguard Worker DataType::Type type) { 154*795d594fSAndroid Build Coastguard Worker DCHECK(a != nullptr && b != nullptr); 155*795d594fSAndroid Build Coastguard Worker return new (graph_->GetAllocator()) InductionInfo(ic, op, a, b, f, type); 156*795d594fSAndroid Build Coastguard Worker } 157*795d594fSAndroid Build Coastguard Worker 158*795d594fSAndroid Build Coastguard Worker // Methods for analysis. 159*795d594fSAndroid Build Coastguard Worker void VisitLoop(const HLoopInformation* loop); 160*795d594fSAndroid Build Coastguard Worker size_t TryVisitNodes(const HLoopInformation* loop, 161*795d594fSAndroid Build Coastguard Worker HInstruction* start_instruction, 162*795d594fSAndroid Build Coastguard Worker size_t global_depth, 163*795d594fSAndroid Build Coastguard Worker /*inout*/ ScopedArenaSafeMap<HInstruction*, NodeInfo>* visited_instructions); 164*795d594fSAndroid Build Coastguard Worker void ExtractScc(ArrayRef<const StackEntry> stack_tail, ScopedArenaVector<HInstruction*>* scc); 165*795d594fSAndroid Build Coastguard Worker void ClassifyTrivial(const HLoopInformation* loop, HInstruction* instruction); 166*795d594fSAndroid Build Coastguard Worker void ClassifyNonTrivial(const HLoopInformation* loop, ArrayRef<const StackEntry> stack_tail); 167*795d594fSAndroid Build Coastguard Worker InductionInfo* RotatePeriodicInduction(InductionInfo* induction, 168*795d594fSAndroid Build Coastguard Worker InductionInfo* last, 169*795d594fSAndroid Build Coastguard Worker DataType::Type type); 170*795d594fSAndroid Build Coastguard Worker 171*795d594fSAndroid Build Coastguard Worker // Transfer operations. 172*795d594fSAndroid Build Coastguard Worker InductionInfo* TransferPhi(const HLoopInformation* loop, 173*795d594fSAndroid Build Coastguard Worker HInstruction* phi, 174*795d594fSAndroid Build Coastguard Worker size_t input_index, 175*795d594fSAndroid Build Coastguard Worker size_t adjust_input_size); 176*795d594fSAndroid Build Coastguard Worker InductionInfo* TransferAddSub(const HBasicBlock* context, 177*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 178*795d594fSAndroid Build Coastguard Worker InductionInfo* a, 179*795d594fSAndroid Build Coastguard Worker InductionInfo* b, 180*795d594fSAndroid Build Coastguard Worker InductionOp op, 181*795d594fSAndroid Build Coastguard Worker DataType::Type type); 182*795d594fSAndroid Build Coastguard Worker InductionInfo* TransferNeg(const HBasicBlock* context, 183*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 184*795d594fSAndroid Build Coastguard Worker InductionInfo* a, 185*795d594fSAndroid Build Coastguard Worker DataType::Type type); 186*795d594fSAndroid Build Coastguard Worker InductionInfo* TransferMul(const HBasicBlock* context, 187*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 188*795d594fSAndroid Build Coastguard Worker InductionInfo* a, 189*795d594fSAndroid Build Coastguard Worker InductionInfo* b, 190*795d594fSAndroid Build Coastguard Worker DataType::Type type); 191*795d594fSAndroid Build Coastguard Worker InductionInfo* TransferConversion(InductionInfo* a, DataType::Type from, DataType::Type to); 192*795d594fSAndroid Build Coastguard Worker 193*795d594fSAndroid Build Coastguard Worker // Solvers. 194*795d594fSAndroid Build Coastguard Worker InductionInfo* SolvePhi(HInstruction* phi, 195*795d594fSAndroid Build Coastguard Worker size_t input_index, 196*795d594fSAndroid Build Coastguard Worker size_t adjust_input_size, 197*795d594fSAndroid Build Coastguard Worker const ScopedArenaSafeMap<HInstruction*, InductionInfo*>& cycle); 198*795d594fSAndroid Build Coastguard Worker InductionInfo* SolvePhiAllInputs(const HLoopInformation* loop, 199*795d594fSAndroid Build Coastguard Worker HInstruction* entry_phi, 200*795d594fSAndroid Build Coastguard Worker HInstruction* phi, 201*795d594fSAndroid Build Coastguard Worker const ScopedArenaSafeMap<HInstruction*, InductionInfo*>& cycle, 202*795d594fSAndroid Build Coastguard Worker DataType::Type type); 203*795d594fSAndroid Build Coastguard Worker InductionInfo* SolveAddSub(const HLoopInformation* loop, 204*795d594fSAndroid Build Coastguard Worker HInstruction* entry_phi, 205*795d594fSAndroid Build Coastguard Worker HInstruction* instruction, 206*795d594fSAndroid Build Coastguard Worker HInstruction* x, 207*795d594fSAndroid Build Coastguard Worker HInstruction* y, 208*795d594fSAndroid Build Coastguard Worker InductionOp op, 209*795d594fSAndroid Build Coastguard Worker const ScopedArenaSafeMap<HInstruction*, InductionInfo*>& cycle, 210*795d594fSAndroid Build Coastguard Worker DataType::Type type); 211*795d594fSAndroid Build Coastguard Worker InductionInfo* SolveOp(const HLoopInformation* loop, 212*795d594fSAndroid Build Coastguard Worker HInstruction* entry_phi, 213*795d594fSAndroid Build Coastguard Worker HInstruction* instruction, 214*795d594fSAndroid Build Coastguard Worker HInstruction* x, 215*795d594fSAndroid Build Coastguard Worker HInstruction* y, 216*795d594fSAndroid Build Coastguard Worker InductionOp op, 217*795d594fSAndroid Build Coastguard Worker DataType::Type type); 218*795d594fSAndroid Build Coastguard Worker InductionInfo* SolveTest(const HLoopInformation* loop, 219*795d594fSAndroid Build Coastguard Worker HInstruction* entry_phi, 220*795d594fSAndroid Build Coastguard Worker HInstruction* instruction, 221*795d594fSAndroid Build Coastguard Worker int64_t opposite_value, 222*795d594fSAndroid Build Coastguard Worker DataType::Type type); 223*795d594fSAndroid Build Coastguard Worker InductionInfo* SolveConversion(const HLoopInformation* loop, 224*795d594fSAndroid Build Coastguard Worker HInstruction* entry_phi, 225*795d594fSAndroid Build Coastguard Worker HTypeConversion* conversion, 226*795d594fSAndroid Build Coastguard Worker const ScopedArenaSafeMap<HInstruction*, InductionInfo*>& cycle, 227*795d594fSAndroid Build Coastguard Worker /*inout*/ DataType::Type* type); 228*795d594fSAndroid Build Coastguard Worker 229*795d594fSAndroid Build Coastguard Worker // 230*795d594fSAndroid Build Coastguard Worker // Loop trip count analysis methods. 231*795d594fSAndroid Build Coastguard Worker // 232*795d594fSAndroid Build Coastguard Worker 233*795d594fSAndroid Build Coastguard Worker // Trip count information. 234*795d594fSAndroid Build Coastguard Worker void VisitControl(const HLoopInformation* loop); 235*795d594fSAndroid Build Coastguard Worker void VisitCondition(const HBasicBlock* context, 236*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 237*795d594fSAndroid Build Coastguard Worker HBasicBlock* body, 238*795d594fSAndroid Build Coastguard Worker InductionInfo* a, 239*795d594fSAndroid Build Coastguard Worker InductionInfo* b, 240*795d594fSAndroid Build Coastguard Worker DataType::Type type, 241*795d594fSAndroid Build Coastguard Worker IfCondition cmp); 242*795d594fSAndroid Build Coastguard Worker void VisitTripCount(const HBasicBlock* context, 243*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 244*795d594fSAndroid Build Coastguard Worker InductionInfo* lower_expr, 245*795d594fSAndroid Build Coastguard Worker InductionInfo* upper_expr, 246*795d594fSAndroid Build Coastguard Worker InductionInfo* stride, 247*795d594fSAndroid Build Coastguard Worker int64_t stride_value, 248*795d594fSAndroid Build Coastguard Worker DataType::Type type, 249*795d594fSAndroid Build Coastguard Worker IfCondition cmp); 250*795d594fSAndroid Build Coastguard Worker bool IsTaken(const HBasicBlock* context, 251*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 252*795d594fSAndroid Build Coastguard Worker InductionInfo* lower_expr, 253*795d594fSAndroid Build Coastguard Worker InductionInfo* upper_expr, 254*795d594fSAndroid Build Coastguard Worker IfCondition cmp); 255*795d594fSAndroid Build Coastguard Worker bool IsFinite(const HBasicBlock* context, 256*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 257*795d594fSAndroid Build Coastguard Worker InductionInfo* upper_expr, 258*795d594fSAndroid Build Coastguard Worker int64_t stride_value, 259*795d594fSAndroid Build Coastguard Worker DataType::Type type, 260*795d594fSAndroid Build Coastguard Worker IfCondition cmp); 261*795d594fSAndroid Build Coastguard Worker bool FitsNarrowerControl(const HBasicBlock* context, 262*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 263*795d594fSAndroid Build Coastguard Worker InductionInfo* lower_expr, 264*795d594fSAndroid Build Coastguard Worker InductionInfo* upper_expr, 265*795d594fSAndroid Build Coastguard Worker int64_t stride_value, 266*795d594fSAndroid Build Coastguard Worker DataType::Type type, 267*795d594fSAndroid Build Coastguard Worker IfCondition cmp); 268*795d594fSAndroid Build Coastguard Worker bool RewriteBreakLoop(const HBasicBlock* context, 269*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 270*795d594fSAndroid Build Coastguard Worker HBasicBlock* body, 271*795d594fSAndroid Build Coastguard Worker int64_t stride_value, 272*795d594fSAndroid Build Coastguard Worker DataType::Type type); 273*795d594fSAndroid Build Coastguard Worker 274*795d594fSAndroid Build Coastguard Worker // 275*795d594fSAndroid Build Coastguard Worker // Helper methods. 276*795d594fSAndroid Build Coastguard Worker // 277*795d594fSAndroid Build Coastguard Worker 278*795d594fSAndroid Build Coastguard Worker // Assign and lookup. 279*795d594fSAndroid Build Coastguard Worker void AssignInfo(const HLoopInformation* loop, HInstruction* instruction, InductionInfo* info); 280*795d594fSAndroid Build Coastguard Worker InductionInfo* LookupInfo(const HLoopInformation* loop, HInstruction* instruction); 281*795d594fSAndroid Build Coastguard Worker InductionInfo* CreateConstant(int64_t value, DataType::Type type); 282*795d594fSAndroid Build Coastguard Worker InductionInfo* CreateSimplifiedInvariant(const HBasicBlock* context, 283*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 284*795d594fSAndroid Build Coastguard Worker InductionOp op, 285*795d594fSAndroid Build Coastguard Worker InductionInfo* a, 286*795d594fSAndroid Build Coastguard Worker InductionInfo* b); 287*795d594fSAndroid Build Coastguard Worker HInstruction* GetShiftConstant(const HLoopInformation* loop, 288*795d594fSAndroid Build Coastguard Worker HInstruction* instruction, 289*795d594fSAndroid Build Coastguard Worker InductionInfo* initial); 290*795d594fSAndroid Build Coastguard Worker void AssignCycle(HPhi* phi, ArrayRef<HInstruction* const> scc); 291*795d594fSAndroid Build Coastguard Worker ArenaSet<HInstruction*>* LookupCycle(HPhi* phi); 292*795d594fSAndroid Build Coastguard Worker 293*795d594fSAndroid Build Coastguard Worker // Constants. 294*795d594fSAndroid Build Coastguard Worker bool IsExact(const HBasicBlock* context, 295*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 296*795d594fSAndroid Build Coastguard Worker InductionInfo* info, 297*795d594fSAndroid Build Coastguard Worker /*out*/int64_t* value); 298*795d594fSAndroid Build Coastguard Worker bool IsAtMost(const HBasicBlock* context, 299*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 300*795d594fSAndroid Build Coastguard Worker InductionInfo* info, 301*795d594fSAndroid Build Coastguard Worker /*out*/int64_t* value); 302*795d594fSAndroid Build Coastguard Worker bool IsAtLeast(const HBasicBlock* context, 303*795d594fSAndroid Build Coastguard Worker const HLoopInformation* loop, 304*795d594fSAndroid Build Coastguard Worker InductionInfo* info, 305*795d594fSAndroid Build Coastguard Worker /*out*/int64_t* value); 306*795d594fSAndroid Build Coastguard Worker 307*795d594fSAndroid Build Coastguard Worker // Helpers. 308*795d594fSAndroid Build Coastguard Worker static bool IsNarrowingLinear(InductionInfo* info); 309*795d594fSAndroid Build Coastguard Worker static bool InductionEqual(InductionInfo* info1, InductionInfo* info2); 310*795d594fSAndroid Build Coastguard Worker static std::string FetchToString(HInstruction* fetch); 311*795d594fSAndroid Build Coastguard Worker static std::string InductionToString(InductionInfo* info); 312*795d594fSAndroid Build Coastguard Worker 313*795d594fSAndroid Build Coastguard Worker // Returns true if we have a pathological case we don't want to analyze. 314*795d594fSAndroid Build Coastguard Worker bool IsPathologicalCase(); 315*795d594fSAndroid Build Coastguard Worker // Starting with initial_phi, it calculates how many loop header phis in a row we have. To do 316*795d594fSAndroid Build Coastguard Worker // this, we count the loop header phi which are used as an input of other loop header phis. It 317*795d594fSAndroid Build Coastguard Worker // uses `cached_values` to avoid recomputing results. 318*795d594fSAndroid Build Coastguard Worker void CalculateLoopHeaderPhisInARow(HPhi* initial_phi, 319*795d594fSAndroid Build Coastguard Worker ScopedArenaSafeMap<HPhi*, int>& cached_values, 320*795d594fSAndroid Build Coastguard Worker ScopedArenaAllocator& allocator); 321*795d594fSAndroid Build Coastguard Worker 322*795d594fSAndroid Build Coastguard Worker /** 323*795d594fSAndroid Build Coastguard Worker * Maintains the results of the analysis as a mapping from loops to a mapping from instructions 324*795d594fSAndroid Build Coastguard Worker * to the induction information for that instruction in that loop. 325*795d594fSAndroid Build Coastguard Worker */ 326*795d594fSAndroid Build Coastguard Worker ArenaSafeMap<const HLoopInformation*, ArenaSafeMap<HInstruction*, InductionInfo*>> induction_; 327*795d594fSAndroid Build Coastguard Worker 328*795d594fSAndroid Build Coastguard Worker /** 329*795d594fSAndroid Build Coastguard Worker * Preserves induction cycle information for each loop-phi. 330*795d594fSAndroid Build Coastguard Worker */ 331*795d594fSAndroid Build Coastguard Worker ArenaSafeMap<HPhi*, ArenaSet<HInstruction*>> cycles_; 332*795d594fSAndroid Build Coastguard Worker 333*795d594fSAndroid Build Coastguard Worker friend class InductionVarAnalysisTest; 334*795d594fSAndroid Build Coastguard Worker friend class InductionVarRange; 335*795d594fSAndroid Build Coastguard Worker friend class InductionVarRangeTest; 336*795d594fSAndroid Build Coastguard Worker 337*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(HInductionVarAnalysis); 338*795d594fSAndroid Build Coastguard Worker }; 339*795d594fSAndroid Build Coastguard Worker 340*795d594fSAndroid Build Coastguard Worker } // namespace art 341*795d594fSAndroid Build Coastguard Worker 342*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_OPTIMIZING_INDUCTION_VAR_ANALYSIS_H_ 343