mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-30 15:00:06 +00:00
0ec08c28c1
For each function, the analysis determine which SSA registers are live at the beginning of each basic block and which one are killed at the end of the basic block. It also includes utilities to simulate the register pressure for loop fusion and fission. The implementation is based on the paper "A non-iterative data-flow algorithm for computing liveness sets in strict ssa programs" from Boissinot et al.
267 lines
7.4 KiB
C++
267 lines
7.4 KiB
C++
// Copyright (c) 2016 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "opt/iterator.h"
|
|
#include "opt/make_unique.h"
|
|
|
|
namespace {
|
|
|
|
using namespace spvtools;
|
|
using ::testing::ContainerEq;
|
|
|
|
TEST(Iterator, IncrementDeref) {
|
|
const int count = 100;
|
|
std::vector<std::unique_ptr<int>> data;
|
|
for (int i = 0; i < count; ++i) {
|
|
data.emplace_back(new int(i));
|
|
}
|
|
|
|
ir::UptrVectorIterator<int> it(&data, data.begin());
|
|
ir::UptrVectorIterator<int> end(&data, data.end());
|
|
|
|
EXPECT_EQ(*data[0], *it);
|
|
for (int i = 1; i < count; ++i) {
|
|
EXPECT_NE(end, it);
|
|
EXPECT_EQ(*data[i], *(++it));
|
|
}
|
|
EXPECT_EQ(end, ++it);
|
|
}
|
|
|
|
TEST(Iterator, DecrementDeref) {
|
|
const int count = 100;
|
|
std::vector<std::unique_ptr<int>> data;
|
|
for (int i = 0; i < count; ++i) {
|
|
data.emplace_back(new int(i));
|
|
}
|
|
|
|
ir::UptrVectorIterator<int> begin(&data, data.begin());
|
|
ir::UptrVectorIterator<int> it(&data, data.end());
|
|
|
|
for (int i = count - 1; i >= 0; --i) {
|
|
EXPECT_NE(begin, it);
|
|
EXPECT_EQ(*data[i], *(--it));
|
|
}
|
|
EXPECT_EQ(begin, it);
|
|
}
|
|
|
|
TEST(Iterator, PostIncrementDeref) {
|
|
const int count = 100;
|
|
std::vector<std::unique_ptr<int>> data;
|
|
for (int i = 0; i < count; ++i) {
|
|
data.emplace_back(new int(i));
|
|
}
|
|
|
|
ir::UptrVectorIterator<int> it(&data, data.begin());
|
|
ir::UptrVectorIterator<int> end(&data, data.end());
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
EXPECT_NE(end, it);
|
|
EXPECT_EQ(*data[i], *(it++));
|
|
}
|
|
EXPECT_EQ(end, it);
|
|
}
|
|
|
|
TEST(Iterator, PostDecrementDeref) {
|
|
const int count = 100;
|
|
std::vector<std::unique_ptr<int>> data;
|
|
for (int i = 0; i < count; ++i) {
|
|
data.emplace_back(new int(i));
|
|
}
|
|
|
|
ir::UptrVectorIterator<int> begin(&data, data.begin());
|
|
ir::UptrVectorIterator<int> end(&data, data.end());
|
|
ir::UptrVectorIterator<int> it(&data, data.end());
|
|
|
|
EXPECT_EQ(end, it--);
|
|
for (int i = count - 1; i >= 1; --i) {
|
|
EXPECT_EQ(*data[i], *(it--));
|
|
}
|
|
// Decrementing .begin() is undefined behavior.
|
|
EXPECT_EQ(*data[0], *it);
|
|
}
|
|
|
|
TEST(Iterator, Access) {
|
|
const int count = 100;
|
|
std::vector<std::unique_ptr<int>> data;
|
|
for (int i = 0; i < count; ++i) {
|
|
data.emplace_back(new int(i));
|
|
}
|
|
|
|
ir::UptrVectorIterator<int> it(&data, data.begin());
|
|
|
|
for (int i = 0; i < count; ++i) EXPECT_EQ(*data[i], it[i]);
|
|
}
|
|
|
|
TEST(Iterator, Comparison) {
|
|
const int count = 100;
|
|
std::vector<std::unique_ptr<int>> data;
|
|
for (int i = 0; i < count; ++i) {
|
|
data.emplace_back(new int(i));
|
|
}
|
|
|
|
ir::UptrVectorIterator<int> it(&data, data.begin());
|
|
ir::UptrVectorIterator<int> end(&data, data.end());
|
|
|
|
for (int i = 0; i < count; ++i, ++it) EXPECT_TRUE(it < end);
|
|
EXPECT_EQ(end, it);
|
|
}
|
|
|
|
TEST(Iterator, InsertBeginEnd) {
|
|
const int count = 100;
|
|
|
|
std::vector<std::unique_ptr<int>> data;
|
|
std::vector<int> expected;
|
|
std::vector<int> actual;
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
data.emplace_back(new int(i));
|
|
expected.push_back(i);
|
|
}
|
|
|
|
// Insert at the beginning
|
|
expected.insert(expected.begin(), -100);
|
|
ir::UptrVectorIterator<int> begin(&data, data.begin());
|
|
auto insert_point = begin.InsertBefore(MakeUnique<int>(-100));
|
|
for (int i = 0; i < count + 1; ++i) {
|
|
actual.push_back(*(insert_point++));
|
|
}
|
|
EXPECT_THAT(actual, ContainerEq(expected));
|
|
|
|
// Insert at the end
|
|
expected.push_back(-42);
|
|
expected.push_back(-36);
|
|
expected.push_back(-77);
|
|
ir::UptrVectorIterator<int> end(&data, data.end());
|
|
end = end.InsertBefore(MakeUnique<int>(-77));
|
|
end = end.InsertBefore(MakeUnique<int>(-36));
|
|
end = end.InsertBefore(MakeUnique<int>(-42));
|
|
|
|
actual.clear();
|
|
begin = ir::UptrVectorIterator<int>(&data, data.begin());
|
|
for (int i = 0; i < count + 4; ++i) {
|
|
actual.push_back(*(begin++));
|
|
}
|
|
EXPECT_THAT(actual, ContainerEq(expected));
|
|
}
|
|
|
|
TEST(Iterator, InsertMiddle) {
|
|
const int count = 100;
|
|
|
|
std::vector<std::unique_ptr<int>> data;
|
|
std::vector<int> expected;
|
|
std::vector<int> actual;
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
data.emplace_back(new int(i));
|
|
expected.push_back(i);
|
|
}
|
|
|
|
const int insert_pos = 42;
|
|
expected.insert(expected.begin() + insert_pos, -100);
|
|
expected.insert(expected.begin() + insert_pos, -42);
|
|
|
|
ir::UptrVectorIterator<int> it(&data, data.begin());
|
|
for (int i = 0; i < insert_pos; ++i) ++it;
|
|
it = it.InsertBefore(MakeUnique<int>(-100));
|
|
it = it.InsertBefore(MakeUnique<int>(-42));
|
|
auto begin = ir::UptrVectorIterator<int>(&data, data.begin());
|
|
for (int i = 0; i < count + 2; ++i) {
|
|
actual.push_back(*(begin++));
|
|
}
|
|
EXPECT_THAT(actual, ContainerEq(expected));
|
|
}
|
|
|
|
TEST(IteratorRange, Interface) {
|
|
const uint32_t count = 100;
|
|
|
|
std::vector<std::unique_ptr<uint32_t>> data;
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
data.emplace_back(new uint32_t(i));
|
|
}
|
|
|
|
auto b = ir::UptrVectorIterator<uint32_t>(&data, data.begin());
|
|
auto e = ir::UptrVectorIterator<uint32_t>(&data, data.end());
|
|
auto range = ir::IteratorRange<decltype(b)>(b, e);
|
|
|
|
EXPECT_EQ(b, range.begin());
|
|
EXPECT_EQ(e, range.end());
|
|
EXPECT_FALSE(range.empty());
|
|
EXPECT_EQ(count, range.size());
|
|
EXPECT_EQ(0u, *range.begin());
|
|
EXPECT_EQ(99u, *(--range.end()));
|
|
|
|
// IteratorRange itself is immutable.
|
|
++b, --e;
|
|
EXPECT_EQ(count, range.size());
|
|
++range.begin(), --range.end();
|
|
EXPECT_EQ(count, range.size());
|
|
}
|
|
|
|
TEST(Iterator, FilterIterator) {
|
|
struct Placeholder {
|
|
int val;
|
|
};
|
|
std::vector<Placeholder> data = {{1}, {2}, {3}, {4}, {5},
|
|
{6}, {7}, {8}, {9}, {10}};
|
|
|
|
// Predicate to only consider odd values.
|
|
struct Predicate {
|
|
bool operator()(const Placeholder& data) { return data.val % 2; }
|
|
};
|
|
Predicate pred;
|
|
|
|
auto filter_range =
|
|
ir::MakeFilterIteratorRange(data.begin(), data.end(), pred);
|
|
|
|
EXPECT_EQ(filter_range.begin().Get(), data.begin());
|
|
EXPECT_EQ(filter_range.end(), filter_range.begin().GetEnd());
|
|
|
|
for (Placeholder& data : filter_range) {
|
|
EXPECT_EQ(data.val % 2, 1);
|
|
}
|
|
|
|
for (auto it = filter_range.begin(); it != filter_range.end(); it++) {
|
|
EXPECT_EQ(it->val % 2, 1);
|
|
EXPECT_EQ((*it).val % 2, 1);
|
|
}
|
|
|
|
for (auto it = filter_range.begin(); it != filter_range.end(); ++it) {
|
|
EXPECT_EQ(it->val % 2, 1);
|
|
EXPECT_EQ((*it).val % 2, 1);
|
|
}
|
|
|
|
EXPECT_EQ(ir::MakeFilterIterator(data.begin(), data.end(), pred).Get(),
|
|
data.begin());
|
|
EXPECT_EQ(ir::MakeFilterIterator(data.end(), data.end(), pred).Get(),
|
|
data.end());
|
|
EXPECT_EQ(ir::MakeFilterIterator(data.begin(), data.end(), pred).GetEnd(),
|
|
ir::MakeFilterIterator(data.end(), data.end(), pred));
|
|
EXPECT_NE(ir::MakeFilterIterator(data.begin(), data.end(), pred),
|
|
ir::MakeFilterIterator(data.end(), data.end(), pred));
|
|
|
|
// Empty range: no values satisfies the predicate.
|
|
auto empty_range = ir::MakeFilterIteratorRange(
|
|
data.begin(), data.end(),
|
|
[](const Placeholder& data) { return data.val > 10; });
|
|
EXPECT_EQ(empty_range.begin(), empty_range.end());
|
|
}
|
|
|
|
} // anonymous namespace
|