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 "nodes.h"
     18 
     19 #include "base/arena_allocator.h"
     20 #include "optimizing_unit_test.h"
     21 
     22 #include "gtest/gtest.h"
     23 
     24 namespace art {
     25 
     26 class NodeTest : public OptimizingUnitTest {};
     27 
     28 /**
     29  * Test that removing instruction from the graph removes itself from user lists
     30  * and environment lists.
     31  */
     32 TEST_F(NodeTest, RemoveInstruction) {
     33   HGraph* graph = CreateGraph();
     34   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
     35   graph->AddBlock(entry);
     36   graph->SetEntryBlock(entry);
     37   HInstruction* parameter = new (GetAllocator()) HParameterValue(
     38       graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
     39   entry->AddInstruction(parameter);
     40   entry->AddInstruction(new (GetAllocator()) HGoto());
     41 
     42   HBasicBlock* first_block = new (GetAllocator()) HBasicBlock(graph);
     43   graph->AddBlock(first_block);
     44   entry->AddSuccessor(first_block);
     45   HInstruction* null_check = new (GetAllocator()) HNullCheck(parameter, 0);
     46   first_block->AddInstruction(null_check);
     47   first_block->AddInstruction(new (GetAllocator()) HReturnVoid());
     48 
     49   HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph);
     50   graph->AddBlock(exit_block);
     51   first_block->AddSuccessor(exit_block);
     52   exit_block->AddInstruction(new (GetAllocator()) HExit());
     53 
     54   HEnvironment* environment = new (GetAllocator()) HEnvironment(
     55       GetAllocator(), 1, graph->GetArtMethod(), 0, 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_F(NodeTest, InsertInstruction) {
     73   HGraph* graph = CreateGraph();
     74   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
     75   graph->AddBlock(entry);
     76   graph->SetEntryBlock(entry);
     77   HInstruction* parameter1 = new (GetAllocator()) HParameterValue(
     78       graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
     79   HInstruction* parameter2 = new (GetAllocator()) HParameterValue(
     80       graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
     81   entry->AddInstruction(parameter1);
     82   entry->AddInstruction(parameter2);
     83   entry->AddInstruction(new (GetAllocator()) HExit());
     84 
     85   ASSERT_FALSE(parameter1->HasUses());
     86 
     87   HInstruction* to_insert = new (GetAllocator()) HNullCheck(parameter1, 0);
     88   entry->InsertInstructionBefore(to_insert, parameter2);
     89 
     90   ASSERT_TRUE(parameter1->HasUses());
     91   ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());
     92 }
     93 
     94 /**
     95  * Test that adding an instruction in the graph updates user lists.
     96  */
     97 TEST_F(NodeTest, AddInstruction) {
     98   HGraph* graph = CreateGraph();
     99   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
    100   graph->AddBlock(entry);
    101   graph->SetEntryBlock(entry);
    102   HInstruction* parameter = new (GetAllocator()) HParameterValue(
    103       graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
    104   entry->AddInstruction(parameter);
    105 
    106   ASSERT_FALSE(parameter->HasUses());
    107 
    108   HInstruction* to_add = new (GetAllocator()) HNullCheck(parameter, 0);
    109   entry->AddInstruction(to_add);
    110 
    111   ASSERT_TRUE(parameter->HasUses());
    112   ASSERT_TRUE(parameter->GetUses().HasExactlyOneElement());
    113 }
    114 
    115 TEST_F(NodeTest, ParentEnvironment) {
    116   HGraph* graph = CreateGraph();
    117   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
    118   graph->AddBlock(entry);
    119   graph->SetEntryBlock(entry);
    120   HInstruction* parameter1 = new (GetAllocator()) HParameterValue(
    121       graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
    122   HInstruction* with_environment = new (GetAllocator()) HNullCheck(parameter1, 0);
    123   entry->AddInstruction(parameter1);
    124   entry->AddInstruction(with_environment);
    125   entry->AddInstruction(new (GetAllocator()) HExit());
    126 
    127   ASSERT_TRUE(parameter1->HasUses());
    128   ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());
    129 
    130   HEnvironment* environment = new (GetAllocator()) HEnvironment(
    131       GetAllocator(), 1, graph->GetArtMethod(), 0, with_environment);
    132   HInstruction* const array[] = { parameter1 };
    133 
    134   environment->CopyFrom(ArrayRef<HInstruction* const>(array));
    135   with_environment->SetRawEnvironment(environment);
    136 
    137   ASSERT_TRUE(parameter1->HasEnvironmentUses());
    138   ASSERT_TRUE(parameter1->GetEnvUses().HasExactlyOneElement());
    139 
    140   HEnvironment* parent1 = new (GetAllocator()) HEnvironment(
    141       GetAllocator(), 1, graph->GetArtMethod(), 0, nullptr);
    142   parent1->CopyFrom(ArrayRef<HInstruction* const>(array));
    143 
    144   ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u);
    145 
    146   HEnvironment* parent2 = new (GetAllocator()) HEnvironment(
    147       GetAllocator(), 1, graph->GetArtMethod(), 0, nullptr);
    148   parent2->CopyFrom(ArrayRef<HInstruction* const>(array));
    149   parent1->SetAndCopyParentChain(GetAllocator(), parent2);
    150 
    151   // One use for parent2, and one other use for the new parent of parent1.
    152   ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 4u);
    153 
    154   // We have copied the parent chain. So we now have two more uses.
    155   environment->SetAndCopyParentChain(GetAllocator(), parent1);
    156   ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 6u);
    157 }
    158 
    159 }  // namespace art
    160