Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2014 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 "nodes.h"
     19 #include "optimizing_unit_test.h"
     20 
     21 #include "gtest/gtest.h"
     22 
     23 namespace art {
     24 
     25 /**
     26  * Test that removing instruction from the graph removes itself from user lists
     27  * and environment lists.
     28  */
     29 TEST(Node, RemoveInstruction) {
     30   ArenaPool pool;
     31   ArenaAllocator allocator(&pool);
     32 
     33   HGraph* graph = CreateGraph(&allocator);
     34   HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
     35   graph->AddBlock(entry);
     36   graph->SetEntryBlock(entry);
     37   HInstruction* parameter = new (&allocator) HParameterValue(
     38       graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
     39   entry->AddInstruction(parameter);
     40   entry->AddInstruction(new (&allocator) HGoto());
     41 
     42   HBasicBlock* first_block = new (&allocator) HBasicBlock(graph);
     43   graph->AddBlock(first_block);
     44   entry->AddSuccessor(first_block);
     45   HInstruction* null_check = new (&allocator) HNullCheck(parameter, 0);
     46   first_block->AddInstruction(null_check);
     47   first_block->AddInstruction(new (&allocator) HReturnVoid());
     48 
     49   HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
     50   graph->AddBlock(exit_block);
     51   first_block->AddSuccessor(exit_block);
     52   exit_block->AddInstruction(new (&allocator) HExit());
     53 
     54   HEnvironment* environment = new (&allocator) HEnvironment(
     55       &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, null_check);
     56   null_check->SetRawEnvironment(environment);
     57   environment->SetRawEnvAt(0, parameter);
     58   parameter->AddEnvUseAt(null_check->GetEnvironment(), 0);
     59 
     60   ASSERT_TRUE(parameter->HasEnvironmentUses());
     61   ASSERT_TRUE(parameter->HasUses());
     62 
     63   first_block->RemoveInstruction(null_check);
     64 
     65   ASSERT_FALSE(parameter->HasEnvironmentUses());
     66   ASSERT_FALSE(parameter->HasUses());
     67 }
     68 
     69 /**
     70  * Test that inserting an instruction in the graph updates user lists.
     71  */
     72 TEST(Node, InsertInstruction) {
     73   ArenaPool pool;
     74   ArenaAllocator allocator(&pool);
     75 
     76   HGraph* graph = CreateGraph(&allocator);
     77   HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
     78   graph->AddBlock(entry);
     79   graph->SetEntryBlock(entry);
     80   HInstruction* parameter1 = new (&allocator) HParameterValue(
     81       graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
     82   HInstruction* parameter2 = new (&allocator) HParameterValue(
     83       graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
     84   entry->AddInstruction(parameter1);
     85   entry->AddInstruction(parameter2);
     86   entry->AddInstruction(new (&allocator) HExit());
     87 
     88   ASSERT_FALSE(parameter1->HasUses());
     89 
     90   HInstruction* to_insert = new (&allocator) HNullCheck(parameter1, 0);
     91   entry->InsertInstructionBefore(to_insert, parameter2);
     92 
     93   ASSERT_TRUE(parameter1->HasUses());
     94   ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());
     95 }
     96 
     97 /**
     98  * Test that adding an instruction in the graph updates user lists.
     99  */
    100 TEST(Node, AddInstruction) {
    101   ArenaPool pool;
    102   ArenaAllocator allocator(&pool);
    103 
    104   HGraph* graph = CreateGraph(&allocator);
    105   HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
    106   graph->AddBlock(entry);
    107   graph->SetEntryBlock(entry);
    108   HInstruction* parameter = new (&allocator) HParameterValue(
    109       graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
    110   entry->AddInstruction(parameter);
    111 
    112   ASSERT_FALSE(parameter->HasUses());
    113 
    114   HInstruction* to_add = new (&allocator) HNullCheck(parameter, 0);
    115   entry->AddInstruction(to_add);
    116 
    117   ASSERT_TRUE(parameter->HasUses());
    118   ASSERT_TRUE(parameter->GetUses().HasExactlyOneElement());
    119 }
    120 
    121 TEST(Node, ParentEnvironment) {
    122   ArenaPool pool;
    123   ArenaAllocator allocator(&pool);
    124 
    125   HGraph* graph = CreateGraph(&allocator);
    126   HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
    127   graph->AddBlock(entry);
    128   graph->SetEntryBlock(entry);
    129   HInstruction* parameter1 = new (&allocator) HParameterValue(
    130       graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
    131   HInstruction* with_environment = new (&allocator) HNullCheck(parameter1, 0);
    132   entry->AddInstruction(parameter1);
    133   entry->AddInstruction(with_environment);
    134   entry->AddInstruction(new (&allocator) HExit());
    135 
    136   ASSERT_TRUE(parameter1->HasUses());
    137   ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());
    138 
    139   HEnvironment* environment = new (&allocator) HEnvironment(
    140       &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, with_environment);
    141   ArenaVector<HInstruction*> array(allocator.Adapter());
    142   array.push_back(parameter1);
    143 
    144   environment->CopyFrom(array);
    145   with_environment->SetRawEnvironment(environment);
    146 
    147   ASSERT_TRUE(parameter1->HasEnvironmentUses());
    148   ASSERT_TRUE(parameter1->GetEnvUses().HasExactlyOneElement());
    149 
    150   HEnvironment* parent1 = new (&allocator) HEnvironment(
    151       &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr);
    152   parent1->CopyFrom(array);
    153 
    154   ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u);
    155 
    156   HEnvironment* parent2 = new (&allocator) HEnvironment(
    157       &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr);
    158   parent2->CopyFrom(array);
    159   parent1->SetAndCopyParentChain(&allocator, parent2);
    160 
    161   // One use for parent2, and one other use for the new parent of parent1.
    162   ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 4u);
    163 
    164   // We have copied the parent chain. So we now have two more uses.
    165   environment->SetAndCopyParentChain(&allocator, parent1);
    166   ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 6u);
    167 }
    168 
    169 }  // namespace art
    170