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