1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "induction_var_range.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include "base/arena_allocator.h"
20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
21*795d594fSAndroid Build Coastguard Worker #include "builder.h"
22*795d594fSAndroid Build Coastguard Worker #include "induction_var_analysis.h"
23*795d594fSAndroid Build Coastguard Worker #include "nodes.h"
24*795d594fSAndroid Build Coastguard Worker #include "optimizing_unit_test.h"
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
27*795d594fSAndroid Build Coastguard Worker
28*795d594fSAndroid Build Coastguard Worker using Value = InductionVarRange::Value;
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Worker /**
31*795d594fSAndroid Build Coastguard Worker * Fixture class for the InductionVarRange tests.
32*795d594fSAndroid Build Coastguard Worker */
33*795d594fSAndroid Build Coastguard Worker class InductionVarRangeTest : public OptimizingUnitTest {
34*795d594fSAndroid Build Coastguard Worker public:
InductionVarRangeTest()35*795d594fSAndroid Build Coastguard Worker InductionVarRangeTest()
36*795d594fSAndroid Build Coastguard Worker : iva_(new (GetAllocator()) HInductionVarAnalysis(BuildGraph())),
37*795d594fSAndroid Build Coastguard Worker range_(iva_) {
38*795d594fSAndroid Build Coastguard Worker // Set arbitrary range analysis hint while testing private methods.
39*795d594fSAndroid Build Coastguard Worker SetHint(x_);
40*795d594fSAndroid Build Coastguard Worker }
41*795d594fSAndroid Build Coastguard Worker
~InductionVarRangeTest()42*795d594fSAndroid Build Coastguard Worker ~InductionVarRangeTest() { }
43*795d594fSAndroid Build Coastguard Worker
ExpectEqual(Value v1,Value v2)44*795d594fSAndroid Build Coastguard Worker void ExpectEqual(Value v1, Value v2) {
45*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(v1.instruction, v2.instruction);
46*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(v1.a_constant, v2.a_constant);
47*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(v1.b_constant, v2.b_constant);
48*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(v1.is_known, v2.is_known);
49*795d594fSAndroid Build Coastguard Worker }
50*795d594fSAndroid Build Coastguard Worker
ExpectInt(int32_t value,HInstruction * i)51*795d594fSAndroid Build Coastguard Worker void ExpectInt(int32_t value, HInstruction* i) {
52*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(i->IsIntConstant());
53*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(value, i->AsIntConstant()->GetValue());
54*795d594fSAndroid Build Coastguard Worker }
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker //
57*795d594fSAndroid Build Coastguard Worker // Construction methods.
58*795d594fSAndroid Build Coastguard Worker //
59*795d594fSAndroid Build Coastguard Worker
60*795d594fSAndroid Build Coastguard Worker /** Constructs bare minimum graph. */
BuildGraph()61*795d594fSAndroid Build Coastguard Worker HGraph* BuildGraph() {
62*795d594fSAndroid Build Coastguard Worker return_block_ = InitEntryMainExitGraphWithReturnVoid();
63*795d594fSAndroid Build Coastguard Worker graph_->SetNumberOfVRegs(1);
64*795d594fSAndroid Build Coastguard Worker // Two parameters.
65*795d594fSAndroid Build Coastguard Worker x_ = MakeParam(DataType::Type::kInt32);
66*795d594fSAndroid Build Coastguard Worker y_ = MakeParam(DataType::Type::kInt32);
67*795d594fSAndroid Build Coastguard Worker return graph_;
68*795d594fSAndroid Build Coastguard Worker }
69*795d594fSAndroid Build Coastguard Worker
70*795d594fSAndroid Build Coastguard Worker /** Constructs loop with given upper bound. */
BuildLoop(int32_t lower,HInstruction * upper,int32_t stride)71*795d594fSAndroid Build Coastguard Worker void BuildLoop(int32_t lower, HInstruction* upper, int32_t stride) {
72*795d594fSAndroid Build Coastguard Worker // Control flow.
73*795d594fSAndroid Build Coastguard Worker std::tie(loop_preheader_, loop_header_, loop_body_) = CreateWhileLoop(return_block_);
74*795d594fSAndroid Build Coastguard Worker loop_header_->SwapSuccessors(); // Move the loop exit to the "else" successor.
75*795d594fSAndroid Build Coastguard Worker // Instructions.
76*795d594fSAndroid Build Coastguard Worker HInstruction* lower_const = graph_->GetIntConstant(lower);
77*795d594fSAndroid Build Coastguard Worker HPhi* phi;
78*795d594fSAndroid Build Coastguard Worker std::tie(phi, increment_) = MakeLinearLoopVar(loop_header_, loop_body_, lower, stride);
79*795d594fSAndroid Build Coastguard Worker IfCondition cond = (stride > 0) ? kCondLT : kCondGT;
80*795d594fSAndroid Build Coastguard Worker condition_ = MakeCondition(loop_header_, cond, phi, upper); // i < u or i > u
81*795d594fSAndroid Build Coastguard Worker MakeIf(loop_header_, condition_);
82*795d594fSAndroid Build Coastguard Worker }
83*795d594fSAndroid Build Coastguard Worker
84*795d594fSAndroid Build Coastguard Worker /** Constructs SSA and performs induction variable analysis. */
PerformInductionVarAnalysis()85*795d594fSAndroid Build Coastguard Worker void PerformInductionVarAnalysis() {
86*795d594fSAndroid Build Coastguard Worker graph_->BuildDominatorTree();
87*795d594fSAndroid Build Coastguard Worker iva_->Run();
88*795d594fSAndroid Build Coastguard Worker }
89*795d594fSAndroid Build Coastguard Worker
90*795d594fSAndroid Build Coastguard Worker /** Sets hint. */
SetHint(HInstruction * hint)91*795d594fSAndroid Build Coastguard Worker void SetHint(HInstruction* hint) {
92*795d594fSAndroid Build Coastguard Worker range_.chase_hint_ = hint;
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker
95*795d594fSAndroid Build Coastguard Worker /** Constructs an invariant. */
CreateInvariant(char opc,HInductionVarAnalysis::InductionInfo * a,HInductionVarAnalysis::InductionInfo * b)96*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreateInvariant(char opc,
97*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* a,
98*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* b) {
99*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionOp op;
100*795d594fSAndroid Build Coastguard Worker switch (opc) {
101*795d594fSAndroid Build Coastguard Worker case '+': op = HInductionVarAnalysis::kAdd; break;
102*795d594fSAndroid Build Coastguard Worker case '-': op = HInductionVarAnalysis::kSub; break;
103*795d594fSAndroid Build Coastguard Worker case 'n': op = HInductionVarAnalysis::kNeg; break;
104*795d594fSAndroid Build Coastguard Worker case '*': op = HInductionVarAnalysis::kMul; break;
105*795d594fSAndroid Build Coastguard Worker case '/': op = HInductionVarAnalysis::kDiv; break;
106*795d594fSAndroid Build Coastguard Worker case '%': op = HInductionVarAnalysis::kRem; break;
107*795d594fSAndroid Build Coastguard Worker case '^': op = HInductionVarAnalysis::kXor; break;
108*795d594fSAndroid Build Coastguard Worker case '<': op = HInductionVarAnalysis::kLT; break;
109*795d594fSAndroid Build Coastguard Worker default: op = HInductionVarAnalysis::kNop; break;
110*795d594fSAndroid Build Coastguard Worker }
111*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
112*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
113*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
114*795d594fSAndroid Build Coastguard Worker return iva_->CreateInvariantOp(context, &loop, op, a, b);
115*795d594fSAndroid Build Coastguard Worker }
116*795d594fSAndroid Build Coastguard Worker
117*795d594fSAndroid Build Coastguard Worker /** Constructs a fetch. */
CreateFetch(HInstruction * fetch)118*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreateFetch(HInstruction* fetch) {
119*795d594fSAndroid Build Coastguard Worker return iva_->CreateInvariantFetch(fetch);
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker
122*795d594fSAndroid Build Coastguard Worker /** Constructs a constant. */
CreateConst(int32_t c)123*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreateConst(int32_t c) {
124*795d594fSAndroid Build Coastguard Worker return CreateFetch(graph_->GetIntConstant(c));
125*795d594fSAndroid Build Coastguard Worker }
126*795d594fSAndroid Build Coastguard Worker
127*795d594fSAndroid Build Coastguard Worker /** Constructs a constant trip-count. */
CreateTripCount(int32_t tc,bool in_loop,bool safe)128*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreateTripCount(int32_t tc, bool in_loop, bool safe) {
129*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionOp op = HInductionVarAnalysis::kTripCountInBodyUnsafe;
130*795d594fSAndroid Build Coastguard Worker if (in_loop && safe) {
131*795d594fSAndroid Build Coastguard Worker op = HInductionVarAnalysis::kTripCountInLoop;
132*795d594fSAndroid Build Coastguard Worker } else if (in_loop) {
133*795d594fSAndroid Build Coastguard Worker op = HInductionVarAnalysis::kTripCountInLoopUnsafe;
134*795d594fSAndroid Build Coastguard Worker } else if (safe) {
135*795d594fSAndroid Build Coastguard Worker op = HInductionVarAnalysis::kTripCountInBody;
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker // Return TC with taken-test 0 < TC.
138*795d594fSAndroid Build Coastguard Worker return iva_->CreateTripCount(op,
139*795d594fSAndroid Build Coastguard Worker CreateConst(tc),
140*795d594fSAndroid Build Coastguard Worker CreateInvariant('<', CreateConst(0), CreateConst(tc)),
141*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32);
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Worker /** Constructs a linear a * i + b induction. */
CreateLinear(int32_t a,int32_t b)145*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreateLinear(int32_t a, int32_t b) {
146*795d594fSAndroid Build Coastguard Worker return iva_->CreateInduction(HInductionVarAnalysis::kLinear,
147*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::kNop,
148*795d594fSAndroid Build Coastguard Worker CreateConst(a),
149*795d594fSAndroid Build Coastguard Worker CreateConst(b),
150*795d594fSAndroid Build Coastguard Worker nullptr,
151*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32);
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker
154*795d594fSAndroid Build Coastguard Worker /** Constructs a polynomial sum(a * i + b) + c induction. */
CreatePolynomial(int32_t a,int32_t b,int32_t c)155*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreatePolynomial(int32_t a, int32_t b, int32_t c) {
156*795d594fSAndroid Build Coastguard Worker return iva_->CreateInduction(HInductionVarAnalysis::kPolynomial,
157*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::kNop,
158*795d594fSAndroid Build Coastguard Worker CreateLinear(a, b),
159*795d594fSAndroid Build Coastguard Worker CreateConst(c),
160*795d594fSAndroid Build Coastguard Worker nullptr,
161*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32);
162*795d594fSAndroid Build Coastguard Worker }
163*795d594fSAndroid Build Coastguard Worker
164*795d594fSAndroid Build Coastguard Worker /** Constructs a geometric a * f^i + b induction. */
CreateGeometric(int32_t a,int32_t b,int32_t f,char op)165*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreateGeometric(int32_t a, int32_t b, int32_t f, char op) {
166*795d594fSAndroid Build Coastguard Worker return iva_->CreateInduction(HInductionVarAnalysis::kGeometric,
167*795d594fSAndroid Build Coastguard Worker op == '*' ? HInductionVarAnalysis::kMul
168*795d594fSAndroid Build Coastguard Worker : HInductionVarAnalysis::kDiv,
169*795d594fSAndroid Build Coastguard Worker CreateConst(a),
170*795d594fSAndroid Build Coastguard Worker CreateConst(b),
171*795d594fSAndroid Build Coastguard Worker graph_->GetIntConstant(f),
172*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32);
173*795d594fSAndroid Build Coastguard Worker }
174*795d594fSAndroid Build Coastguard Worker
175*795d594fSAndroid Build Coastguard Worker /** Constructs a range [lo, hi] using a periodic induction. */
CreateRange(int32_t lo,int32_t hi)176*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreateRange(int32_t lo, int32_t hi) {
177*795d594fSAndroid Build Coastguard Worker return iva_->CreateInduction(HInductionVarAnalysis::kPeriodic,
178*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::kNop,
179*795d594fSAndroid Build Coastguard Worker CreateConst(lo),
180*795d594fSAndroid Build Coastguard Worker CreateConst(hi),
181*795d594fSAndroid Build Coastguard Worker nullptr,
182*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32);
183*795d594fSAndroid Build Coastguard Worker }
184*795d594fSAndroid Build Coastguard Worker
185*795d594fSAndroid Build Coastguard Worker /** Constructs a wrap-around induction consisting of a constant, followed by info. */
CreateWrapAround(int32_t initial,HInductionVarAnalysis::InductionInfo * info)186*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreateWrapAround(
187*795d594fSAndroid Build Coastguard Worker int32_t initial,
188*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* info) {
189*795d594fSAndroid Build Coastguard Worker return iva_->CreateInduction(HInductionVarAnalysis::kWrapAround,
190*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::kNop,
191*795d594fSAndroid Build Coastguard Worker CreateConst(initial),
192*795d594fSAndroid Build Coastguard Worker info,
193*795d594fSAndroid Build Coastguard Worker nullptr,
194*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32);
195*795d594fSAndroid Build Coastguard Worker }
196*795d594fSAndroid Build Coastguard Worker
197*795d594fSAndroid Build Coastguard Worker /** Constructs a wrap-around induction consisting of a constant, followed by a range. */
CreateWrapAround(int32_t initial,int32_t lo,int32_t hi)198*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* CreateWrapAround(int32_t initial, int32_t lo, int32_t hi) {
199*795d594fSAndroid Build Coastguard Worker return CreateWrapAround(initial, CreateRange(lo, hi));
200*795d594fSAndroid Build Coastguard Worker }
201*795d594fSAndroid Build Coastguard Worker
202*795d594fSAndroid Build Coastguard Worker //
203*795d594fSAndroid Build Coastguard Worker // Relay methods.
204*795d594fSAndroid Build Coastguard Worker //
205*795d594fSAndroid Build Coastguard Worker
NeedsTripCount(HInductionVarAnalysis::InductionInfo * info)206*795d594fSAndroid Build Coastguard Worker bool NeedsTripCount(HInductionVarAnalysis::InductionInfo* info) {
207*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
208*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
209*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
210*795d594fSAndroid Build Coastguard Worker int64_t s = 0;
211*795d594fSAndroid Build Coastguard Worker return range_.NeedsTripCount(context, &loop, info, &s);
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker
IsBodyTripCount(HInductionVarAnalysis::InductionInfo * trip)214*795d594fSAndroid Build Coastguard Worker bool IsBodyTripCount(HInductionVarAnalysis::InductionInfo* trip) {
215*795d594fSAndroid Build Coastguard Worker return range_.IsBodyTripCount(trip);
216*795d594fSAndroid Build Coastguard Worker }
217*795d594fSAndroid Build Coastguard Worker
IsUnsafeTripCount(HInductionVarAnalysis::InductionInfo * trip)218*795d594fSAndroid Build Coastguard Worker bool IsUnsafeTripCount(HInductionVarAnalysis::InductionInfo* trip) {
219*795d594fSAndroid Build Coastguard Worker return range_.IsUnsafeTripCount(trip);
220*795d594fSAndroid Build Coastguard Worker }
221*795d594fSAndroid Build Coastguard Worker
GetMin(HInductionVarAnalysis::InductionInfo * info,HInductionVarAnalysis::InductionInfo * trip)222*795d594fSAndroid Build Coastguard Worker Value GetMin(HInductionVarAnalysis::InductionInfo* info,
223*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* trip) {
224*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
225*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
226*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
227*795d594fSAndroid Build Coastguard Worker return GetMin(context, &loop, info, trip);
228*795d594fSAndroid Build Coastguard Worker }
229*795d594fSAndroid Build Coastguard Worker
GetMin(HBasicBlock * context,HLoopInformation * loop,HInductionVarAnalysis::InductionInfo * info,HInductionVarAnalysis::InductionInfo * trip)230*795d594fSAndroid Build Coastguard Worker Value GetMin(HBasicBlock* context,
231*795d594fSAndroid Build Coastguard Worker HLoopInformation* loop,
232*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* info,
233*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* trip) {
234*795d594fSAndroid Build Coastguard Worker return range_.GetVal(context, loop, info, trip, /*is_min=*/ true);
235*795d594fSAndroid Build Coastguard Worker }
236*795d594fSAndroid Build Coastguard Worker
GetMax(HInductionVarAnalysis::InductionInfo * info,HInductionVarAnalysis::InductionInfo * trip)237*795d594fSAndroid Build Coastguard Worker Value GetMax(HInductionVarAnalysis::InductionInfo* info,
238*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* trip) {
239*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
240*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
241*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
242*795d594fSAndroid Build Coastguard Worker return GetMax(context, &loop, info, trip);
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker
GetMax(HBasicBlock * context,HLoopInformation * loop,HInductionVarAnalysis::InductionInfo * info,HInductionVarAnalysis::InductionInfo * trip)245*795d594fSAndroid Build Coastguard Worker Value GetMax(HBasicBlock* context,
246*795d594fSAndroid Build Coastguard Worker HLoopInformation* loop,
247*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* info,
248*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* trip) {
249*795d594fSAndroid Build Coastguard Worker return range_.GetVal(context, loop, info, trip, /*is_min=*/ false);
250*795d594fSAndroid Build Coastguard Worker }
251*795d594fSAndroid Build Coastguard Worker
GetMul(HInductionVarAnalysis::InductionInfo * info1,HInductionVarAnalysis::InductionInfo * info2,bool is_min)252*795d594fSAndroid Build Coastguard Worker Value GetMul(HInductionVarAnalysis::InductionInfo* info1,
253*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* info2,
254*795d594fSAndroid Build Coastguard Worker bool is_min) {
255*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
256*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
257*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
258*795d594fSAndroid Build Coastguard Worker return range_.GetMul(context, &loop, info1, info2, nullptr, is_min);
259*795d594fSAndroid Build Coastguard Worker }
260*795d594fSAndroid Build Coastguard Worker
GetDiv(HInductionVarAnalysis::InductionInfo * info1,HInductionVarAnalysis::InductionInfo * info2,bool is_min)261*795d594fSAndroid Build Coastguard Worker Value GetDiv(HInductionVarAnalysis::InductionInfo* info1,
262*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* info2,
263*795d594fSAndroid Build Coastguard Worker bool is_min) {
264*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
265*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
266*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
267*795d594fSAndroid Build Coastguard Worker return range_.GetDiv(context, &loop, info1, info2, nullptr, is_min);
268*795d594fSAndroid Build Coastguard Worker }
269*795d594fSAndroid Build Coastguard Worker
GetRem(HInductionVarAnalysis::InductionInfo * info1,HInductionVarAnalysis::InductionInfo * info2)270*795d594fSAndroid Build Coastguard Worker Value GetRem(HInductionVarAnalysis::InductionInfo* info1,
271*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* info2) {
272*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
273*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
274*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
275*795d594fSAndroid Build Coastguard Worker return range_.GetRem(context, &loop, info1, info2);
276*795d594fSAndroid Build Coastguard Worker }
277*795d594fSAndroid Build Coastguard Worker
GetXor(HInductionVarAnalysis::InductionInfo * info1,HInductionVarAnalysis::InductionInfo * info2)278*795d594fSAndroid Build Coastguard Worker Value GetXor(HInductionVarAnalysis::InductionInfo* info1,
279*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis::InductionInfo* info2) {
280*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
281*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
282*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
283*795d594fSAndroid Build Coastguard Worker return range_.GetXor(context, &loop, info1, info2);
284*795d594fSAndroid Build Coastguard Worker }
285*795d594fSAndroid Build Coastguard Worker
IsExact(HInductionVarAnalysis::InductionInfo * info,int64_t * value)286*795d594fSAndroid Build Coastguard Worker bool IsExact(HInductionVarAnalysis::InductionInfo* info, int64_t* value) {
287*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
288*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
289*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
290*795d594fSAndroid Build Coastguard Worker return range_.IsConstant(context, &loop, info, InductionVarRange::kExact, value);
291*795d594fSAndroid Build Coastguard Worker }
292*795d594fSAndroid Build Coastguard Worker
IsAtMost(HInductionVarAnalysis::InductionInfo * info,int64_t * value)293*795d594fSAndroid Build Coastguard Worker bool IsAtMost(HInductionVarAnalysis::InductionInfo* info, int64_t* value) {
294*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
295*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
296*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
297*795d594fSAndroid Build Coastguard Worker return range_.IsConstant(context, &loop, info, InductionVarRange::kAtMost, value);
298*795d594fSAndroid Build Coastguard Worker }
299*795d594fSAndroid Build Coastguard Worker
IsAtLeast(HInductionVarAnalysis::InductionInfo * info,int64_t * value)300*795d594fSAndroid Build Coastguard Worker bool IsAtLeast(HInductionVarAnalysis::InductionInfo* info, int64_t* value) {
301*795d594fSAndroid Build Coastguard Worker // Use bogus loop information and context out of the bogus loop.
302*795d594fSAndroid Build Coastguard Worker HLoopInformation loop(exit_block_, graph_);
303*795d594fSAndroid Build Coastguard Worker HBasicBlock* context = entry_block_;
304*795d594fSAndroid Build Coastguard Worker return range_.IsConstant(context, &loop, info, InductionVarRange::kAtLeast, value);
305*795d594fSAndroid Build Coastguard Worker }
306*795d594fSAndroid Build Coastguard Worker
AddValue(Value v1,Value v2)307*795d594fSAndroid Build Coastguard Worker Value AddValue(Value v1, Value v2) { return range_.AddValue(v1, v2); }
SubValue(Value v1,Value v2)308*795d594fSAndroid Build Coastguard Worker Value SubValue(Value v1, Value v2) { return range_.SubValue(v1, v2); }
MulValue(Value v1,Value v2)309*795d594fSAndroid Build Coastguard Worker Value MulValue(Value v1, Value v2) { return range_.MulValue(v1, v2); }
DivValue(Value v1,Value v2)310*795d594fSAndroid Build Coastguard Worker Value DivValue(Value v1, Value v2) { return range_.DivValue(v1, v2); }
MinValue(Value v1,Value v2)311*795d594fSAndroid Build Coastguard Worker Value MinValue(Value v1, Value v2) { return range_.MergeVal(v1, v2, true); }
MaxValue(Value v1,Value v2)312*795d594fSAndroid Build Coastguard Worker Value MaxValue(Value v1, Value v2) { return range_.MergeVal(v1, v2, false); }
313*795d594fSAndroid Build Coastguard Worker
314*795d594fSAndroid Build Coastguard Worker // General building fields.
315*795d594fSAndroid Build Coastguard Worker HBasicBlock* return_block_;
316*795d594fSAndroid Build Coastguard Worker HBasicBlock* loop_preheader_;
317*795d594fSAndroid Build Coastguard Worker HBasicBlock* loop_header_;
318*795d594fSAndroid Build Coastguard Worker HBasicBlock* loop_body_;
319*795d594fSAndroid Build Coastguard Worker HInductionVarAnalysis* iva_;
320*795d594fSAndroid Build Coastguard Worker InductionVarRange range_;
321*795d594fSAndroid Build Coastguard Worker
322*795d594fSAndroid Build Coastguard Worker // Instructions.
323*795d594fSAndroid Build Coastguard Worker HInstruction* condition_;
324*795d594fSAndroid Build Coastguard Worker HInstruction* increment_;
325*795d594fSAndroid Build Coastguard Worker HInstruction* x_;
326*795d594fSAndroid Build Coastguard Worker HInstruction* y_;
327*795d594fSAndroid Build Coastguard Worker };
328*795d594fSAndroid Build Coastguard Worker
329*795d594fSAndroid Build Coastguard Worker //
330*795d594fSAndroid Build Coastguard Worker // Tests on private methods.
331*795d594fSAndroid Build Coastguard Worker //
332*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,IsConstant)333*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, IsConstant) {
334*795d594fSAndroid Build Coastguard Worker int64_t value;
335*795d594fSAndroid Build Coastguard Worker // Constant.
336*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsExact(CreateConst(12345), &value));
337*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(12345, value);
338*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsAtMost(CreateConst(12345), &value));
339*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(12345, value);
340*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsAtLeast(CreateConst(12345), &value));
341*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(12345, value);
342*795d594fSAndroid Build Coastguard Worker // Constant trivial range.
343*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsExact(CreateRange(111, 111), &value));
344*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(111, value);
345*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsAtMost(CreateRange(111, 111), &value));
346*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(111, value);
347*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsAtLeast(CreateRange(111, 111), &value));
348*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(111, value);
349*795d594fSAndroid Build Coastguard Worker // Constant non-trivial range.
350*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsExact(CreateRange(11, 22), &value));
351*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsAtMost(CreateRange(11, 22), &value));
352*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(22, value);
353*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsAtLeast(CreateRange(11, 22), &value));
354*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(11, value);
355*795d594fSAndroid Build Coastguard Worker // Symbolic.
356*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsExact(CreateFetch(x_), &value));
357*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsAtMost(CreateFetch(x_), &value));
358*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsAtLeast(CreateFetch(x_), &value));
359*795d594fSAndroid Build Coastguard Worker }
360*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,TripCountProperties)361*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, TripCountProperties) {
362*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(NeedsTripCount(nullptr));
363*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(NeedsTripCount(CreateConst(1)));
364*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(NeedsTripCount(CreateLinear(1, 1)));
365*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(NeedsTripCount(CreateWrapAround(1, 2, 3)));
366*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(NeedsTripCount(CreateWrapAround(1, CreateLinear(1, 1))));
367*795d594fSAndroid Build Coastguard Worker
368*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsBodyTripCount(nullptr));
369*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsBodyTripCount(CreateTripCount(100, true, true)));
370*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsBodyTripCount(CreateTripCount(100, true, false)));
371*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsBodyTripCount(CreateTripCount(100, false, true)));
372*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsBodyTripCount(CreateTripCount(100, false, false)));
373*795d594fSAndroid Build Coastguard Worker
374*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsUnsafeTripCount(nullptr));
375*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsUnsafeTripCount(CreateTripCount(100, true, true)));
376*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsUnsafeTripCount(CreateTripCount(100, true, false)));
377*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(IsUnsafeTripCount(CreateTripCount(100, false, true)));
378*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(IsUnsafeTripCount(CreateTripCount(100, false, false)));
379*795d594fSAndroid Build Coastguard Worker }
380*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxNull)381*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxNull) {
382*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMin(nullptr, nullptr));
383*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMax(nullptr, nullptr));
384*795d594fSAndroid Build Coastguard Worker }
385*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxAdd)386*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxAdd) {
387*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(12),
388*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('+', CreateConst(2), CreateRange(10, 20)), nullptr));
389*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(22),
390*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('+', CreateConst(2), CreateRange(10, 20)), nullptr));
391*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -20),
392*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('+', CreateFetch(x_), CreateRange(-20, -10)), nullptr));
393*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -10),
394*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('+', CreateFetch(x_), CreateRange(-20, -10)), nullptr));
395*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 10),
396*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('+', CreateRange(10, 20), CreateFetch(x_)), nullptr));
397*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 20),
398*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('+', CreateRange(10, 20), CreateFetch(x_)), nullptr));
399*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(5),
400*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('+', CreateRange(-5, -1), CreateRange(10, 20)), nullptr));
401*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(19),
402*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('+', CreateRange(-5, -1), CreateRange(10, 20)), nullptr));
403*795d594fSAndroid Build Coastguard Worker }
404*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxSub)405*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxSub) {
406*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-18),
407*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('-', CreateConst(2), CreateRange(10, 20)), nullptr));
408*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-8),
409*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('-', CreateConst(2), CreateRange(10, 20)), nullptr));
410*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 10),
411*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('-', CreateFetch(x_), CreateRange(-20, -10)), nullptr));
412*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 20),
413*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('-', CreateFetch(x_), CreateRange(-20, -10)), nullptr));
414*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, -1, 10),
415*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('-', CreateRange(10, 20), CreateFetch(x_)), nullptr));
416*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, -1, 20),
417*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('-', CreateRange(10, 20), CreateFetch(x_)), nullptr));
418*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-25),
419*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('-', CreateRange(-5, -1), CreateRange(10, 20)), nullptr));
420*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-11),
421*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('-', CreateRange(-5, -1), CreateRange(10, 20)), nullptr));
422*795d594fSAndroid Build Coastguard Worker }
423*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxNeg)424*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxNeg) {
425*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-20), GetMin(CreateInvariant('n', nullptr, CreateRange(10, 20)), nullptr));
426*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-10), GetMax(CreateInvariant('n', nullptr, CreateRange(10, 20)), nullptr));
427*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(10), GetMin(CreateInvariant('n', nullptr, CreateRange(-20, -10)), nullptr));
428*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(20), GetMax(CreateInvariant('n', nullptr, CreateRange(-20, -10)), nullptr));
429*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, -1, 0), GetMin(CreateInvariant('n', nullptr, CreateFetch(x_)), nullptr));
430*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, -1, 0), GetMax(CreateInvariant('n', nullptr, CreateFetch(x_)), nullptr));
431*795d594fSAndroid Build Coastguard Worker }
432*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxMul)433*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxMul) {
434*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(20),
435*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('*', CreateConst(2), CreateRange(10, 20)), nullptr));
436*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(40),
437*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('*', CreateConst(2), CreateRange(10, 20)), nullptr));
438*795d594fSAndroid Build Coastguard Worker }
439*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxDiv)440*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxDiv) {
441*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(3),
442*795d594fSAndroid Build Coastguard Worker GetMin(CreateInvariant('/', CreateRange(12, 20), CreateConst(4)), nullptr));
443*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(5),
444*795d594fSAndroid Build Coastguard Worker GetMax(CreateInvariant('/', CreateRange(12, 20), CreateConst(4)), nullptr));
445*795d594fSAndroid Build Coastguard Worker }
446*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxConstant)447*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxConstant) {
448*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(12345), GetMin(CreateConst(12345), nullptr));
449*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(12345), GetMax(CreateConst(12345), nullptr));
450*795d594fSAndroid Build Coastguard Worker }
451*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxFetch)452*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxFetch) {
453*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 0), GetMin(CreateFetch(x_), nullptr));
454*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 0), GetMax(CreateFetch(x_), nullptr));
455*795d594fSAndroid Build Coastguard Worker }
456*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxLinear)457*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxLinear) {
458*795d594fSAndroid Build Coastguard Worker BuildLoop(0, graph_->GetIntConstant(100), 1);
459*795d594fSAndroid Build Coastguard Worker PerformInductionVarAnalysis();
460*795d594fSAndroid Build Coastguard Worker HLoopInformation* loop = loop_header_->GetLoopInformation();
461*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loop != nullptr);
462*795d594fSAndroid Build Coastguard Worker
463*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(20),
464*795d594fSAndroid Build Coastguard Worker GetMin(loop_header_, loop, CreateLinear(10, 20), CreateTripCount(100, true, true)));
465*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1020),
466*795d594fSAndroid Build Coastguard Worker GetMax(loop_header_, loop, CreateLinear(10, 20), CreateTripCount(100, true, true)));
467*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(20),
468*795d594fSAndroid Build Coastguard Worker GetMin(loop_body_, loop, CreateLinear(10, 20), CreateTripCount(100, true, true)));
469*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1010),
470*795d594fSAndroid Build Coastguard Worker GetMax(loop_body_, loop, CreateLinear(10, 20), CreateTripCount(100, true, true)));
471*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1020),
472*795d594fSAndroid Build Coastguard Worker GetMin(exit_block_, loop, CreateLinear(10, 20), CreateTripCount(100, true, true)));
473*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1020),
474*795d594fSAndroid Build Coastguard Worker GetMax(exit_block_, loop, CreateLinear(10, 20), CreateTripCount(100, true, true)));
475*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(20),
476*795d594fSAndroid Build Coastguard Worker GetMin(entry_block_, loop, CreateLinear(10, 20), CreateTripCount(100, true, true)));
477*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(),
478*795d594fSAndroid Build Coastguard Worker GetMax(entry_block_, loop, CreateLinear(10, 20), CreateTripCount(100, true, true)));
479*795d594fSAndroid Build Coastguard Worker
480*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-980),
481*795d594fSAndroid Build Coastguard Worker GetMin(loop_header_, loop, CreateLinear(-10, 20), CreateTripCount(100, true, true)));
482*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(20),
483*795d594fSAndroid Build Coastguard Worker GetMax(loop_header_, loop, CreateLinear(-10, 20), CreateTripCount(100, true, true)));
484*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-970),
485*795d594fSAndroid Build Coastguard Worker GetMin(loop_body_, loop, CreateLinear(-10, 20), CreateTripCount(100, true, true)));
486*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(20),
487*795d594fSAndroid Build Coastguard Worker GetMax(loop_body_, loop, CreateLinear(-10, 20), CreateTripCount(100, true, true)));
488*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-980),
489*795d594fSAndroid Build Coastguard Worker GetMin(exit_block_, loop, CreateLinear(-10, 20), CreateTripCount(100, true, true)));
490*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-980),
491*795d594fSAndroid Build Coastguard Worker GetMax(exit_block_, loop, CreateLinear(-10, 20), CreateTripCount(100, true, true)));
492*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(),
493*795d594fSAndroid Build Coastguard Worker GetMin(entry_block_, loop, CreateLinear(-10, 20), CreateTripCount(100, true, true)));
494*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(20),
495*795d594fSAndroid Build Coastguard Worker GetMax(entry_block_, loop, CreateLinear(-10, 20), CreateTripCount(100, true, true)));
496*795d594fSAndroid Build Coastguard Worker }
497*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxWrapAround)498*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxWrapAround) {
499*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-5), GetMin(CreateWrapAround(-5, -1, 10), nullptr));
500*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(10), GetMax(CreateWrapAround(-5, -1, 10), nullptr));
501*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-1), GetMin(CreateWrapAround(2, -1, 10), nullptr));
502*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(10), GetMax(CreateWrapAround(2, -1, 10), nullptr));
503*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-1), GetMin(CreateWrapAround(20, -1, 10), nullptr));
504*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(20), GetMax(CreateWrapAround(20, -1, 10), nullptr));
505*795d594fSAndroid Build Coastguard Worker }
506*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxPolynomial)507*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxPolynomial) {
508*795d594fSAndroid Build Coastguard Worker BuildLoop(0, graph_->GetIntConstant(100), 1);
509*795d594fSAndroid Build Coastguard Worker PerformInductionVarAnalysis();
510*795d594fSAndroid Build Coastguard Worker HLoopInformation* loop = loop_header_->GetLoopInformation();
511*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loop != nullptr);
512*795d594fSAndroid Build Coastguard Worker
513*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMin(CreatePolynomial(3, 5, 7), nullptr));
514*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMax(CreatePolynomial(3, 5, 7), nullptr));
515*795d594fSAndroid Build Coastguard Worker
516*795d594fSAndroid Build Coastguard Worker ExpectEqual(
517*795d594fSAndroid Build Coastguard Worker Value(7),
518*795d594fSAndroid Build Coastguard Worker GetMin(loop_header_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
519*795d594fSAndroid Build Coastguard Worker ExpectEqual(
520*795d594fSAndroid Build Coastguard Worker Value(62),
521*795d594fSAndroid Build Coastguard Worker GetMax(loop_header_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
522*795d594fSAndroid Build Coastguard Worker ExpectEqual(
523*795d594fSAndroid Build Coastguard Worker Value(7),
524*795d594fSAndroid Build Coastguard Worker GetMin(loop_body_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
525*795d594fSAndroid Build Coastguard Worker ExpectEqual(
526*795d594fSAndroid Build Coastguard Worker Value(45),
527*795d594fSAndroid Build Coastguard Worker GetMax(loop_body_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
528*795d594fSAndroid Build Coastguard Worker ExpectEqual(
529*795d594fSAndroid Build Coastguard Worker Value(62),
530*795d594fSAndroid Build Coastguard Worker GetMin(exit_block_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
531*795d594fSAndroid Build Coastguard Worker ExpectEqual(
532*795d594fSAndroid Build Coastguard Worker Value(62),
533*795d594fSAndroid Build Coastguard Worker GetMax(exit_block_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
534*795d594fSAndroid Build Coastguard Worker ExpectEqual(
535*795d594fSAndroid Build Coastguard Worker Value(7),
536*795d594fSAndroid Build Coastguard Worker GetMin(entry_block_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
537*795d594fSAndroid Build Coastguard Worker ExpectEqual(
538*795d594fSAndroid Build Coastguard Worker Value(),
539*795d594fSAndroid Build Coastguard Worker GetMax(entry_block_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(5, true, true)));
540*795d594fSAndroid Build Coastguard Worker
541*795d594fSAndroid Build Coastguard Worker ExpectEqual(
542*795d594fSAndroid Build Coastguard Worker Value(7),
543*795d594fSAndroid Build Coastguard Worker GetMin(loop_header_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
544*795d594fSAndroid Build Coastguard Worker ExpectEqual(
545*795d594fSAndroid Build Coastguard Worker Value(192),
546*795d594fSAndroid Build Coastguard Worker GetMax(loop_header_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
547*795d594fSAndroid Build Coastguard Worker ExpectEqual(
548*795d594fSAndroid Build Coastguard Worker Value(7),
549*795d594fSAndroid Build Coastguard Worker GetMin(loop_body_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
550*795d594fSAndroid Build Coastguard Worker ExpectEqual(
551*795d594fSAndroid Build Coastguard Worker Value(160),
552*795d594fSAndroid Build Coastguard Worker GetMax(loop_body_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
553*795d594fSAndroid Build Coastguard Worker ExpectEqual(
554*795d594fSAndroid Build Coastguard Worker Value(192),
555*795d594fSAndroid Build Coastguard Worker GetMin(exit_block_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
556*795d594fSAndroid Build Coastguard Worker ExpectEqual(
557*795d594fSAndroid Build Coastguard Worker Value(192),
558*795d594fSAndroid Build Coastguard Worker GetMax(exit_block_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
559*795d594fSAndroid Build Coastguard Worker ExpectEqual(
560*795d594fSAndroid Build Coastguard Worker Value(7),
561*795d594fSAndroid Build Coastguard Worker GetMin(entry_block_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
562*795d594fSAndroid Build Coastguard Worker ExpectEqual(
563*795d594fSAndroid Build Coastguard Worker Value(),
564*795d594fSAndroid Build Coastguard Worker GetMax(entry_block_, loop, CreatePolynomial(3, 5, 7), CreateTripCount(10, true, true)));
565*795d594fSAndroid Build Coastguard Worker
566*795d594fSAndroid Build Coastguard Worker ExpectEqual(
567*795d594fSAndroid Build Coastguard Worker Value(-7),
568*795d594fSAndroid Build Coastguard Worker GetMin(loop_header_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(5, true, true)));
569*795d594fSAndroid Build Coastguard Worker ExpectEqual(
570*795d594fSAndroid Build Coastguard Worker Value(168),
571*795d594fSAndroid Build Coastguard Worker GetMax(loop_header_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(5, true, true)));
572*795d594fSAndroid Build Coastguard Worker ExpectEqual(
573*795d594fSAndroid Build Coastguard Worker Value(-7),
574*795d594fSAndroid Build Coastguard Worker GetMin(loop_body_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(5, true, true)));
575*795d594fSAndroid Build Coastguard Worker ExpectEqual(
576*795d594fSAndroid Build Coastguard Worker Value(111),
577*795d594fSAndroid Build Coastguard Worker GetMax(loop_body_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(5, true, true)));
578*795d594fSAndroid Build Coastguard Worker ExpectEqual(
579*795d594fSAndroid Build Coastguard Worker Value(168),
580*795d594fSAndroid Build Coastguard Worker GetMin(exit_block_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(5, true, true)));
581*795d594fSAndroid Build Coastguard Worker ExpectEqual(
582*795d594fSAndroid Build Coastguard Worker Value(168),
583*795d594fSAndroid Build Coastguard Worker GetMax(exit_block_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(5, true, true)));
584*795d594fSAndroid Build Coastguard Worker ExpectEqual(
585*795d594fSAndroid Build Coastguard Worker Value(-7),
586*795d594fSAndroid Build Coastguard Worker GetMin(entry_block_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(5, true, true)));
587*795d594fSAndroid Build Coastguard Worker ExpectEqual(
588*795d594fSAndroid Build Coastguard Worker Value(),
589*795d594fSAndroid Build Coastguard Worker GetMax(entry_block_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(5, true, true)));
590*795d594fSAndroid Build Coastguard Worker
591*795d594fSAndroid Build Coastguard Worker ExpectEqual(
592*795d594fSAndroid Build Coastguard Worker Value(-7),
593*795d594fSAndroid Build Coastguard Worker GetMin(loop_header_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(10, true, true)));
594*795d594fSAndroid Build Coastguard Worker ExpectEqual(
595*795d594fSAndroid Build Coastguard Worker Value(618),
596*795d594fSAndroid Build Coastguard Worker GetMax(loop_header_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(10, true, true)));
597*795d594fSAndroid Build Coastguard Worker ExpectEqual(
598*795d594fSAndroid Build Coastguard Worker Value(-7),
599*795d594fSAndroid Build Coastguard Worker GetMin(loop_body_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(10, true, true)));
600*795d594fSAndroid Build Coastguard Worker ExpectEqual(
601*795d594fSAndroid Build Coastguard Worker Value(506),
602*795d594fSAndroid Build Coastguard Worker GetMax(loop_body_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(10, true, true)));
603*795d594fSAndroid Build Coastguard Worker ExpectEqual(
604*795d594fSAndroid Build Coastguard Worker Value(618),
605*795d594fSAndroid Build Coastguard Worker GetMin(exit_block_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(10, true, true)));
606*795d594fSAndroid Build Coastguard Worker ExpectEqual(
607*795d594fSAndroid Build Coastguard Worker Value(618),
608*795d594fSAndroid Build Coastguard Worker GetMax(exit_block_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(10, true, true)));
609*795d594fSAndroid Build Coastguard Worker ExpectEqual(
610*795d594fSAndroid Build Coastguard Worker Value(-7),
611*795d594fSAndroid Build Coastguard Worker GetMin(entry_block_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(10, true, true)));
612*795d594fSAndroid Build Coastguard Worker ExpectEqual(
613*795d594fSAndroid Build Coastguard Worker Value(),
614*795d594fSAndroid Build Coastguard Worker GetMax(entry_block_, loop, CreatePolynomial(11, 13, -7), CreateTripCount(10, true, true)));
615*795d594fSAndroid Build Coastguard Worker
616*795d594fSAndroid Build Coastguard Worker ExpectEqual(
617*795d594fSAndroid Build Coastguard Worker Value(),
618*795d594fSAndroid Build Coastguard Worker GetMin(loop_header_, loop, CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
619*795d594fSAndroid Build Coastguard Worker ExpectEqual(
620*795d594fSAndroid Build Coastguard Worker Value(),
621*795d594fSAndroid Build Coastguard Worker GetMax(loop_header_, loop, CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
622*795d594fSAndroid Build Coastguard Worker ExpectEqual(
623*795d594fSAndroid Build Coastguard Worker Value(),
624*795d594fSAndroid Build Coastguard Worker GetMin(loop_body_, loop, CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
625*795d594fSAndroid Build Coastguard Worker ExpectEqual(
626*795d594fSAndroid Build Coastguard Worker Value(),
627*795d594fSAndroid Build Coastguard Worker GetMax(loop_body_, loop, CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
628*795d594fSAndroid Build Coastguard Worker ExpectEqual(
629*795d594fSAndroid Build Coastguard Worker Value(),
630*795d594fSAndroid Build Coastguard Worker GetMin(exit_block_, loop, CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
631*795d594fSAndroid Build Coastguard Worker ExpectEqual(
632*795d594fSAndroid Build Coastguard Worker Value(),
633*795d594fSAndroid Build Coastguard Worker GetMax(exit_block_, loop, CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
634*795d594fSAndroid Build Coastguard Worker ExpectEqual(
635*795d594fSAndroid Build Coastguard Worker Value(),
636*795d594fSAndroid Build Coastguard Worker GetMin(entry_block_, loop, CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
637*795d594fSAndroid Build Coastguard Worker ExpectEqual(
638*795d594fSAndroid Build Coastguard Worker Value(),
639*795d594fSAndroid Build Coastguard Worker GetMax(entry_block_, loop, CreatePolynomial(-3, 5, 7), CreateTripCount(10, true, true)));
640*795d594fSAndroid Build Coastguard Worker
641*795d594fSAndroid Build Coastguard Worker ExpectEqual(
642*795d594fSAndroid Build Coastguard Worker Value(),
643*795d594fSAndroid Build Coastguard Worker GetMin(loop_header_, loop, CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
644*795d594fSAndroid Build Coastguard Worker ExpectEqual(
645*795d594fSAndroid Build Coastguard Worker Value(),
646*795d594fSAndroid Build Coastguard Worker GetMax(loop_header_, loop, CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
647*795d594fSAndroid Build Coastguard Worker ExpectEqual(
648*795d594fSAndroid Build Coastguard Worker Value(),
649*795d594fSAndroid Build Coastguard Worker GetMin(loop_body_, loop, CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
650*795d594fSAndroid Build Coastguard Worker ExpectEqual(
651*795d594fSAndroid Build Coastguard Worker Value(),
652*795d594fSAndroid Build Coastguard Worker GetMax(loop_body_, loop, CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
653*795d594fSAndroid Build Coastguard Worker ExpectEqual(
654*795d594fSAndroid Build Coastguard Worker Value(),
655*795d594fSAndroid Build Coastguard Worker GetMin(exit_block_, loop, CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
656*795d594fSAndroid Build Coastguard Worker ExpectEqual(
657*795d594fSAndroid Build Coastguard Worker Value(),
658*795d594fSAndroid Build Coastguard Worker GetMax(exit_block_, loop, CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
659*795d594fSAndroid Build Coastguard Worker ExpectEqual(
660*795d594fSAndroid Build Coastguard Worker Value(),
661*795d594fSAndroid Build Coastguard Worker GetMin(entry_block_, loop, CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
662*795d594fSAndroid Build Coastguard Worker ExpectEqual(
663*795d594fSAndroid Build Coastguard Worker Value(),
664*795d594fSAndroid Build Coastguard Worker GetMax(entry_block_, loop, CreatePolynomial(3, -5, 7), CreateTripCount(10, true, true)));
665*795d594fSAndroid Build Coastguard Worker }
666*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxGeometricMul)667*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxGeometricMul) {
668*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMin(CreateGeometric(1, 1, 1, '*'), nullptr));
669*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMax(CreateGeometric(1, 1, 1, '*'), nullptr));
670*795d594fSAndroid Build Coastguard Worker }
671*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxGeometricDiv)672*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxGeometricDiv) {
673*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(5), GetMin(CreateGeometric(11, 5, 3, '/'), nullptr));
674*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(16), GetMax(CreateGeometric(11, 5, 3, '/'), nullptr));
675*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-5), GetMin(CreateGeometric(11, -5, 3, '/'), nullptr));
676*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(6), GetMax(CreateGeometric(11, -5, 3, '/'), nullptr));
677*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-6), GetMin(CreateGeometric(-11, 5, 3, '/'), nullptr));
678*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(5), GetMax(CreateGeometric(-11, 5, 3, '/'), nullptr));
679*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-16), GetMin(CreateGeometric(-11, -5, 3, '/'), nullptr));
680*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-5), GetMax(CreateGeometric(-11, -5, 3, '/'), nullptr));
681*795d594fSAndroid Build Coastguard Worker }
682*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxPeriodic)683*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxPeriodic) {
684*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-2), GetMin(CreateRange(-2, 99), nullptr));
685*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(99), GetMax(CreateRange(-2, 99), nullptr));
686*795d594fSAndroid Build Coastguard Worker }
687*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMulMin)688*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMulMin) {
689*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-14), GetMul(CreateConst(2), CreateRange(-7, 8), true));
690*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-16), GetMul(CreateConst(-2), CreateRange(-7, 8), true));
691*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-14), GetMul(CreateRange(-7, 8), CreateConst(2), true));
692*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-16), GetMul(CreateRange(-7, 8), CreateConst(-2), true));
693*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(6), GetMul(CreateRange(2, 10), CreateRange(3, 5), true));
694*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-50), GetMul(CreateRange(2, 10), CreateRange(-5, -3), true));
695*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(2, 10), CreateRange(-1, 1), true));
696*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-50), GetMul(CreateRange(-10, -2), CreateRange(3, 5), true));
697*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(6), GetMul(CreateRange(-10, -2), CreateRange(-5, -3), true));
698*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(-10, -2), CreateRange(-1, 1), true));
699*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(2, 10), true));
700*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(-10, -2), true));
701*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(-1, 1), true));
702*795d594fSAndroid Build Coastguard Worker }
703*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMulMax)704*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMulMax) {
705*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(16), GetMul(CreateConst(2), CreateRange(-7, 8), false));
706*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(14), GetMul(CreateConst(-2), CreateRange(-7, 8), false));
707*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(16), GetMul(CreateRange(-7, 8), CreateConst(2), false));
708*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(14), GetMul(CreateRange(-7, 8), CreateConst(-2), false));
709*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(50), GetMul(CreateRange(2, 10), CreateRange(3, 5), false));
710*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-6), GetMul(CreateRange(2, 10), CreateRange(-5, -3), false));
711*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(2, 10), CreateRange(-1, 1), false));
712*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-6), GetMul(CreateRange(-10, -2), CreateRange(3, 5), false));
713*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(50), GetMul(CreateRange(-10, -2), CreateRange(-5, -3), false));
714*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(-10, -2), CreateRange(-1, 1), false));
715*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(2, 10), false));
716*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(-10, -2), false));
717*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMul(CreateRange(-1, 1), CreateRange(-1, 1), false));
718*795d594fSAndroid Build Coastguard Worker }
719*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetDivMin)720*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetDivMin) {
721*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-5), GetDiv(CreateRange(-10, 20), CreateConst(2), true));
722*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-10), GetDiv(CreateRange(-10, 20), CreateConst(-2), true));
723*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(10), GetDiv(CreateRange(40, 1000), CreateRange(2, 4), true));
724*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-500), GetDiv(CreateRange(40, 1000), CreateRange(-4, -2), true));
725*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(40, 1000), CreateRange(-1, 1), true));
726*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-500), GetDiv(CreateRange(-1000, -40), CreateRange(2, 4), true));
727*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(10), GetDiv(CreateRange(-1000, -40), CreateRange(-4, -2), true));
728*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(-1000, -40), CreateRange(-1, 1), true));
729*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(40, 1000), true));
730*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(-1000, -40), true));
731*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(-1, 1), true));
732*795d594fSAndroid Build Coastguard Worker }
733*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetDivMax)734*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetDivMax) {
735*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(10), GetDiv(CreateRange(-10, 20), CreateConst(2), false));
736*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(5), GetDiv(CreateRange(-10, 20), CreateConst(-2), false));
737*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(500), GetDiv(CreateRange(40, 1000), CreateRange(2, 4), false));
738*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-10), GetDiv(CreateRange(40, 1000), CreateRange(-4, -2), false));
739*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(40, 1000), CreateRange(-1, 1), false));
740*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-10), GetDiv(CreateRange(-1000, -40), CreateRange(2, 4), false));
741*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(500), GetDiv(CreateRange(-1000, -40), CreateRange(-4, -2), false));
742*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(-1000, -40), CreateRange(-1, 1), false));
743*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(40, 1000), false));
744*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(-1000, 40), false));
745*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetDiv(CreateRange(-1, 1), CreateRange(-1, 1), false));
746*795d594fSAndroid Build Coastguard Worker }
747*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxRem)748*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxRem) {
749*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMin(CreateInvariant('%', CreateConst(2), CreateRange(10, 20)), nullptr));
750*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMax(CreateInvariant('%', CreateConst(2), CreateRange(10, 20)), nullptr));
751*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMin(CreateInvariant('%', CreateRange(10, 20), CreateConst(2)), nullptr));
752*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMax(CreateInvariant('%', CreateRange(10, 20), CreateConst(2)), nullptr));
753*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(2), GetMin(CreateInvariant('%', CreateConst(2), CreateConst(5)), nullptr));
754*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(2), GetMax(CreateInvariant('%', CreateConst(2), CreateConst(5)), nullptr));
755*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), GetMin(CreateInvariant('%', CreateConst(11), CreateConst(5)), nullptr));
756*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), GetMax(CreateInvariant('%', CreateConst(11), CreateConst(5)), nullptr));
757*795d594fSAndroid Build Coastguard Worker }
758*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetRem)759*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetRem) {
760*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), GetRem(CreateConst(1), CreateConst(1)));
761*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(2), GetRem(CreateConst(2), CreateConst(5)));
762*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), GetRem(CreateConst(11), CreateConst(5)));
763*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-2), GetRem(CreateConst(-2), CreateConst(5)));
764*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-1), GetRem(CreateConst(-11), CreateConst(5)));
765*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(2), GetRem(CreateConst(2), CreateConst(-5)));
766*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), GetRem(CreateConst(11), CreateConst(-5)));
767*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-2), GetRem(CreateConst(-2), CreateConst(-5)));
768*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-1), GetRem(CreateConst(-11), CreateConst(-5)));
769*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetRem(CreateConst(1), CreateConst(0)));
770*795d594fSAndroid Build Coastguard Worker }
771*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetMinMaxXor)772*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetMinMaxXor) {
773*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMin(CreateInvariant('^', CreateConst(2), CreateRange(10, 20)), nullptr));
774*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMax(CreateInvariant('^', CreateConst(2), CreateRange(10, 20)), nullptr));
775*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMin(CreateInvariant('^', CreateRange(10, 20), CreateConst(2)), nullptr));
776*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), GetMax(CreateInvariant('^', CreateRange(10, 20), CreateConst(2)), nullptr));
777*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(3), GetMin(CreateInvariant('^', CreateConst(1), CreateConst(2)), nullptr));
778*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(3), GetMax(CreateInvariant('^', CreateConst(1), CreateConst(2)), nullptr));
779*795d594fSAndroid Build Coastguard Worker }
780*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,GetXor)781*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, GetXor) {
782*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), GetXor(CreateConst(1), CreateConst(1)));
783*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(3), GetXor(CreateConst(1), CreateConst(2)));
784*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-2), GetXor(CreateConst(1), CreateConst(-1)));
785*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), GetXor(CreateConst(-1), CreateConst(-1)));
786*795d594fSAndroid Build Coastguard Worker }
787*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,AddValue)788*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, AddValue) {
789*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(110), AddValue(Value(10), Value(100)));
790*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-5), AddValue(Value(x_, 1, -4), Value(x_, -1, -1)));
791*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 3, -5), AddValue(Value(x_, 2, -4), Value(x_, 1, -1)));
792*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), AddValue(Value(x_, 1, 5), Value(y_, 1, -7)));
793*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 23), AddValue(Value(x_, 1, 20), Value(3)));
794*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(y_, 1, 5), AddValue(Value(55), Value(y_, 1, -50)));
795*795d594fSAndroid Build Coastguard Worker const int32_t max_value = std::numeric_limits<int32_t>::max();
796*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(max_value), AddValue(Value(max_value - 5), Value(5)));
797*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), AddValue(Value(max_value - 5), Value(6))); // unsafe
798*795d594fSAndroid Build Coastguard Worker }
799*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,SubValue)800*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, SubValue) {
801*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-90), SubValue(Value(10), Value(100)));
802*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-3), SubValue(Value(x_, 1, -4), Value(x_, 1, -1)));
803*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 2, -3), SubValue(Value(x_, 3, -4), Value(x_, 1, -1)));
804*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), SubValue(Value(x_, 1, 5), Value(y_, 1, -7)));
805*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 17), SubValue(Value(x_, 1, 20), Value(3)));
806*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(y_, -4, 105), SubValue(Value(55), Value(y_, 4, -50)));
807*795d594fSAndroid Build Coastguard Worker const int32_t min_value = std::numeric_limits<int32_t>::min();
808*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(min_value), SubValue(Value(min_value + 5), Value(5)));
809*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), SubValue(Value(min_value + 5), Value(6))); // unsafe
810*795d594fSAndroid Build Coastguard Worker }
811*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,MulValue)812*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, MulValue) {
813*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1000), MulValue(Value(10), Value(100)));
814*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MulValue(Value(x_, 1, -4), Value(x_, 1, -1)));
815*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MulValue(Value(x_, 1, 5), Value(y_, 1, -7)));
816*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 9, 60), MulValue(Value(x_, 3, 20), Value(3)));
817*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(y_, 55, -110), MulValue(Value(55), Value(y_, 1, -2)));
818*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MulValue(Value(90000), Value(-90000))); // unsafe
819*795d594fSAndroid Build Coastguard Worker }
820*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,MulValueSpecial)821*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, MulValueSpecial) {
822*795d594fSAndroid Build Coastguard Worker const int32_t min_value = std::numeric_limits<int32_t>::min();
823*795d594fSAndroid Build Coastguard Worker const int32_t max_value = std::numeric_limits<int32_t>::max();
824*795d594fSAndroid Build Coastguard Worker
825*795d594fSAndroid Build Coastguard Worker // Unsafe.
826*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MulValue(Value(min_value), Value(min_value)));
827*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MulValue(Value(min_value), Value(-1)));
828*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MulValue(Value(min_value), Value(max_value)));
829*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MulValue(Value(max_value), Value(max_value)));
830*795d594fSAndroid Build Coastguard Worker
831*795d594fSAndroid Build Coastguard Worker // Safe.
832*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(min_value), MulValue(Value(min_value), Value(1)));
833*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(max_value), MulValue(Value(max_value), Value(1)));
834*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-max_value), MulValue(Value(max_value), Value(-1)));
835*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-1), MulValue(Value(1), Value(-1)));
836*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), MulValue(Value(-1), Value(-1)));
837*795d594fSAndroid Build Coastguard Worker }
838*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,DivValue)839*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, DivValue) {
840*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(25), DivValue(Value(100), Value(4)));
841*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), DivValue(Value(x_, 1, -4), Value(x_, 1, -1)));
842*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), DivValue(Value(x_, 1, 5), Value(y_, 1, -7)));
843*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), DivValue(Value(x_, 12, 24), Value(3)));
844*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), DivValue(Value(55), Value(y_, 1, -50)));
845*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), DivValue(Value(1), Value(0))); // unsafe
846*795d594fSAndroid Build Coastguard Worker }
847*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,DivValueSpecial)848*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, DivValueSpecial) {
849*795d594fSAndroid Build Coastguard Worker const int32_t min_value = std::numeric_limits<int32_t>::min();
850*795d594fSAndroid Build Coastguard Worker const int32_t max_value = std::numeric_limits<int32_t>::max();
851*795d594fSAndroid Build Coastguard Worker
852*795d594fSAndroid Build Coastguard Worker // Unsafe.
853*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), DivValue(Value(min_value), Value(-1)));
854*795d594fSAndroid Build Coastguard Worker
855*795d594fSAndroid Build Coastguard Worker // Safe.
856*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), DivValue(Value(min_value), Value(min_value)));
857*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), DivValue(Value(max_value), Value(max_value)));
858*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(min_value), DivValue(Value(min_value), Value(1)));
859*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(max_value), DivValue(Value(max_value), Value(1)));
860*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-max_value), DivValue(Value(max_value), Value(-1)));
861*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(-1), DivValue(Value(1), Value(-1)));
862*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), DivValue(Value(-1), Value(-1)));
863*795d594fSAndroid Build Coastguard Worker }
864*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,MinValue)865*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, MinValue) {
866*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(10), MinValue(Value(10), Value(100)));
867*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -4), MinValue(Value(x_, 1, -4), Value(x_, 1, -1)));
868*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 4, -4), MinValue(Value(x_, 4, -4), Value(x_, 4, -1)));
869*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MinValue(Value(x_, 1, 5), Value(y_, 1, -7)));
870*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MinValue(Value(x_, 1, 20), Value(3)));
871*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MinValue(Value(55), Value(y_, 1, -50)));
872*795d594fSAndroid Build Coastguard Worker }
873*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,MaxValue)874*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, MaxValue) {
875*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(100), MaxValue(Value(10), Value(100)));
876*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -1), MaxValue(Value(x_, 1, -4), Value(x_, 1, -1)));
877*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 4, -1), MaxValue(Value(x_, 4, -4), Value(x_, 4, -1)));
878*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MaxValue(Value(x_, 1, 5), Value(y_, 1, -7)));
879*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MaxValue(Value(x_, 1, 20), Value(3)));
880*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), MaxValue(Value(55), Value(y_, 1, -50)));
881*795d594fSAndroid Build Coastguard Worker }
882*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,ArrayLengthAndHints)883*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, ArrayLengthAndHints) {
884*795d594fSAndroid Build Coastguard Worker // We pass a bogus constant for the class to avoid mocking one.
885*795d594fSAndroid Build Coastguard Worker HInstruction* new_array = MakeNewArray(entry_block_, /* cls= */ x_, /* length= */ x_);
886*795d594fSAndroid Build Coastguard Worker HInstruction* array_length = MakeArrayLength(entry_block_, new_array);
887*795d594fSAndroid Build Coastguard Worker // With null hint: yields extreme constants.
888*795d594fSAndroid Build Coastguard Worker const int32_t max_value = std::numeric_limits<int32_t>::max();
889*795d594fSAndroid Build Coastguard Worker SetHint(nullptr);
890*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), GetMin(CreateFetch(array_length), nullptr));
891*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(max_value), GetMax(CreateFetch(array_length), nullptr));
892*795d594fSAndroid Build Coastguard Worker // With explicit hint: yields the length instruction.
893*795d594fSAndroid Build Coastguard Worker SetHint(array_length);
894*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(array_length, 1, 0), GetMin(CreateFetch(array_length), nullptr));
895*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(array_length, 1, 0), GetMax(CreateFetch(array_length), nullptr));
896*795d594fSAndroid Build Coastguard Worker // With any non-null hint: chases beyond the length instruction.
897*795d594fSAndroid Build Coastguard Worker SetHint(x_);
898*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 0), GetMin(CreateFetch(array_length), nullptr));
899*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 0), GetMax(CreateFetch(array_length), nullptr));
900*795d594fSAndroid Build Coastguard Worker }
901*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,AddOrSubAndConstant)902*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, AddOrSubAndConstant) {
903*795d594fSAndroid Build Coastguard Worker HInstruction* plus1 = graph_->GetIntConstant(1);
904*795d594fSAndroid Build Coastguard Worker HInstruction* minus1 = graph_->GetIntConstant(-1);
905*795d594fSAndroid Build Coastguard Worker HInstruction* add = MakeBinOp<HAdd>(entry_block_, DataType::Type::kInt32, x_, minus1);
906*795d594fSAndroid Build Coastguard Worker HInstruction* alt = MakeBinOp<HAdd>(entry_block_, DataType::Type::kInt32, minus1, x_);
907*795d594fSAndroid Build Coastguard Worker HInstruction* sub = MakeBinOp<HSub>(entry_block_, DataType::Type::kInt32, x_, plus1);
908*795d594fSAndroid Build Coastguard Worker HInstruction* rev = MakeBinOp<HSub>(entry_block_, DataType::Type::kInt32, plus1, x_);
909*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -1), GetMin(CreateFetch(add), nullptr));
910*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -1), GetMax(CreateFetch(add), nullptr));
911*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -1), GetMin(CreateFetch(alt), nullptr));
912*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -1), GetMax(CreateFetch(alt), nullptr));
913*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -1), GetMin(CreateFetch(sub), nullptr));
914*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -1), GetMax(CreateFetch(sub), nullptr));
915*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, -1, 1), GetMin(CreateFetch(rev), nullptr));
916*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, -1, 1), GetMax(CreateFetch(rev), nullptr));
917*795d594fSAndroid Build Coastguard Worker }
918*795d594fSAndroid Build Coastguard Worker
919*795d594fSAndroid Build Coastguard Worker //
920*795d594fSAndroid Build Coastguard Worker // Tests on public methods.
921*795d594fSAndroid Build Coastguard Worker //
922*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,ConstantTripCountUp)923*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, ConstantTripCountUp) {
924*795d594fSAndroid Build Coastguard Worker BuildLoop(0, graph_->GetIntConstant(1000), 1);
925*795d594fSAndroid Build Coastguard Worker PerformInductionVarAnalysis();
926*795d594fSAndroid Build Coastguard Worker
927*795d594fSAndroid Build Coastguard Worker Value v1, v2;
928*795d594fSAndroid Build Coastguard Worker bool needs_finite_test = true;
929*795d594fSAndroid Build Coastguard Worker bool needs_taken_test = true;
930*795d594fSAndroid Build Coastguard Worker
931*795d594fSAndroid Build Coastguard Worker HInstruction* phi = condition_->InputAt(0);
932*795d594fSAndroid Build Coastguard Worker HInstruction* exit = exit_block_->GetLastInstruction();
933*795d594fSAndroid Build Coastguard Worker
934*795d594fSAndroid Build Coastguard Worker // In context of header: known.
935*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(condition_->GetBlock(), phi, x_, &v1, &v2, &needs_finite_test);
936*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
937*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), v1);
938*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1000), v2);
939*795d594fSAndroid Build Coastguard Worker
940*795d594fSAndroid Build Coastguard Worker // In context of loop-body: known.
941*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), phi, x_, &v1, &v2, &needs_finite_test);
942*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
943*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), v1);
944*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(999), v2);
945*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), increment_, x_, &v1, &v2, &needs_finite_test);
946*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
947*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), v1);
948*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1000), v2);
949*795d594fSAndroid Build Coastguard Worker
950*795d594fSAndroid Build Coastguard Worker // Induction vs. no-induction.
951*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(
952*795d594fSAndroid Build Coastguard Worker range_.CanGenerateRange(increment_->GetBlock(), phi, &needs_finite_test, &needs_taken_test));
953*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(range_.CanGenerateLastValue(phi));
954*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(
955*795d594fSAndroid Build Coastguard Worker range_.CanGenerateRange(exit->GetBlock(), exit, &needs_finite_test, &needs_taken_test));
956*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(range_.CanGenerateLastValue(exit));
957*795d594fSAndroid Build Coastguard Worker
958*795d594fSAndroid Build Coastguard Worker // Last value (unsimplified).
959*795d594fSAndroid Build Coastguard Worker HInstruction* last = range_.GenerateLastValue(phi, graph_, loop_preheader_);
960*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(last->IsAdd());
961*795d594fSAndroid Build Coastguard Worker ExpectInt(1000, last->InputAt(0));
962*795d594fSAndroid Build Coastguard Worker ExpectInt(0, last->InputAt(1));
963*795d594fSAndroid Build Coastguard Worker
964*795d594fSAndroid Build Coastguard Worker // Loop logic.
965*795d594fSAndroid Build Coastguard Worker int64_t tc = 0;
966*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
967*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(1000, tc);
968*795d594fSAndroid Build Coastguard Worker HInstruction* offset = nullptr;
969*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(range_.IsUnitStride(phi->GetBlock(), phi, graph_, &offset));
970*795d594fSAndroid Build Coastguard Worker ExpectInt(0, offset);
971*795d594fSAndroid Build Coastguard Worker HInstruction* tce = range_.GenerateTripCount(
972*795d594fSAndroid Build Coastguard Worker loop_header_->GetLoopInformation(), graph_, loop_preheader_);
973*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(tce != nullptr);
974*795d594fSAndroid Build Coastguard Worker ExpectInt(1000, tce);
975*795d594fSAndroid Build Coastguard Worker }
976*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,ConstantTripCountDown)977*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, ConstantTripCountDown) {
978*795d594fSAndroid Build Coastguard Worker BuildLoop(1000, graph_->GetIntConstant(0), -1);
979*795d594fSAndroid Build Coastguard Worker PerformInductionVarAnalysis();
980*795d594fSAndroid Build Coastguard Worker
981*795d594fSAndroid Build Coastguard Worker Value v1, v2;
982*795d594fSAndroid Build Coastguard Worker bool needs_finite_test = true;
983*795d594fSAndroid Build Coastguard Worker bool needs_taken_test = true;
984*795d594fSAndroid Build Coastguard Worker
985*795d594fSAndroid Build Coastguard Worker HInstruction* phi = condition_->InputAt(0);
986*795d594fSAndroid Build Coastguard Worker HInstruction* exit = exit_block_->GetLastInstruction();
987*795d594fSAndroid Build Coastguard Worker
988*795d594fSAndroid Build Coastguard Worker // In context of header: known.
989*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(condition_->GetBlock(), phi, x_, &v1, &v2, &needs_finite_test);
990*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
991*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), v1);
992*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1000), v2);
993*795d594fSAndroid Build Coastguard Worker
994*795d594fSAndroid Build Coastguard Worker // In context of loop-body: known.
995*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), phi, x_, &v1, &v2, &needs_finite_test);
996*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
997*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), v1);
998*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1000), v2);
999*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), increment_, x_, &v1, &v2, &needs_finite_test);
1000*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1001*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), v1);
1002*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(999), v2);
1003*795d594fSAndroid Build Coastguard Worker
1004*795d594fSAndroid Build Coastguard Worker // Induction vs. no-induction.
1005*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(
1006*795d594fSAndroid Build Coastguard Worker range_.CanGenerateRange(increment_->GetBlock(), phi, &needs_finite_test, &needs_taken_test));
1007*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(range_.CanGenerateLastValue(phi));
1008*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(
1009*795d594fSAndroid Build Coastguard Worker range_.CanGenerateRange(exit->GetBlock(), exit, &needs_finite_test, &needs_taken_test));
1010*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(range_.CanGenerateLastValue(exit));
1011*795d594fSAndroid Build Coastguard Worker
1012*795d594fSAndroid Build Coastguard Worker // Last value (unsimplified). We expect Sub(1000, Neg(-1000)) which is equivalent to Sub(1000,
1013*795d594fSAndroid Build Coastguard Worker // 1000) aka 0.
1014*795d594fSAndroid Build Coastguard Worker HInstruction* last = range_.GenerateLastValue(phi, graph_, loop_preheader_);
1015*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(last->IsSub());
1016*795d594fSAndroid Build Coastguard Worker ExpectInt(1000, last->InputAt(0));
1017*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(last->InputAt(1)->IsNeg());
1018*795d594fSAndroid Build Coastguard Worker ExpectInt(-1000, last->InputAt(1)->AsNeg()->InputAt(0));
1019*795d594fSAndroid Build Coastguard Worker
1020*795d594fSAndroid Build Coastguard Worker // Loop logic.
1021*795d594fSAndroid Build Coastguard Worker int64_t tc = 0;
1022*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
1023*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(1000, tc);
1024*795d594fSAndroid Build Coastguard Worker HInstruction* offset = nullptr;
1025*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(range_.IsUnitStride(phi->GetBlock(), phi, graph_, &offset));
1026*795d594fSAndroid Build Coastguard Worker HInstruction* tce = range_.GenerateTripCount(
1027*795d594fSAndroid Build Coastguard Worker loop_header_->GetLoopInformation(), graph_, loop_preheader_);
1028*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(tce != nullptr);
1029*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(tce->IsNeg());
1030*795d594fSAndroid Build Coastguard Worker last = tce->InputAt(0);
1031*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(last->IsSub());
1032*795d594fSAndroid Build Coastguard Worker ExpectInt(0, last->InputAt(0));
1033*795d594fSAndroid Build Coastguard Worker ExpectInt(1000, last->InputAt(1));
1034*795d594fSAndroid Build Coastguard Worker }
1035*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,SymbolicTripCountUp)1036*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, SymbolicTripCountUp) {
1037*795d594fSAndroid Build Coastguard Worker BuildLoop(0, x_, 1);
1038*795d594fSAndroid Build Coastguard Worker PerformInductionVarAnalysis();
1039*795d594fSAndroid Build Coastguard Worker
1040*795d594fSAndroid Build Coastguard Worker Value v1, v2;
1041*795d594fSAndroid Build Coastguard Worker bool needs_finite_test = true;
1042*795d594fSAndroid Build Coastguard Worker bool needs_taken_test = true;
1043*795d594fSAndroid Build Coastguard Worker
1044*795d594fSAndroid Build Coastguard Worker HInstruction* phi = condition_->InputAt(0);
1045*795d594fSAndroid Build Coastguard Worker
1046*795d594fSAndroid Build Coastguard Worker // In context of header: upper unknown.
1047*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(condition_->GetBlock(), phi, x_, &v1, &v2, &needs_finite_test);
1048*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1049*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), v1);
1050*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), v2);
1051*795d594fSAndroid Build Coastguard Worker
1052*795d594fSAndroid Build Coastguard Worker // In context of loop-body: known.
1053*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), phi, x_, &v1, &v2, &needs_finite_test);
1054*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1055*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(0), v1);
1056*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, -1), v2);
1057*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), increment_, x_, &v1, &v2, &needs_finite_test);
1058*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1059*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), v1);
1060*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 0), v2);
1061*795d594fSAndroid Build Coastguard Worker
1062*795d594fSAndroid Build Coastguard Worker HInstruction* lower = nullptr;
1063*795d594fSAndroid Build Coastguard Worker HInstruction* upper = nullptr;
1064*795d594fSAndroid Build Coastguard Worker
1065*795d594fSAndroid Build Coastguard Worker // Can generate code in context of loop-body only.
1066*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(
1067*795d594fSAndroid Build Coastguard Worker range_.CanGenerateRange(condition_->GetBlock(), phi, &needs_finite_test, &needs_taken_test));
1068*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(
1069*795d594fSAndroid Build Coastguard Worker range_.CanGenerateRange(increment_->GetBlock(), phi, &needs_finite_test, &needs_taken_test));
1070*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1071*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(needs_taken_test);
1072*795d594fSAndroid Build Coastguard Worker
1073*795d594fSAndroid Build Coastguard Worker // Generates code (unsimplified).
1074*795d594fSAndroid Build Coastguard Worker range_.GenerateRange(increment_->GetBlock(), phi, graph_, loop_preheader_, &lower, &upper);
1075*795d594fSAndroid Build Coastguard Worker
1076*795d594fSAndroid Build Coastguard Worker // Verify lower is 0+0.
1077*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(lower != nullptr);
1078*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(lower->IsAdd());
1079*795d594fSAndroid Build Coastguard Worker ExpectInt(0, lower->InputAt(0));
1080*795d594fSAndroid Build Coastguard Worker ExpectInt(0, lower->InputAt(1));
1081*795d594fSAndroid Build Coastguard Worker
1082*795d594fSAndroid Build Coastguard Worker // Verify upper is (V-1)+0.
1083*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(upper != nullptr);
1084*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(upper->IsAdd());
1085*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(upper->InputAt(0)->IsSub());
1086*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(upper->InputAt(0)->InputAt(0)->IsParameterValue());
1087*795d594fSAndroid Build Coastguard Worker ExpectInt(1, upper->InputAt(0)->InputAt(1));
1088*795d594fSAndroid Build Coastguard Worker ExpectInt(0, upper->InputAt(1));
1089*795d594fSAndroid Build Coastguard Worker
1090*795d594fSAndroid Build Coastguard Worker // Verify taken-test is 0<V.
1091*795d594fSAndroid Build Coastguard Worker HInstruction* taken = range_.GenerateTakenTest(increment_, graph_, loop_preheader_);
1092*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(taken != nullptr);
1093*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(taken->IsLessThan());
1094*795d594fSAndroid Build Coastguard Worker ExpectInt(0, taken->InputAt(0));
1095*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(taken->InputAt(1)->IsParameterValue());
1096*795d594fSAndroid Build Coastguard Worker
1097*795d594fSAndroid Build Coastguard Worker // Replacement.
1098*795d594fSAndroid Build Coastguard Worker range_.Replace(loop_header_->GetLastInstruction(), x_, y_);
1099*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), increment_, x_, &v1, &v2, &needs_finite_test);
1100*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1101*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1), v1);
1102*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(y_, 1, 0), v2);
1103*795d594fSAndroid Build Coastguard Worker
1104*795d594fSAndroid Build Coastguard Worker // Loop logic.
1105*795d594fSAndroid Build Coastguard Worker int64_t tc = 0;
1106*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
1107*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(0, tc); // unknown
1108*795d594fSAndroid Build Coastguard Worker HInstruction* offset = nullptr;
1109*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(range_.IsUnitStride(phi->GetBlock(), phi, graph_, &offset));
1110*795d594fSAndroid Build Coastguard Worker ExpectInt(0, offset);
1111*795d594fSAndroid Build Coastguard Worker HInstruction* tce = range_.GenerateTripCount(
1112*795d594fSAndroid Build Coastguard Worker loop_header_->GetLoopInformation(), graph_, loop_preheader_);
1113*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(tce != nullptr);
1114*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(tce->IsSelect()); // guarded by taken-test
1115*795d594fSAndroid Build Coastguard Worker ExpectInt(0, tce->InputAt(0));
1116*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(tce->InputAt(1)->IsParameterValue());
1117*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(tce->InputAt(2)->IsLessThan());
1118*795d594fSAndroid Build Coastguard Worker }
1119*795d594fSAndroid Build Coastguard Worker
TEST_F(InductionVarRangeTest,SymbolicTripCountDown)1120*795d594fSAndroid Build Coastguard Worker TEST_F(InductionVarRangeTest, SymbolicTripCountDown) {
1121*795d594fSAndroid Build Coastguard Worker BuildLoop(1000, x_, -1);
1122*795d594fSAndroid Build Coastguard Worker PerformInductionVarAnalysis();
1123*795d594fSAndroid Build Coastguard Worker
1124*795d594fSAndroid Build Coastguard Worker Value v1, v2;
1125*795d594fSAndroid Build Coastguard Worker bool needs_finite_test = true;
1126*795d594fSAndroid Build Coastguard Worker bool needs_taken_test = true;
1127*795d594fSAndroid Build Coastguard Worker
1128*795d594fSAndroid Build Coastguard Worker HInstruction* phi = condition_->InputAt(0);
1129*795d594fSAndroid Build Coastguard Worker
1130*795d594fSAndroid Build Coastguard Worker // In context of header: lower unknown.
1131*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(condition_->GetBlock(), phi, x_, &v1, &v2, &needs_finite_test);
1132*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1133*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(), v1);
1134*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1000), v2);
1135*795d594fSAndroid Build Coastguard Worker
1136*795d594fSAndroid Build Coastguard Worker // In context of loop-body: known.
1137*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), phi, x_, &v1, &v2, &needs_finite_test);
1138*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1139*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 1), v1);
1140*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(1000), v2);
1141*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), increment_, x_, &v1, &v2, &needs_finite_test);
1142*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1143*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(x_, 1, 0), v1);
1144*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(999), v2);
1145*795d594fSAndroid Build Coastguard Worker
1146*795d594fSAndroid Build Coastguard Worker HInstruction* lower = nullptr;
1147*795d594fSAndroid Build Coastguard Worker HInstruction* upper = nullptr;
1148*795d594fSAndroid Build Coastguard Worker
1149*795d594fSAndroid Build Coastguard Worker // Can generate code in context of loop-body only.
1150*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(
1151*795d594fSAndroid Build Coastguard Worker range_.CanGenerateRange(condition_->GetBlock(), phi, &needs_finite_test, &needs_taken_test));
1152*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(
1153*795d594fSAndroid Build Coastguard Worker range_.CanGenerateRange(increment_->GetBlock(), phi, &needs_finite_test, &needs_taken_test));
1154*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1155*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(needs_taken_test);
1156*795d594fSAndroid Build Coastguard Worker
1157*795d594fSAndroid Build Coastguard Worker // Generates code (unsimplified).
1158*795d594fSAndroid Build Coastguard Worker range_.GenerateRange(increment_->GetBlock(), phi, graph_, loop_preheader_, &lower, &upper);
1159*795d594fSAndroid Build Coastguard Worker
1160*795d594fSAndroid Build Coastguard Worker // Verify lower is 1000-((1000-V)-1).
1161*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(lower != nullptr);
1162*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(lower->IsSub());
1163*795d594fSAndroid Build Coastguard Worker ExpectInt(1000, lower->InputAt(0));
1164*795d594fSAndroid Build Coastguard Worker lower = lower->InputAt(1);
1165*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(lower->IsSub());
1166*795d594fSAndroid Build Coastguard Worker ExpectInt(1, lower->InputAt(1));
1167*795d594fSAndroid Build Coastguard Worker lower = lower->InputAt(0);
1168*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(lower->IsSub());
1169*795d594fSAndroid Build Coastguard Worker ExpectInt(1000, lower->InputAt(0));
1170*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(lower->InputAt(1)->IsParameterValue());
1171*795d594fSAndroid Build Coastguard Worker
1172*795d594fSAndroid Build Coastguard Worker // Verify upper is 1000-0.
1173*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(upper != nullptr);
1174*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(upper->IsSub());
1175*795d594fSAndroid Build Coastguard Worker ExpectInt(1000, upper->InputAt(0));
1176*795d594fSAndroid Build Coastguard Worker ExpectInt(0, upper->InputAt(1));
1177*795d594fSAndroid Build Coastguard Worker
1178*795d594fSAndroid Build Coastguard Worker // Verify taken-test is 1000>V.
1179*795d594fSAndroid Build Coastguard Worker HInstruction* taken = range_.GenerateTakenTest(increment_, graph_, loop_preheader_);
1180*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(taken != nullptr);
1181*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(taken->IsGreaterThan());
1182*795d594fSAndroid Build Coastguard Worker ExpectInt(1000, taken->InputAt(0));
1183*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(taken->InputAt(1)->IsParameterValue());
1184*795d594fSAndroid Build Coastguard Worker
1185*795d594fSAndroid Build Coastguard Worker // Replacement.
1186*795d594fSAndroid Build Coastguard Worker range_.Replace(loop_header_->GetLastInstruction(), x_, y_);
1187*795d594fSAndroid Build Coastguard Worker range_.GetInductionRange(increment_->GetBlock(), increment_, x_, &v1, &v2, &needs_finite_test);
1188*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(needs_finite_test);
1189*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(y_, 1, 0), v1);
1190*795d594fSAndroid Build Coastguard Worker ExpectEqual(Value(999), v2);
1191*795d594fSAndroid Build Coastguard Worker
1192*795d594fSAndroid Build Coastguard Worker // Loop logic.
1193*795d594fSAndroid Build Coastguard Worker int64_t tc = 0;
1194*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
1195*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(0, tc); // unknown
1196*795d594fSAndroid Build Coastguard Worker HInstruction* offset = nullptr;
1197*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(range_.IsUnitStride(phi->GetBlock(), phi, graph_, &offset));
1198*795d594fSAndroid Build Coastguard Worker HInstruction* tce = range_.GenerateTripCount(
1199*795d594fSAndroid Build Coastguard Worker loop_header_->GetLoopInformation(), graph_, loop_preheader_);
1200*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(tce != nullptr);
1201*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(tce->IsSelect()); // guarded by taken-test
1202*795d594fSAndroid Build Coastguard Worker ExpectInt(0, tce->InputAt(0));
1203*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(tce->InputAt(1)->IsSub());
1204*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(tce->InputAt(2)->IsGreaterThan());
1205*795d594fSAndroid Build Coastguard Worker tce = tce->InputAt(1);
1206*795d594fSAndroid Build Coastguard Worker ExpectInt(1000, taken->InputAt(0));
1207*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(taken->InputAt(1)->IsParameterValue());
1208*795d594fSAndroid Build Coastguard Worker }
1209*795d594fSAndroid Build Coastguard Worker
1210*795d594fSAndroid Build Coastguard Worker } // namespace art
1211