summaryrefslogtreecommitdiff
path: root/compiler/optimizing/induction_var_analysis.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/induction_var_analysis.cc')
-rw-r--r--compiler/optimizing/induction_var_analysis.cc415
1 files changed, 253 insertions, 162 deletions
diff --git a/compiler/optimizing/induction_var_analysis.cc b/compiler/optimizing/induction_var_analysis.cc
index 8aaec6804d..8b38414de0 100644
--- a/compiler/optimizing/induction_var_analysis.cc
+++ b/compiler/optimizing/induction_var_analysis.cc
@@ -42,6 +42,33 @@ static bool IsEntryPhi(HLoopInformation* loop, HInstruction* instruction) {
instruction->GetBlock() == loop->GetHeader();
}
+/**
+ * Returns true for 32/64-bit integral constant, passing its value as output parameter.
+ */
+static bool IsIntAndGet(HInstruction* instruction, int64_t* value) {
+ if (instruction->IsIntConstant()) {
+ *value = instruction->AsIntConstant()->GetValue();
+ return true;
+ } else if (instruction->IsLongConstant()) {
+ *value = instruction->AsLongConstant()->GetValue();
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Returns a string representation of an instruction
+ * (for testing and debugging only).
+ */
+static std::string InstructionToString(HInstruction* instruction) {
+ if (instruction->IsIntConstant()) {
+ return std::to_string(instruction->AsIntConstant()->GetValue());
+ } else if (instruction->IsLongConstant()) {
+ return std::to_string(instruction->AsLongConstant()->GetValue()) + "L";
+ }
+ return std::to_string(instruction->GetId()) + ":" + instruction->DebugName();
+}
+
//
// Class methods.
//
@@ -51,14 +78,15 @@ HInductionVarAnalysis::HInductionVarAnalysis(HGraph* graph)
global_depth_(0),
stack_(graph->GetArena()->Adapter()),
scc_(graph->GetArena()->Adapter()),
- map_(std::less<int>(), graph->GetArena()->Adapter()),
- cycle_(std::less<int>(), graph->GetArena()->Adapter()),
- induction_(std::less<int>(), graph->GetArena()->Adapter()) {
+ map_(std::less<HInstruction*>(), graph->GetArena()->Adapter()),
+ cycle_(std::less<HInstruction*>(), graph->GetArena()->Adapter()),
+ induction_(std::less<HLoopInformation*>(), graph->GetArena()->Adapter()) {
}
void HInductionVarAnalysis::Run() {
- // Detects sequence variables (generalized induction variables) during an
- // inner-loop-first traversal of all loops using Gerlek's algorithm.
+ // Detects sequence variables (generalized induction variables) during an inner-loop-first
+ // traversal of all loops using Gerlek's algorithm. The order is only relevant if outer
+ // loops would use induction information of inner loops (not currently done).
for (HPostOrderIterator it_graph(*graph_); !it_graph.Done(); it_graph.Advance()) {
HBasicBlock* graph_block = it_graph.Current();
if (graph_block->IsLoopHeader()) {
@@ -71,38 +99,37 @@ void HInductionVarAnalysis::VisitLoop(HLoopInformation* loop) {
// Find strongly connected components (SSCs) in the SSA graph of this loop using Tarjan's
// algorithm. Due to the descendant-first nature, classification happens "on-demand".
global_depth_ = 0;
- CHECK(stack_.empty());
+ DCHECK(stack_.empty());
map_.clear();
for (HBlocksInLoopIterator it_loop(*loop); !it_loop.Done(); it_loop.Advance()) {
HBasicBlock* loop_block = it_loop.Current();
- CHECK(loop_block->IsInLoop());
+ DCHECK(loop_block->IsInLoop());
if (loop_block->GetLoopInformation() != loop) {
continue; // Inner loops already visited.
}
// Visit phi-operations and instructions.
for (HInstructionIterator it(loop_block->GetPhis()); !it.Done(); it.Advance()) {
HInstruction* instruction = it.Current();
- if (!IsVisitedNode(instruction->GetId())) {
+ if (!IsVisitedNode(instruction)) {
VisitNode(loop, instruction);
}
}
for (HInstructionIterator it(loop_block->GetInstructions()); !it.Done(); it.Advance()) {
HInstruction* instruction = it.Current();
- if (!IsVisitedNode(instruction->GetId())) {
+ if (!IsVisitedNode(instruction)) {
VisitNode(loop, instruction);
}
}
}
- CHECK(stack_.empty());
+ DCHECK(stack_.empty());
map_.clear();
}
void HInductionVarAnalysis::VisitNode(HLoopInformation* loop, HInstruction* instruction) {
- const int id = instruction->GetId();
const uint32_t d1 = ++global_depth_;
- map_.Put(id, NodeInfo(d1));
+ map_.Put(instruction, NodeInfo(d1));
stack_.push_back(instruction);
// Visit all descendants.
@@ -113,7 +140,7 @@ void HInductionVarAnalysis::VisitNode(HLoopInformation* loop, HInstruction* inst
// Lower or found SCC?
if (low < d1) {
- map_.find(id)->second.depth = low;
+ map_.find(instruction)->second.depth = low;
} else {
scc_.clear();
cycle_.clear();
@@ -123,7 +150,7 @@ void HInductionVarAnalysis::VisitNode(HLoopInformation* loop, HInstruction* inst
HInstruction* x = stack_.back();
scc_.push_back(x);
stack_.pop_back();
- map_.find(x->GetId())->second.done = true;
+ map_.find(x)->second.done = true;
if (x == instruction) {
break;
}
@@ -150,12 +177,11 @@ uint32_t HInductionVarAnalysis::VisitDescendant(HLoopInformation* loop, HInstruc
}
// Inspect descendant node.
- const int id = instruction->GetId();
- if (!IsVisitedNode(id)) {
+ if (!IsVisitedNode(instruction)) {
VisitNode(loop, instruction);
- return map_.find(id)->second.depth;
+ return map_.find(instruction)->second.depth;
} else {
- auto it = map_.find(id);
+ auto it = map_.find(instruction);
return it->second.done ? global_depth_ : it->second.depth;
}
}
@@ -176,8 +202,20 @@ void HInductionVarAnalysis::ClassifyTrivial(HLoopInformation* loop, HInstruction
} else if (instruction->IsMul()) {
info = TransferMul(LookupInfo(loop, instruction->InputAt(0)),
LookupInfo(loop, instruction->InputAt(1)));
+ } else if (instruction->IsShl()) {
+ info = TransferShl(LookupInfo(loop, instruction->InputAt(0)),
+ LookupInfo(loop, instruction->InputAt(1)),
+ instruction->InputAt(0)->GetType());
} else if (instruction->IsNeg()) {
info = TransferNeg(LookupInfo(loop, instruction->InputAt(0)));
+ } else if (instruction->IsBoundsCheck()) {
+ info = LookupInfo(loop, instruction->InputAt(0)); // Pass-through.
+ } else if (instruction->IsTypeConversion()) {
+ HTypeConversion* conversion = instruction->AsTypeConversion();
+ // TODO: accept different conversion scenarios.
+ if (conversion->GetResultType() == conversion->GetInputType()) {
+ info = LookupInfo(loop, conversion->GetInput());
+ }
}
// Successfully classified?
@@ -188,7 +226,7 @@ void HInductionVarAnalysis::ClassifyTrivial(HLoopInformation* loop, HInstruction
void HInductionVarAnalysis::ClassifyNonTrivial(HLoopInformation* loop) {
const size_t size = scc_.size();
- CHECK_GE(size, 1u);
+ DCHECK_GE(size, 1u);
HInstruction* phi = scc_[size - 1];
if (!IsEntryPhi(loop, phi)) {
return;
@@ -204,41 +242,74 @@ void HInductionVarAnalysis::ClassifyNonTrivial(HLoopInformation* loop) {
if (size == 1) {
InductionInfo* update = LookupInfo(loop, internal);
if (update != nullptr) {
- AssignInfo(loop, phi, NewInductionInfo(kWrapAround, kNop, initial, update, nullptr));
+ AssignInfo(loop, phi, NewInduction(kWrapAround, initial, update));
}
return;
}
// Inspect remainder of the cycle that resides in scc_. The cycle_ mapping assigns
- // temporary meaning to its nodes.
- cycle_.Overwrite(phi->GetId(), nullptr);
+ // temporary meaning to its nodes, seeded from the phi instruction and back.
for (size_t i = 0; i < size - 1; i++) {
- HInstruction* operation = scc_[i];
+ HInstruction* instruction = scc_[i];
InductionInfo* update = nullptr;
- if (operation->IsPhi()) {
- update = TransferCycleOverPhi(operation);
- } else if (operation->IsAdd()) {
- update = TransferCycleOverAddSub(loop, operation->InputAt(0), operation->InputAt(1), kAdd, true);
- } else if (operation->IsSub()) {
- update = TransferCycleOverAddSub(loop, operation->InputAt(0), operation->InputAt(1), kSub, true);
+ if (instruction->IsPhi()) {
+ update = SolvePhi(loop, phi, instruction);
+ } else if (instruction->IsAdd()) {
+ update = SolveAddSub(
+ loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kAdd, true);
+ } else if (instruction->IsSub()) {
+ update = SolveAddSub(
+ loop, phi, instruction, instruction->InputAt(0), instruction->InputAt(1), kSub, true);
}
if (update == nullptr) {
return;
}
- cycle_.Overwrite(operation->GetId(), update);
+ cycle_.Put(instruction, update);
}
- // Success if the internal link received accumulated nonzero update.
- auto it = cycle_.find(internal->GetId());
- if (it != cycle_.end() && it->second != nullptr) {
- // Classify header phi and feed the cycle "on-demand".
- AssignInfo(loop, phi, NewInductionInfo(kLinear, kNop, it->second, initial, nullptr));
- for (size_t i = 0; i < size - 1; i++) {
- ClassifyTrivial(loop, scc_[i]);
+ // Success if the internal link received a meaning.
+ auto it = cycle_.find(internal);
+ if (it != cycle_.end()) {
+ InductionInfo* induction = it->second;
+ switch (induction->induction_class) {
+ case kInvariant:
+ // Classify phi (last element in scc_) and then the rest of the cycle "on-demand".
+ // Statements are scanned in the Tarjan SCC order, with phi first.
+ AssignInfo(loop, phi, NewInduction(kLinear, induction, initial));
+ for (size_t i = 0; i < size - 1; i++) {
+ ClassifyTrivial(loop, scc_[i]);
+ }
+ break;
+ case kPeriodic:
+ // Classify all elements in the cycle with the found periodic induction while rotating
+ // each first element to the end. Lastly, phi (last element in scc_) is classified.
+ // Statements are scanned in the reverse Tarjan SCC order, with phi last.
+ for (size_t i = 2; i <= size; i++) {
+ AssignInfo(loop, scc_[size - i], induction);
+ induction = RotatePeriodicInduction(induction->op_b, induction->op_a);
+ }
+ AssignInfo(loop, phi, induction);
+ break;
+ default:
+ break;
}
}
}
+HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::RotatePeriodicInduction(
+ InductionInfo* induction,
+ InductionInfo* last) {
+ // Rotates a periodic induction of the form
+ // (a, b, c, d, e)
+ // into
+ // (b, c, d, e, a)
+ // in preparation of assigning this to the previous variable in the sequence.
+ if (induction->induction_class == kInvariant) {
+ return NewInduction(kPeriodic, induction, last);
+ }
+ return NewInduction(kPeriodic, induction->op_a, RotatePeriodicInduction(induction->op_b, last));
+}
+
HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferPhi(InductionInfo* a,
InductionInfo* b) {
// Transfer over a phi: if both inputs are identical, result is input.
@@ -251,36 +322,33 @@ HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferPhi(Inducti
HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferAddSub(InductionInfo* a,
InductionInfo* b,
InductionOp op) {
- // Transfer over an addition or subtraction: invariant or linear
- // inputs combine into new invariant or linear result.
+ // Transfer over an addition or subtraction: any invariant, linear, wrap-around, or periodic
+ // can be combined with an invariant to yield a similar result. Even two linear inputs can
+ // be combined. All other combinations fail, however.
if (a != nullptr && b != nullptr) {
if (a->induction_class == kInvariant && b->induction_class == kInvariant) {
- return NewInductionInfo(kInvariant, op, a, b, nullptr);
- } else if (a->induction_class == kLinear && b->induction_class == kInvariant) {
- return NewInductionInfo(
- kLinear,
- kNop,
- a->op_a,
- NewInductionInfo(kInvariant, op, a->op_b, b, nullptr),
- nullptr);
- } else if (a->induction_class == kInvariant && b->induction_class == kLinear) {
- InductionInfo* ba = b->op_a;
- if (op == kSub) { // negation required
- ba = NewInductionInfo(kInvariant, kNeg, nullptr, ba, nullptr);
- }
- return NewInductionInfo(
- kLinear,
- kNop,
- ba,
- NewInductionInfo(kInvariant, op, a, b->op_b, nullptr),
- nullptr);
+ return NewInvariantOp(op, a, b);
} else if (a->induction_class == kLinear && b->induction_class == kLinear) {
- return NewInductionInfo(
- kLinear,
- kNop,
- NewInductionInfo(kInvariant, op, a->op_a, b->op_a, nullptr),
- NewInductionInfo(kInvariant, op, a->op_b, b->op_b, nullptr),
- nullptr);
+ return NewInduction(
+ kLinear, TransferAddSub(a->op_a, b->op_a, op), TransferAddSub(a->op_b, b->op_b, op));
+ } else if (a->induction_class == kInvariant) {
+ InductionInfo* new_a = b->op_a;
+ InductionInfo* new_b = TransferAddSub(a, b->op_b, op);
+ if (b->induction_class != kLinear) {
+ DCHECK(b->induction_class == kWrapAround || b->induction_class == kPeriodic);
+ new_a = TransferAddSub(a, new_a, op);
+ } else if (op == kSub) { // Negation required.
+ new_a = TransferNeg(new_a);
+ }
+ return NewInduction(b->induction_class, new_a, new_b);
+ } else if (b->induction_class == kInvariant) {
+ InductionInfo* new_a = a->op_a;
+ InductionInfo* new_b = TransferAddSub(a->op_b, b, op);
+ if (a->induction_class != kLinear) {
+ DCHECK(a->induction_class == kWrapAround || a->induction_class == kPeriodic);
+ new_a = TransferAddSub(new_a, b, op);
+ }
+ return NewInduction(a->induction_class, new_a, new_b);
}
}
return nullptr;
@@ -288,141 +356,164 @@ HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferAddSub(Indu
HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferMul(InductionInfo* a,
InductionInfo* b) {
- // Transfer over a multiplication: invariant or linear
- // inputs combine into new invariant or linear result.
- // Two linear inputs would become quadratic.
+ // Transfer over a multiplication: any invariant, linear, wrap-around, or periodic
+ // can be multiplied with an invariant to yield a similar but multiplied result.
+ // Two non-invariant inputs cannot be multiplied, however.
if (a != nullptr && b != nullptr) {
if (a->induction_class == kInvariant && b->induction_class == kInvariant) {
- return NewInductionInfo(kInvariant, kMul, a, b, nullptr);
- } else if (a->induction_class == kLinear && b->induction_class == kInvariant) {
- return NewInductionInfo(
- kLinear,
- kNop,
- NewInductionInfo(kInvariant, kMul, a->op_a, b, nullptr),
- NewInductionInfo(kInvariant, kMul, a->op_b, b, nullptr),
- nullptr);
- } else if (a->induction_class == kInvariant && b->induction_class == kLinear) {
- return NewInductionInfo(
- kLinear,
- kNop,
- NewInductionInfo(kInvariant, kMul, a, b->op_a, nullptr),
- NewInductionInfo(kInvariant, kMul, a, b->op_b, nullptr),
- nullptr);
+ return NewInvariantOp(kMul, a, b);
+ } else if (a->induction_class == kInvariant) {
+ return NewInduction(b->induction_class, TransferMul(a, b->op_a), TransferMul(a, b->op_b));
+ } else if (b->induction_class == kInvariant) {
+ return NewInduction(a->induction_class, TransferMul(a->op_a, b), TransferMul(a->op_b, b));
+ }
+ }
+ return nullptr;
+}
+
+HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferShl(InductionInfo* a,
+ InductionInfo* b,
+ Primitive::Type t) {
+ // Transfer over a shift left: treat shift by restricted constant as equivalent multiplication.
+ if (a != nullptr && b != nullptr && b->induction_class == kInvariant && b->operation == kFetch) {
+ int64_t value = -1;
+ // Obtain the constant needed for the multiplication. This yields an existing instruction
+ // if the constants is already there. Otherwise, this has a side effect on the HIR.
+ // The restriction on the shift factor avoids generating a negative constant
+ // (viz. 1 << 31 and 1L << 63 set the sign bit). The code assumes that generalization
+ // for shift factors outside [0,32) and [0,64) ranges is done by earlier simplification.
+ if (IsIntAndGet(b->fetch, &value)) {
+ if (t == Primitive::kPrimInt && 0 <= value && value < 31) {
+ return TransferMul(a, NewInvariantFetch(graph_->GetIntConstant(1 << value)));
+ } else if (t == Primitive::kPrimLong && 0 <= value && value < 63) {
+ return TransferMul(a, NewInvariantFetch(graph_->GetLongConstant(1L << value)));
+ }
}
}
return nullptr;
}
HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferNeg(InductionInfo* a) {
- // Transfer over a unary negation: invariant or linear input
- // yields a similar, but negated result.
+ // Transfer over a unary negation: an invariant, linear, wrap-around, or periodic input
+ // yields a similar but negated induction as result.
if (a != nullptr) {
if (a->induction_class == kInvariant) {
- return NewInductionInfo(kInvariant, kNeg, nullptr, a, nullptr);
- } else if (a->induction_class == kLinear) {
- return NewInductionInfo(
- kLinear,
- kNop,
- NewInductionInfo(kInvariant, kNeg, nullptr, a->op_a, nullptr),
- NewInductionInfo(kInvariant, kNeg, nullptr, a->op_b, nullptr),
- nullptr);
+ return NewInvariantOp(kNeg, nullptr, a);
}
+ return NewInduction(a->induction_class, TransferNeg(a->op_a), TransferNeg(a->op_b));
}
return nullptr;
}
-HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferCycleOverPhi(HInstruction* phi) {
- // Transfer within a cycle over a phi: only identical inputs
- // can be combined into that input as result.
- const size_t count = phi->InputCount();
- CHECK_GT(count, 0u);
- auto ita = cycle_.find(phi->InputAt(0)->GetId());
+HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolvePhi(HLoopInformation* loop,
+ HInstruction* phi,
+ HInstruction* instruction) {
+ // Solve within a cycle over a phi: identical inputs are combined into that input as result.
+ const size_t count = instruction->InputCount();
+ DCHECK_GT(count, 0u);
+ auto ita = cycle_.find(instruction->InputAt(0));
if (ita != cycle_.end()) {
InductionInfo* a = ita->second;
for (size_t i = 1; i < count; i++) {
- auto itb = cycle_.find(phi->InputAt(i)->GetId());
- if (itb == cycle_.end() ||!HInductionVarAnalysis::InductionEqual(a, itb->second)) {
+ auto itb = cycle_.find(instruction->InputAt(i));
+ if (itb == cycle_.end() || !HInductionVarAnalysis::InductionEqual(a, itb->second)) {
return nullptr;
}
}
return a;
}
+
+ // Solve within a cycle over another entry-phi: add invariants into a periodic.
+ if (IsEntryPhi(loop, instruction)) {
+ InductionInfo* a = LookupInfo(loop, instruction->InputAt(0));
+ if (a != nullptr && a->induction_class == kInvariant) {
+ if (instruction->InputAt(1) == phi) {
+ InductionInfo* initial = LookupInfo(loop, phi->InputAt(0));
+ return NewInduction(kPeriodic, a, initial);
+ }
+ auto it = cycle_.find(instruction->InputAt(1));
+ if (it != cycle_.end()) {
+ InductionInfo* b = it->second;
+ if (b->induction_class == kPeriodic) {
+ return NewInduction(kPeriodic, a, b);
+ }
+ }
+ }
+ }
+
return nullptr;
}
-HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferCycleOverAddSub(
- HLoopInformation* loop,
- HInstruction* x,
- HInstruction* y,
- InductionOp op,
- bool first) {
- // Transfer within a cycle over an addition or subtraction: adding or
- // subtracting an invariant value adds to the stride of the induction,
- // starting with the phi value denoted by the unusual nullptr value.
- auto it = cycle_.find(x->GetId());
- if (it != cycle_.end()) {
- InductionInfo* a = it->second;
- InductionInfo* b = LookupInfo(loop, y);
- if (b != nullptr && b->induction_class == kInvariant) {
- if (a == nullptr) {
- if (op == kSub) { // negation required
- return NewInductionInfo(kInvariant, kNeg, nullptr, b, nullptr);
- }
- return b;
- } else if (a->induction_class == kInvariant) {
- return NewInductionInfo(kInvariant, op, a, b, nullptr);
+HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolveAddSub(HLoopInformation* loop,
+ HInstruction* phi,
+ HInstruction* instruction,
+ HInstruction* x,
+ HInstruction* y,
+ InductionOp op,
+ bool is_first_call) {
+ // Solve within a cycle over an addition or subtraction: adding or subtracting an
+ // invariant value, seeded from phi, keeps adding to the stride of the induction.
+ InductionInfo* b = LookupInfo(loop, y);
+ if (b != nullptr && b->induction_class == kInvariant) {
+ if (x == phi) {
+ return (op == kAdd) ? b : NewInvariantOp(kNeg, nullptr, b);
+ }
+ auto it = cycle_.find(x);
+ if (it != cycle_.end()) {
+ InductionInfo* a = it->second;
+ if (a->induction_class == kInvariant) {
+ return NewInvariantOp(op, a, b);
}
}
}
- // On failure, try alternatives.
+
+ // Try some alternatives before failing.
if (op == kAdd) {
- // Try the other way around for an addition.
- if (first) {
- return TransferCycleOverAddSub(loop, y, x, op, false);
+ // Try the other way around for an addition if considered for first time.
+ if (is_first_call) {
+ return SolveAddSub(loop, phi, instruction, y, x, op, false);
+ }
+ } else if (op == kSub) {
+ // Solve within a tight cycle for a periodic idiom k = c - k;
+ if (y == phi && instruction == phi->InputAt(1)) {
+ InductionInfo* a = LookupInfo(loop, x);
+ if (a != nullptr && a->induction_class == kInvariant) {
+ InductionInfo* initial = LookupInfo(loop, phi->InputAt(0));
+ return NewInduction(kPeriodic, NewInvariantOp(kSub, a, initial), initial);
+ }
}
}
+
return nullptr;
}
-void HInductionVarAnalysis::PutInfo(int loop_id, int id, InductionInfo* info) {
- auto it = induction_.find(loop_id);
+void HInductionVarAnalysis::AssignInfo(HLoopInformation* loop,
+ HInstruction* instruction,
+ InductionInfo* info) {
+ auto it = induction_.find(loop);
if (it == induction_.end()) {
- it = induction_.Put(
- loop_id, ArenaSafeMap<int, InductionInfo*>(std::less<int>(), graph_->GetArena()->Adapter()));
+ it = induction_.Put(loop,
+ ArenaSafeMap<HInstruction*, InductionInfo*>(
+ std::less<HInstruction*>(), graph_->GetArena()->Adapter()));
}
- it->second.Overwrite(id, info);
+ it->second.Put(instruction, info);
}
-HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::GetInfo(int loop_id, int id) {
- auto it = induction_.find(loop_id);
+HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::LookupInfo(HLoopInformation* loop,
+ HInstruction* instruction) {
+ auto it = induction_.find(loop);
if (it != induction_.end()) {
- auto loop_it = it->second.find(id);
+ auto loop_it = it->second.find(instruction);
if (loop_it != it->second.end()) {
return loop_it->second;
}
}
- return nullptr;
-}
-
-void HInductionVarAnalysis::AssignInfo(HLoopInformation* loop,
- HInstruction* instruction,
- InductionInfo* info) {
- const int loopId = loop->GetHeader()->GetBlockId();
- const int id = instruction->GetId();
- PutInfo(loopId, id, info);
-}
-
-HInductionVarAnalysis::InductionInfo*
-HInductionVarAnalysis::LookupInfo(HLoopInformation* loop,
- HInstruction* instruction) {
- const int loop_id = loop->GetHeader()->GetBlockId();
- const int id = instruction->GetId();
- InductionInfo* info = GetInfo(loop_id, id);
- if (info == nullptr && IsLoopInvariant(loop, instruction)) {
- info = NewInductionInfo(kInvariant, kFetch, nullptr, nullptr, instruction);
- PutInfo(loop_id, id, info);
+ if (IsLoopInvariant(loop, instruction)) {
+ InductionInfo* info = NewInvariantFetch(instruction);
+ AssignInfo(loop, instruction, info);
+ return info;
}
- return info;
+ return nullptr;
}
bool HInductionVarAnalysis::InductionEqual(InductionInfo* info1,
@@ -446,21 +537,21 @@ std::string HInductionVarAnalysis::InductionToString(InductionInfo* info) {
std::string inv = "(";
inv += InductionToString(info->op_a);
switch (info->operation) {
- case kNop: inv += " ? "; break;
- case kAdd: inv += " + "; break;
+ case kNop: inv += " @ "; break;
+ case kAdd: inv += " + "; break;
case kSub:
- case kNeg: inv += " - "; break;
- case kMul: inv += " * "; break;
- case kDiv: inv += " / "; break;
+ case kNeg: inv += " - "; break;
+ case kMul: inv += " * "; break;
+ case kDiv: inv += " / "; break;
case kFetch:
- CHECK(info->fetch != nullptr);
- inv += std::to_string(info->fetch->GetId()) + ":" + info->fetch->DebugName();
+ DCHECK(info->fetch);
+ inv += InstructionToString(info->fetch);
break;
}
inv += InductionToString(info->op_b);
return inv + ")";
} else {
- CHECK(info->operation == kNop);
+ DCHECK(info->operation == kNop);
if (info->induction_class == kLinear) {
return "(" + InductionToString(info->op_a) + " * i + " +
InductionToString(info->op_b) + ")";