blob: 0d0443176293cdbab0f247489e6b1b7251c984cd [file] [log] [blame]
Aart Bikd14c5952015-09-08 15:25:15 -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
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070017#include "induction_var_range.h"
18
Aart Bikd14c5952015-09-08 15:25:15 -070019#include "base/arena_allocator.h"
Vladimir Markoe2727152019-10-10 10:46:42 +010020#include "base/macros.h"
Aart Bikd14c5952015-09-08 15:25:15 -070021#include "builder.h"
Aart Bikd14c5952015-09-08 15:25:15 -070022#include "induction_var_analysis.h"
Aart Bikd14c5952015-09-08 15:25:15 -070023#include "nodes.h"
24#include "optimizing_unit_test.h"
25
Vladimir Markoe2727152019-10-10 10:46:42 +010026namespace art HIDDEN {
Aart Bikd14c5952015-09-08 15:25:15 -070027
28using Value = InductionVarRange::Value;
29
30/**
31 * Fixture class for the InductionVarRange tests.
32 */
Vladimir Markoca6fff82017-10-03 14:49:14 +010033class InductionVarRangeTest : public OptimizingUnitTest {
Aart Bikd14c5952015-09-08 15:25:15 -070034 public:
Aart Bik7d57d7f2015-12-09 14:39:48 -080035 InductionVarRangeTest()
Vladimir Markoca6fff82017-10-03 14:49:14 +010036 : graph_(CreateGraph()),
37 iva_(new (GetAllocator()) HInductionVarAnalysis(graph_)),
Aart Bik7d57d7f2015-12-09 14:39:48 -080038 range_(iva_) {
Aart Bikd14c5952015-09-08 15:25:15 -070039 BuildGraph();
40 }
41
42 ~InductionVarRangeTest() { }
43
44 void ExpectEqual(Value v1, Value v2) {
45 EXPECT_EQ(v1.instruction, v2.instruction);
46 EXPECT_EQ(v1.a_constant, v2.a_constant);
47 EXPECT_EQ(v1.b_constant, v2.b_constant);
Aart Bikb3365e02015-09-21 14:45:05 -070048 EXPECT_EQ(v1.is_known, v2.is_known);
Aart Bikd14c5952015-09-08 15:25:15 -070049 }
50
Aart Bik8e02e3e2017-02-28 14:41:55 -080051 void ExpectInt(int32_t value, HInstruction* i) {
52 ASSERT_TRUE(i->IsIntConstant());
53 EXPECT_EQ(value, i->AsIntConstant()->GetValue());
54 }
55
Aart Bik389b3db2015-10-28 14:23:40 -070056 //
57 // Construction methods.
58 //
59
Aart Bikd14c5952015-09-08 15:25:15 -070060 /** Constructs bare minimum graph. */
61 void BuildGraph() {
62 graph_->SetNumberOfVRegs(1);
Vladimir Markoca6fff82017-10-03 14:49:14 +010063 entry_block_ = new (GetAllocator()) HBasicBlock(graph_);
64 exit_block_ = new (GetAllocator()) HBasicBlock(graph_);
Aart Bikaec3cce2015-10-14 17:44:55 -070065 graph_->AddBlock(entry_block_);
66 graph_->AddBlock(exit_block_);
67 graph_->SetEntryBlock(entry_block_);
68 graph_->SetExitBlock(exit_block_);
Aart Bik7d57d7f2015-12-09 14:39:48 -080069 // Two parameters.
Vladimir Markoca6fff82017-10-03 14:49:14 +010070 x_ = new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
71 dex::TypeIndex(0),
72 0,
73 DataType::Type::kInt32);
Aart Bik7d57d7f2015-12-09 14:39:48 -080074 entry_block_->AddInstruction(x_);
Vladimir Markoca6fff82017-10-03 14:49:14 +010075 y_ = new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
76 dex::TypeIndex(0),
77 0,
78 DataType::Type::kInt32);
Aart Bik7d57d7f2015-12-09 14:39:48 -080079 entry_block_->AddInstruction(y_);
Aart Bik52be7e72016-06-23 11:20:41 -070080 // Set arbitrary range analysis hint while testing private methods.
81 SetHint(x_);
Aart Bikaec3cce2015-10-14 17:44:55 -070082 }
83
84 /** Constructs loop with given upper bound. */
Aart Bik389b3db2015-10-28 14:23:40 -070085 void BuildLoop(int32_t lower, HInstruction* upper, int32_t stride) {
Aart Bikaec3cce2015-10-14 17:44:55 -070086 // Control flow.
Vladimir Markoca6fff82017-10-03 14:49:14 +010087 loop_preheader_ = new (GetAllocator()) HBasicBlock(graph_);
Aart Bikaec3cce2015-10-14 17:44:55 -070088 graph_->AddBlock(loop_preheader_);
Vladimir Markoca6fff82017-10-03 14:49:14 +010089 loop_header_ = new (GetAllocator()) HBasicBlock(graph_);
Aart Bik16d3a652016-09-09 10:33:50 -070090 graph_->AddBlock(loop_header_);
Vladimir Markoca6fff82017-10-03 14:49:14 +010091 loop_body_ = new (GetAllocator()) HBasicBlock(graph_);
Aart Bik16d3a652016-09-09 10:33:50 -070092 graph_->AddBlock(loop_body_);
Vladimir Markoca6fff82017-10-03 14:49:14 +010093 HBasicBlock* return_block = new (GetAllocator()) HBasicBlock(graph_);
David Brazdildb51efb2015-11-06 01:36:20 +000094 graph_->AddBlock(return_block);
Aart Bikaec3cce2015-10-14 17:44:55 -070095 entry_block_->AddSuccessor(loop_preheader_);
Aart Bik16d3a652016-09-09 10:33:50 -070096 loop_preheader_->AddSuccessor(loop_header_);
97 loop_header_->AddSuccessor(loop_body_);
98 loop_header_->AddSuccessor(return_block);
99 loop_body_->AddSuccessor(loop_header_);
David Brazdildb51efb2015-11-06 01:36:20 +0000100 return_block->AddSuccessor(exit_block_);
Aart Bikaec3cce2015-10-14 17:44:55 -0700101 // Instructions.
Vladimir Markoca6fff82017-10-03 14:49:14 +0100102 loop_preheader_->AddInstruction(new (GetAllocator()) HGoto());
103 HPhi* phi = new (GetAllocator()) HPhi(GetAllocator(), 0, 0, DataType::Type::kInt32);
Aart Bik16d3a652016-09-09 10:33:50 -0700104 loop_header_->AddPhi(phi);
David Brazdilbadd8262016-02-02 16:28:56 +0000105 phi->AddInput(graph_->GetIntConstant(lower)); // i = l
Aart Bik389b3db2015-10-28 14:23:40 -0700106 if (stride > 0) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100107 condition_ = new (GetAllocator()) HLessThan(phi, upper); // i < u
Aart Bik389b3db2015-10-28 14:23:40 -0700108 } else {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100109 condition_ = new (GetAllocator()) HGreaterThan(phi, upper); // i > u
Aart Bik389b3db2015-10-28 14:23:40 -0700110 }
Aart Bik16d3a652016-09-09 10:33:50 -0700111 loop_header_->AddInstruction(condition_);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100112 loop_header_->AddInstruction(new (GetAllocator()) HIf(condition_));
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100113 increment_ =
Vladimir Markoca6fff82017-10-03 14:49:14 +0100114 new (GetAllocator()) HAdd(DataType::Type::kInt32, phi, graph_->GetIntConstant(stride));
Aart Bik16d3a652016-09-09 10:33:50 -0700115 loop_body_->AddInstruction(increment_); // i += s
David Brazdilbadd8262016-02-02 16:28:56 +0000116 phi->AddInput(increment_);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100117 loop_body_->AddInstruction(new (GetAllocator()) HGoto());
118 return_block->AddInstruction(new (GetAllocator()) HReturnVoid());
119 exit_block_->AddInstruction(new (GetAllocator()) HExit());
Aart Bikaec3cce2015-10-14 17:44:55 -0700120 }
121
Aart Bik7d57d7f2015-12-09 14:39:48 -0800122 /** Constructs SSA and performs induction variable analysis. */
Aart Bikaec3cce2015-10-14 17:44:55 -0700123 void PerformInductionVarAnalysis() {
David Brazdilbadd8262016-02-02 16:28:56 +0000124 graph_->BuildDominatorTree();
Aart Bikaec3cce2015-10-14 17:44:55 -0700125 iva_->Run();
Aart Bikd14c5952015-09-08 15:25:15 -0700126 }
127
Aart Bik52be7e72016-06-23 11:20:41 -0700128 /** Sets hint. */
129 void SetHint(HInstruction* hint) {
130 range_.chase_hint_ = hint;
131 }
132
Aart Bikd14c5952015-09-08 15:25:15 -0700133 /** Constructs an invariant. */
134 HInductionVarAnalysis::InductionInfo* CreateInvariant(char opc,
135 HInductionVarAnalysis::InductionInfo* a,
136 HInductionVarAnalysis::InductionInfo* b) {
137 HInductionVarAnalysis::InductionOp op;
138 switch (opc) {
139 case '+': op = HInductionVarAnalysis::kAdd; break;
140 case '-': op = HInductionVarAnalysis::kSub; break;
141 case 'n': op = HInductionVarAnalysis::kNeg; break;
142 case '*': op = HInductionVarAnalysis::kMul; break;
143 case '/': op = HInductionVarAnalysis::kDiv; break;
Aart Bikdf7822e2016-12-06 10:05:30 -0800144 case '%': op = HInductionVarAnalysis::kRem; break;
145 case '^': op = HInductionVarAnalysis::kXor; break;
Aart Bik52be7e72016-06-23 11:20:41 -0700146 case '<': op = HInductionVarAnalysis::kLT; break;
Aart Bikd14c5952015-09-08 15:25:15 -0700147 default: op = HInductionVarAnalysis::kNop; break;
148 }
149 return iva_->CreateInvariantOp(op, a, b);
150 }
151
152 /** Constructs a fetch. */
153 HInductionVarAnalysis::InductionInfo* CreateFetch(HInstruction* fetch) {
154 return iva_->CreateInvariantFetch(fetch);
155 }
156
157 /** Constructs a constant. */
158 HInductionVarAnalysis::InductionInfo* CreateConst(int32_t c) {
159 return CreateFetch(graph_->GetIntConstant(c));
160 }
161
Aart Bik52be7e72016-06-23 11:20:41 -0700162 /** Constructs a constant trip-count. */
Aart Bik389b3db2015-10-28 14:23:40 -0700163 HInductionVarAnalysis::InductionInfo* CreateTripCount(int32_t tc, bool in_loop, bool safe) {
Aart Bik52be7e72016-06-23 11:20:41 -0700164 HInductionVarAnalysis::InductionOp op = HInductionVarAnalysis::kTripCountInBodyUnsafe;
Aart Bik389b3db2015-10-28 14:23:40 -0700165 if (in_loop && safe) {
Aart Bik52be7e72016-06-23 11:20:41 -0700166 op = HInductionVarAnalysis::kTripCountInLoop;
Aart Bik389b3db2015-10-28 14:23:40 -0700167 } else if (in_loop) {
Aart Bik52be7e72016-06-23 11:20:41 -0700168 op = HInductionVarAnalysis::kTripCountInLoopUnsafe;
Aart Bik389b3db2015-10-28 14:23:40 -0700169 } else if (safe) {
Aart Bik52be7e72016-06-23 11:20:41 -0700170 op = HInductionVarAnalysis::kTripCountInBody;
Aart Bik389b3db2015-10-28 14:23:40 -0700171 }
Aart Bik52be7e72016-06-23 11:20:41 -0700172 // Return TC with taken-test 0 < TC.
173 return iva_->CreateTripCount(op,
174 CreateConst(tc),
175 CreateInvariant('<', CreateConst(0), CreateConst(tc)),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100176 DataType::Type::kInt32);
Aart Bikd14c5952015-09-08 15:25:15 -0700177 }
178
179 /** Constructs a linear a * i + b induction. */
180 HInductionVarAnalysis::InductionInfo* CreateLinear(int32_t a, int32_t b) {
Aart Bikc071a012016-12-01 10:22:31 -0800181 return iva_->CreateInduction(HInductionVarAnalysis::kLinear,
182 HInductionVarAnalysis::kNop,
183 CreateConst(a),
184 CreateConst(b),
185 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100186 DataType::Type::kInt32);
Aart Bikc071a012016-12-01 10:22:31 -0800187 }
188
Aart Bikdf7822e2016-12-06 10:05:30 -0800189 /** Constructs a polynomial sum(a * i + b) + c induction. */
190 HInductionVarAnalysis::InductionInfo* CreatePolynomial(int32_t a, int32_t b, int32_t c) {
191 return iva_->CreateInduction(HInductionVarAnalysis::kPolynomial,
192 HInductionVarAnalysis::kNop,
193 CreateLinear(a, b),
194 CreateConst(c),
195 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100196 DataType::Type::kInt32);
Aart Bikdf7822e2016-12-06 10:05:30 -0800197 }
198
Aart Bikc071a012016-12-01 10:22:31 -0800199 /** Constructs a geometric a * f^i + b induction. */
200 HInductionVarAnalysis::InductionInfo* CreateGeometric(int32_t a, int32_t b, int32_t f, char op) {
201 return iva_->CreateInduction(HInductionVarAnalysis::kGeometric,
Aart Bikdf7822e2016-12-06 10:05:30 -0800202 op == '*' ? HInductionVarAnalysis::kMul
203 : HInductionVarAnalysis::kDiv,
Aart Bikc071a012016-12-01 10:22:31 -0800204 CreateConst(a),
205 CreateConst(b),
206 graph_->GetIntConstant(f),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100207 DataType::Type::kInt32);
Aart Bikd14c5952015-09-08 15:25:15 -0700208 }
209
210 /** Constructs a range [lo, hi] using a periodic induction. */
211 HInductionVarAnalysis::InductionInfo* CreateRange(int32_t lo, int32_t hi) {
Aart Bikc071a012016-12-01 10:22:31 -0800212 return iva_->CreateInduction(HInductionVarAnalysis::kPeriodic,
213 HInductionVarAnalysis::kNop,
214 CreateConst(lo),
215 CreateConst(hi),
216 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100217 DataType::Type::kInt32);
Aart Bikd14c5952015-09-08 15:25:15 -0700218 }
219
Aart Bikdf7822e2016-12-06 10:05:30 -0800220 /** Constructs a wrap-around induction consisting of a constant, followed by info. */
Aart Bik389b3db2015-10-28 14:23:40 -0700221 HInductionVarAnalysis::InductionInfo* CreateWrapAround(
222 int32_t initial,
223 HInductionVarAnalysis::InductionInfo* info) {
Aart Bikc071a012016-12-01 10:22:31 -0800224 return iva_->CreateInduction(HInductionVarAnalysis::kWrapAround,
225 HInductionVarAnalysis::kNop,
226 CreateConst(initial),
227 info,
228 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100229 DataType::Type::kInt32);
Aart Bik389b3db2015-10-28 14:23:40 -0700230 }
231
Aart Bikd14c5952015-09-08 15:25:15 -0700232 /** Constructs a wrap-around induction consisting of a constant, followed by a range. */
233 HInductionVarAnalysis::InductionInfo* CreateWrapAround(int32_t initial, int32_t lo, int32_t hi) {
Aart Bik389b3db2015-10-28 14:23:40 -0700234 return CreateWrapAround(initial, CreateRange(lo, hi));
Aart Bikd14c5952015-09-08 15:25:15 -0700235 }
236
237 //
238 // Relay methods.
239 //
240
Aart Bik389b3db2015-10-28 14:23:40 -0700241 bool NeedsTripCount(HInductionVarAnalysis::InductionInfo* info) {
Aart Bik16d3a652016-09-09 10:33:50 -0700242 int64_t s = 0;
243 return range_.NeedsTripCount(info, &s);
Aart Bik389b3db2015-10-28 14:23:40 -0700244 }
245
246 bool IsBodyTripCount(HInductionVarAnalysis::InductionInfo* trip) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800247 return range_.IsBodyTripCount(trip);
Aart Bik389b3db2015-10-28 14:23:40 -0700248 }
249
250 bool IsUnsafeTripCount(HInductionVarAnalysis::InductionInfo* trip) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800251 return range_.IsUnsafeTripCount(trip);
Aart Bik389b3db2015-10-28 14:23:40 -0700252 }
253
Aart Bikd14c5952015-09-08 15:25:15 -0700254 Value GetMin(HInductionVarAnalysis::InductionInfo* info,
Aart Bik52be7e72016-06-23 11:20:41 -0700255 HInductionVarAnalysis::InductionInfo* trip) {
Andreas Gampe3db70682018-12-26 15:12:03 -0800256 return range_.GetVal(info, trip, /* in_body= */ true, /* is_min= */ true);
Aart Bikd14c5952015-09-08 15:25:15 -0700257 }
258
259 Value GetMax(HInductionVarAnalysis::InductionInfo* info,
Aart Bik52be7e72016-06-23 11:20:41 -0700260 HInductionVarAnalysis::InductionInfo* trip) {
Andreas Gampe3db70682018-12-26 15:12:03 -0800261 return range_.GetVal(info, trip, /* in_body= */ true, /* is_min= */ false);
Aart Bikd14c5952015-09-08 15:25:15 -0700262 }
263
264 Value GetMul(HInductionVarAnalysis::InductionInfo* info1,
Aart Bikb3365e02015-09-21 14:45:05 -0700265 HInductionVarAnalysis::InductionInfo* info2,
266 bool is_min) {
Andreas Gampe3db70682018-12-26 15:12:03 -0800267 return range_.GetMul(info1, info2, nullptr, /* in_body= */ true, is_min);
Aart Bikd14c5952015-09-08 15:25:15 -0700268 }
269
270 Value GetDiv(HInductionVarAnalysis::InductionInfo* info1,
Aart Bikb3365e02015-09-21 14:45:05 -0700271 HInductionVarAnalysis::InductionInfo* info2,
272 bool is_min) {
Andreas Gampe3db70682018-12-26 15:12:03 -0800273 return range_.GetDiv(info1, info2, nullptr, /* in_body= */ true, is_min);
Aart Bik9401f532015-09-28 16:25:56 -0700274 }
275
Aart Bikdf7822e2016-12-06 10:05:30 -0800276 Value GetRem(HInductionVarAnalysis::InductionInfo* info1,
277 HInductionVarAnalysis::InductionInfo* info2) {
278 return range_.GetRem(info1, info2);
279 }
280
281 Value GetXor(HInductionVarAnalysis::InductionInfo* info1,
282 HInductionVarAnalysis::InductionInfo* info2) {
283 return range_.GetXor(info1, info2);
284 }
285
Aart Bik97412c922016-02-19 20:14:38 -0800286 bool IsExact(HInductionVarAnalysis::InductionInfo* info, int64_t* value) {
287 return range_.IsConstant(info, InductionVarRange::kExact, value);
288 }
289
290 bool IsAtMost(HInductionVarAnalysis::InductionInfo* info, int64_t* value) {
291 return range_.IsConstant(info, InductionVarRange::kAtMost, value);
292 }
293
294 bool IsAtLeast(HInductionVarAnalysis::InductionInfo* info, int64_t* value) {
295 return range_.IsConstant(info, InductionVarRange::kAtLeast, value);
Aart Bikd14c5952015-09-08 15:25:15 -0700296 }
297
Aart Bik7d57d7f2015-12-09 14:39:48 -0800298 Value AddValue(Value v1, Value v2) { return range_.AddValue(v1, v2); }
299 Value SubValue(Value v1, Value v2) { return range_.SubValue(v1, v2); }
300 Value MulValue(Value v1, Value v2) { return range_.MulValue(v1, v2); }
301 Value DivValue(Value v1, Value v2) { return range_.DivValue(v1, v2); }
302 Value MinValue(Value v1, Value v2) { return range_.MergeVal(v1, v2, true); }
303 Value MaxValue(Value v1, Value v2) { return range_.MergeVal(v1, v2, false); }
Aart Bikd14c5952015-09-08 15:25:15 -0700304
305 // General building fields.
Aart Bikd14c5952015-09-08 15:25:15 -0700306 HGraph* graph_;
Aart Bikaec3cce2015-10-14 17:44:55 -0700307 HBasicBlock* entry_block_;
308 HBasicBlock* exit_block_;
309 HBasicBlock* loop_preheader_;
Aart Bik16d3a652016-09-09 10:33:50 -0700310 HBasicBlock* loop_header_;
311 HBasicBlock* loop_body_;
Aart Bikd14c5952015-09-08 15:25:15 -0700312 HInductionVarAnalysis* iva_;
Aart Bik7d57d7f2015-12-09 14:39:48 -0800313 InductionVarRange range_;
Aart Bikd14c5952015-09-08 15:25:15 -0700314
Aart Bikaec3cce2015-10-14 17:44:55 -0700315 // Instructions.
316 HInstruction* condition_;
317 HInstruction* increment_;
Aart Bik7d57d7f2015-12-09 14:39:48 -0800318 HInstruction* x_;
319 HInstruction* y_;
Aart Bikd14c5952015-09-08 15:25:15 -0700320};
321
322//
Aart Bik7d57d7f2015-12-09 14:39:48 -0800323// Tests on private methods.
Aart Bikd14c5952015-09-08 15:25:15 -0700324//
325
Aart Bik97412c922016-02-19 20:14:38 -0800326TEST_F(InductionVarRangeTest, IsConstant) {
327 int64_t value;
328 // Constant.
329 EXPECT_TRUE(IsExact(CreateConst(12345), &value));
330 EXPECT_EQ(12345, value);
331 EXPECT_TRUE(IsAtMost(CreateConst(12345), &value));
332 EXPECT_EQ(12345, value);
333 EXPECT_TRUE(IsAtLeast(CreateConst(12345), &value));
334 EXPECT_EQ(12345, value);
335 // Constant trivial range.
336 EXPECT_TRUE(IsExact(CreateRange(111, 111), &value));
337 EXPECT_EQ(111, value);
338 EXPECT_TRUE(IsAtMost(CreateRange(111, 111), &value));
339 EXPECT_EQ(111, value);
340 EXPECT_TRUE(IsAtLeast(CreateRange(111, 111), &value));
341 EXPECT_EQ(111, value);
342 // Constant non-trivial range.
343 EXPECT_FALSE(IsExact(CreateRange(11, 22), &value));
344 EXPECT_TRUE(IsAtMost(CreateRange(11, 22), &value));
345 EXPECT_EQ(22, value);
346 EXPECT_TRUE(IsAtLeast(CreateRange(11, 22), &value));
347 EXPECT_EQ(11, value);
348 // Symbolic.
349 EXPECT_FALSE(IsExact(CreateFetch(x_), &value));
350 EXPECT_FALSE(IsAtMost(CreateFetch(x_), &value));
351 EXPECT_FALSE(IsAtLeast(CreateFetch(x_), &value));
352}
353
Aart Bik389b3db2015-10-28 14:23:40 -0700354TEST_F(InductionVarRangeTest, TripCountProperties) {
355 EXPECT_FALSE(NeedsTripCount(nullptr));
356 EXPECT_FALSE(NeedsTripCount(CreateConst(1)));
357 EXPECT_TRUE(NeedsTripCount(CreateLinear(1, 1)));
358 EXPECT_FALSE(NeedsTripCount(CreateWrapAround(1, 2, 3)));
359 EXPECT_TRUE(NeedsTripCount(CreateWrapAround(1, CreateLinear(1, 1))));
360
361 EXPECT_FALSE(IsBodyTripCount(nullptr));
362 EXPECT_FALSE(IsBodyTripCount(CreateTripCount(100, true, true)));
363 EXPECT_FALSE(IsBodyTripCount(CreateTripCount(100, true, false)));
364 EXPECT_TRUE(IsBodyTripCount(CreateTripCount(100, false, true)));
365 EXPECT_TRUE(IsBodyTripCount(CreateTripCount(100, false, false)));
366
367 EXPECT_FALSE(IsUnsafeTripCount(nullptr));
368 EXPECT_FALSE(IsUnsafeTripCount(CreateTripCount(100, true, true)));
369 EXPECT_TRUE(IsUnsafeTripCount(CreateTripCount(100, true, false)));
370 EXPECT_FALSE(IsUnsafeTripCount(CreateTripCount(100, false, true)));
371 EXPECT_TRUE(IsUnsafeTripCount(CreateTripCount(100, false, false)));
372}
373
Aart Bikd14c5952015-09-08 15:25:15 -0700374TEST_F(InductionVarRangeTest, GetMinMaxNull) {
Aart Bikb3365e02015-09-21 14:45:05 -0700375 ExpectEqual(Value(), GetMin(nullptr, nullptr));
376 ExpectEqual(Value(), GetMax(nullptr, nullptr));
Aart Bikd14c5952015-09-08 15:25:15 -0700377}
378
379TEST_F(InductionVarRangeTest, GetMinMaxAdd) {
380 ExpectEqual(Value(12),
381 GetMin(CreateInvariant('+', CreateConst(2), CreateRange(10, 20)), nullptr));
382 ExpectEqual(Value(22),
383 GetMax(CreateInvariant('+', CreateConst(2), CreateRange(10, 20)), nullptr));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800384 ExpectEqual(Value(x_, 1, -20),
385 GetMin(CreateInvariant('+', CreateFetch(x_), CreateRange(-20, -10)), nullptr));
386 ExpectEqual(Value(x_, 1, -10),
387 GetMax(CreateInvariant('+', CreateFetch(x_), CreateRange(-20, -10)), nullptr));
388 ExpectEqual(Value(x_, 1, 10),
389 GetMin(CreateInvariant('+', CreateRange(10, 20), CreateFetch(x_)), nullptr));
390 ExpectEqual(Value(x_, 1, 20),
391 GetMax(CreateInvariant('+', CreateRange(10, 20), CreateFetch(x_)), nullptr));
Aart Bikd14c5952015-09-08 15:25:15 -0700392 ExpectEqual(Value(5),
393 GetMin(CreateInvariant('+', CreateRange(-5, -1), CreateRange(10, 20)), nullptr));
394 ExpectEqual(Value(19),
395 GetMax(CreateInvariant('+', CreateRange(-5, -1), CreateRange(10, 20)), nullptr));
396}
397
398TEST_F(InductionVarRangeTest, GetMinMaxSub) {
399 ExpectEqual(Value(-18),
400 GetMin(CreateInvariant('-', CreateConst(2), CreateRange(10, 20)), nullptr));
401 ExpectEqual(Value(-8),
402 GetMax(CreateInvariant('-', CreateConst(2), CreateRange(10, 20)), nullptr));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800403 ExpectEqual(Value(x_, 1, 10),
404 GetMin(CreateInvariant('-', CreateFetch(x_), CreateRange(-20, -10)), nullptr));
405 ExpectEqual(Value(x_, 1, 20),
406 GetMax(CreateInvariant('-', CreateFetch(x_), CreateRange(-20, -10)), nullptr));
407 ExpectEqual(Value(x_, -1, 10),
408 GetMin(CreateInvariant('-', CreateRange(10, 20), CreateFetch(x_)), nullptr));
409 ExpectEqual(Value(x_, -1, 20),
410 GetMax(CreateInvariant('-', CreateRange(10, 20), CreateFetch(x_)), nullptr));
Aart Bikd14c5952015-09-08 15:25:15 -0700411 ExpectEqual(Value(-25),
412 GetMin(CreateInvariant('-', CreateRange(-5, -1), CreateRange(10, 20)), nullptr));
413 ExpectEqual(Value(-11),
414 GetMax(CreateInvariant('-', CreateRange(-5, -1), CreateRange(10, 20)), nullptr));
415}
416
417TEST_F(InductionVarRangeTest, GetMinMaxNeg) {
418 ExpectEqual(Value(-20), GetMin(CreateInvariant('n', nullptr, CreateRange(10, 20)), nullptr));
419 ExpectEqual(Value(-10), GetMax(CreateInvariant('n', nullptr, CreateRange(10, 20)), nullptr));
420 ExpectEqual(Value(10), GetMin(CreateInvariant('n', nullptr, CreateRange(-20, -10)), nullptr));
421 ExpectEqual(Value(20), GetMax(CreateInvariant('n', nullptr, CreateRange(-20, -10)), nullptr));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800422 ExpectEqual(Value(x_, -1, 0), GetMin(CreateInvariant('n', nullptr, CreateFetch(x_)), nullptr));
423 ExpectEqual(Value(x_, -1, 0), GetMax(CreateInvariant('n', nullptr, CreateFetch(x_)), nullptr));
Aart Bikd14c5952015-09-08 15:25:15 -0700424}
425
426TEST_F(InductionVarRangeTest, GetMinMaxMul) {
427 ExpectEqual(Value(20),
428 GetMin(CreateInvariant('*', CreateConst(2), CreateRange(10, 20)), nullptr));
429 ExpectEqual(Value(40),
430 GetMax(CreateInvariant('*', CreateConst(2), CreateRange(10, 20)), nullptr));
431}
432
433TEST_F(InductionVarRangeTest, GetMinMaxDiv) {
434 ExpectEqual(Value(3),
435 GetMin(CreateInvariant('/', CreateRange(12, 20), CreateConst(4)), nullptr));
436 ExpectEqual(Value(5),
437 GetMax(CreateInvariant('/', CreateRange(12, 20), CreateConst(4)), nullptr));
438}
439
440TEST_F(InductionVarRangeTest, GetMinMaxConstant) {
441 ExpectEqual(Value(12345), GetMin(CreateConst(12345), nullptr));
442 ExpectEqual(Value(12345), GetMax(CreateConst(12345), nullptr));
443}
444
445TEST_F(InductionVarRangeTest, GetMinMaxFetch) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800446 ExpectEqual(Value(x_, 1, 0), GetMin(CreateFetch(x_), nullptr));
447 ExpectEqual(Value(x_, 1, 0), GetMax(CreateFetch(x_), nullptr));
Aart Bikd14c5952015-09-08 15:25:15 -0700448}
449
450TEST_F(InductionVarRangeTest, GetMinMaxLinear) {
Aart Bik389b3db2015-10-28 14:23:40 -0700451 ExpectEqual(Value(20), GetMin(CreateLinear(10, 20), CreateTripCount(100, true, true)));
452 ExpectEqual(Value(1010), GetMax(CreateLinear(10, 20), CreateTripCount(100, true, true)));
453 ExpectEqual(Value(-970), GetMin(CreateLinear(-10, 20), CreateTripCount(100, true, true)));
454 ExpectEqual(Value(20), GetMax(CreateLinear(-10, 20), CreateTripCount(100, true, true)));
Aart Bikd14c5952015-09-08 15:25:15 -0700455}
456
457TEST_F(InductionVarRangeTest, GetMinMaxWrapAround) {
458 ExpectEqual(Value(-5), GetMin(CreateWrapAround(-5, -1, 10), nullptr));
459 ExpectEqual(Value(10), GetMax(CreateWrapAround(-5, -1, 10), nullptr));
460 ExpectEqual(Value(-1), GetMin(CreateWrapAround(2, -1, 10), nullptr));
461 ExpectEqual(Value(10), GetMax(CreateWrapAround(2, -1, 10), nullptr));
462 ExpectEqual(Value(-1), GetMin(CreateWrapAround(20, -1, 10), nullptr));
463 ExpectEqual(Value(20), GetMax(CreateWrapAround(20, -1, 10), nullptr));
464}
465
Aart Bikdf7822e2016-12-06 10:05:30 -0800466TEST_F(InductionVarRangeTest, GetMinMaxPolynomial) {
467 ExpectEqual(Value(7), GetMin(CreatePolynomial(3, 5, 7), nullptr));
468 ExpectEqual(Value(), GetMax(CreatePolynomial(3, 5, 7), nullptr));
469 ExpectEqual(Value(7), GetMin(CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
470 ExpectEqual(Value(45), GetMax(CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
471 ExpectEqual(Value(7), GetMin(CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
472 ExpectEqual(Value(160), GetMax(CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
473 ExpectEqual(Value(-7), GetMin(CreatePolynomial(11, 13, -7),
474 CreateTripCount(5, true, true)));
475 ExpectEqual(Value(111), GetMax(CreatePolynomial(11, 13, -7),
476 CreateTripCount(5, true, true)));
477 ExpectEqual(Value(-7), GetMin(CreatePolynomial(11, 13, -7),
478 CreateTripCount(10, true, true)));
479 ExpectEqual(Value(506), GetMax(CreatePolynomial(11, 13, -7),
480 CreateTripCount(10, true, true)));
481 ExpectEqual(Value(), GetMin(CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
482 ExpectEqual(Value(), GetMax(CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
483 ExpectEqual(Value(), GetMin(CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
484 ExpectEqual(Value(), GetMax(CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
485}
486
Aart Bikc071a012016-12-01 10:22:31 -0800487TEST_F(InductionVarRangeTest, GetMinMaxGeometricMul) {
488 ExpectEqual(Value(), GetMin(CreateGeometric(1, 1, 1, '*'), nullptr));
489 ExpectEqual(Value(), GetMax(CreateGeometric(1, 1, 1, '*'), nullptr));
490}
491
492TEST_F(InductionVarRangeTest, GetMinMaxGeometricDiv) {
493 ExpectEqual(Value(5), GetMin(CreateGeometric(11, 5, 3, '/'), nullptr));
494 ExpectEqual(Value(16), GetMax(CreateGeometric(11, 5, 3, '/'), nullptr));
495 ExpectEqual(Value(-5), GetMin(CreateGeometric(11, -5, 3, '/'), nullptr));
496 ExpectEqual(Value(6), GetMax(CreateGeometric(11, -5, 3, '/'), nullptr));
497 ExpectEqual(Value(-6), GetMin(CreateGeometric(-11, 5, 3, '/'), nullptr));
498 ExpectEqual(Value(5), GetMax(CreateGeometric(-11, 5, 3, '/'), nullptr));
499 ExpectEqual(Value(-16), GetMin(CreateGeometric(-11, -5, 3, '/'), nullptr));
500 ExpectEqual(Value(-5), GetMax(CreateGeometric(-11, -5, 3, '/'), nullptr));
501}
502
Aart Bikd14c5952015-09-08 15:25:15 -0700503TEST_F(InductionVarRangeTest, GetMinMaxPeriodic) {
504 ExpectEqual(Value(-2), GetMin(CreateRange(-2, 99), nullptr));
505 ExpectEqual(Value(99), GetMax(CreateRange(-2, 99), nullptr));
506}
507
508TEST_F(InductionVarRangeTest, GetMulMin) {
Aart Bik97412c922016-02-19 20:14:38 -0800509 ExpectEqual(Value(-14), GetMul(CreateConst(2), CreateRange(-7, 8), true));
510 ExpectEqual(Value(-16), GetMul(CreateConst(-2), CreateRange(-7, 8), true));
511 ExpectEqual(Value(-14), GetMul(CreateRange(-7, 8), CreateConst(2), true));
512 ExpectEqual(Value(-16), GetMul(CreateRange(-7, 8), CreateConst(-2), true));
Aart Bikb3365e02015-09-21 14:45:05 -0700513 ExpectEqual(Value(6), GetMul(CreateRange(2, 10), CreateRange(3, 5), true));
514 ExpectEqual(Value(-50), GetMul(CreateRange(2, 10), CreateRange(-5, -3), true));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800515 ExpectEqual(Value(), GetMul(CreateRange(2, 10), CreateRange(-1, 1), true));
Aart Bikb3365e02015-09-21 14:45:05 -0700516 ExpectEqual(Value(-50), GetMul(CreateRange(-10, -2), CreateRange(3, 5), true));
517 ExpectEqual(Value(6), GetMul(CreateRange(-10, -2), CreateRange(-5, -3), true));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800518 ExpectEqual(Value(), GetMul(CreateRange(-10, -2), CreateRange(-1, 1), true));
519 ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(2, 10), true));
520 ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(-10, -2), true));
521 ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(-1, 1), true));
Aart Bikd14c5952015-09-08 15:25:15 -0700522}
523
524TEST_F(InductionVarRangeTest, GetMulMax) {
Aart Bik97412c922016-02-19 20:14:38 -0800525 ExpectEqual(Value(16), GetMul(CreateConst(2), CreateRange(-7, 8), false));
526 ExpectEqual(Value(14), GetMul(CreateConst(-2), CreateRange(-7, 8), false));
527 ExpectEqual(Value(16), GetMul(CreateRange(-7, 8), CreateConst(2), false));
528 ExpectEqual(Value(14), GetMul(CreateRange(-7, 8), CreateConst(-2), false));
Aart Bikb3365e02015-09-21 14:45:05 -0700529 ExpectEqual(Value(50), GetMul(CreateRange(2, 10), CreateRange(3, 5), false));
530 ExpectEqual(Value(-6), GetMul(CreateRange(2, 10), CreateRange(-5, -3), false));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800531 ExpectEqual(Value(), GetMul(CreateRange(2, 10), CreateRange(-1, 1), false));
Aart Bikb3365e02015-09-21 14:45:05 -0700532 ExpectEqual(Value(-6), GetMul(CreateRange(-10, -2), CreateRange(3, 5), false));
533 ExpectEqual(Value(50), GetMul(CreateRange(-10, -2), CreateRange(-5, -3), false));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800534 ExpectEqual(Value(), GetMul(CreateRange(-10, -2), CreateRange(-1, 1), false));
535 ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(2, 10), false));
536 ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(-10, -2), false));
537 ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(-1, 1), false));
Aart Bikd14c5952015-09-08 15:25:15 -0700538}
539
540TEST_F(InductionVarRangeTest, GetDivMin) {
Aart Bik97412c922016-02-19 20:14:38 -0800541 ExpectEqual(Value(-5), GetDiv(CreateRange(-10, 20), CreateConst(2), true));
542 ExpectEqual(Value(-10), GetDiv(CreateRange(-10, 20), CreateConst(-2), true));
Aart Bikb3365e02015-09-21 14:45:05 -0700543 ExpectEqual(Value(10), GetDiv(CreateRange(40, 1000), CreateRange(2, 4), true));
544 ExpectEqual(Value(-500), GetDiv(CreateRange(40, 1000), CreateRange(-4, -2), true));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800545 ExpectEqual(Value(), GetDiv(CreateRange(40, 1000), CreateRange(-1, 1), true));
Aart Bikb3365e02015-09-21 14:45:05 -0700546 ExpectEqual(Value(-500), GetDiv(CreateRange(-1000, -40), CreateRange(2, 4), true));
547 ExpectEqual(Value(10), GetDiv(CreateRange(-1000, -40), CreateRange(-4, -2), true));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800548 ExpectEqual(Value(), GetDiv(CreateRange(-1000, -40), CreateRange(-1, 1), true));
549 ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(40, 1000), true));
550 ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(-1000, -40), true));
551 ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(-1, 1), true));
Aart Bikd14c5952015-09-08 15:25:15 -0700552}
553
554TEST_F(InductionVarRangeTest, GetDivMax) {
Aart Bik97412c922016-02-19 20:14:38 -0800555 ExpectEqual(Value(10), GetDiv(CreateRange(-10, 20), CreateConst(2), false));
556 ExpectEqual(Value(5), GetDiv(CreateRange(-10, 20), CreateConst(-2), false));
Aart Bikb3365e02015-09-21 14:45:05 -0700557 ExpectEqual(Value(500), GetDiv(CreateRange(40, 1000), CreateRange(2, 4), false));
558 ExpectEqual(Value(-10), GetDiv(CreateRange(40, 1000), CreateRange(-4, -2), false));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800559 ExpectEqual(Value(), GetDiv(CreateRange(40, 1000), CreateRange(-1, 1), false));
Aart Bikb3365e02015-09-21 14:45:05 -0700560 ExpectEqual(Value(-10), GetDiv(CreateRange(-1000, -40), CreateRange(2, 4), false));
561 ExpectEqual(Value(500), GetDiv(CreateRange(-1000, -40), CreateRange(-4, -2), false));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800562 ExpectEqual(Value(), GetDiv(CreateRange(-1000, -40), CreateRange(-1, 1), false));
563 ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(40, 1000), false));
564 ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(-1000, 40), false));
565 ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(-1, 1), false));
Aart Bikd14c5952015-09-08 15:25:15 -0700566}
567
Aart Bikdf7822e2016-12-06 10:05:30 -0800568TEST_F(InductionVarRangeTest, GetMinMaxRem) {
569 ExpectEqual(Value(), GetMin(CreateInvariant('%', CreateConst(2), CreateRange(10, 20)), nullptr));
570 ExpectEqual(Value(), GetMax(CreateInvariant('%', CreateConst(2), CreateRange(10, 20)), nullptr));
571 ExpectEqual(Value(), GetMin(CreateInvariant('%', CreateRange(10, 20), CreateConst(2)), nullptr));
572 ExpectEqual(Value(), GetMax(CreateInvariant('%', CreateRange(10, 20), CreateConst(2)), nullptr));
573 ExpectEqual(Value(2), GetMin(CreateInvariant('%', CreateConst(2), CreateConst(5)), nullptr));
574 ExpectEqual(Value(2), GetMax(CreateInvariant('%', CreateConst(2), CreateConst(5)), nullptr));
575 ExpectEqual(Value(1), GetMin(CreateInvariant('%', CreateConst(11), CreateConst(5)), nullptr));
576 ExpectEqual(Value(1), GetMax(CreateInvariant('%', CreateConst(11), CreateConst(5)), nullptr));
577}
578
579TEST_F(InductionVarRangeTest, GetRem) {
580 ExpectEqual(Value(0), GetRem(CreateConst(1), CreateConst(1)));
581 ExpectEqual(Value(2), GetRem(CreateConst(2), CreateConst(5)));
582 ExpectEqual(Value(1), GetRem(CreateConst(11), CreateConst(5)));
583 ExpectEqual(Value(-2), GetRem(CreateConst(-2), CreateConst(5)));
584 ExpectEqual(Value(-1), GetRem(CreateConst(-11), CreateConst(5)));
585 ExpectEqual(Value(2), GetRem(CreateConst(2), CreateConst(-5)));
586 ExpectEqual(Value(1), GetRem(CreateConst(11), CreateConst(-5)));
587 ExpectEqual(Value(-2), GetRem(CreateConst(-2), CreateConst(-5)));
588 ExpectEqual(Value(-1), GetRem(CreateConst(-11), CreateConst(-5)));
589 ExpectEqual(Value(), GetRem(CreateConst(1), CreateConst(0)));
590}
591
592TEST_F(InductionVarRangeTest, GetMinMaxXor) {
593 ExpectEqual(Value(), GetMin(CreateInvariant('^', CreateConst(2), CreateRange(10, 20)), nullptr));
594 ExpectEqual(Value(), GetMax(CreateInvariant('^', CreateConst(2), CreateRange(10, 20)), nullptr));
595 ExpectEqual(Value(), GetMin(CreateInvariant('^', CreateRange(10, 20), CreateConst(2)), nullptr));
596 ExpectEqual(Value(), GetMax(CreateInvariant('^', CreateRange(10, 20), CreateConst(2)), nullptr));
597 ExpectEqual(Value(3), GetMin(CreateInvariant('^', CreateConst(1), CreateConst(2)), nullptr));
598 ExpectEqual(Value(3), GetMax(CreateInvariant('^', CreateConst(1), CreateConst(2)), nullptr));
599}
600
601TEST_F(InductionVarRangeTest, GetXor) {
602 ExpectEqual(Value(0), GetXor(CreateConst(1), CreateConst(1)));
603 ExpectEqual(Value(3), GetXor(CreateConst(1), CreateConst(2)));
604 ExpectEqual(Value(-2), GetXor(CreateConst(1), CreateConst(-1)));
605 ExpectEqual(Value(0), GetXor(CreateConst(-1), CreateConst(-1)));
606}
607
Aart Bikd14c5952015-09-08 15:25:15 -0700608TEST_F(InductionVarRangeTest, AddValue) {
609 ExpectEqual(Value(110), AddValue(Value(10), Value(100)));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800610 ExpectEqual(Value(-5), AddValue(Value(x_, 1, -4), Value(x_, -1, -1)));
611 ExpectEqual(Value(x_, 3, -5), AddValue(Value(x_, 2, -4), Value(x_, 1, -1)));
612 ExpectEqual(Value(), AddValue(Value(x_, 1, 5), Value(y_, 1, -7)));
613 ExpectEqual(Value(x_, 1, 23), AddValue(Value(x_, 1, 20), Value(3)));
614 ExpectEqual(Value(y_, 1, 5), AddValue(Value(55), Value(y_, 1, -50)));
Aart Bikcd26feb2015-09-23 17:50:50 -0700615 const int32_t max_value = std::numeric_limits<int32_t>::max();
616 ExpectEqual(Value(max_value), AddValue(Value(max_value - 5), Value(5)));
617 ExpectEqual(Value(), AddValue(Value(max_value - 5), Value(6))); // unsafe
Aart Bikd14c5952015-09-08 15:25:15 -0700618}
619
620TEST_F(InductionVarRangeTest, SubValue) {
621 ExpectEqual(Value(-90), SubValue(Value(10), Value(100)));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800622 ExpectEqual(Value(-3), SubValue(Value(x_, 1, -4), Value(x_, 1, -1)));
623 ExpectEqual(Value(x_, 2, -3), SubValue(Value(x_, 3, -4), Value(x_, 1, -1)));
624 ExpectEqual(Value(), SubValue(Value(x_, 1, 5), Value(y_, 1, -7)));
625 ExpectEqual(Value(x_, 1, 17), SubValue(Value(x_, 1, 20), Value(3)));
626 ExpectEqual(Value(y_, -4, 105), SubValue(Value(55), Value(y_, 4, -50)));
Aart Bikcd26feb2015-09-23 17:50:50 -0700627 const int32_t min_value = std::numeric_limits<int32_t>::min();
628 ExpectEqual(Value(min_value), SubValue(Value(min_value + 5), Value(5)));
629 ExpectEqual(Value(), SubValue(Value(min_value + 5), Value(6))); // unsafe
Aart Bikd14c5952015-09-08 15:25:15 -0700630}
631
632TEST_F(InductionVarRangeTest, MulValue) {
633 ExpectEqual(Value(1000), MulValue(Value(10), Value(100)));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800634 ExpectEqual(Value(), MulValue(Value(x_, 1, -4), Value(x_, 1, -1)));
635 ExpectEqual(Value(), MulValue(Value(x_, 1, 5), Value(y_, 1, -7)));
636 ExpectEqual(Value(x_, 9, 60), MulValue(Value(x_, 3, 20), Value(3)));
637 ExpectEqual(Value(y_, 55, -110), MulValue(Value(55), Value(y_, 1, -2)));
Aart Bikb3365e02015-09-21 14:45:05 -0700638 ExpectEqual(Value(), MulValue(Value(90000), Value(-90000))); // unsafe
Aart Bikd14c5952015-09-08 15:25:15 -0700639}
640
Aart Bik97412c922016-02-19 20:14:38 -0800641TEST_F(InductionVarRangeTest, MulValueSpecial) {
642 const int32_t min_value = std::numeric_limits<int32_t>::min();
643 const int32_t max_value = std::numeric_limits<int32_t>::max();
644
645 // Unsafe.
646 ExpectEqual(Value(), MulValue(Value(min_value), Value(min_value)));
647 ExpectEqual(Value(), MulValue(Value(min_value), Value(-1)));
648 ExpectEqual(Value(), MulValue(Value(min_value), Value(max_value)));
649 ExpectEqual(Value(), MulValue(Value(max_value), Value(max_value)));
650
651 // Safe.
652 ExpectEqual(Value(min_value), MulValue(Value(min_value), Value(1)));
653 ExpectEqual(Value(max_value), MulValue(Value(max_value), Value(1)));
654 ExpectEqual(Value(-max_value), MulValue(Value(max_value), Value(-1)));
655 ExpectEqual(Value(-1), MulValue(Value(1), Value(-1)));
656 ExpectEqual(Value(1), MulValue(Value(-1), Value(-1)));
657}
658
Aart Bikd14c5952015-09-08 15:25:15 -0700659TEST_F(InductionVarRangeTest, DivValue) {
660 ExpectEqual(Value(25), DivValue(Value(100), Value(4)));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800661 ExpectEqual(Value(), DivValue(Value(x_, 1, -4), Value(x_, 1, -1)));
662 ExpectEqual(Value(), DivValue(Value(x_, 1, 5), Value(y_, 1, -7)));
663 ExpectEqual(Value(), DivValue(Value(x_, 12, 24), Value(3)));
664 ExpectEqual(Value(), DivValue(Value(55), Value(y_, 1, -50)));
Aart Bikb3365e02015-09-21 14:45:05 -0700665 ExpectEqual(Value(), DivValue(Value(1), Value(0))); // unsafe
Aart Bikd14c5952015-09-08 15:25:15 -0700666}
667
Aart Bik97412c922016-02-19 20:14:38 -0800668TEST_F(InductionVarRangeTest, DivValueSpecial) {
669 const int32_t min_value = std::numeric_limits<int32_t>::min();
670 const int32_t max_value = std::numeric_limits<int32_t>::max();
671
672 // Unsafe.
673 ExpectEqual(Value(), DivValue(Value(min_value), Value(-1)));
674
675 // Safe.
676 ExpectEqual(Value(1), DivValue(Value(min_value), Value(min_value)));
677 ExpectEqual(Value(1), DivValue(Value(max_value), Value(max_value)));
678 ExpectEqual(Value(min_value), DivValue(Value(min_value), Value(1)));
679 ExpectEqual(Value(max_value), DivValue(Value(max_value), Value(1)));
680 ExpectEqual(Value(-max_value), DivValue(Value(max_value), Value(-1)));
681 ExpectEqual(Value(-1), DivValue(Value(1), Value(-1)));
682 ExpectEqual(Value(1), DivValue(Value(-1), Value(-1)));
683}
684
Aart Bikd14c5952015-09-08 15:25:15 -0700685TEST_F(InductionVarRangeTest, MinValue) {
686 ExpectEqual(Value(10), MinValue(Value(10), Value(100)));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800687 ExpectEqual(Value(x_, 1, -4), MinValue(Value(x_, 1, -4), Value(x_, 1, -1)));
688 ExpectEqual(Value(x_, 4, -4), MinValue(Value(x_, 4, -4), Value(x_, 4, -1)));
689 ExpectEqual(Value(), MinValue(Value(x_, 1, 5), Value(y_, 1, -7)));
690 ExpectEqual(Value(), MinValue(Value(x_, 1, 20), Value(3)));
691 ExpectEqual(Value(), MinValue(Value(55), Value(y_, 1, -50)));
Aart Bikd14c5952015-09-08 15:25:15 -0700692}
693
694TEST_F(InductionVarRangeTest, MaxValue) {
695 ExpectEqual(Value(100), MaxValue(Value(10), Value(100)));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800696 ExpectEqual(Value(x_, 1, -1), MaxValue(Value(x_, 1, -4), Value(x_, 1, -1)));
697 ExpectEqual(Value(x_, 4, -1), MaxValue(Value(x_, 4, -4), Value(x_, 4, -1)));
698 ExpectEqual(Value(), MaxValue(Value(x_, 1, 5), Value(y_, 1, -7)));
699 ExpectEqual(Value(), MaxValue(Value(x_, 1, 20), Value(3)));
700 ExpectEqual(Value(), MaxValue(Value(55), Value(y_, 1, -50)));
Aart Bikd14c5952015-09-08 15:25:15 -0700701}
702
Aart Bik52be7e72016-06-23 11:20:41 -0700703TEST_F(InductionVarRangeTest, ArrayLengthAndHints) {
Nicolas Geoffraye761bcc2017-01-19 08:59:37 +0000704 // We pass a bogus constant for the class to avoid mocking one.
Vladimir Markob5461632018-10-15 14:24:21 +0100705 HInstruction* new_array = new (GetAllocator()) HNewArray(
706 /* cls= */ x_,
707 /* length= */ x_,
708 /* dex_pc= */ 0,
709 /* component_size_shift= */ 0);
Aart Bik52be7e72016-06-23 11:20:41 -0700710 entry_block_->AddInstruction(new_array);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100711 HInstruction* array_length = new (GetAllocator()) HArrayLength(new_array, 0);
Aart Bik52be7e72016-06-23 11:20:41 -0700712 entry_block_->AddInstruction(array_length);
713 // With null hint: yields extreme constants.
714 const int32_t max_value = std::numeric_limits<int32_t>::max();
715 SetHint(nullptr);
716 ExpectEqual(Value(0), GetMin(CreateFetch(array_length), nullptr));
717 ExpectEqual(Value(max_value), GetMax(CreateFetch(array_length), nullptr));
718 // With explicit hint: yields the length instruction.
719 SetHint(array_length);
720 ExpectEqual(Value(array_length, 1, 0), GetMin(CreateFetch(array_length), nullptr));
721 ExpectEqual(Value(array_length, 1, 0), GetMax(CreateFetch(array_length), nullptr));
722 // With any non-null hint: chases beyond the length instruction.
723 SetHint(x_);
724 ExpectEqual(Value(x_, 1, 0), GetMin(CreateFetch(array_length), nullptr));
725 ExpectEqual(Value(x_, 1, 0), GetMax(CreateFetch(array_length), nullptr));
726}
727
Aart Bik8e9090b2017-09-08 16:46:50 -0700728TEST_F(InductionVarRangeTest, AddOrSubAndConstant) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100729 HInstruction* add = new (GetAllocator())
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100730 HAdd(DataType::Type::kInt32, x_, graph_->GetIntConstant(-1));
Vladimir Markoca6fff82017-10-03 14:49:14 +0100731 HInstruction* alt = new (GetAllocator())
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100732 HAdd(DataType::Type::kInt32, graph_->GetIntConstant(-1), x_);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100733 HInstruction* sub = new (GetAllocator())
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100734 HSub(DataType::Type::kInt32, x_, graph_->GetIntConstant(1));
Vladimir Markoca6fff82017-10-03 14:49:14 +0100735 HInstruction* rev = new (GetAllocator())
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100736 HSub(DataType::Type::kInt32, graph_->GetIntConstant(1), x_);
Aart Bik8e9090b2017-09-08 16:46:50 -0700737 entry_block_->AddInstruction(add);
738 entry_block_->AddInstruction(alt);
739 entry_block_->AddInstruction(sub);
740 entry_block_->AddInstruction(rev);
741 ExpectEqual(Value(x_, 1, -1), GetMin(CreateFetch(add), nullptr));
742 ExpectEqual(Value(x_, 1, -1), GetMax(CreateFetch(add), nullptr));
743 ExpectEqual(Value(x_, 1, -1), GetMin(CreateFetch(alt), nullptr));
744 ExpectEqual(Value(x_, 1, -1), GetMax(CreateFetch(alt), nullptr));
745 ExpectEqual(Value(x_, 1, -1), GetMin(CreateFetch(sub), nullptr));
746 ExpectEqual(Value(x_, 1, -1), GetMax(CreateFetch(sub), nullptr));
747 ExpectEqual(Value(x_, -1, 1), GetMin(CreateFetch(rev), nullptr));
748 ExpectEqual(Value(x_, -1, 1), GetMax(CreateFetch(rev), nullptr));
749}
750
Aart Bikaec3cce2015-10-14 17:44:55 -0700751//
Aart Bik7d57d7f2015-12-09 14:39:48 -0800752// Tests on public methods.
Aart Bikaec3cce2015-10-14 17:44:55 -0700753//
754
Aart Bik389b3db2015-10-28 14:23:40 -0700755TEST_F(InductionVarRangeTest, ConstantTripCountUp) {
756 BuildLoop(0, graph_->GetIntConstant(1000), 1);
Aart Bikaec3cce2015-10-14 17:44:55 -0700757 PerformInductionVarAnalysis();
Aart Bikaec3cce2015-10-14 17:44:55 -0700758
Aart Bik389b3db2015-10-28 14:23:40 -0700759 Value v1, v2;
760 bool needs_finite_test = true;
Aart Bik16d3a652016-09-09 10:33:50 -0700761 bool needs_taken_test = true;
762
763 HInstruction* phi = condition_->InputAt(0);
764 HInstruction* exit = exit_block_->GetLastInstruction();
Aart Bik389b3db2015-10-28 14:23:40 -0700765
Aart Bikaec3cce2015-10-14 17:44:55 -0700766 // In context of header: known.
Aart Bik16d3a652016-09-09 10:33:50 -0700767 range_.GetInductionRange(condition_, phi, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700768 EXPECT_FALSE(needs_finite_test);
769 ExpectEqual(Value(0), v1);
770 ExpectEqual(Value(1000), v2);
Aart Bikaec3cce2015-10-14 17:44:55 -0700771
772 // In context of loop-body: known.
Aart Bik16d3a652016-09-09 10:33:50 -0700773 range_.GetInductionRange(increment_, phi, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700774 EXPECT_FALSE(needs_finite_test);
775 ExpectEqual(Value(0), v1);
776 ExpectEqual(Value(999), v2);
Aart Bik52be7e72016-06-23 11:20:41 -0700777 range_.GetInductionRange(increment_, increment_, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700778 EXPECT_FALSE(needs_finite_test);
779 ExpectEqual(Value(1), v1);
780 ExpectEqual(Value(1000), v2);
Aart Bik16d3a652016-09-09 10:33:50 -0700781
782 // Induction vs. no-induction.
783 EXPECT_TRUE(range_.CanGenerateRange(increment_, phi, &needs_finite_test, &needs_taken_test));
784 EXPECT_TRUE(range_.CanGenerateLastValue(phi));
785 EXPECT_FALSE(range_.CanGenerateRange(exit, exit, &needs_finite_test, &needs_taken_test));
786 EXPECT_FALSE(range_.CanGenerateLastValue(exit));
787
788 // Last value (unsimplified).
789 HInstruction* last = range_.GenerateLastValue(phi, graph_, loop_preheader_);
790 ASSERT_TRUE(last->IsAdd());
Aart Bik8e02e3e2017-02-28 14:41:55 -0800791 ExpectInt(1000, last->InputAt(0));
792 ExpectInt(0, last->InputAt(1));
793
794 // Loop logic.
795 int64_t tc = 0;
796 EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
797 EXPECT_EQ(1000, tc);
798 HInstruction* offset = nullptr;
Aart Bik37dc4df2017-06-28 14:08:00 -0700799 EXPECT_TRUE(range_.IsUnitStride(phi, phi, graph_, &offset));
800 ExpectInt(0, offset);
Aart Bik8e02e3e2017-02-28 14:41:55 -0800801 HInstruction* tce = range_.GenerateTripCount(
802 loop_header_->GetLoopInformation(), graph_, loop_preheader_);
803 ASSERT_TRUE(tce != nullptr);
804 ExpectInt(1000, tce);
Aart Bikaec3cce2015-10-14 17:44:55 -0700805}
806
Aart Bik389b3db2015-10-28 14:23:40 -0700807TEST_F(InductionVarRangeTest, ConstantTripCountDown) {
808 BuildLoop(1000, graph_->GetIntConstant(0), -1);
Aart Bikaec3cce2015-10-14 17:44:55 -0700809 PerformInductionVarAnalysis();
Aart Bikaec3cce2015-10-14 17:44:55 -0700810
Aart Bik389b3db2015-10-28 14:23:40 -0700811 Value v1, v2;
812 bool needs_finite_test = true;
Aart Bik16d3a652016-09-09 10:33:50 -0700813 bool needs_taken_test = true;
814
815 HInstruction* phi = condition_->InputAt(0);
816 HInstruction* exit = exit_block_->GetLastInstruction();
Aart Bik389b3db2015-10-28 14:23:40 -0700817
818 // In context of header: known.
Aart Bik16d3a652016-09-09 10:33:50 -0700819 range_.GetInductionRange(condition_, phi, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700820 EXPECT_FALSE(needs_finite_test);
821 ExpectEqual(Value(0), v1);
822 ExpectEqual(Value(1000), v2);
Aart Bikaec3cce2015-10-14 17:44:55 -0700823
824 // In context of loop-body: known.
Aart Bik16d3a652016-09-09 10:33:50 -0700825 range_.GetInductionRange(increment_, phi, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700826 EXPECT_FALSE(needs_finite_test);
827 ExpectEqual(Value(1), v1);
828 ExpectEqual(Value(1000), v2);
Aart Bik52be7e72016-06-23 11:20:41 -0700829 range_.GetInductionRange(increment_, increment_, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700830 EXPECT_FALSE(needs_finite_test);
831 ExpectEqual(Value(0), v1);
832 ExpectEqual(Value(999), v2);
Aart Bik16d3a652016-09-09 10:33:50 -0700833
834 // Induction vs. no-induction.
835 EXPECT_TRUE(range_.CanGenerateRange(increment_, phi, &needs_finite_test, &needs_taken_test));
836 EXPECT_TRUE(range_.CanGenerateLastValue(phi));
837 EXPECT_FALSE(range_.CanGenerateRange(exit, exit, &needs_finite_test, &needs_taken_test));
838 EXPECT_FALSE(range_.CanGenerateLastValue(exit));
839
840 // Last value (unsimplified).
841 HInstruction* last = range_.GenerateLastValue(phi, graph_, loop_preheader_);
842 ASSERT_TRUE(last->IsSub());
Aart Bik8e02e3e2017-02-28 14:41:55 -0800843 ExpectInt(1000, last->InputAt(0));
Aart Bik16d3a652016-09-09 10:33:50 -0700844 ASSERT_TRUE(last->InputAt(1)->IsNeg());
845 last = last->InputAt(1)->InputAt(0);
846 ASSERT_TRUE(last->IsSub());
Aart Bik8e02e3e2017-02-28 14:41:55 -0800847 ExpectInt(0, last->InputAt(0));
848 ExpectInt(1000, last->InputAt(1));
849
850 // Loop logic.
851 int64_t tc = 0;
852 EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
853 EXPECT_EQ(1000, tc);
854 HInstruction* offset = nullptr;
Aart Bik37dc4df2017-06-28 14:08:00 -0700855 EXPECT_FALSE(range_.IsUnitStride(phi, phi, graph_, &offset));
Aart Bik8e02e3e2017-02-28 14:41:55 -0800856 HInstruction* tce = range_.GenerateTripCount(
857 loop_header_->GetLoopInformation(), graph_, loop_preheader_);
858 ASSERT_TRUE(tce != nullptr);
859 ASSERT_TRUE(tce->IsNeg());
860 last = tce->InputAt(0);
861 EXPECT_TRUE(last->IsSub());
862 ExpectInt(0, last->InputAt(0));
863 ExpectInt(1000, last->InputAt(1));
Aart Bikaec3cce2015-10-14 17:44:55 -0700864}
865
Aart Bik389b3db2015-10-28 14:23:40 -0700866TEST_F(InductionVarRangeTest, SymbolicTripCountUp) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800867 BuildLoop(0, x_, 1);
Aart Bikaec3cce2015-10-14 17:44:55 -0700868 PerformInductionVarAnalysis();
Aart Bikaec3cce2015-10-14 17:44:55 -0700869
Aart Bik389b3db2015-10-28 14:23:40 -0700870 Value v1, v2;
871 bool needs_finite_test = true;
872 bool needs_taken_test = true;
873
Aart Bik16d3a652016-09-09 10:33:50 -0700874 HInstruction* phi = condition_->InputAt(0);
875
Aart Bik389b3db2015-10-28 14:23:40 -0700876 // In context of header: upper unknown.
Aart Bik16d3a652016-09-09 10:33:50 -0700877 range_.GetInductionRange(condition_, phi, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700878 EXPECT_FALSE(needs_finite_test);
879 ExpectEqual(Value(0), v1);
880 ExpectEqual(Value(), v2);
881
882 // In context of loop-body: known.
Aart Bik16d3a652016-09-09 10:33:50 -0700883 range_.GetInductionRange(increment_, phi, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700884 EXPECT_FALSE(needs_finite_test);
885 ExpectEqual(Value(0), v1);
Aart Bik7d57d7f2015-12-09 14:39:48 -0800886 ExpectEqual(Value(x_, 1, -1), v2);
Aart Bik52be7e72016-06-23 11:20:41 -0700887 range_.GetInductionRange(increment_, increment_, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700888 EXPECT_FALSE(needs_finite_test);
889 ExpectEqual(Value(1), v1);
Aart Bik7d57d7f2015-12-09 14:39:48 -0800890 ExpectEqual(Value(x_, 1, 0), v2);
Aart Bik389b3db2015-10-28 14:23:40 -0700891
Aart Bikaec3cce2015-10-14 17:44:55 -0700892 HInstruction* lower = nullptr;
893 HInstruction* upper = nullptr;
Aart Bikaec3cce2015-10-14 17:44:55 -0700894
895 // Can generate code in context of loop-body only.
Aart Bik16d3a652016-09-09 10:33:50 -0700896 EXPECT_FALSE(range_.CanGenerateRange(condition_, phi, &needs_finite_test, &needs_taken_test));
897 ASSERT_TRUE(range_.CanGenerateRange(increment_, phi, &needs_finite_test, &needs_taken_test));
Aart Bik389b3db2015-10-28 14:23:40 -0700898 EXPECT_FALSE(needs_finite_test);
899 EXPECT_TRUE(needs_taken_test);
Aart Bikaec3cce2015-10-14 17:44:55 -0700900
Aart Bik16d3a652016-09-09 10:33:50 -0700901 // Generates code (unsimplified).
902 range_.GenerateRange(increment_, phi, graph_, loop_preheader_, &lower, &upper);
Aart Bikaec3cce2015-10-14 17:44:55 -0700903
904 // Verify lower is 0+0.
905 ASSERT_TRUE(lower != nullptr);
906 ASSERT_TRUE(lower->IsAdd());
Aart Bik8e02e3e2017-02-28 14:41:55 -0800907 ExpectInt(0, lower->InputAt(0));
908 ExpectInt(0, lower->InputAt(1));
Aart Bikaec3cce2015-10-14 17:44:55 -0700909
Aart Bik389b3db2015-10-28 14:23:40 -0700910 // Verify upper is (V-1)+0.
Aart Bikaec3cce2015-10-14 17:44:55 -0700911 ASSERT_TRUE(upper != nullptr);
912 ASSERT_TRUE(upper->IsAdd());
913 ASSERT_TRUE(upper->InputAt(0)->IsSub());
914 EXPECT_TRUE(upper->InputAt(0)->InputAt(0)->IsParameterValue());
Aart Bik8e02e3e2017-02-28 14:41:55 -0800915 ExpectInt(1, upper->InputAt(0)->InputAt(1));
916 ExpectInt(0, upper->InputAt(1));
Aart Bik389b3db2015-10-28 14:23:40 -0700917
918 // Verify taken-test is 0<V.
Aart Bik16d3a652016-09-09 10:33:50 -0700919 HInstruction* taken = range_.GenerateTakenTest(increment_, graph_, loop_preheader_);
Aart Bik389b3db2015-10-28 14:23:40 -0700920 ASSERT_TRUE(taken != nullptr);
921 ASSERT_TRUE(taken->IsLessThan());
Aart Bik8e02e3e2017-02-28 14:41:55 -0800922 ExpectInt(0, taken->InputAt(0));
Aart Bik389b3db2015-10-28 14:23:40 -0700923 EXPECT_TRUE(taken->InputAt(1)->IsParameterValue());
Aart Bik16d3a652016-09-09 10:33:50 -0700924
925 // Replacement.
926 range_.Replace(loop_header_->GetLastInstruction(), x_, y_);
927 range_.GetInductionRange(increment_, increment_, x_, &v1, &v2, &needs_finite_test);
928 EXPECT_FALSE(needs_finite_test);
929 ExpectEqual(Value(1), v1);
930 ExpectEqual(Value(y_, 1, 0), v2);
Aart Bik8e02e3e2017-02-28 14:41:55 -0800931
932 // Loop logic.
933 int64_t tc = 0;
934 EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
935 EXPECT_EQ(0, tc); // unknown
936 HInstruction* offset = nullptr;
Aart Bik37dc4df2017-06-28 14:08:00 -0700937 EXPECT_TRUE(range_.IsUnitStride(phi, phi, graph_, &offset));
938 ExpectInt(0, offset);
Aart Bik8e02e3e2017-02-28 14:41:55 -0800939 HInstruction* tce = range_.GenerateTripCount(
940 loop_header_->GetLoopInformation(), graph_, loop_preheader_);
941 ASSERT_TRUE(tce != nullptr);
942 EXPECT_TRUE(tce->IsSelect()); // guarded by taken-test
943 ExpectInt(0, tce->InputAt(0));
944 EXPECT_TRUE(tce->InputAt(1)->IsParameterValue());
945 EXPECT_TRUE(tce->InputAt(2)->IsLessThan());
Aart Bik389b3db2015-10-28 14:23:40 -0700946}
947
948TEST_F(InductionVarRangeTest, SymbolicTripCountDown) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800949 BuildLoop(1000, x_, -1);
Aart Bik389b3db2015-10-28 14:23:40 -0700950 PerformInductionVarAnalysis();
Aart Bik389b3db2015-10-28 14:23:40 -0700951
952 Value v1, v2;
953 bool needs_finite_test = true;
954 bool needs_taken_test = true;
955
Aart Bik16d3a652016-09-09 10:33:50 -0700956 HInstruction* phi = condition_->InputAt(0);
957
Aart Bik389b3db2015-10-28 14:23:40 -0700958 // In context of header: lower unknown.
Aart Bik16d3a652016-09-09 10:33:50 -0700959 range_.GetInductionRange(condition_, phi, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700960 EXPECT_FALSE(needs_finite_test);
961 ExpectEqual(Value(), v1);
962 ExpectEqual(Value(1000), v2);
963
964 // In context of loop-body: known.
Aart Bik16d3a652016-09-09 10:33:50 -0700965 range_.GetInductionRange(increment_, phi, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700966 EXPECT_FALSE(needs_finite_test);
Aart Bik7d57d7f2015-12-09 14:39:48 -0800967 ExpectEqual(Value(x_, 1, 1), v1);
Aart Bik389b3db2015-10-28 14:23:40 -0700968 ExpectEqual(Value(1000), v2);
Aart Bik52be7e72016-06-23 11:20:41 -0700969 range_.GetInductionRange(increment_, increment_, x_, &v1, &v2, &needs_finite_test);
Aart Bik389b3db2015-10-28 14:23:40 -0700970 EXPECT_FALSE(needs_finite_test);
Aart Bik7d57d7f2015-12-09 14:39:48 -0800971 ExpectEqual(Value(x_, 1, 0), v1);
Aart Bik389b3db2015-10-28 14:23:40 -0700972 ExpectEqual(Value(999), v2);
973
974 HInstruction* lower = nullptr;
975 HInstruction* upper = nullptr;
Aart Bik389b3db2015-10-28 14:23:40 -0700976
977 // Can generate code in context of loop-body only.
Aart Bik16d3a652016-09-09 10:33:50 -0700978 EXPECT_FALSE(range_.CanGenerateRange(condition_, phi, &needs_finite_test, &needs_taken_test));
979 ASSERT_TRUE(range_.CanGenerateRange(increment_, phi, &needs_finite_test, &needs_taken_test));
Aart Bik389b3db2015-10-28 14:23:40 -0700980 EXPECT_FALSE(needs_finite_test);
981 EXPECT_TRUE(needs_taken_test);
982
Aart Bik16d3a652016-09-09 10:33:50 -0700983 // Generates code (unsimplified).
984 range_.GenerateRange(increment_, phi, graph_, loop_preheader_, &lower, &upper);
Aart Bik389b3db2015-10-28 14:23:40 -0700985
Aart Bik7d57d7f2015-12-09 14:39:48 -0800986 // Verify lower is 1000-((1000-V)-1).
Aart Bik389b3db2015-10-28 14:23:40 -0700987 ASSERT_TRUE(lower != nullptr);
988 ASSERT_TRUE(lower->IsSub());
Aart Bik8e02e3e2017-02-28 14:41:55 -0800989 ExpectInt(1000, lower->InputAt(0));
Aart Bik389b3db2015-10-28 14:23:40 -0700990 lower = lower->InputAt(1);
991 ASSERT_TRUE(lower->IsSub());
Aart Bik8e02e3e2017-02-28 14:41:55 -0800992 ExpectInt(1, lower->InputAt(1));
Aart Bik389b3db2015-10-28 14:23:40 -0700993 lower = lower->InputAt(0);
Aart Bik389b3db2015-10-28 14:23:40 -0700994 ASSERT_TRUE(lower->IsSub());
Aart Bik8e02e3e2017-02-28 14:41:55 -0800995 ExpectInt(1000, lower->InputAt(0));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800996 EXPECT_TRUE(lower->InputAt(1)->IsParameterValue());
Aart Bik389b3db2015-10-28 14:23:40 -0700997
998 // Verify upper is 1000-0.
999 ASSERT_TRUE(upper != nullptr);
1000 ASSERT_TRUE(upper->IsSub());
Aart Bik8e02e3e2017-02-28 14:41:55 -08001001 ExpectInt(1000, upper->InputAt(0));
1002 ExpectInt(0, upper->InputAt(1));
Aart Bik389b3db2015-10-28 14:23:40 -07001003
1004 // Verify taken-test is 1000>V.
Aart Bik16d3a652016-09-09 10:33:50 -07001005 HInstruction* taken = range_.GenerateTakenTest(increment_, graph_, loop_preheader_);
Aart Bik389b3db2015-10-28 14:23:40 -07001006 ASSERT_TRUE(taken != nullptr);
1007 ASSERT_TRUE(taken->IsGreaterThan());
Aart Bik8e02e3e2017-02-28 14:41:55 -08001008 ExpectInt(1000, taken->InputAt(0));
Aart Bik389b3db2015-10-28 14:23:40 -07001009 EXPECT_TRUE(taken->InputAt(1)->IsParameterValue());
Aart Bik16d3a652016-09-09 10:33:50 -07001010
1011 // Replacement.
1012 range_.Replace(loop_header_->GetLastInstruction(), x_, y_);
1013 range_.GetInductionRange(increment_, increment_, x_, &v1, &v2, &needs_finite_test);
1014 EXPECT_FALSE(needs_finite_test);
1015 ExpectEqual(Value(y_, 1, 0), v1);
1016 ExpectEqual(Value(999), v2);
Aart Bik8e02e3e2017-02-28 14:41:55 -08001017
1018 // Loop logic.
1019 int64_t tc = 0;
1020 EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
1021 EXPECT_EQ(0, tc); // unknown
1022 HInstruction* offset = nullptr;
Aart Bik37dc4df2017-06-28 14:08:00 -07001023 EXPECT_FALSE(range_.IsUnitStride(phi, phi, graph_, &offset));
Aart Bik8e02e3e2017-02-28 14:41:55 -08001024 HInstruction* tce = range_.GenerateTripCount(
1025 loop_header_->GetLoopInformation(), graph_, loop_preheader_);
1026 ASSERT_TRUE(tce != nullptr);
1027 EXPECT_TRUE(tce->IsSelect()); // guarded by taken-test
1028 ExpectInt(0, tce->InputAt(0));
1029 EXPECT_TRUE(tce->InputAt(1)->IsSub());
1030 EXPECT_TRUE(tce->InputAt(2)->IsGreaterThan());
1031 tce = tce->InputAt(1);
1032 ExpectInt(1000, taken->InputAt(0));
1033 EXPECT_TRUE(taken->InputAt(1)->IsParameterValue());
Aart Bikaec3cce2015-10-14 17:44:55 -07001034}
1035
Aart Bikd14c5952015-09-08 15:25:15 -07001036} // namespace art