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
17b666f4805c8ae707ea6fd7f6c7f375e0b000dba8Mathieu Chartier#include "base/arena_allocator.h"
18724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray#include "nodes.h"
190a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray#include "optimizing_unit_test.h"
20724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
21724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray#include "gtest/gtest.h"
22724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
23724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffraynamespace art {
24724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
25724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray/**
26724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * Test that removing instruction from the graph removes itself from user lists
27724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray * and environment lists.
28724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray */
29724c96326dea6ec33287a0076279c136abb0208aNicolas GeoffrayTEST(Node, RemoveInstruction) {
30724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  ArenaPool pool;
31724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  ArenaAllocator allocator(&pool);
32724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
330a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HGraph* graph = CreateGraph(&allocator);
34724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
35724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  graph->AddBlock(entry);
36724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  graph->SetEntryBlock(entry);
37e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle  HInstruction* parameter = new (&allocator) HParameterValue(
38e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
39724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  entry->AddInstruction(parameter);
40724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  entry->AddInstruction(new (&allocator) HGoto());
41724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
42724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  HBasicBlock* first_block = new (&allocator) HBasicBlock(graph);
43724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  graph->AddBlock(first_block);
44724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  entry->AddSuccessor(first_block);
45724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  HInstruction* null_check = new (&allocator) HNullCheck(parameter, 0);
46724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  first_block->AddInstruction(null_check);
47724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  first_block->AddInstruction(new (&allocator) HReturnVoid());
48724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
49724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
50724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  graph->AddBlock(exit_block);
51724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  first_block->AddSuccessor(exit_block);
52724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray  exit_block->AddInstruction(new (&allocator) HExit());
53724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray
540a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HEnvironment* environment = new (&allocator) HEnvironment(
55d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, 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 */
72191c4b1372aef7c0272f8fa3985b55513029e728Nicolas GeoffrayTEST(Node, InsertInstruction) {
73191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ArenaPool pool;
74191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ArenaAllocator allocator(&pool);
75191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
760a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HGraph* graph = CreateGraph(&allocator);
77191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
78191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  graph->AddBlock(entry);
79191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  graph->SetEntryBlock(entry);
80e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle  HInstruction* parameter1 = new (&allocator) HParameterValue(
81e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
82e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle  HInstruction* parameter2 = new (&allocator) HParameterValue(
83e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
84191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->AddInstruction(parameter1);
85191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->AddInstruction(parameter2);
86191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->AddInstruction(new (&allocator) HExit());
87191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
88191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ASSERT_FALSE(parameter1->HasUses());
89191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
90191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  HInstruction* to_insert = new (&allocator) HNullCheck(parameter1, 0);
91191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->InsertInstructionBefore(to_insert, parameter2);
92191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
93191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ASSERT_TRUE(parameter1->HasUses());
94d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());
95191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray}
96191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
97191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray/**
98191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray * Test that adding an instruction in the graph updates user lists.
99191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray */
100191c4b1372aef7c0272f8fa3985b55513029e728Nicolas GeoffrayTEST(Node, AddInstruction) {
101191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ArenaPool pool;
102191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ArenaAllocator allocator(&pool);
103191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
1040a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HGraph* graph = CreateGraph(&allocator);
105191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
106191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  graph->AddBlock(entry);
107191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  graph->SetEntryBlock(entry);
108e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle  HInstruction* parameter = new (&allocator) HParameterValue(
109e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
110191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->AddInstruction(parameter);
111191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
112191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ASSERT_FALSE(parameter->HasUses());
113191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
114191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  HInstruction* to_add = new (&allocator) HNullCheck(parameter, 0);
115191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  entry->AddInstruction(to_add);
116191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
117191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray  ASSERT_TRUE(parameter->HasUses());
118d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  ASSERT_TRUE(parameter->GetUses().HasExactlyOneElement());
119191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray}
120191c4b1372aef7c0272f8fa3985b55513029e728Nicolas Geoffray
1210a23d74dc2751440822960eab218be4cb8843647Nicolas GeoffrayTEST(Node, ParentEnvironment) {
1220a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ArenaPool pool;
1230a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ArenaAllocator allocator(&pool);
1240a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1250a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HGraph* graph = CreateGraph(&allocator);
1260a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
1270a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  graph->AddBlock(entry);
1280a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  graph->SetEntryBlock(entry);
129e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle  HInstruction* parameter1 = new (&allocator) HParameterValue(
130e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
1310a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HInstruction* with_environment = new (&allocator) HNullCheck(parameter1, 0);
1320a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  entry->AddInstruction(parameter1);
1330a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  entry->AddInstruction(with_environment);
1340a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  entry->AddInstruction(new (&allocator) HExit());
1350a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1360a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_TRUE(parameter1->HasUses());
137d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());
1380a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1390a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HEnvironment* environment = new (&allocator) HEnvironment(
140d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, with_environment);
14171bf8090663d02869cafafdd530976f7f2a9db7fVladimir Marko  ArenaVector<HInstruction*> array(allocator.Adapter());
14271bf8090663d02869cafafdd530976f7f2a9db7fVladimir Marko  array.push_back(parameter1);
1430a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1440a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  environment->CopyFrom(array);
1450a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  with_environment->SetRawEnvironment(environment);
1460a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1470a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_TRUE(parameter1->HasEnvironmentUses());
148d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  ASSERT_TRUE(parameter1->GetEnvUses().HasExactlyOneElement());
1490a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1500a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HEnvironment* parent1 = new (&allocator) HEnvironment(
151d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr);
1520a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  parent1->CopyFrom(array);
1530a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1540a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u);
1550a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1560a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  HEnvironment* parent2 = new (&allocator) HEnvironment(
157d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr);
1580a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  parent2->CopyFrom(array);
1590a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  parent1->SetAndCopyParentChain(&allocator, parent2);
1600a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1610a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  // One use for parent2, and one other use for the new parent of parent1.
1620a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 4u);
1630a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
1640a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  // We have copied the parent chain. So we now have two more uses.
1650a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  environment->SetAndCopyParentChain(&allocator, parent1);
1660a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray  ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 6u);
1670a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray}
1680a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray
169724c96326dea6ec33287a0076279c136abb0208aNicolas Geoffray}  // namespace art
170