blob: 09a0a380a1190e4ee17b6db8a32835ac86e9b71c [file] [log] [blame]
Aart Bik30efb4e2015-07-30 12:14:31 -07001/*
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#ifndef ART_COMPILER_OPTIMIZING_INDUCTION_VAR_ANALYSIS_H_
18#define ART_COMPILER_OPTIMIZING_INDUCTION_VAR_ANALYSIS_H_
19
20#include <string>
21
22#include "nodes.h"
23#include "optimization.h"
24
25namespace art {
26
27/**
28 * Induction variable analysis.
29 *
30 * Based on the paper by M. Gerlek et al.
31 * "Beyond Induction Variables: Detecting and Classifying Sequences Using a Demand-Driven SSA Form"
32 * (ACM Transactions on Programming Languages and Systems, Volume 17 Issue 1, Jan. 1995).
33 */
34class HInductionVarAnalysis : public HOptimization {
35 public:
36 explicit HInductionVarAnalysis(HGraph* graph);
37
38 // TODO: design public API useful in later phases
39
40 /**
41 * Returns string representation of induction found for the instruction
42 * in the given loop (for testing and debugging only).
43 */
44 std::string InductionToString(HLoopInformation* loop, HInstruction* instruction) {
45 return InductionToString(LookupInfo(loop, instruction));
46 }
47
48 void Run() OVERRIDE;
49
50 private:
51 static constexpr const char* kInductionPassName = "induction_var_analysis";
52
53 struct NodeInfo {
54 explicit NodeInfo(uint32_t d) : depth(d), done(false) {}
55 uint32_t depth;
56 bool done;
57 };
58
59 enum InductionClass {
60 kNone,
61 kInvariant,
62 kLinear,
63 kWrapAround,
64 kPeriodic,
65 kMonotonic
66 };
67
68 enum InductionOp {
69 kNop, // no-operation: a true induction
70 kAdd,
71 kSub,
72 kNeg,
73 kMul,
74 kDiv,
75 kFetch
76 };
77
78 /**
79 * Defines a detected induction as:
80 * (1) invariant:
81 * operation: a + b, a - b, -b, a * b, a / b
82 * or
83 * fetch: fetch from HIR
84 * (2) linear:
85 * nop: a * i + b
86 * (3) wrap-around
87 * nop: a, then defined by b
88 * (4) periodic
89 * nop: a, then defined by b (repeated when exhausted)
90 * (5) monotonic
91 * // TODO: determine representation
92 */
93 struct InductionInfo : public ArenaObject<kArenaAllocMisc> {
94 InductionInfo(InductionClass ic,
95 InductionOp op,
96 InductionInfo* a,
97 InductionInfo* b,
98 HInstruction* f)
99 : induction_class(ic),
100 operation(op),
101 op_a(a),
102 op_b(b),
103 fetch(f) {}
104 InductionClass induction_class;
105 InductionOp operation;
106 InductionInfo* op_a;
107 InductionInfo* op_b;
108 HInstruction* fetch;
109 };
110
111 inline bool IsVisitedNode(int id) const {
112 return map_.find(id) != map_.end();
113 }
114
115 inline InductionInfo* NewInductionInfo(
116 InductionClass c,
117 InductionOp op,
118 InductionInfo* a,
119 InductionInfo* b,
120 HInstruction* i) {
121 return new (graph_->GetArena()) InductionInfo(c, op, a, b, i);
122 }
123
124 // Methods for analysis.
125 void VisitLoop(HLoopInformation* loop);
126 void VisitNode(HLoopInformation* loop, HInstruction* instruction);
127 uint32_t VisitDescendant(HLoopInformation* loop, HInstruction* instruction);
128 void ClassifyTrivial(HLoopInformation* loop, HInstruction* instruction);
129 void ClassifyNonTrivial(HLoopInformation* loop);
130
131 // Transfer operations.
132 InductionInfo* TransferPhi(InductionInfo* a, InductionInfo* b);
133 InductionInfo* TransferAddSub(InductionInfo* a, InductionInfo* b, InductionOp op);
134 InductionInfo* TransferMul(InductionInfo* a, InductionInfo* b);
135 InductionInfo* TransferNeg(InductionInfo* a);
136 InductionInfo* TransferCycleOverPhi(HInstruction* phi);
137 InductionInfo* TransferCycleOverAddSub(HLoopInformation* loop,
138 HInstruction* x,
139 HInstruction* y,
140 InductionOp op,
141 bool first);
142
143 // Assign and lookup.
144 void PutInfo(int loop_id, int id, InductionInfo* info);
145 InductionInfo* GetInfo(int loop_id, int id);
146 void AssignInfo(HLoopInformation* loop, HInstruction* instruction, InductionInfo* info);
147 InductionInfo* LookupInfo(HLoopInformation* loop, HInstruction* instruction);
148 bool InductionEqual(InductionInfo* info1, InductionInfo* info2);
149 std::string InductionToString(InductionInfo* info);
150
151 // Bookkeeping during and after analysis.
152 // TODO: fine tune data structures, only keep relevant data
153
154 uint32_t global_depth_;
155
156 ArenaVector<HInstruction*> stack_;
157 ArenaVector<HInstruction*> scc_;
158
159 // Mappings of instruction id to node and induction information.
160 ArenaSafeMap<int, NodeInfo> map_;
161 ArenaSafeMap<int, InductionInfo*> cycle_;
162
163 // Mapping from loop id to mapping of instruction id to induction information.
164 ArenaSafeMap<int, ArenaSafeMap<int, InductionInfo*>> induction_;
165
166 DISALLOW_COPY_AND_ASSIGN(HInductionVarAnalysis);
167};
168
169} // namespace art
170
171#endif // ART_COMPILER_OPTIMIZING_INDUCTION_VAR_ANALYSIS_H_