1724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray/*
2724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray *
4724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * you may not use this file except in compliance with the License.
6724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * You may obtain a copy of the License at
7724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray *
8724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray *
10724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * See the License for the specific language governing permissions and
14724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * limitations under the License.
15724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray */
16724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
17724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray#include "nodes.h"
188cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe
198cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe#include "base/arena_allocator.h"
200a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray#include "optimizing_unit_test.h"
21724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
22724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray#include "gtest/gtest.h"
23724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
24724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffraynamespace art {
25724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
26ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Markoclass NodeTest : public OptimizingUnitTest {};
27ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko
28724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray/**
29724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * Test that removing instruction from the graph removes itself from user lists
30724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * and environment lists.
31724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray */
32ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir MarkoTEST_F(NodeTest, RemoveInstruction) {
33ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HGraph* graph = CreateGraph();
34ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
35724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  graph->AddBlock(entry);
36724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  graph->SetEntryBlock(entry);
37ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* parameter = new (GetAllocator()) HParameterValue(
380ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
39724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  entry->AddInstruction(parameter);
40ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  entry->AddInstruction(new (GetAllocator()) HGoto());
41724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
42ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* first_block = new (GetAllocator()) HBasicBlock(graph);
43724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  graph->AddBlock(first_block);
44724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  entry->AddSuccessor(first_block);
45ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* null_check = new (GetAllocator()) HNullCheck(parameter, 0);
46724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  first_block->AddInstruction(null_check);
47ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  first_block->AddInstruction(new (GetAllocator()) HReturnVoid());
48724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
49ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph);
50724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  graph->AddBlock(exit_block);
51724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  first_block->AddSuccessor(exit_block);
52ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  exit_block->AddInstruction(new (GetAllocator()) HExit());
53724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
54ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HEnvironment* environment = new (GetAllocator()) HEnvironment(
55ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko      GetAllocator(), 1, graph->GetArtMethod(), 0, null_check);
563dcd58cd54a922b864494fb7fff4a7f7a8562db9Nicolas Geoffray  null_check->SetRawEnvironment(environment);
57724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  environment->SetRawEnvAt(0, parameter);
58724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  parameter->AddEnvUseAt(null_check->GetEnvironment(), 0);
59724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
60724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  ASSERT_TRUE(parameter->HasEnvironmentUses());
61724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  ASSERT_TRUE(parameter->HasUses());
62724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
63724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  first_block->RemoveInstruction(null_check);
64724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
65724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  ASSERT_FALSE(parameter->HasEnvironmentUses());
66724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  ASSERT_FALSE(parameter->HasUses());
67724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray}
68724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
69191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray/**
70191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray * Test that inserting an instruction in the graph updates user lists.
71191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray */
72ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir MarkoTEST_F(NodeTest, InsertInstruction) {
73ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HGraph* graph = CreateGraph();
74ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
75191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  graph->AddBlock(entry);
76191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  graph->SetEntryBlock(entry);
77ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* parameter1 = new (GetAllocator()) HParameterValue(
780ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
79ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* parameter2 = new (GetAllocator()) HParameterValue(
800ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
81191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->AddInstruction(parameter1);
82191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->AddInstruction(parameter2);
83ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  entry->AddInstruction(new (GetAllocator()) HExit());
84191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
85191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ASSERT_FALSE(parameter1->HasUses());
86191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
87ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* to_insert = new (GetAllocator()) HNullCheck(parameter1, 0);
88191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->InsertInstructionBefore(to_insert, parameter2);
89191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
90191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ASSERT_TRUE(parameter1->HasUses());
9146817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko  ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());
92191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray}
93191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
94191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray/**
95191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray * Test that adding an instruction in the graph updates user lists.
96191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray */
97ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir MarkoTEST_F(NodeTest, AddInstruction) {
98ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HGraph* graph = CreateGraph();
99ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
100191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  graph->AddBlock(entry);
101191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  graph->SetEntryBlock(entry);
102ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* parameter = new (GetAllocator()) HParameterValue(
1030ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
104191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->AddInstruction(parameter);
105191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
106191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ASSERT_FALSE(parameter->HasUses());
107191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
108ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* to_add = new (GetAllocator()) HNullCheck(parameter, 0);
109191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->AddInstruction(to_add);
110191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
111191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ASSERT_TRUE(parameter->HasUses());
11246817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko  ASSERT_TRUE(parameter->GetUses().HasExactlyOneElement());
113191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray}
114191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
115ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir MarkoTEST_F(NodeTest, ParentEnvironment) {
116ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HGraph* graph = CreateGraph();
117ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
1180a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  graph->AddBlock(entry);
1190a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  graph->SetEntryBlock(entry);
120ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* parameter1 = new (GetAllocator()) HParameterValue(
1210ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
122ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* with_environment = new (GetAllocator()) HNullCheck(parameter1, 0);
1230a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  entry->AddInstruction(parameter1);
1240a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  entry->AddInstruction(with_environment);
125ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  entry->AddInstruction(new (GetAllocator()) HExit());
1260a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1270a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_TRUE(parameter1->HasUses());
12846817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko  ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());
1290a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
130ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HEnvironment* environment = new (GetAllocator()) HEnvironment(
131ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko      GetAllocator(), 1, graph->GetArtMethod(), 0, with_environment);
13269d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko  HInstruction* const array[] = { parameter1 };
1330a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
13469d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko  environment->CopyFrom(ArrayRef<HInstruction* const>(array));
1350a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  with_environment->SetRawEnvironment(environment);
1360a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1370a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_TRUE(parameter1->HasEnvironmentUses());
13846817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko  ASSERT_TRUE(parameter1->GetEnvUses().HasExactlyOneElement());
1390a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
140ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HEnvironment* parent1 = new (GetAllocator()) HEnvironment(
141ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko      GetAllocator(), 1, graph->GetArtMethod(), 0, nullptr);
14269d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko  parent1->CopyFrom(ArrayRef<HInstruction* const>(array));
1430a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1440a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u);
1450a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
146ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HEnvironment* parent2 = new (GetAllocator()) HEnvironment(
147ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko      GetAllocator(), 1, graph->GetArtMethod(), 0, nullptr);
14869d310e0317e2fce97bf8c9c133c5c2c0332e61dVladimir Marko  parent2->CopyFrom(ArrayRef<HInstruction* const>(array));
149ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  parent1->SetAndCopyParentChain(GetAllocator(), parent2);
1500a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1510a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  // One use for parent2, and one other use for the new parent of parent1.
1520a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 4u);
1530a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1540a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  // We have copied the parent chain. So we now have two more uses.
155ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  environment->SetAndCopyParentChain(GetAllocator(), parent1);
1560a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 6u);
1570a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray}
1580a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
159724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray}  // namespace art
160