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