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 loop-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 loop-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 loop-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(DataType::Type from, DataType::Type to) {
     60   switch (from) {
     61     case DataType::Type::kInt64:
     62       return to == DataType::Type::kUint8 ||
     63              to == DataType::Type::kInt8 ||
     64              to == DataType::Type::kUint16 ||
     65              to == DataType::Type::kInt16 ||
     66              to == DataType::Type::kInt32;
     67     case DataType::Type::kInt32:
     68       return to == DataType::Type::kUint8 ||
     69              to == DataType::Type::kInt8 ||
     70              to == DataType::Type::kUint16 ||
     71              to == DataType::Type::kInt16;
     72     case DataType::Type::kUint16:
     73     case DataType::Type::kInt16:
     74       return to == DataType::Type::kUint8 || to == DataType::Type::kInt8;
     75     default:
     76       return false;
     77   }
     78 }
     79 
     80 /**
     81  * Returns result of implicit widening type conversion done in HIR.
     82  */
     83 static DataType::Type ImplicitConversion(DataType::Type type) {
     84   switch (type) {
     85     case DataType::Type::kBool:
     86     case DataType::Type::kUint8:
     87     case DataType::Type::kInt8:
     88     case DataType::Type::kUint16:
     89     case DataType::Type::kInt16:
     90       return DataType::Type::kInt32;
     91     default:
     92       return type;
     93   }
     94 }
     95 
     96 /**
     97  * Returns true if loop is guarded by "a cmp b" on entry.
     98  */
     99 static bool IsGuardedBy(HLoopInformation* loop,
    100                         IfCondition cmp,
    101                         HInstruction* a,
    102                         HInstruction* b) {
    103   // Chase back through straightline code to the first potential
    104   // block that has a control dependence.
    105   // guard:   if (x) bypass
    106   //              |
    107   // entry: straightline code
    108   //              |
    109   //           preheader
    110   //              |
    111   //            header
    112   HBasicBlock* guard = loop->GetPreHeader();
    113   HBasicBlock* entry = loop->GetHeader();
    114   while (guard->GetPredecessors().size() == 1 &&
    115          guard->GetSuccessors().size() == 1) {
    116     entry = guard;
    117     guard = guard->GetSinglePredecessor();
    118   }
    119   // Find guard.
    120   HInstruction* control = guard->GetLastInstruction();
    121   if (!control->IsIf()) {
    122     return false;
    123   }
    124   HIf* ifs = control->AsIf();
    125   HInstruction* if_expr = ifs->InputAt(0);
    126   if (if_expr->IsCondition()) {
    127     IfCondition other_cmp = ifs->IfTrueSuccessor() == entry
    128         ? if_expr->AsCondition()->GetCondition()
    129         : if_expr->AsCondition()->GetOppositeCondition();
    130     if (if_expr->InputAt(0) == a && if_expr->InputAt(1) == b) {
    131       return cmp == other_cmp;
    132     } else if (if_expr->InputAt(1) == a && if_expr->InputAt(0) == b) {
    133       switch (cmp) {
    134         case kCondLT: return other_cmp == kCondGT;
    135         case kCondLE: return other_cmp == kCondGE;
    136         case kCondGT: return other_cmp == kCondLT;
    137         case kCondGE: return other_cmp == kCondLE;
    138         default: LOG(FATAL) << "unexpected cmp: " << cmp;
    139       }
    140     }
    141   }
    142   return false;
    143 }
    144 
    145 /* Finds first loop header phi use. */
    146 HInstruction* FindFirstLoopHeaderPhiUse(HLoopInformation* loop, HInstruction* instruction) {
    147   for (const HUseListNode<HInstruction*>& use : instruction->GetUses()) {
    148     if (use.GetUser()->GetBlock() == loop->GetHeader() &&
    149         use.GetUser()->IsPhi() &&
    150         use.GetUser()->InputAt(1) == instruction) {
    151       return use.GetUser();
    152     }
    153   }
    154   return nullptr;
    155 }
    156 
    157 /**
    158  * Relinks the Phi structure after break-loop rewriting.
    159  */
    160 bool FixOutsideUse(HLoopInformation* loop,
    161                    HInstruction* instruction,
    162                    HInstruction* replacement,
    163                    bool rewrite) {
    164   // Deal with regular uses.
    165   const HUseList<HInstruction*>& uses = instruction->GetUses();
    166   for (auto it = uses.begin(), end = uses.end(); it != end; ) {
    167     HInstruction* user = it->GetUser();
    168     size_t index = it->GetIndex();
    169     ++it;  // increment prior to potential removal
    170     if (user->GetBlock()->GetLoopInformation() != loop) {
    171       if (replacement == nullptr) {
    172         return false;
    173       } else if (rewrite) {
    174         user->ReplaceInput(replacement, index);
    175       }
    176     }
    177   }
    178   // Deal with environment uses.
    179   const HUseList<HEnvironment*>& env_uses = instruction->GetEnvUses();
    180   for (auto it = env_uses.begin(), end = env_uses.end(); it != end;) {
    181     HEnvironment* user = it->GetUser();
    182     size_t index = it->GetIndex();
    183     ++it;  // increment prior to potential removal
    184     if (user->GetHolder()->GetBlock()->GetLoopInformation() != loop) {
    185       if (replacement == nullptr) {
    186         return false;
    187       } else if (rewrite) {
    188         user->RemoveAsUserOfInput(index);
    189         user->SetRawEnvAt(index, replacement);
    190         replacement->AddEnvUseAt(user, index);
    191       }
    192     }
    193   }
    194   return true;
    195 }
    196 
    197 /**
    198  * Test and rewrite the loop body of a break-loop. Returns true on success.
    199  */
    200 bool RewriteBreakLoopBody(HLoopInformation* loop,
    201                           HBasicBlock* body,
    202                           HInstruction* cond,
    203                           HInstruction* index,
    204                           HInstruction* upper,
    205                           bool rewrite) {
    206   // Deal with Phis. Outside use prohibited, except for index (which gets exit value).
    207   for (HInstructionIterator it(loop->GetHeader()->GetPhis()); !it.Done(); it.Advance()) {
    208     HInstruction* exit_value = it.Current() == index ? upper : nullptr;
    209     if (!FixOutsideUse(loop, it.Current(), exit_value, rewrite)) {
    210       return false;
    211     }
    212   }
    213   // Deal with other statements in header.
    214   for (HInstruction* m = cond->GetPrevious(), *p = nullptr; m && !m->IsSuspendCheck(); m = p) {
    215     p = m->GetPrevious();
    216     if (rewrite) {
    217       m->MoveBefore(body->GetFirstInstruction(), false);
    218     }
    219     if (!FixOutsideUse(loop, m, FindFirstLoopHeaderPhiUse(loop, m), rewrite)) {
    220       return false;
    221     }
    222   }
    223   return true;
    224 }
    225 
    226 //
    227 // Class methods.
    228 //
    229 
    230 HInductionVarAnalysis::HInductionVarAnalysis(HGraph* graph, const char* name)
    231     : HOptimization(graph, name),
    232       global_depth_(0),
    233       stack_(graph->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis)),
    234       map_(std::less<HInstruction*>(),
    235            graph->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis)),
    236       scc_(graph->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis)),
    237       cycle_(std::less<HInstruction*>(),
    238              graph->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis)),
    239       type_(DataType::Type::kVoid),
    240       induction_(std::less<HLoopInformation*>(),
    241                  graph->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis)),
    242       cycles_(std::less<HPhi*>(),
    243               graph->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis)) {
    244 }
    245 
    246 void HInductionVarAnalysis::Run() {
    247   // Detects sequence variables (generalized induction variables) during an outer to inner
    248   // traversal of all loops using Gerlek's algorithm. The order is important to enable
    249   // range analysis on outer loop while visiting inner loops.
    250   for (HBasicBlock* graph_block : graph_->GetReversePostOrder()) {
    251     // Don't analyze irreducible loops.
    252     if (graph_block->IsLoopHeader() && !graph_block->GetLoopInformation()->IsIrreducible()) {
    253       VisitLoop(graph_block->GetLoopInformation());
    254     }
    255   }
    256 }
    257 
    258 void HInductionVarAnalysis::VisitLoop(HLoopInformation* loop) {
    259   // Find strongly connected components (SSCs) in the SSA graph of this loop using Tarjan's
    260   // algorithm. Due to the descendant-first nature, classification happens "on-demand".
    261   global_depth_ = 0;
    262   DCHECK(stack_.empty());
    263   map_.clear();
    264 
    265   for (HBlocksInLoopIterator it_loop(*loop); !it_loop.Done(); it_loop.Advance()) {
    266     HBasicBlock* loop_block = it_loop.Current();
    267     DCHECK(loop_block->IsInLoop());
    268     if (loop_block->GetLoopInformation() != loop) {
    269       continue;  // Inner loops visited later.
    270     }
    271     // Visit phi-operations and instructions.
    272     for (HInstructionIterator it(loop_block->GetPhis()); !it.Done(); it.Advance()) {
    273       HInstruction* instruction = it.Current();
    274       if (!IsVisitedNode(instruction)) {
    275         VisitNode(loop, instruction);
    276       }
    277     }
    278     for (HInstructionIterator it(loop_block->GetInstructions()); !it.Done(); it.Advance()) {
    279       HInstruction* instruction = it.Current();
    280       if (!IsVisitedNode(instruction)) {
    281         VisitNode(loop, instruction);
    282       }
    283     }
    284   }
    285 
    286   DCHECK(stack_.empty());
    287   map_.clear();
    288 
    289   // Determine the loop's trip-count.
    290   VisitControl(loop);
    291 }
    292 
    293 void HInductionVarAnalysis::VisitNode(HLoopInformation* loop, HInstruction* instruction) {
    294   const uint32_t d1 = ++global_depth_;
    295   map_.Put(instruction, NodeInfo(d1));
    296   stack_.push_back(instruction);
    297 
    298   // Visit all descendants.
    299   uint32_t low = d1;
    300   for (HInstruction* input : instruction->GetInputs()) {
    301     low = std::min(low, VisitDescendant(loop, input));
    302   }
    303 
    304   // Lower or found SCC?
    305   if (low < d1) {
    306     map_.find(instruction)->second.depth = low;
    307   } else {
    308     scc_.clear();
    309     cycle_.clear();
    310 
    311     // Pop the stack to build the SCC for classification.
    312     while (!stack_.empty()) {
    313       HInstruction* x = stack_.back();
    314       scc_.push_back(x);
    315       stack_.pop_back();
    316       map_.find(x)->second.done = true;
    317       if (x == instruction) {
    318         break;
    319       }
    320     }
    321 
    322     // Type of induction.
    323     type_ = scc_[0]->GetType();
    324 
    325     // Classify the SCC.
    326     if (scc_.size() == 1 && !scc_[0]->IsLoopHeaderPhi()) {
    327       ClassifyTrivial(loop, scc_[0]);
    328     } else {
    329       ClassifyNonTrivial(loop);
    330     }
    331 
    332     scc_.clear();
    333     cycle_.clear();
    334   }
    335 }
    336 
    337 uint32_t HInductionVarAnalysis::VisitDescendant(HLoopInformation* loop, HInstruction* instruction) {
    338   // If the definition is either outside the loop (loop invariant entry value)
    339   // or assigned in inner loop (inner exit value), the traversal stops.
    340   HLoopInformation* otherLoop = instruction->GetBlock()->GetLoopInformation();
    341   if (otherLoop != loop) {
    342     return global_depth_;
    343   }
    344 
    345   // Inspect descendant node.
    346   if (!IsVisitedNode(instruction)) {
    347     VisitNode(loop, instruction);
    348     return map_.find(instruction)->second.depth;
    349   } else {
    350     auto it = map_.find(instruction);
    351     return it->second.done ? global_depth_ : it->second.depth;
    352   }
    353 }
    354 
    355 void HInductionVarAnalysis::ClassifyTrivial(HLoopInformation* loop, HInstruction* instruction) {
    356   InductionInfo* info = nullptr;
    357   if (instruction->IsPhi()) {
    358     info = TransferPhi(loop, instruction, /*input_index*/ 0, /*adjust_input_size*/ 0);
    359   } else if (instruction->IsAdd()) {
    360     info = TransferAddSub(LookupInfo(loop, instruction->InputAt(0)),
    361                           LookupInfo(loop, instruction->InputAt(1)), kAdd);
    362   } else if (instruction->IsSub()) {
    363     info = TransferAddSub(LookupInfo(loop, instruction->InputAt(0)),
    364                           LookupInfo(loop, instruction->InputAt(1)), kSub);
    365   } else if (instruction->IsNeg()) {
    366     info = TransferNeg(LookupInfo(loop, instruction->InputAt(0)));
    367   } else if (instruction->IsMul()) {
    368     info = TransferMul(LookupInfo(loop, instruction->InputAt(0)),
    369                        LookupInfo(loop, instruction->InputAt(1)));
    370   } else if (instruction->IsShl()) {
    371     HInstruction* mulc = GetShiftConstant(loop, instruction, /*initial*/ nullptr);
    372     if (mulc != nullptr) {
    373       info = TransferMul(LookupInfo(loop, instruction->InputAt(0)),
    374                          LookupInfo(loop, mulc));
    375     }
    376   } else if (instruction->IsSelect()) {
    377     info = TransferPhi(loop, instruction, /*input_index*/ 0, /*adjust_input_size*/ 1);
    378   } else if (instruction->IsTypeConversion()) {
    379     info = TransferConversion(LookupInfo(loop, instruction->InputAt(0)),
    380                               instruction->AsTypeConversion()->GetInputType(),
    381                               instruction->AsTypeConversion()->GetResultType());
    382   } else if (instruction->IsBoundsCheck()) {
    383     info = LookupInfo(loop, instruction->InputAt(0));  // Pass-through.
    384   }
    385 
    386   // Successfully classified?
    387   if (info != nullptr) {
    388     AssignInfo(loop, instruction, info);
    389   }
    390 }
    391 
    392 void HInductionVarAnalysis::ClassifyNonTrivial(HLoopInformation* loop) {
    393   const size_t size = scc_.size();
    394   DCHECK_GE(size, 1u);
    395 
    396   // Rotate proper loop-phi to front.
    397   if (size > 1) {
    398     ArenaVector<HInstruction*> other(
    399         graph_->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis));
    400     RotateEntryPhiFirst(loop, &scc_, &other);
    401   }
    402 
    403   // Analyze from loop-phi onwards.
    404   HInstruction* phi = scc_[0];
    405   if (!phi->IsLoopHeaderPhi()) {
    406     return;
    407   }
    408 
    409   // External link should be loop invariant.
    410   InductionInfo* initial = LookupInfo(loop, phi->InputAt(0));
    411   if (initial == nullptr || initial->induction_class != kInvariant) {
    412     return;
    413   }
    414 
    415   // Store interesting cycle in each loop phi.
    416   for (size_t i = 0; i < size; i++) {
    417     if (scc_[i]->IsLoopHeaderPhi()) {
    418       AssignCycle(scc_[i]->AsPhi());
    419     }
    420   }
    421 
    422   // Singleton is wrap-around induction if all internal links have the same meaning.
    423   if (size == 1) {
    424     InductionInfo* update = TransferPhi(loop, phi, /*input_index*/ 1, /*adjust_input_size*/ 0);
    425     if (update != nullptr) {
    426       AssignInfo(loop, phi, CreateInduction(kWrapAround,
    427                                             kNop,
    428                                             initial,
    429                                             update,
    430                                             /*fetch*/ nullptr,
    431                                             type_));
    432     }
    433     return;
    434   }
    435 
    436   // Inspect remainder of the cycle that resides in scc_. The cycle_ mapping assigns
    437   // temporary meaning to its nodes, seeded from the phi instruction and back.
    438   for (size_t i = 1; i < size; i++) {
    439     HInstruction* instruction = scc_[i];
    440     InductionInfo* update = nullptr;
    441     if (instruction->IsPhi()) {
    442       update = SolvePhiAllInputs(loop, phi, instruction);
    443     } else if (instruction->IsAdd()) {
    444       update = SolveAddSub(
    445           loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kAdd, true);
    446     } else if (instruction->IsSub()) {
    447       update = SolveAddSub(
    448           loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kSub, true);
    449     } else if (instruction->IsMul()) {
    450       update = SolveOp(
    451           loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kMul);
    452     } else if (instruction->IsDiv()) {
    453       update = SolveOp(
    454           loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kDiv);
    455     } else if (instruction->IsRem()) {
    456       update = SolveOp(
    457           loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kRem);
    458     } else if (instruction->IsShl()) {
    459       HInstruction* mulc = GetShiftConstant(loop, instruction, /*initial*/ nullptr);
    460       if (mulc != nullptr) {
    461         update = SolveOp(loop, phi, instruction, instruction->InputAt(0), mulc, kMul);
    462       }
    463     } else if (instruction->IsShr() || instruction->IsUShr()) {
    464       HInstruction* divc = GetShiftConstant(loop, instruction, initial);
    465       if (divc != nullptr) {
    466         update = SolveOp(loop, phi, instruction, instruction->InputAt(0), divc, kDiv);
    467       }
    468     } else if (instruction->IsXor()) {
    469       update = SolveOp(
    470           loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kXor);
    471     } else if (instruction->IsEqual()) {
    472       update = SolveTest(loop, phi, instruction, 0);
    473     } else if (instruction->IsNotEqual()) {
    474       update = SolveTest(loop, phi, instruction, 1);
    475     } else if (instruction->IsSelect()) {
    476       update = SolvePhi(instruction, /*input_index*/ 0, /*adjust_input_size*/ 1);  // acts like Phi
    477     } else if (instruction->IsTypeConversion()) {
    478       update = SolveConversion(loop, phi, instruction->AsTypeConversion());
    479     }
    480     if (update == nullptr) {
    481       return;
    482     }
    483     cycle_.Put(instruction, update);
    484   }
    485 
    486   // Success if all internal links received the same temporary meaning.
    487   InductionInfo* induction = SolvePhi(phi, /*input_index*/ 1, /*adjust_input_size*/ 0);
    488   if (induction != nullptr) {
    489     switch (induction->induction_class) {
    490       case kInvariant:
    491         // Construct combined stride of the linear induction.
    492         induction = CreateInduction(kLinear, kNop, induction, initial, /*fetch*/ nullptr, type_);
    493         FALLTHROUGH_INTENDED;
    494       case kPolynomial:
    495       case kGeometric:
    496       case kWrapAround:
    497         // Classify first phi and then the rest of the cycle "on-demand".
    498         // Statements are scanned in order.
    499         AssignInfo(loop, phi, induction);
    500         for (size_t i = 1; i < size; i++) {
    501           ClassifyTrivial(loop, scc_[i]);
    502         }
    503         break;
    504       case kPeriodic:
    505         // Classify all elements in the cycle with the found periodic induction while
    506         // rotating each first element to the end. Lastly, phi is classified.
    507         // Statements are scanned in reverse order.
    508         for (size_t i = size - 1; i >= 1; i--) {
    509           AssignInfo(loop, scc_[i], induction);
    510           induction = RotatePeriodicInduction(induction->op_b, induction->op_a);
    511         }
    512         AssignInfo(loop, phi, induction);
    513         break;
    514       default:
    515         break;
    516     }
    517   }
    518 }
    519 
    520 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::RotatePeriodicInduction(
    521     InductionInfo* induction,
    522     InductionInfo* last) {
    523   // Rotates a periodic induction of the form
    524   //   (a, b, c, d, e)
    525   // into
    526   //   (b, c, d, e, a)
    527   // in preparation of assigning this to the previous variable in the sequence.
    528   if (induction->induction_class == kInvariant) {
    529     return CreateInduction(kPeriodic,
    530                            kNop,
    531                            induction,
    532                            last,
    533                            /*fetch*/ nullptr,
    534                            type_);
    535   }
    536   return CreateInduction(kPeriodic,
    537                          kNop,
    538                          induction->op_a,
    539                          RotatePeriodicInduction(induction->op_b, last),
    540                          /*fetch*/ nullptr,
    541                          type_);
    542 }
    543 
    544 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferPhi(HLoopInformation* loop,
    545                                                                          HInstruction* phi,
    546                                                                          size_t input_index,
    547                                                                          size_t adjust_input_size) {
    548   // Match all phi inputs from input_index onwards exactly.
    549   HInputsRef inputs = phi->GetInputs();
    550   DCHECK_LT(input_index, inputs.size());
    551   InductionInfo* a = LookupInfo(loop, inputs[input_index]);
    552   for (size_t i = input_index + 1, n = inputs.size() - adjust_input_size; i < n; i++) {
    553     InductionInfo* b = LookupInfo(loop, inputs[i]);
    554     if (!InductionEqual(a, b)) {
    555       return nullptr;
    556     }
    557   }
    558   return a;
    559 }
    560 
    561 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferAddSub(InductionInfo* a,
    562                                                                             InductionInfo* b,
    563                                                                             InductionOp op) {
    564   // Transfer over an addition or subtraction: any invariant, linear, polynomial, geometric,
    565   // wrap-around, or periodic can be combined with an invariant to yield a similar result.
    566   // Two linear or two polynomial inputs can be combined too. Other combinations fail.
    567   if (a != nullptr && b != nullptr) {
    568     if (IsNarrowingLinear(a) || IsNarrowingLinear(b)) {
    569       return nullptr;  // no transfer
    570     } else if (a->induction_class == kInvariant && b->induction_class == kInvariant) {
    571       return CreateInvariantOp(op, a, b);  // direct invariant
    572     } else if ((a->induction_class == kLinear && b->induction_class == kLinear) ||
    573                (a->induction_class == kPolynomial && b->induction_class == kPolynomial)) {
    574       // Rule induc(a, b) + induc(a', b') -> induc(a + a', b + b').
    575       InductionInfo* new_a = TransferAddSub(a->op_a, b->op_a, op);
    576       InductionInfo* new_b = TransferAddSub(a->op_b, b->op_b, op);
    577       if (new_a != nullptr && new_b != nullptr)  {
    578         return CreateInduction(a->induction_class, a->operation, new_a, new_b, a->fetch, type_);
    579       }
    580     } else if (a->induction_class == kInvariant) {
    581       // Rule a + induc(a', b') -> induc(a', a + b') or induc(a + a', a + b').
    582       InductionInfo* new_a = b->op_a;
    583       InductionInfo* new_b = TransferAddSub(a, b->op_b, op);
    584       if (b->induction_class == kWrapAround || b->induction_class == kPeriodic) {
    585         new_a = TransferAddSub(a, new_a, op);
    586       } else if (op == kSub) {  // Negation required.
    587         new_a = TransferNeg(new_a);
    588       }
    589       if (new_a != nullptr && new_b != nullptr)  {
    590         return CreateInduction(b->induction_class, b->operation, new_a, new_b, b->fetch, type_);
    591       }
    592     } else if (b->induction_class == kInvariant) {
    593       // Rule induc(a, b) + b' -> induc(a, b + b') or induc(a + b', b + b').
    594       InductionInfo* new_a = a->op_a;
    595       InductionInfo* new_b = TransferAddSub(a->op_b, b, op);
    596       if (a->induction_class == kWrapAround || a->induction_class == kPeriodic) {
    597         new_a = TransferAddSub(new_a, b, op);
    598       }
    599       if (new_a != nullptr && new_b != nullptr)  {
    600         return CreateInduction(a->induction_class, a->operation, new_a, new_b, a->fetch, type_);
    601       }
    602     }
    603   }
    604   return nullptr;
    605 }
    606 
    607 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferNeg(InductionInfo* a) {
    608   // Transfer over a unary negation: an invariant, linear, polynomial, geometric (mul),
    609   // wrap-around, or periodic input yields a similar but negated induction as result.
    610   if (a != nullptr) {
    611     if (IsNarrowingLinear(a)) {
    612       return nullptr;  // no transfer
    613     } else if (a->induction_class == kInvariant) {
    614       return CreateInvariantOp(kNeg, nullptr, a);  // direct invariant
    615     } else if (a->induction_class != kGeometric || a->operation == kMul) {
    616       // Rule - induc(a, b) -> induc(-a, -b).
    617       InductionInfo* new_a = TransferNeg(a->op_a);
    618       InductionInfo* new_b = TransferNeg(a->op_b);
    619       if (new_a != nullptr && new_b != nullptr) {
    620         return CreateInduction(a->induction_class, a->operation, new_a, new_b, a->fetch, type_);
    621       }
    622     }
    623   }
    624   return nullptr;
    625 }
    626 
    627 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferMul(InductionInfo* a,
    628                                                                          InductionInfo* b) {
    629   // Transfer over a multiplication: any invariant, linear, polynomial, geometric (mul),
    630   // wrap-around, or periodic can be multiplied with an invariant to yield a similar
    631   // but multiplied result. Two non-invariant inputs cannot be multiplied, however.
    632   if (a != nullptr && b != nullptr) {
    633     if (IsNarrowingLinear(a) || IsNarrowingLinear(b)) {
    634       return nullptr;  // no transfer
    635     } else if (a->induction_class == kInvariant && b->induction_class == kInvariant) {
    636       return CreateInvariantOp(kMul, a, b);  // direct invariant
    637     } else if (a->induction_class == kInvariant && (b->induction_class != kGeometric ||
    638                                                     b->operation == kMul)) {
    639       // Rule a * induc(a', b') -> induc(a * a', b * b').
    640       InductionInfo* new_a = TransferMul(a, b->op_a);
    641       InductionInfo* new_b = TransferMul(a, b->op_b);
    642       if (new_a != nullptr && new_b != nullptr) {
    643         return CreateInduction(b->induction_class, b->operation, new_a, new_b, b->fetch, type_);
    644       }
    645     } else if (b->induction_class == kInvariant && (a->induction_class != kGeometric ||
    646                                                     a->operation == kMul)) {
    647       // Rule induc(a, b) * b' -> induc(a * b', b * b').
    648       InductionInfo* new_a = TransferMul(a->op_a, b);
    649       InductionInfo* new_b = TransferMul(a->op_b, b);
    650       if (new_a != nullptr && new_b != nullptr) {
    651         return CreateInduction(a->induction_class, a->operation, new_a, new_b, a->fetch, type_);
    652       }
    653     }
    654   }
    655   return nullptr;
    656 }
    657 
    658 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferConversion(
    659     InductionInfo* a,
    660     DataType::Type from,
    661     DataType::Type to) {
    662   if (a != nullptr) {
    663     // Allow narrowing conversion on linear induction in certain cases:
    664     // induction is already at narrow type, or can be made narrower.
    665     if (IsNarrowingIntegralConversion(from, to) &&
    666         a->induction_class == kLinear &&
    667         (a->type == to || IsNarrowingIntegralConversion(a->type, to))) {
    668       return CreateInduction(kLinear, kNop, a->op_a, a->op_b, a->fetch, to);
    669     }
    670   }
    671   return nullptr;
    672 }
    673 
    674 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolvePhi(HInstruction* phi,
    675                                                                       size_t input_index,
    676                                                                       size_t adjust_input_size) {
    677   // Match all phi inputs from input_index onwards exactly.
    678   HInputsRef inputs = phi->GetInputs();
    679   DCHECK_LT(input_index, inputs.size());
    680   auto ita = cycle_.find(inputs[input_index]);
    681   if (ita != cycle_.end()) {
    682     for (size_t i = input_index + 1, n = inputs.size() - adjust_input_size; i < n; i++) {
    683       auto itb = cycle_.find(inputs[i]);
    684       if (itb == cycle_.end() ||
    685           !HInductionVarAnalysis::InductionEqual(ita->second, itb->second)) {
    686         return nullptr;
    687       }
    688     }
    689     return ita->second;
    690   }
    691   return nullptr;
    692 }
    693 
    694 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolvePhiAllInputs(
    695     HLoopInformation* loop,
    696     HInstruction* entry_phi,
    697     HInstruction* phi) {
    698   // Match all phi inputs.
    699   InductionInfo* match = SolvePhi(phi, /*input_index*/ 0, /*adjust_input_size*/ 0);
    700   if (match != nullptr) {
    701     return match;
    702   }
    703 
    704   // Otherwise, try to solve for a periodic seeded from phi onward.
    705   // Only tight multi-statement cycles are considered in order to
    706   // simplify rotating the periodic during the final classification.
    707   if (phi->IsLoopHeaderPhi() && phi->InputCount() == 2) {
    708     InductionInfo* a = LookupInfo(loop, phi->InputAt(0));
    709     if (a != nullptr && a->induction_class == kInvariant) {
    710       if (phi->InputAt(1) == entry_phi) {
    711         InductionInfo* initial = LookupInfo(loop, entry_phi->InputAt(0));
    712         return CreateInduction(kPeriodic, kNop, a, initial, /*fetch*/ nullptr, type_);
    713       }
    714       InductionInfo* b = SolvePhi(phi, /*input_index*/ 1, /*adjust_input_size*/ 0);
    715       if (b != nullptr && b->induction_class == kPeriodic) {
    716         return CreateInduction(kPeriodic, kNop, a, b, /*fetch*/ nullptr, type_);
    717       }
    718     }
    719   }
    720   return nullptr;
    721 }
    722 
    723 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolveAddSub(HLoopInformation* loop,
    724                                                                          HInstruction* entry_phi,
    725                                                                          HInstruction* instruction,
    726                                                                          HInstruction* x,
    727                                                                          HInstruction* y,
    728                                                                          InductionOp op,
    729                                                                          bool is_first_call) {
    730   // Solve within a cycle over an addition or subtraction.
    731   InductionInfo* b = LookupInfo(loop, y);
    732   if (b != nullptr) {
    733     if (b->induction_class == kInvariant) {
    734       // Adding or subtracting an invariant value, seeded from phi,
    735       // keeps adding to the stride of the linear induction.
    736       if (x == entry_phi) {
    737         return (op == kAdd) ? b : CreateInvariantOp(kNeg, nullptr, b);
    738       }
    739       auto it = cycle_.find(x);
    740       if (it != cycle_.end()) {
    741         InductionInfo* a = it->second;
    742         if (a->induction_class == kInvariant) {
    743           return CreateInvariantOp(op, a, b);
    744         }
    745       }
    746     } else if (b->induction_class == kLinear && b->type == type_) {
    747       // Solve within a tight cycle that adds a term that is already classified as a linear
    748       // induction for a polynomial induction k = k + i (represented as sum over linear terms).
    749       if (x == entry_phi && entry_phi->InputCount() == 2 && instruction == entry_phi->InputAt(1)) {
    750         InductionInfo* initial = LookupInfo(loop, entry_phi->InputAt(0));
    751         InductionInfo* new_a = op == kAdd ? b : TransferNeg(b);
    752         if (new_a != nullptr) {
    753           return CreateInduction(kPolynomial, kNop, new_a, initial, /*fetch*/ nullptr, type_);
    754         }
    755       }
    756     }
    757   }
    758 
    759   // Try some alternatives before failing.
    760   if (op == kAdd) {
    761     // Try the other way around for an addition if considered for first time.
    762     if (is_first_call) {
    763       return SolveAddSub(loop, entry_phi, instruction, y, x, op, false);
    764     }
    765   } else if (op == kSub) {
    766     // Solve within a tight cycle that is formed by exactly two instructions,
    767     // one phi and one update, for a periodic idiom of the form k = c - k.
    768     if (y == entry_phi && entry_phi->InputCount() == 2 && instruction == entry_phi->InputAt(1)) {
    769       InductionInfo* a = LookupInfo(loop, x);
    770       if (a != nullptr && a->induction_class == kInvariant) {
    771         InductionInfo* initial = LookupInfo(loop, entry_phi->InputAt(0));
    772         return CreateInduction(kPeriodic,
    773                                kNop,
    774                                CreateInvariantOp(kSub, a, initial),
    775                                initial,
    776                                /*fetch*/ nullptr,
    777                                type_);
    778       }
    779     }
    780   }
    781   return nullptr;
    782 }
    783 
    784 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolveOp(HLoopInformation* loop,
    785                                                                       HInstruction* entry_phi,
    786                                                                       HInstruction* instruction,
    787                                                                       HInstruction* x,
    788                                                                       HInstruction* y,
    789                                                                       InductionOp op) {
    790   // Solve within a tight cycle for a binary operation k = k op c or, for some op, k = c op k.
    791   if (entry_phi->InputCount() == 2 && instruction == entry_phi->InputAt(1)) {
    792     InductionInfo* c = nullptr;
    793     InductionInfo* b = LookupInfo(loop, y);
    794     if (b != nullptr && b->induction_class == kInvariant && entry_phi == x) {
    795       c = b;
    796     } else if (op != kDiv && op != kRem) {
    797       InductionInfo* a = LookupInfo(loop, x);
    798       if (a != nullptr && a->induction_class == kInvariant && entry_phi == y) {
    799         c = a;
    800       }
    801     }
    802     // Found suitable operand left or right?
    803     if (c != nullptr) {
    804       InductionInfo* initial = LookupInfo(loop, entry_phi->InputAt(0));
    805       switch (op) {
    806         case kMul:
    807         case kDiv:
    808           // Restrict base of geometric induction to direct fetch.
    809           if (c->operation == kFetch) {
    810             return CreateInduction(kGeometric,
    811                                    op,
    812                                    initial,
    813                                    CreateConstant(0, type_),
    814                                    c->fetch,
    815                                    type_);
    816           }
    817           break;
    818         case kRem:
    819           // Idiomatic MOD wrap-around induction.
    820           return CreateInduction(kWrapAround,
    821                                  kNop,
    822                                  initial,
    823                                  CreateInvariantOp(kRem, initial, c),
    824                                  /*fetch*/ nullptr,
    825                                  type_);
    826         case kXor:
    827           // Idiomatic XOR periodic induction.
    828           return CreateInduction(kPeriodic,
    829                                  kNop,
    830                                  CreateInvariantOp(kXor, initial, c),
    831                                  initial,
    832                                  /*fetch*/ nullptr,
    833                                  type_);
    834         default:
    835           LOG(FATAL) << op;
    836           UNREACHABLE();
    837       }
    838     }
    839   }
    840   return nullptr;
    841 }
    842 
    843 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolveTest(HLoopInformation* loop,
    844                                                                        HInstruction* entry_phi,
    845                                                                        HInstruction* instruction,
    846                                                                        int64_t opposite_value) {
    847   // Detect hidden XOR construction in x = (x == false) or x = (x != true).
    848   int64_t value = -1;
    849   HInstruction* x = instruction->InputAt(0);
    850   HInstruction* y = instruction->InputAt(1);
    851   if (IsExact(LookupInfo(loop, x), &value) && value == opposite_value) {
    852     return SolveOp(loop, entry_phi, instruction, graph_->GetIntConstant(1), y, kXor);
    853   } else if (IsExact(LookupInfo(loop, y), &value) && value == opposite_value) {
    854     return SolveOp(loop, entry_phi, instruction, x, graph_->GetIntConstant(1), kXor);
    855   }
    856   return nullptr;
    857 }
    858 
    859 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolveConversion(
    860     HLoopInformation* loop,
    861     HInstruction* entry_phi,
    862     HTypeConversion* conversion) {
    863   DataType::Type from = conversion->GetInputType();
    864   DataType::Type to = conversion->GetResultType();
    865   // A narrowing conversion is allowed as *last* operation of the cycle of a linear induction
    866   // with an initial value that fits the type, provided that the narrowest encountered type is
    867   // recorded with the induction to account for the precision loss. The narrower induction does
    868   // *not* transfer to any wider operations, however, since these may yield out-of-type values
    869   if (entry_phi->InputCount() == 2 && conversion == entry_phi->InputAt(1)) {
    870     int64_t min = DataType::MinValueOfIntegralType(to);
    871     int64_t max = DataType::MaxValueOfIntegralType(to);
    872     int64_t value = 0;
    873     InductionInfo* initial = LookupInfo(loop, entry_phi->InputAt(0));
    874     if (IsNarrowingIntegralConversion(from, to) &&
    875         IsAtLeast(initial, &value) && value >= min &&
    876         IsAtMost(initial, &value)  && value <= max) {
    877       auto it = cycle_.find(conversion->GetInput());
    878       if (it != cycle_.end() && it->second->induction_class == kInvariant) {
    879         type_ = to;
    880         return it->second;
    881       }
    882     }
    883   }
    884   return nullptr;
    885 }
    886 
    887 //
    888 // Loop trip count analysis methods.
    889 //
    890 
    891 void HInductionVarAnalysis::VisitControl(HLoopInformation* loop) {
    892   HInstruction* control = loop->GetHeader()->GetLastInstruction();
    893   if (control->IsIf()) {
    894     HIf* ifs = control->AsIf();
    895     HBasicBlock* if_true = ifs->IfTrueSuccessor();
    896     HBasicBlock* if_false = ifs->IfFalseSuccessor();
    897     HInstruction* if_expr = ifs->InputAt(0);
    898     // Determine if loop has following structure in header.
    899     // loop-header: ....
    900     //              if (condition) goto X
    901     if (if_expr->IsCondition()) {
    902       HCondition* condition = if_expr->AsCondition();
    903       InductionInfo* a = LookupInfo(loop, condition->InputAt(0));
    904       InductionInfo* b = LookupInfo(loop, condition->InputAt(1));
    905       DataType::Type type = ImplicitConversion(condition->InputAt(0)->GetType());
    906       // Determine if the loop control uses a known sequence on an if-exit (X outside) or on
    907       // an if-iterate (X inside), expressed as if-iterate when passed into VisitCondition().
    908       if (a == nullptr || b == nullptr) {
    909         return;  // Loop control is not a sequence.
    910       } else if (if_true->GetLoopInformation() != loop && if_false->GetLoopInformation() == loop) {
    911         VisitCondition(loop, if_false, a, b, type, condition->GetOppositeCondition());
    912       } else if (if_true->GetLoopInformation() == loop && if_false->GetLoopInformation() != loop) {
    913         VisitCondition(loop, if_true, a, b, type, condition->GetCondition());
    914       }
    915     }
    916   }
    917 }
    918 
    919 void HInductionVarAnalysis::VisitCondition(HLoopInformation* loop,
    920                                            HBasicBlock* body,
    921                                            InductionInfo* a,
    922                                            InductionInfo* b,
    923                                            DataType::Type type,
    924                                            IfCondition cmp) {
    925   if (a->induction_class == kInvariant && b->induction_class == kLinear) {
    926     // Swap condition if induction is at right-hand-side (e.g. U > i is same as i < U).
    927     switch (cmp) {
    928       case kCondLT: VisitCondition(loop, body, b, a, type, kCondGT); break;
    929       case kCondLE: VisitCondition(loop, body, b, a, type, kCondGE); break;
    930       case kCondGT: VisitCondition(loop, body, b, a, type, kCondLT); break;
    931       case kCondGE: VisitCondition(loop, body, b, a, type, kCondLE); break;
    932       case kCondNE: VisitCondition(loop, body, b, a, type, kCondNE); break;
    933       default: break;
    934     }
    935   } else if (a->induction_class == kLinear && b->induction_class == kInvariant) {
    936     // Analyze condition with induction at left-hand-side (e.g. i < U).
    937     InductionInfo* lower_expr = a->op_b;
    938     InductionInfo* upper_expr = b;
    939     InductionInfo* stride_expr = a->op_a;
    940     // Test for constant stride and integral condition.
    941     int64_t stride_value = 0;
    942     if (!IsExact(stride_expr, &stride_value)) {
    943       return;  // unknown stride
    944     } else if (type != DataType::Type::kInt32 && type != DataType::Type::kInt64) {
    945       return;  // not integral
    946     }
    947     // Since loops with a i != U condition will not be normalized by the method below, first
    948     // try to rewrite a break-loop with terminating condition i != U into an equivalent loop
    949     // with non-strict end condition i <= U or i >= U if such a rewriting is possible and safe.
    950     if (cmp == kCondNE && RewriteBreakLoop(loop, body, stride_value, type)) {
    951       cmp = stride_value > 0 ? kCondLE : kCondGE;
    952     }
    953     // If this rewriting failed, try to rewrite condition i != U into strict end condition i < U
    954     // or i > U if this end condition is reached exactly (tested by verifying if the loop has a
    955     // unit stride and the non-strict condition would be always taken).
    956     if (cmp == kCondNE && ((stride_value == +1 && IsTaken(lower_expr, upper_expr, kCondLE)) ||
    957                            (stride_value == -1 && IsTaken(lower_expr, upper_expr, kCondGE)))) {
    958       cmp = stride_value > 0 ? kCondLT : kCondGT;
    959     }
    960     // A mismatch between the type of condition and the induction is only allowed if the,
    961     // necessarily narrower, induction range fits the narrower control.
    962     if (type != a->type &&
    963         !FitsNarrowerControl(lower_expr, upper_expr, stride_value, a->type, cmp)) {
    964       return;  // mismatched type
    965     }
    966     // Normalize a linear loop control with a nonzero stride:
    967     //   stride > 0, either i < U or i <= U
    968     //   stride < 0, either i > U or i >= U
    969     if ((stride_value > 0 && (cmp == kCondLT || cmp == kCondLE)) ||
    970         (stride_value < 0 && (cmp == kCondGT || cmp == kCondGE))) {
    971       VisitTripCount(loop, lower_expr, upper_expr, stride_expr, stride_value, type, cmp);
    972     }
    973   }
    974 }
    975 
    976 void HInductionVarAnalysis::VisitTripCount(HLoopInformation* loop,
    977                                            InductionInfo* lower_expr,
    978                                            InductionInfo* upper_expr,
    979                                            InductionInfo* stride_expr,
    980                                            int64_t stride_value,
    981                                            DataType::Type type,
    982                                            IfCondition cmp) {
    983   // Any loop of the general form:
    984   //
    985   //    for (i = L; i <= U; i += S) // S > 0
    986   // or for (i = L; i >= U; i += S) // S < 0
    987   //      .. i ..
    988   //
    989   // can be normalized into:
    990   //
    991   //    for (n = 0; n < TC; n++) // where TC = (U + S - L) / S
    992   //      .. L + S * n ..
    993   //
    994   // taking the following into consideration:
    995   //
    996   // (1) Using the same precision, the TC (trip-count) expression should be interpreted as
    997   //     an unsigned entity, for example, as in the following loop that uses the full range:
    998   //     for (int i = INT_MIN; i < INT_MAX; i++) // TC = UINT_MAX
    999   // (2) The TC is only valid if the loop is taken, otherwise TC = 0, as in:
   1000   //     for (int i = 12; i < U; i++) // TC = 0 when U <= 12
   1001   //     If this cannot be determined at compile-time, the TC is only valid within the
   1002   //     loop-body proper, not the loop-header unless enforced with an explicit taken-test.
   1003   // (3) The TC is only valid if the loop is finite, otherwise TC has no value, as in:
   1004   //     for (int i = 0; i <= U; i++) // TC = Inf when U = INT_MAX
   1005   //     If this cannot be determined at compile-time, the TC is only valid when enforced
   1006   //     with an explicit finite-test.
   1007   // (4) For loops which early-exits, the TC forms an upper bound, as in:
   1008   //     for (int i = 0; i < 10 && ....; i++) // TC <= 10
   1009   InductionInfo* trip_count = upper_expr;
   1010   const bool is_taken = IsTaken(lower_expr, upper_expr, cmp);
   1011   const bool is_finite = IsFinite(upper_expr, stride_value, type, cmp);
   1012   const bool cancels = (cmp == kCondLT || cmp == kCondGT) && std::abs(stride_value) == 1;
   1013   if (!cancels) {
   1014     // Convert exclusive integral inequality into inclusive integral inequality,
   1015     // viz. condition i < U is i <= U - 1 and condition i > U is i >= U + 1.
   1016     if (cmp == kCondLT) {
   1017       trip_count = CreateInvariantOp(kSub, trip_count, CreateConstant(1, type));
   1018     } else if (cmp == kCondGT) {
   1019       trip_count = CreateInvariantOp(kAdd, trip_count, CreateConstant(1, type));
   1020     }
   1021     // Compensate for stride.
   1022     trip_count = CreateInvariantOp(kAdd, trip_count, stride_expr);
   1023   }
   1024   trip_count = CreateInvariantOp(
   1025       kDiv, CreateInvariantOp(kSub, trip_count, lower_expr), stride_expr);
   1026   // Assign the trip-count expression to the loop control. Clients that use the information
   1027   // should be aware that the expression is only valid under the conditions listed above.
   1028   InductionOp tcKind = kTripCountInBodyUnsafe;  // needs both tests
   1029   if (is_taken && is_finite) {
   1030     tcKind = kTripCountInLoop;  // needs neither test
   1031   } else if (is_finite) {
   1032     tcKind = kTripCountInBody;  // needs taken-test
   1033   } else if (is_taken) {
   1034     tcKind = kTripCountInLoopUnsafe;  // needs finite-test
   1035   }
   1036   InductionOp op = kNop;
   1037   switch (cmp) {
   1038     case kCondLT: op = kLT; break;
   1039     case kCondLE: op = kLE; break;
   1040     case kCondGT: op = kGT; break;
   1041     case kCondGE: op = kGE; break;
   1042     default:      LOG(FATAL) << "CONDITION UNREACHABLE";
   1043   }
   1044   // Associate trip count with control instruction, rather than the condition (even
   1045   // though it's its use) since former provides a convenient use-free placeholder.
   1046   HInstruction* control = loop->GetHeader()->GetLastInstruction();
   1047   InductionInfo* taken_test = CreateInvariantOp(op, lower_expr, upper_expr);
   1048   DCHECK(control->IsIf());
   1049   AssignInfo(loop, control, CreateTripCount(tcKind, trip_count, taken_test, type));
   1050 }
   1051 
   1052 bool HInductionVarAnalysis::IsTaken(InductionInfo* lower_expr,
   1053                                     InductionInfo* upper_expr,
   1054                                     IfCondition cmp) {
   1055   int64_t lower_value;
   1056   int64_t upper_value;
   1057   switch (cmp) {
   1058     case kCondLT:
   1059       return IsAtMost(lower_expr, &lower_value)
   1060           && IsAtLeast(upper_expr, &upper_value)
   1061           && lower_value < upper_value;
   1062     case kCondLE:
   1063       return IsAtMost(lower_expr, &lower_value)
   1064           && IsAtLeast(upper_expr, &upper_value)
   1065           && lower_value <= upper_value;
   1066     case kCondGT:
   1067       return IsAtLeast(lower_expr, &lower_value)
   1068           && IsAtMost(upper_expr, &upper_value)
   1069           && lower_value > upper_value;
   1070     case kCondGE:
   1071       return IsAtLeast(lower_expr, &lower_value)
   1072           && IsAtMost(upper_expr, &upper_value)
   1073           && lower_value >= upper_value;
   1074     default:
   1075       LOG(FATAL) << "CONDITION UNREACHABLE";
   1076   }
   1077   return false;  // not certain, may be untaken
   1078 }
   1079 
   1080 bool HInductionVarAnalysis::IsFinite(InductionInfo* upper_expr,
   1081                                      int64_t stride_value,
   1082                                      DataType::Type type,
   1083                                      IfCondition cmp) {
   1084   int64_t min = DataType::MinValueOfIntegralType(type);
   1085   int64_t max = DataType::MaxValueOfIntegralType(type);
   1086   // Some rules under which it is certain at compile-time that the loop is finite.
   1087   int64_t value;
   1088   switch (cmp) {
   1089     case kCondLT:
   1090       return stride_value == 1 ||
   1091           (IsAtMost(upper_expr, &value) && value <= (max - stride_value + 1));
   1092     case kCondLE:
   1093       return (IsAtMost(upper_expr, &value) && value <= (max - stride_value));
   1094     case kCondGT:
   1095       return stride_value == -1 ||
   1096           (IsAtLeast(upper_expr, &value) && value >= (min - stride_value - 1));
   1097     case kCondGE:
   1098       return (IsAtLeast(upper_expr, &value) && value >= (min - stride_value));
   1099     default:
   1100       LOG(FATAL) << "CONDITION UNREACHABLE";
   1101   }
   1102   return false;  // not certain, may be infinite
   1103 }
   1104 
   1105 bool HInductionVarAnalysis::FitsNarrowerControl(InductionInfo* lower_expr,
   1106                                                 InductionInfo* upper_expr,
   1107                                                 int64_t stride_value,
   1108                                                 DataType::Type type,
   1109                                                 IfCondition cmp) {
   1110   int64_t min = DataType::MinValueOfIntegralType(type);
   1111   int64_t max = DataType::MaxValueOfIntegralType(type);
   1112   // Inclusive test need one extra.
   1113   if (stride_value != 1 && stride_value != -1) {
   1114     return false;  // non-unit stride
   1115   } else if (cmp == kCondLE) {
   1116     max--;
   1117   } else if (cmp == kCondGE) {
   1118     min++;
   1119   }
   1120   // Do both bounds fit the range?
   1121   int64_t value = 0;
   1122   return IsAtLeast(lower_expr, &value) && value >= min &&
   1123          IsAtMost(lower_expr, &value)  && value <= max &&
   1124          IsAtLeast(upper_expr, &value) && value >= min &&
   1125          IsAtMost(upper_expr, &value)  && value <= max;
   1126 }
   1127 
   1128 bool HInductionVarAnalysis::RewriteBreakLoop(HLoopInformation* loop,
   1129                                              HBasicBlock* body,
   1130                                              int64_t stride_value,
   1131                                              DataType::Type type) {
   1132   // Only accept unit stride.
   1133   if (std::abs(stride_value) != 1) {
   1134     return false;
   1135   }
   1136   // Simple terminating i != U condition, used nowhere else.
   1137   HIf* ifs = loop->GetHeader()->GetLastInstruction()->AsIf();
   1138   HInstruction* cond = ifs->InputAt(0);
   1139   if (ifs->GetPrevious() != cond || !cond->HasOnlyOneNonEnvironmentUse()) {
   1140     return false;
   1141   }
   1142   int c = LookupInfo(loop, cond->InputAt(0))->induction_class == kLinear ? 0 : 1;
   1143   HInstruction* index = cond->InputAt(c);
   1144   HInstruction* upper = cond->InputAt(1 - c);
   1145   // Safe to rewrite into i <= U?
   1146   IfCondition cmp = stride_value > 0 ? kCondLE : kCondGE;
   1147   if (!index->IsPhi() || !IsFinite(LookupInfo(loop, upper), stride_value, type, cmp)) {
   1148     return false;
   1149   }
   1150   // Body consists of update to index i only, used nowhere else.
   1151   if (body->GetSuccessors().size() != 1 ||
   1152       body->GetSingleSuccessor() != loop->GetHeader() ||
   1153       !body->GetPhis().IsEmpty() ||
   1154       body->GetInstructions().IsEmpty() ||
   1155       body->GetFirstInstruction() != index->InputAt(1) ||
   1156       !body->GetFirstInstruction()->HasOnlyOneNonEnvironmentUse() ||
   1157       !body->GetFirstInstruction()->GetNext()->IsGoto()) {
   1158     return false;
   1159   }
   1160   // Always taken or guarded by enclosing condition.
   1161   if (!IsTaken(LookupInfo(loop, index)->op_b, LookupInfo(loop, upper), cmp) &&
   1162       !IsGuardedBy(loop, cmp, index->InputAt(0), upper)) {
   1163     return false;
   1164   }
   1165   // Test if break-loop body can be written, and do so on success.
   1166   if (RewriteBreakLoopBody(loop, body, cond, index, upper, /*rewrite*/ false)) {
   1167     RewriteBreakLoopBody(loop, body, cond, index, upper, /*rewrite*/ true);
   1168   } else {
   1169     return false;
   1170   }
   1171   // Rewrite condition in HIR.
   1172   if (ifs->IfTrueSuccessor() != body) {
   1173     cmp = (cmp == kCondLE) ? kCondGT : kCondLT;
   1174   }
   1175   HInstruction* rep = nullptr;
   1176   switch (cmp) {
   1177     case kCondLT: rep = new (graph_->GetAllocator()) HLessThan(index, upper); break;
   1178     case kCondGT: rep = new (graph_->GetAllocator()) HGreaterThan(index, upper); break;
   1179     case kCondLE: rep = new (graph_->GetAllocator()) HLessThanOrEqual(index, upper); break;
   1180     case kCondGE: rep = new (graph_->GetAllocator()) HGreaterThanOrEqual(index, upper); break;
   1181     default: LOG(FATAL) << cmp; UNREACHABLE();
   1182   }
   1183   loop->GetHeader()->ReplaceAndRemoveInstructionWith(cond, rep);
   1184   return true;
   1185 }
   1186 
   1187 //
   1188 // Helper methods.
   1189 //
   1190 
   1191 void HInductionVarAnalysis::AssignInfo(HLoopInformation* loop,
   1192                                        HInstruction* instruction,
   1193                                        InductionInfo* info) {
   1194   auto it = induction_.find(loop);
   1195   if (it == induction_.end()) {
   1196     it = induction_.Put(loop,
   1197                         ArenaSafeMap<HInstruction*, InductionInfo*>(
   1198                             std::less<HInstruction*>(),
   1199                             graph_->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis)));
   1200   }
   1201   it->second.Put(instruction, info);
   1202 }
   1203 
   1204 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::LookupInfo(HLoopInformation* loop,
   1205                                                                         HInstruction* instruction) {
   1206   auto it = induction_.find(loop);
   1207   if (it != induction_.end()) {
   1208     auto loop_it = it->second.find(instruction);
   1209     if (loop_it != it->second.end()) {
   1210       return loop_it->second;
   1211     }
   1212   }
   1213   if (loop->IsDefinedOutOfTheLoop(instruction)) {
   1214     InductionInfo* info = CreateInvariantFetch(instruction);
   1215     AssignInfo(loop, instruction, info);
   1216     return info;
   1217   }
   1218   return nullptr;
   1219 }
   1220 
   1221 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::CreateConstant(int64_t value,
   1222                                                                             DataType::Type type) {
   1223   HInstruction* constant;
   1224   switch (type) {
   1225     case DataType::Type::kFloat64: constant = graph_->GetDoubleConstant(value); break;
   1226     case DataType::Type::kFloat32: constant = graph_->GetFloatConstant(value);  break;
   1227     case DataType::Type::kInt64:   constant = graph_->GetLongConstant(value);   break;
   1228     default:                       constant = graph_->GetIntConstant(value);    break;
   1229   }
   1230   return CreateInvariantFetch(constant);
   1231 }
   1232 
   1233 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::CreateSimplifiedInvariant(
   1234     InductionOp op,
   1235     InductionInfo* a,
   1236     InductionInfo* b) {
   1237   // Perform some light-weight simplifications during construction of a new invariant.
   1238   // This often safes memory and yields a more concise representation of the induction.
   1239   // More exhaustive simplifications are done by later phases once induction nodes are
   1240   // translated back into HIR code (e.g. by loop optimizations or BCE).
   1241   int64_t value = -1;
   1242   if (IsExact(a, &value)) {
   1243     if (value == 0) {
   1244       // Simplify 0 + b = b, 0 ^ b = b, 0 * b = 0.
   1245       if (op == kAdd || op == kXor) {
   1246         return b;
   1247       } else if (op == kMul) {
   1248         return a;
   1249       }
   1250     } else if (op == kMul) {
   1251       // Simplify 1 * b = b, -1 * b = -b
   1252       if (value == 1) {
   1253         return b;
   1254       } else if (value == -1) {
   1255         return CreateSimplifiedInvariant(kNeg, nullptr, b);
   1256       }
   1257     }
   1258   }
   1259   if (IsExact(b, &value)) {
   1260     if (value == 0) {
   1261       // Simplify a + 0 = a, a - 0 = a, a ^ 0 = a, a * 0 = 0, -0 = 0.
   1262       if (op == kAdd || op == kSub || op == kXor) {
   1263         return a;
   1264       } else if (op == kMul || op == kNeg) {
   1265         return b;
   1266       }
   1267     } else if (op == kMul || op == kDiv) {
   1268       // Simplify a * 1 = a, a / 1 = a, a * -1 = -a, a / -1 = -a
   1269       if (value == 1) {
   1270         return a;
   1271       } else if (value == -1) {
   1272         return CreateSimplifiedInvariant(kNeg, nullptr, a);
   1273       }
   1274     }
   1275   } else if (b->operation == kNeg) {
   1276     // Simplify a + (-b) = a - b, a - (-b) = a + b, -(-b) = b.
   1277     if (op == kAdd) {
   1278       return CreateSimplifiedInvariant(kSub, a, b->op_b);
   1279     } else if (op == kSub) {
   1280       return CreateSimplifiedInvariant(kAdd, a, b->op_b);
   1281     } else if (op == kNeg) {
   1282       return b->op_b;
   1283     }
   1284   } else if (b->operation == kSub) {
   1285     // Simplify - (a - b) = b - a.
   1286     if (op == kNeg) {
   1287       return CreateSimplifiedInvariant(kSub, b->op_b, b->op_a);
   1288     }
   1289   }
   1290   return new (graph_->GetAllocator()) InductionInfo(
   1291       kInvariant, op, a, b, nullptr, ImplicitConversion(b->type));
   1292 }
   1293 
   1294 HInstruction* HInductionVarAnalysis::GetShiftConstant(HLoopInformation* loop,
   1295                                                       HInstruction* instruction,
   1296                                                       InductionInfo* initial) {
   1297   DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr());
   1298   // Shift-rights are only the same as division for non-negative initial inputs.
   1299   // Otherwise we would round incorrectly.
   1300   if (initial != nullptr) {
   1301     int64_t value = -1;
   1302     if (!IsAtLeast(initial, &value) || value < 0) {
   1303       return nullptr;
   1304     }
   1305   }
   1306   // Obtain the constant needed to treat shift as equivalent multiplication or division.
   1307   // This yields an existing instruction if the constant is already there. Otherwise, this
   1308   // has a side effect on the HIR. The restriction on the shift factor avoids generating a
   1309   // negative constant (viz. 1 << 31 and 1L << 63 set the sign bit). The code assumes that
   1310   // generalization for shift factors outside [0,32) and [0,64) ranges is done earlier.
   1311   InductionInfo* b = LookupInfo(loop, instruction->InputAt(1));
   1312   int64_t value = -1;
   1313   if (IsExact(b, &value)) {
   1314     DataType::Type type = instruction->InputAt(0)->GetType();
   1315     if (type == DataType::Type::kInt32 && 0 <= value && value < 31) {
   1316       return graph_->GetIntConstant(1 << value);
   1317     }
   1318     if (type == DataType::Type::kInt64 && 0 <= value && value < 63) {
   1319       return graph_->GetLongConstant(1L << value);
   1320     }
   1321   }
   1322   return nullptr;
   1323 }
   1324 
   1325 void HInductionVarAnalysis::AssignCycle(HPhi* phi) {
   1326   ArenaSet<HInstruction*>* set = &cycles_.Put(phi, ArenaSet<HInstruction*>(
   1327       graph_->GetAllocator()->Adapter(kArenaAllocInductionVarAnalysis)))->second;
   1328   for (HInstruction* i : scc_) {
   1329     set->insert(i);
   1330   }
   1331 }
   1332 
   1333 ArenaSet<HInstruction*>* HInductionVarAnalysis::LookupCycle(HPhi* phi) {
   1334   auto it = cycles_.find(phi);
   1335   if (it != cycles_.end()) {
   1336     return &it->second;
   1337   }
   1338   return nullptr;
   1339 }
   1340 
   1341 bool HInductionVarAnalysis::IsExact(InductionInfo* info, int64_t* value) {
   1342   return InductionVarRange(this).IsConstant(info, InductionVarRange::kExact, value);
   1343 }
   1344 
   1345 bool HInductionVarAnalysis::IsAtMost(InductionInfo* info, int64_t* value) {
   1346   return InductionVarRange(this).IsConstant(info, InductionVarRange::kAtMost, value);
   1347 }
   1348 
   1349 bool HInductionVarAnalysis::IsAtLeast(InductionInfo* info, int64_t* value) {
   1350   return InductionVarRange(this).IsConstant(info, InductionVarRange::kAtLeast, value);
   1351 }
   1352 
   1353 bool HInductionVarAnalysis::IsNarrowingLinear(InductionInfo* info) {
   1354   return info != nullptr &&
   1355       info->induction_class == kLinear &&
   1356       (info->type == DataType::Type::kUint8 ||
   1357        info->type == DataType::Type::kInt8 ||
   1358        info->type == DataType::Type::kUint16 ||
   1359        info->type == DataType::Type::kInt16 ||
   1360        (info->type == DataType::Type::kInt32 && (info->op_a->type == DataType::Type::kInt64 ||
   1361                                                  info->op_b->type == DataType::Type::kInt64)));
   1362 }
   1363 
   1364 bool HInductionVarAnalysis::InductionEqual(InductionInfo* info1,
   1365                                            InductionInfo* info2) {
   1366   // Test structural equality only, without accounting for simplifications.
   1367   if (info1 != nullptr && info2 != nullptr) {
   1368     return
   1369         info1->induction_class == info2->induction_class &&
   1370         info1->operation       == info2->operation       &&
   1371         info1->fetch           == info2->fetch           &&
   1372         info1->type            == info2->type            &&
   1373         InductionEqual(info1->op_a, info2->op_a)         &&
   1374         InductionEqual(info1->op_b, info2->op_b);
   1375   }
   1376   // Otherwise only two nullptrs are considered equal.
   1377   return info1 == info2;
   1378 }
   1379 
   1380 std::string HInductionVarAnalysis::FetchToString(HInstruction* fetch) {
   1381   DCHECK(fetch != nullptr);
   1382   if (fetch->IsIntConstant()) {
   1383     return std::to_string(fetch->AsIntConstant()->GetValue());
   1384   } else if (fetch->IsLongConstant()) {
   1385     return std::to_string(fetch->AsLongConstant()->GetValue());
   1386   }
   1387   return std::to_string(fetch->GetId()) + ":" + fetch->DebugName();
   1388 }
   1389 
   1390 std::string HInductionVarAnalysis::InductionToString(InductionInfo* info) {
   1391   if (info != nullptr) {
   1392     if (info->induction_class == kInvariant) {
   1393       std::string inv = "(";
   1394       inv += InductionToString(info->op_a);
   1395       switch (info->operation) {
   1396         case kNop:   inv += " @ ";  break;
   1397         case kAdd:   inv += " + ";  break;
   1398         case kSub:
   1399         case kNeg:   inv += " - ";  break;
   1400         case kMul:   inv += " * ";  break;
   1401         case kDiv:   inv += " / ";  break;
   1402         case kRem:   inv += " % ";  break;
   1403         case kXor:   inv += " ^ ";  break;
   1404         case kLT:    inv += " < ";  break;
   1405         case kLE:    inv += " <= "; break;
   1406         case kGT:    inv += " > ";  break;
   1407         case kGE:    inv += " >= "; break;
   1408         case kFetch: inv += FetchToString(info->fetch); break;
   1409         case kTripCountInLoop:       inv += " (TC-loop) ";        break;
   1410         case kTripCountInBody:       inv += " (TC-body) ";        break;
   1411         case kTripCountInLoopUnsafe: inv += " (TC-loop-unsafe) "; break;
   1412         case kTripCountInBodyUnsafe: inv += " (TC-body-unsafe) "; break;
   1413       }
   1414       inv += InductionToString(info->op_b);
   1415       inv += ")";
   1416       return inv;
   1417     } else {
   1418       if (info->induction_class == kLinear) {
   1419         DCHECK(info->operation == kNop);
   1420         return "(" + InductionToString(info->op_a) + " * i + " +
   1421                      InductionToString(info->op_b) + "):" +
   1422                      DataType::PrettyDescriptor(info->type);
   1423       } else if (info->induction_class == kPolynomial) {
   1424         DCHECK(info->operation == kNop);
   1425         return "poly(sum_lt(" + InductionToString(info->op_a) + ") + " +
   1426                                 InductionToString(info->op_b) + "):" +
   1427                                 DataType::PrettyDescriptor(info->type);
   1428       } else if (info->induction_class == kGeometric) {
   1429         DCHECK(info->operation == kMul || info->operation == kDiv);
   1430         DCHECK(info->fetch != nullptr);
   1431         return "geo(" + InductionToString(info->op_a) + " * " +
   1432                         FetchToString(info->fetch) +
   1433                         (info->operation == kMul ? " ^ i + " : " ^ -i + ") +
   1434                         InductionToString(info->op_b) + "):" +
   1435                         DataType::PrettyDescriptor(info->type);
   1436       } else if (info->induction_class == kWrapAround) {
   1437         DCHECK(info->operation == kNop);
   1438         return "wrap(" + InductionToString(info->op_a) + ", " +
   1439                          InductionToString(info->op_b) + "):" +
   1440                          DataType::PrettyDescriptor(info->type);
   1441       } else if (info->induction_class == kPeriodic) {
   1442         DCHECK(info->operation == kNop);
   1443         return "periodic(" + InductionToString(info->op_a) + ", " +
   1444                              InductionToString(info->op_b) + "):" +
   1445                              DataType::PrettyDescriptor(info->type);
   1446       }
   1447     }
   1448   }
   1449   return "";
   1450 }
   1451 
   1452 }  // namespace art
   1453