Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "induction_var_analysis.h"
     18 #include "induction_var_range.h"
     19 
     20 namespace art {
     21 
     22 /**
     23  * Since graph traversal may enter a SCC at any position, an initial representation may be rotated,
     24  * along dependences, viz. any of (a, b, c, d), (d, a, b, c)  (c, d, a, b), (b, c, d, a) assuming
     25  * a chain of dependences (mutual independent items may occur in arbitrary order). For proper
     26  * classification, the lexicographically first entry-phi is rotated to the front.
     27  */
     28 static void RotateEntryPhiFirst(HLoopInformation* loop,
     29                                 ArenaVector<HInstruction*>* scc,
     30                                 ArenaVector<HInstruction*>* new_scc) {
     31   // Find very first entry-phi.
     32   const HInstructionList& phis = loop->GetHeader()->GetPhis();
     33   HInstruction* phi = nullptr;
     34   size_t phi_pos = -1;
     35   const size_t size = scc->size();
     36   for (size_t i = 0; i < size; i++) {
     37     HInstruction* other = (*scc)[i];
     38     if (other->IsLoopHeaderPhi() && (phi == nullptr || phis.FoundBefore(other, phi))) {
     39       phi = other;
     40       phi_pos = i;
     41     }
     42   }
     43 
     44   // If found, bring that entry-phi to front.
     45   if (phi != nullptr) {
     46     new_scc->clear();
     47     for (size_t i = 0; i < size; i++) {
     48       new_scc->push_back((*scc)[phi_pos]);
     49       if (++phi_pos >= size) phi_pos = 0;
     50     }
     51     DCHECK_EQ(size, new_scc->size());
     52     scc->swap(*new_scc);
     53   }
     54 }
     55 
     56 /**
     57  * Returns true if the from/to types denote a narrowing, integral conversion (precision loss).
     58  */
     59 static bool IsNarrowingIntegralConversion(Primitive::Type from, Primitive::Type to) {
     60   switch (from) {
     61     case Primitive::kPrimLong:
     62       return to == Primitive::kPrimByte || to == Primitive::kPrimShort
     63           || to == Primitive::kPrimChar || to == Primitive::kPrimInt;
     64     case Primitive::kPrimInt:
     65       return to == Primitive::kPrimByte || to == Primitive::kPrimShort
     66           || to == Primitive::kPrimChar;
     67     case Primitive::kPrimChar:
     68     case Primitive::kPrimShort:
     69       return to == Primitive::kPrimByte;
     70     default:
     71       return false;
     72   }
     73 }
     74 
     75 /**
     76  * Returns narrowest data type.
     77  */
     78 static Primitive::Type Narrowest(Primitive::Type type1, Primitive::Type type2) {
     79   return Primitive::ComponentSize(type1) <= Primitive::ComponentSize(type2) ? type1 : type2;
     80 }
     81 
     82 //
     83 // Class methods.
     84 //
     85 
     86 HInductionVarAnalysis::HInductionVarAnalysis(HGraph* graph)
     87     : HOptimization(graph, kInductionPassName),
     88       global_depth_(0),
     89       stack_(graph->GetArena()->Adapter(kArenaAllocInductionVarAnalysis)),
     90       scc_(graph->GetArena()->Adapter(kArenaAllocInductionVarAnalysis)),
     91       map_(std::less<HInstruction*>(),
     92            graph->GetArena()->Adapter(kArenaAllocInductionVarAnalysis)),
     93       cycle_(std::less<HInstruction*>(),
     94              graph->GetArena()->Adapter(kArenaAllocInductionVarAnalysis)),
     95       induction_(std::less<HLoopInformation*>(),
     96                  graph->GetArena()->Adapter(kArenaAllocInductionVarAnalysis)) {
     97 }
     98 
     99 void HInductionVarAnalysis::Run() {
    100   // Detects sequence variables (generalized induction variables) during an outer to inner
    101   // traversal of all loops using Gerlek's algorithm. The order is important to enable
    102   // range analysis on outer loop while visiting inner loops.
    103   for (HReversePostOrderIterator it_graph(*graph_); !it_graph.Done(); it_graph.Advance()) {
    104     HBasicBlock* graph_block = it_graph.Current();
    105     // Don't analyze irreducible loops.
    106     // TODO(ajcbik): could/should we remove this restriction?
    107     if (graph_block->IsLoopHeader() && !graph_block->GetLoopInformation()->IsIrreducible()) {
    108       VisitLoop(graph_block->GetLoopInformation());
    109     }
    110   }
    111 }
    112 
    113 void HInductionVarAnalysis::VisitLoop(HLoopInformation* loop) {
    114   // Find strongly connected components (SSCs) in the SSA graph of this loop using Tarjan's
    115   // algorithm. Due to the descendant-first nature, classification happens "on-demand".
    116   global_depth_ = 0;
    117   DCHECK(stack_.empty());
    118   map_.clear();
    119 
    120   for (HBlocksInLoopIterator it_loop(*loop); !it_loop.Done(); it_loop.Advance()) {
    121     HBasicBlock* loop_block = it_loop.Current();
    122     DCHECK(loop_block->IsInLoop());
    123     if (loop_block->GetLoopInformation() != loop) {
    124       continue;  // Inner loops already visited.
    125     }
    126     // Visit phi-operations and instructions.
    127     for (HInstructionIterator it(loop_block->GetPhis()); !it.Done(); it.Advance()) {
    128       HInstruction* instruction = it.Current();
    129       if (!IsVisitedNode(instruction)) {
    130         VisitNode(loop, instruction);
    131       }
    132     }
    133     for (HInstructionIterator it(loop_block->GetInstructions()); !it.Done(); it.Advance()) {
    134       HInstruction* instruction = it.Current();
    135       if (!IsVisitedNode(instruction)) {
    136         VisitNode(loop, instruction);
    137       }
    138     }
    139   }
    140 
    141   DCHECK(stack_.empty());
    142   map_.clear();
    143 
    144   // Determine the loop's trip-count.
    145   VisitControl(loop);
    146 }
    147 
    148 void HInductionVarAnalysis::VisitNode(HLoopInformation* loop, HInstruction* instruction) {
    149   const uint32_t d1 = ++global_depth_;
    150   map_.Put(instruction, NodeInfo(d1));
    151   stack_.push_back(instruction);
    152 
    153   // Visit all descendants.
    154   uint32_t low = d1;
    155   for (size_t i = 0, count = instruction->InputCount(); i < count; ++i) {
    156     low = std::min(low, VisitDescendant(loop, instruction->InputAt(i)));
    157   }
    158 
    159   // Lower or found SCC?
    160   if (low < d1) {
    161     map_.find(instruction)->second.depth = low;
    162   } else {
    163     scc_.clear();
    164     cycle_.clear();
    165 
    166     // Pop the stack to build the SCC for classification.
    167     while (!stack_.empty()) {
    168       HInstruction* x = stack_.back();
    169       scc_.push_back(x);
    170       stack_.pop_back();
    171       map_.find(x)->second.done = true;
    172       if (x == instruction) {
    173         break;
    174       }
    175     }
    176 
    177     // Type of induction.
    178     type_ = scc_[0]->GetType();
    179 
    180     // Classify the SCC.
    181     if (scc_.size() == 1 && !scc_[0]->IsLoopHeaderPhi()) {
    182       ClassifyTrivial(loop, scc_[0]);
    183     } else {
    184       ClassifyNonTrivial(loop);
    185     }
    186 
    187     scc_.clear();
    188     cycle_.clear();
    189   }
    190 }
    191 
    192 uint32_t HInductionVarAnalysis::VisitDescendant(HLoopInformation* loop, HInstruction* instruction) {
    193   // If the definition is either outside the loop (loop invariant entry value)
    194   // or assigned in inner loop (inner exit value), the traversal stops.
    195   HLoopInformation* otherLoop = instruction->GetBlock()->GetLoopInformation();
    196   if (otherLoop != loop) {
    197     return global_depth_;
    198   }
    199 
    200   // Inspect descendant node.
    201   if (!IsVisitedNode(instruction)) {
    202     VisitNode(loop, instruction);
    203     return map_.find(instruction)->second.depth;
    204   } else {
    205     auto it = map_.find(instruction);
    206     return it->second.done ? global_depth_ : it->second.depth;
    207   }
    208 }
    209 
    210 void HInductionVarAnalysis::ClassifyTrivial(HLoopInformation* loop, HInstruction* instruction) {
    211   InductionInfo* info = nullptr;
    212   if (instruction->IsPhi()) {
    213     info = TransferPhi(loop, instruction, /* input_index */ 0);
    214   } else if (instruction->IsAdd()) {
    215     info = TransferAddSub(LookupInfo(loop, instruction->InputAt(0)),
    216                           LookupInfo(loop, instruction->InputAt(1)), kAdd);
    217   } else if (instruction->IsSub()) {
    218     info = TransferAddSub(LookupInfo(loop, instruction->InputAt(0)),
    219                           LookupInfo(loop, instruction->InputAt(1)), kSub);
    220   } else if (instruction->IsMul()) {
    221     info = TransferMul(LookupInfo(loop, instruction->InputAt(0)),
    222                        LookupInfo(loop, instruction->InputAt(1)));
    223   } else if (instruction->IsShl()) {
    224     info = TransferShl(LookupInfo(loop, instruction->InputAt(0)),
    225                        LookupInfo(loop, instruction->InputAt(1)),
    226                        instruction->InputAt(0)->GetType());
    227   } else if (instruction->IsNeg()) {
    228     info = TransferNeg(LookupInfo(loop, instruction->InputAt(0)));
    229   } else if (instruction->IsTypeConversion()) {
    230     info = TransferCnv(LookupInfo(loop, instruction->InputAt(0)),
    231                        instruction->AsTypeConversion()->GetInputType(),
    232                        instruction->AsTypeConversion()->GetResultType());
    233 
    234   } else if (instruction->IsBoundsCheck()) {
    235     info = LookupInfo(loop, instruction->InputAt(0));  // Pass-through.
    236   }
    237 
    238   // Successfully classified?
    239   if (info != nullptr) {
    240     AssignInfo(loop, instruction, info);
    241   }
    242 }
    243 
    244 void HInductionVarAnalysis::ClassifyNonTrivial(HLoopInformation* loop) {
    245   const size_t size = scc_.size();
    246   DCHECK_GE(size, 1u);
    247 
    248   // Rotate proper entry-phi to front.
    249   if (size > 1) {
    250     ArenaVector<HInstruction*> other(graph_->GetArena()->Adapter(kArenaAllocInductionVarAnalysis));
    251     RotateEntryPhiFirst(loop, &scc_, &other);
    252   }
    253 
    254   // Analyze from entry-phi onwards.
    255   HInstruction* phi = scc_[0];
    256   if (!phi->IsLoopHeaderPhi()) {
    257     return;
    258   }
    259 
    260   // External link should be loop invariant.
    261   InductionInfo* initial = LookupInfo(loop, phi->InputAt(0));
    262   if (initial == nullptr || initial->induction_class != kInvariant) {
    263     return;
    264   }
    265 
    266   // Singleton is wrap-around induction if all internal links have the same meaning.
    267   if (size == 1) {
    268     InductionInfo* update = TransferPhi(loop, phi, /* input_index */ 1);
    269     if (update != nullptr) {
    270       AssignInfo(loop, phi, CreateInduction(kWrapAround, initial, update, type_));
    271     }
    272     return;
    273   }
    274 
    275   // Inspect remainder of the cycle that resides in scc_. The cycle_ mapping assigns
    276   // temporary meaning to its nodes, seeded from the phi instruction and back.
    277   for (size_t i = 1; i < size; i++) {
    278     HInstruction* instruction = scc_[i];
    279     InductionInfo* update = nullptr;
    280     if (instruction->IsPhi()) {
    281       update = SolvePhiAllInputs(loop, phi, instruction);
    282     } else if (instruction->IsAdd()) {
    283       update = SolveAddSub(
    284           loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kAdd, true);
    285     } else if (instruction->IsSub()) {
    286       update = SolveAddSub(
    287           loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kSub, true);
    288     } else if (instruction->IsTypeConversion()) {
    289       update = SolveCnv(instruction->AsTypeConversion());
    290     }
    291     if (update == nullptr) {
    292       return;
    293     }
    294     cycle_.Put(instruction, update);
    295   }
    296 
    297   // Success if all internal links received the same temporary meaning.
    298   InductionInfo* induction = SolvePhi(phi, /* input_index */ 1);
    299   if (induction != nullptr) {
    300     switch (induction->induction_class) {
    301       case kInvariant:
    302         // Classify first phi and then the rest of the cycle "on-demand".
    303         // Statements are scanned in order.
    304         AssignInfo(loop, phi, CreateInduction(kLinear, induction, initial, type_));
    305         for (size_t i = 1; i < size; i++) {
    306           ClassifyTrivial(loop, scc_[i]);
    307         }
    308         break;
    309       case kPeriodic:
    310         // Classify all elements in the cycle with the found periodic induction while
    311         // rotating each first element to the end. Lastly, phi is classified.
    312         // Statements are scanned in reverse order.
    313         for (size_t i = size - 1; i >= 1; i--) {
    314           AssignInfo(loop, scc_[i], induction);
    315           induction = RotatePeriodicInduction(induction->op_b, induction->op_a);
    316         }
    317         AssignInfo(loop, phi, induction);
    318         break;
    319       default:
    320         break;
    321     }
    322   }
    323 }
    324 
    325 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::RotatePeriodicInduction(
    326     InductionInfo* induction,
    327     InductionInfo* last) {
    328   // Rotates a periodic induction of the form
    329   //   (a, b, c, d, e)
    330   // into
    331   //   (b, c, d, e, a)
    332   // in preparation of assigning this to the previous variable in the sequence.
    333   if (induction->induction_class == kInvariant) {
    334     return CreateInduction(kPeriodic, induction, last, type_);
    335   }
    336   return CreateInduction(
    337       kPeriodic, induction->op_a, RotatePeriodicInduction(induction->op_b, last), type_);
    338 }
    339 
    340 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferPhi(HLoopInformation* loop,
    341                                                                          HInstruction* phi,
    342                                                                          size_t input_index) {
    343   // Match all phi inputs from input_index onwards exactly.
    344   const size_t count = phi->InputCount();
    345   DCHECK_LT(input_index, count);
    346   InductionInfo* a = LookupInfo(loop, phi->InputAt(input_index));
    347   for (size_t i = input_index + 1; i < count; i++) {
    348     InductionInfo* b = LookupInfo(loop, phi->InputAt(i));
    349     if (!InductionEqual(a, b)) {
    350       return nullptr;
    351     }
    352   }
    353   return a;
    354 }
    355 
    356 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferAddSub(InductionInfo* a,
    357                                                                             InductionInfo* b,
    358                                                                             InductionOp op) {
    359   // Transfer over an addition or subtraction: any invariant, linear, wrap-around, or periodic
    360   // can be combined with an invariant to yield a similar result. Even two linear inputs can
    361   // be combined. All other combinations fail, however.
    362   if (a != nullptr && b != nullptr) {
    363     if (a->induction_class == kInvariant && b->induction_class == kInvariant) {
    364       return CreateInvariantOp(op, a, b);
    365     } else if (a->induction_class == kLinear && b->induction_class == kLinear) {
    366       return CreateInduction(kLinear,
    367                              TransferAddSub(a->op_a, b->op_a, op),
    368                              TransferAddSub(a->op_b, b->op_b, op),
    369                              type_);
    370     } else if (a->induction_class == kInvariant) {
    371       InductionInfo* new_a = b->op_a;
    372       InductionInfo* new_b = TransferAddSub(a, b->op_b, op);
    373       if (b->induction_class != kLinear) {
    374         DCHECK(b->induction_class == kWrapAround || b->induction_class == kPeriodic);
    375         new_a = TransferAddSub(a, new_a, op);
    376       } else if (op == kSub) {  // Negation required.
    377         new_a = TransferNeg(new_a);
    378       }
    379       return CreateInduction(b->induction_class, new_a, new_b, type_);
    380     } else if (b->induction_class == kInvariant) {
    381       InductionInfo* new_a = a->op_a;
    382       InductionInfo* new_b = TransferAddSub(a->op_b, b, op);
    383       if (a->induction_class != kLinear) {
    384         DCHECK(a->induction_class == kWrapAround || a->induction_class == kPeriodic);
    385         new_a = TransferAddSub(new_a, b, op);
    386       }
    387       return CreateInduction(a->induction_class, new_a, new_b, type_);
    388     }
    389   }
    390   return nullptr;
    391 }
    392 
    393 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferMul(InductionInfo* a,
    394                                                                          InductionInfo* b) {
    395   // Transfer over a multiplication: any invariant, linear, wrap-around, or periodic
    396   // can be multiplied with an invariant to yield a similar but multiplied result.
    397   // Two non-invariant inputs cannot be multiplied, however.
    398   if (a != nullptr && b != nullptr) {
    399     if (a->induction_class == kInvariant && b->induction_class == kInvariant) {
    400       return CreateInvariantOp(kMul, a, b);
    401     } else if (a->induction_class == kInvariant) {
    402       return CreateInduction(b->induction_class,
    403                              TransferMul(a, b->op_a),
    404                              TransferMul(a, b->op_b),
    405                              type_);
    406     } else if (b->induction_class == kInvariant) {
    407       return CreateInduction(a->induction_class,
    408                              TransferMul(a->op_a, b),
    409                              TransferMul(a->op_b, b),
    410                              type_);
    411     }
    412   }
    413   return nullptr;
    414 }
    415 
    416 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferShl(InductionInfo* a,
    417                                                                          InductionInfo* b,
    418                                                                          Primitive::Type type) {
    419   // Transfer over a shift left: treat shift by restricted constant as equivalent multiplication.
    420   int64_t value = -1;
    421   if (a != nullptr && IsExact(b, &value)) {
    422     // Obtain the constant needed for the multiplication. This yields an existing instruction
    423     // if the constants is already there. Otherwise, this has a side effect on the HIR.
    424     // The restriction on the shift factor avoids generating a negative constant
    425     // (viz. 1 << 31 and 1L << 63 set the sign bit). The code assumes that generalization
    426     // for shift factors outside [0,32) and [0,64) ranges is done by earlier simplification.
    427     if ((type == Primitive::kPrimInt  && 0 <= value && value < 31) ||
    428         (type == Primitive::kPrimLong && 0 <= value && value < 63)) {
    429       return TransferMul(a, CreateConstant(1 << value, type));
    430     }
    431   }
    432   return nullptr;
    433 }
    434 
    435 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferNeg(InductionInfo* a) {
    436   // Transfer over a unary negation: an invariant, linear, wrap-around, or periodic input
    437   // yields a similar but negated induction as result.
    438   if (a != nullptr) {
    439     if (a->induction_class == kInvariant) {
    440       return CreateInvariantOp(kNeg, nullptr, a);
    441     }
    442     return CreateInduction(a->induction_class, TransferNeg(a->op_a), TransferNeg(a->op_b), type_);
    443   }
    444   return nullptr;
    445 }
    446 
    447 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferCnv(InductionInfo* a,
    448                                                                          Primitive::Type from,
    449                                                                          Primitive::Type to) {
    450   if (a != nullptr) {
    451     // Allow narrowing conversion in certain cases.
    452     if (IsNarrowingIntegralConversion(from, to)) {
    453       if (a->induction_class == kLinear) {
    454         if (a->type == to || (a->type == from && IsNarrowingIntegralConversion(from, to))) {
    455           return CreateInduction(kLinear, a->op_a, a->op_b, to);
    456         }
    457       }
    458       // TODO: other cases useful too?
    459     }
    460   }
    461   return nullptr;
    462 }
    463 
    464 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolvePhi(HInstruction* phi,
    465                                                                       size_t input_index) {
    466   // Match all phi inputs from input_index onwards exactly.
    467   const size_t count = phi->InputCount();
    468   DCHECK_LT(input_index, count);
    469   auto ita = cycle_.find(phi->InputAt(input_index));
    470   if (ita != cycle_.end()) {
    471     for (size_t i = input_index + 1; i < count; i++) {
    472       auto itb = cycle_.find(phi->InputAt(i));
    473       if (itb == cycle_.end() ||
    474           !HInductionVarAnalysis::InductionEqual(ita->second, itb->second)) {
    475         return nullptr;
    476       }
    477     }
    478     return ita->second;
    479   }
    480   return nullptr;
    481 }
    482 
    483 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolvePhiAllInputs(
    484     HLoopInformation* loop,
    485     HInstruction* entry_phi,
    486     HInstruction* phi) {
    487   // Match all phi inputs.
    488   InductionInfo* match = SolvePhi(phi, /* input_index */ 0);
    489   if (match != nullptr) {
    490     return match;
    491   }
    492 
    493   // Otherwise, try to solve for a periodic seeded from phi onward.
    494   // Only tight multi-statement cycles are considered in order to
    495   // simplify rotating the periodic during the final classification.
    496   if (phi->IsLoopHeaderPhi() && phi->InputCount() == 2) {
    497     InductionInfo* a = LookupInfo(loop, phi->InputAt(0));
    498     if (a != nullptr && a->induction_class == kInvariant) {
    499       if (phi->InputAt(1) == entry_phi) {
    500         InductionInfo* initial = LookupInfo(loop, entry_phi->InputAt(0));
    501         return CreateInduction(kPeriodic, a, initial, type_);
    502       }
    503       InductionInfo* b = SolvePhi(phi, /* input_index */ 1);
    504       if (b != nullptr && b->induction_class == kPeriodic) {
    505         return CreateInduction(kPeriodic, a, b, type_);
    506       }
    507     }
    508   }
    509   return nullptr;
    510 }
    511 
    512 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolveAddSub(HLoopInformation* loop,
    513                                                                          HInstruction* entry_phi,
    514                                                                          HInstruction* instruction,
    515                                                                          HInstruction* x,
    516                                                                          HInstruction* y,
    517                                                                          InductionOp op,
    518                                                                          bool is_first_call) {
    519   // Solve within a cycle over an addition or subtraction: adding or subtracting an
    520   // invariant value, seeded from phi, keeps adding to the stride of the induction.
    521   InductionInfo* b = LookupInfo(loop, y);
    522   if (b != nullptr && b->induction_class == kInvariant) {
    523     if (x == entry_phi) {
    524       return (op == kAdd) ? b : CreateInvariantOp(kNeg, nullptr, b);
    525     }
    526     auto it = cycle_.find(x);
    527     if (it != cycle_.end()) {
    528       InductionInfo* a = it->second;
    529       if (a->induction_class == kInvariant) {
    530         return CreateInvariantOp(op, a, b);
    531       }
    532     }
    533   }
    534 
    535   // Try some alternatives before failing.
    536   if (op == kAdd) {
    537     // Try the other way around for an addition if considered for first time.
    538     if (is_first_call) {
    539       return SolveAddSub(loop, entry_phi, instruction, y, x, op, false);
    540     }
    541   } else if (op == kSub) {
    542     // Solve within a tight cycle that is formed by exactly two instructions,
    543     // one phi and one update, for a periodic idiom of the form k = c - k;
    544     if (y == entry_phi && entry_phi->InputCount() == 2 && instruction == entry_phi->InputAt(1)) {
    545       InductionInfo* a = LookupInfo(loop, x);
    546       if (a != nullptr && a->induction_class == kInvariant) {
    547         InductionInfo* initial = LookupInfo(loop, entry_phi->InputAt(0));
    548         return CreateInduction(kPeriodic, CreateInvariantOp(kSub, a, initial), initial, type_);
    549       }
    550     }
    551   }
    552 
    553   return nullptr;
    554 }
    555 
    556 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolveCnv(HTypeConversion* conversion) {
    557   Primitive::Type from = conversion->GetInputType();
    558   Primitive::Type to = conversion->GetResultType();
    559   // A narrowing conversion is allowed within the cycle of a linear induction, provided that the
    560   // narrowest encountered type is recorded with the induction to account for the precision loss.
    561   if (IsNarrowingIntegralConversion(from, to)) {
    562     auto it = cycle_.find(conversion->GetInput());
    563     if (it != cycle_.end() && it->second->induction_class == kInvariant) {
    564       type_ = Narrowest(type_, to);
    565       return it->second;
    566     }
    567   }
    568   return nullptr;
    569 }
    570 
    571 void HInductionVarAnalysis::VisitControl(HLoopInformation* loop) {
    572   HInstruction* control = loop->GetHeader()->GetLastInstruction();
    573   if (control->IsIf()) {
    574     HIf* ifs = control->AsIf();
    575     HBasicBlock* if_true = ifs->IfTrueSuccessor();
    576     HBasicBlock* if_false = ifs->IfFalseSuccessor();
    577     HInstruction* if_expr = ifs->InputAt(0);
    578     // Determine if loop has following structure in header.
    579     // loop-header: ....
    580     //              if (condition) goto X
    581     if (if_expr->IsCondition()) {
    582       HCondition* condition = if_expr->AsCondition();
    583       InductionInfo* a = LookupInfo(loop, condition->InputAt(0));
    584       InductionInfo* b = LookupInfo(loop, condition->InputAt(1));
    585       Primitive::Type type = condition->InputAt(0)->GetType();
    586       // Determine if the loop control uses a known sequence on an if-exit (X outside) or on
    587       // an if-iterate (X inside), expressed as if-iterate when passed into VisitCondition().
    588       if (a == nullptr || b == nullptr) {
    589         return;  // Loop control is not a sequence.
    590       } else if (if_true->GetLoopInformation() != loop && if_false->GetLoopInformation() == loop) {
    591         VisitCondition(loop, a, b, type, condition->GetOppositeCondition());
    592       } else if (if_true->GetLoopInformation() == loop && if_false->GetLoopInformation() != loop) {
    593         VisitCondition(loop, a, b, type, condition->GetCondition());
    594       }
    595     }
    596   }
    597 }
    598 
    599 void HInductionVarAnalysis::VisitCondition(HLoopInformation* loop,
    600                                            InductionInfo* a,
    601                                            InductionInfo* b,
    602                                            Primitive::Type type,
    603                                            IfCondition cmp) {
    604   if (a->induction_class == kInvariant && b->induction_class == kLinear) {
    605     // Swap condition if induction is at right-hand-side (e.g. U > i is same as i < U).
    606     switch (cmp) {
    607       case kCondLT: VisitCondition(loop, b, a, type, kCondGT); break;
    608       case kCondLE: VisitCondition(loop, b, a, type, kCondGE); break;
    609       case kCondGT: VisitCondition(loop, b, a, type, kCondLT); break;
    610       case kCondGE: VisitCondition(loop, b, a, type, kCondLE); break;
    611       case kCondNE: VisitCondition(loop, b, a, type, kCondNE); break;
    612       default: break;
    613     }
    614   } else if (a->induction_class == kLinear && b->induction_class == kInvariant) {
    615     // Analyze condition with induction at left-hand-side (e.g. i < U).
    616     InductionInfo* lower_expr = a->op_b;
    617     InductionInfo* upper_expr = b;
    618     InductionInfo* stride_expr = a->op_a;
    619     // Constant stride?
    620     int64_t stride_value = 0;
    621     if (!IsExact(stride_expr, &stride_value)) {
    622       return;
    623     }
    624     // Rewrite condition i != U into strict end condition i < U or i > U if this end condition
    625     // is reached exactly (tested by verifying if the loop has a unit stride and the non-strict
    626     // condition would be always taken).
    627     if (cmp == kCondNE && ((stride_value == +1 && IsTaken(lower_expr, upper_expr, kCondLE)) ||
    628                            (stride_value == -1 && IsTaken(lower_expr, upper_expr, kCondGE)))) {
    629       cmp = stride_value > 0 ? kCondLT : kCondGT;
    630     }
    631     // Only accept integral condition. A mismatch between the type of condition and the induction
    632     // is only allowed if the, necessarily narrower, induction range fits the narrower control.
    633     if (type != Primitive::kPrimInt && type != Primitive::kPrimLong) {
    634       return;  // not integral
    635     } else if (type != a->type &&
    636                !FitsNarrowerControl(lower_expr, upper_expr, stride_value, a->type, cmp)) {
    637       return;  // mismatched type
    638     }
    639     // Normalize a linear loop control with a nonzero stride:
    640     //   stride > 0, either i < U or i <= U
    641     //   stride < 0, either i > U or i >= U
    642     if ((stride_value > 0 && (cmp == kCondLT || cmp == kCondLE)) ||
    643         (stride_value < 0 && (cmp == kCondGT || cmp == kCondGE))) {
    644       VisitTripCount(loop, lower_expr, upper_expr, stride_expr, stride_value, type, cmp);
    645     }
    646   }
    647 }
    648 
    649 void HInductionVarAnalysis::VisitTripCount(HLoopInformation* loop,
    650                                            InductionInfo* lower_expr,
    651                                            InductionInfo* upper_expr,
    652                                            InductionInfo* stride_expr,
    653                                            int64_t stride_value,
    654                                            Primitive::Type type,
    655                                            IfCondition cmp) {
    656   // Any loop of the general form:
    657   //
    658   //    for (i = L; i <= U; i += S) // S > 0
    659   // or for (i = L; i >= U; i += S) // S < 0
    660   //      .. i ..
    661   //
    662   // can be normalized into:
    663   //
    664   //    for (n = 0; n < TC; n++) // where TC = (U + S - L) / S
    665   //      .. L + S * n ..
    666   //
    667   // taking the following into consideration:
    668   //
    669   // (1) Using the same precision, the TC (trip-count) expression should be interpreted as
    670   //     an unsigned entity, for example, as in the following loop that uses the full range:
    671   //     for (int i = INT_MIN; i < INT_MAX; i++) // TC = UINT_MAX
    672   // (2) The TC is only valid if the loop is taken, otherwise TC = 0, as in:
    673   //     for (int i = 12; i < U; i++) // TC = 0 when U < 12
    674   //     If this cannot be determined at compile-time, the TC is only valid within the
    675   //     loop-body proper, not the loop-header unless enforced with an explicit taken-test.
    676   // (3) The TC is only valid if the loop is finite, otherwise TC has no value, as in:
    677   //     for (int i = 0; i <= U; i++) // TC = Inf when U = INT_MAX
    678   //     If this cannot be determined at compile-time, the TC is only valid when enforced
    679   //     with an explicit finite-test.
    680   // (4) For loops which early-exits, the TC forms an upper bound, as in:
    681   //     for (int i = 0; i < 10 && ....; i++) // TC <= 10
    682   InductionInfo* trip_count = upper_expr;
    683   const bool is_taken = IsTaken(lower_expr, upper_expr, cmp);
    684   const bool is_finite = IsFinite(upper_expr, stride_value, type, cmp);
    685   const bool cancels = (cmp == kCondLT || cmp == kCondGT) && std::abs(stride_value) == 1;
    686   if (!cancels) {
    687     // Convert exclusive integral inequality into inclusive integral inequality,
    688     // viz. condition i < U is i <= U - 1 and condition i > U is i >= U + 1.
    689     if (cmp == kCondLT) {
    690       trip_count = CreateInvariantOp(kSub, trip_count, CreateConstant(1, type));
    691     } else if (cmp == kCondGT) {
    692       trip_count = CreateInvariantOp(kAdd, trip_count, CreateConstant(1, type));
    693     }
    694     // Compensate for stride.
    695     trip_count = CreateInvariantOp(kAdd, trip_count, stride_expr);
    696   }
    697   trip_count = CreateInvariantOp(
    698       kDiv, CreateInvariantOp(kSub, trip_count, lower_expr), stride_expr);
    699   // Assign the trip-count expression to the loop control. Clients that use the information
    700   // should be aware that the expression is only valid under the conditions listed above.
    701   InductionOp tcKind = kTripCountInBodyUnsafe;  // needs both tests
    702   if (is_taken && is_finite) {
    703     tcKind = kTripCountInLoop;  // needs neither test
    704   } else if (is_finite) {
    705     tcKind = kTripCountInBody;  // needs taken-test
    706   } else if (is_taken) {
    707     tcKind = kTripCountInLoopUnsafe;  // needs finite-test
    708   }
    709   InductionOp op = kNop;
    710   switch (cmp) {
    711     case kCondLT: op = kLT; break;
    712     case kCondLE: op = kLE; break;
    713     case kCondGT: op = kGT; break;
    714     case kCondGE: op = kGE; break;
    715     default:      LOG(FATAL) << "CONDITION UNREACHABLE";
    716   }
    717   InductionInfo* taken_test = CreateInvariantOp(op, lower_expr, upper_expr);
    718   AssignInfo(loop,
    719              loop->GetHeader()->GetLastInstruction(),
    720              CreateTripCount(tcKind, trip_count, taken_test, type));
    721 }
    722 
    723 bool HInductionVarAnalysis::IsTaken(InductionInfo* lower_expr,
    724                                     InductionInfo* upper_expr,
    725                                     IfCondition cmp) {
    726   int64_t lower_value;
    727   int64_t upper_value;
    728   switch (cmp) {
    729     case kCondLT:
    730       return IsAtMost(lower_expr, &lower_value)
    731           && IsAtLeast(upper_expr, &upper_value)
    732           && lower_value < upper_value;
    733     case kCondLE:
    734       return IsAtMost(lower_expr, &lower_value)
    735           && IsAtLeast(upper_expr, &upper_value)
    736           && lower_value <= upper_value;
    737     case kCondGT:
    738       return IsAtLeast(lower_expr, &lower_value)
    739           && IsAtMost(upper_expr, &upper_value)
    740           && lower_value > upper_value;
    741     case kCondGE:
    742       return IsAtLeast(lower_expr, &lower_value)
    743           && IsAtMost(upper_expr, &upper_value)
    744           && lower_value >= upper_value;
    745     default:
    746       LOG(FATAL) << "CONDITION UNREACHABLE";
    747   }
    748   return false;  // not certain, may be untaken
    749 }
    750 
    751 bool HInductionVarAnalysis::IsFinite(InductionInfo* upper_expr,
    752                                      int64_t stride_value,
    753                                      Primitive::Type type,
    754                                      IfCondition cmp) {
    755   const int64_t min = Primitive::MinValueOfIntegralType(type);
    756   const int64_t max = Primitive::MaxValueOfIntegralType(type);
    757   // Some rules under which it is certain at compile-time that the loop is finite.
    758   int64_t value;
    759   switch (cmp) {
    760     case kCondLT:
    761       return stride_value == 1 ||
    762           (IsAtMost(upper_expr, &value) && value <= (max - stride_value + 1));
    763     case kCondLE:
    764       return (IsAtMost(upper_expr, &value) && value <= (max - stride_value));
    765     case kCondGT:
    766       return stride_value == -1 ||
    767           (IsAtLeast(upper_expr, &value) && value >= (min - stride_value - 1));
    768     case kCondGE:
    769       return (IsAtLeast(upper_expr, &value) && value >= (min - stride_value));
    770     default:
    771       LOG(FATAL) << "CONDITION UNREACHABLE";
    772   }
    773   return false;  // not certain, may be infinite
    774 }
    775 
    776 bool HInductionVarAnalysis::FitsNarrowerControl(InductionInfo* lower_expr,
    777                                                 InductionInfo* upper_expr,
    778                                                 int64_t stride_value,
    779                                                 Primitive::Type type,
    780                                                 IfCondition cmp) {
    781   int64_t min = Primitive::MinValueOfIntegralType(type);
    782   int64_t max = Primitive::MaxValueOfIntegralType(type);
    783   // Inclusive test need one extra.
    784   if (stride_value != 1 && stride_value != -1) {
    785     return false;  // non-unit stride
    786   } else if (cmp == kCondLE) {
    787     max--;
    788   } else if (cmp == kCondGE) {
    789     min++;
    790   }
    791   // Do both bounds fit the range?
    792   // Note: The `value` is initialized to please valgrind - the compiler can reorder
    793   // the return value check with the `value` check, b/27651442 .
    794   int64_t value = 0;
    795   return IsAtLeast(lower_expr, &value) && value >= min &&
    796          IsAtMost(lower_expr, &value)  && value <= max &&
    797          IsAtLeast(upper_expr, &value) && value >= min &&
    798          IsAtMost(upper_expr, &value)  && value <= max;
    799 }
    800 
    801 void HInductionVarAnalysis::AssignInfo(HLoopInformation* loop,
    802                                        HInstruction* instruction,
    803                                        InductionInfo* info) {
    804   auto it = induction_.find(loop);
    805   if (it == induction_.end()) {
    806     it = induction_.Put(loop,
    807                         ArenaSafeMap<HInstruction*, InductionInfo*>(
    808                             std::less<HInstruction*>(),
    809                             graph_->GetArena()->Adapter(kArenaAllocInductionVarAnalysis)));
    810   }
    811   it->second.Put(instruction, info);
    812 }
    813 
    814 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::LookupInfo(HLoopInformation* loop,
    815                                                                         HInstruction* instruction) {
    816   auto it = induction_.find(loop);
    817   if (it != induction_.end()) {
    818     auto loop_it = it->second.find(instruction);
    819     if (loop_it != it->second.end()) {
    820       return loop_it->second;
    821     }
    822   }
    823   if (loop->IsDefinedOutOfTheLoop(instruction)) {
    824     InductionInfo* info = CreateInvariantFetch(instruction);
    825     AssignInfo(loop, instruction, info);
    826     return info;
    827   }
    828   return nullptr;
    829 }
    830 
    831 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::CreateConstant(int64_t value,
    832                                                                             Primitive::Type type) {
    833   if (type == Primitive::kPrimInt) {
    834     return CreateInvariantFetch(graph_->GetIntConstant(value));
    835   }
    836   DCHECK_EQ(type, Primitive::kPrimLong);
    837   return CreateInvariantFetch(graph_->GetLongConstant(value));
    838 }
    839 
    840 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::CreateSimplifiedInvariant(
    841     InductionOp op,
    842     InductionInfo* a,
    843     InductionInfo* b) {
    844   // Perform some light-weight simplifications during construction of a new invariant.
    845   // This often safes memory and yields a more concise representation of the induction.
    846   // More exhaustive simplifications are done by later phases once induction nodes are
    847   // translated back into HIR code (e.g. by loop optimizations or BCE).
    848   int64_t value = -1;
    849   if (IsExact(a, &value)) {
    850     if (value == 0) {
    851       // Simplify 0 + b = b, 0 * b = 0.
    852       if (op == kAdd) {
    853         return b;
    854       } else if (op == kMul) {
    855         return a;
    856       }
    857     } else if (op == kMul) {
    858       // Simplify 1 * b = b, -1 * b = -b
    859       if (value == 1) {
    860         return b;
    861       } else if (value == -1) {
    862         return CreateSimplifiedInvariant(kNeg, nullptr, b);
    863       }
    864     }
    865   }
    866   if (IsExact(b, &value)) {
    867     if (value == 0) {
    868       // Simplify a + 0 = a, a - 0 = a, a * 0 = 0, -0 = 0.
    869       if (op == kAdd || op == kSub) {
    870         return a;
    871       } else if (op == kMul || op == kNeg) {
    872         return b;
    873       }
    874     } else if (op == kMul || op == kDiv) {
    875       // Simplify a * 1 = a, a / 1 = a, a * -1 = -a, a / -1 = -a
    876       if (value == 1) {
    877         return a;
    878       } else if (value == -1) {
    879         return CreateSimplifiedInvariant(kNeg, nullptr, a);
    880       }
    881     }
    882   } else if (b->operation == kNeg) {
    883     // Simplify a + (-b) = a - b, a - (-b) = a + b, -(-b) = b.
    884     if (op == kAdd) {
    885       return CreateSimplifiedInvariant(kSub, a, b->op_b);
    886     } else if (op == kSub) {
    887       return CreateSimplifiedInvariant(kAdd, a, b->op_b);
    888     } else if (op == kNeg) {
    889       return b->op_b;
    890     }
    891   } else if (b->operation == kSub) {
    892     // Simplify - (a - b) = b - a.
    893     if (op == kNeg) {
    894       return CreateSimplifiedInvariant(kSub, b->op_b, b->op_a);
    895     }
    896   }
    897   return new (graph_->GetArena()) InductionInfo(kInvariant, op, a, b, nullptr, b->type);
    898 }
    899 
    900 bool HInductionVarAnalysis::IsExact(InductionInfo* info, int64_t* value) {
    901   return InductionVarRange(this).IsConstant(info, InductionVarRange::kExact, value);
    902 }
    903 
    904 bool HInductionVarAnalysis::IsAtMost(InductionInfo* info, int64_t* value) {
    905   return InductionVarRange(this).IsConstant(info, InductionVarRange::kAtMost, value);
    906 }
    907 
    908 bool HInductionVarAnalysis::IsAtLeast(InductionInfo* info, int64_t* value) {
    909   return InductionVarRange(this).IsConstant(info, InductionVarRange::kAtLeast, value);
    910 }
    911 
    912 bool HInductionVarAnalysis::InductionEqual(InductionInfo* info1,
    913                                            InductionInfo* info2) {
    914   // Test structural equality only, without accounting for simplifications.
    915   if (info1 != nullptr && info2 != nullptr) {
    916     return
    917         info1->induction_class == info2->induction_class &&
    918         info1->operation       == info2->operation       &&
    919         info1->fetch           == info2->fetch           &&
    920         info1->type            == info2->type            &&
    921         InductionEqual(info1->op_a, info2->op_a)         &&
    922         InductionEqual(info1->op_b, info2->op_b);
    923   }
    924   // Otherwise only two nullptrs are considered equal.
    925   return info1 == info2;
    926 }
    927 
    928 std::string HInductionVarAnalysis::InductionToString(InductionInfo* info) {
    929   if (info != nullptr) {
    930     if (info->induction_class == kInvariant) {
    931       std::string inv = "(";
    932       inv += InductionToString(info->op_a);
    933       switch (info->operation) {
    934         case kNop:   inv += " @ ";  break;
    935         case kAdd:   inv += " + ";  break;
    936         case kSub:
    937         case kNeg:   inv += " - ";  break;
    938         case kMul:   inv += " * ";  break;
    939         case kDiv:   inv += " / ";  break;
    940         case kLT:    inv += " < ";  break;
    941         case kLE:    inv += " <= "; break;
    942         case kGT:    inv += " > ";  break;
    943         case kGE:    inv += " >= "; break;
    944         case kFetch:
    945           DCHECK(info->fetch);
    946           if (info->fetch->IsIntConstant()) {
    947             inv += std::to_string(info->fetch->AsIntConstant()->GetValue());
    948           } else if (info->fetch->IsLongConstant()) {
    949             inv += std::to_string(info->fetch->AsLongConstant()->GetValue());
    950           } else {
    951             inv += std::to_string(info->fetch->GetId()) + ":" + info->fetch->DebugName();
    952           }
    953           break;
    954         case kTripCountInLoop:       inv += " (TC-loop) ";        break;
    955         case kTripCountInBody:       inv += " (TC-body) ";        break;
    956         case kTripCountInLoopUnsafe: inv += " (TC-loop-unsafe) "; break;
    957         case kTripCountInBodyUnsafe: inv += " (TC-body-unsafe) "; break;
    958       }
    959       inv += InductionToString(info->op_b);
    960       inv += ")";
    961       return inv;
    962     } else {
    963       DCHECK(info->operation == kNop);
    964       if (info->induction_class == kLinear) {
    965         return "(" + InductionToString(info->op_a) + " * i + " +
    966                      InductionToString(info->op_b) + "):" +
    967                      Primitive::PrettyDescriptor(info->type);
    968       } else if (info->induction_class == kWrapAround) {
    969         return "wrap(" + InductionToString(info->op_a) + ", " +
    970                          InductionToString(info->op_b) + "):" +
    971                          Primitive::PrettyDescriptor(info->type);
    972       } else if (info->induction_class == kPeriodic) {
    973         return "periodic(" + InductionToString(info->op_a) + ", " +
    974                              InductionToString(info->op_b) + "):" +
    975                              Primitive::PrettyDescriptor(info->type);
    976       }
    977     }
    978   }
    979   return "";
    980 }
    981 
    982 }  // namespace art
    983