1/*
2 * Copyright 2017, 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 "transformer.h"
18
19#include "file_utils.h"
20#include "spirit.h"
21#include "test_utils.h"
22#include "gtest/gtest.h"
23
24#include <stdint.h>
25
26namespace android {
27namespace spirit {
28
29namespace {
30
31class MulToAddTransformer : public Transformer {
32public:
33  Instruction *transform(IMulInst *mul) override {
34    auto ret = new IAddInst(mul->mResultType, mul->mOperand1, mul->mOperand2);
35    ret->setId(mul->getId());
36    return ret;
37  }
38};
39
40class Deleter : public Transformer {
41public:
42  Instruction *transform(IMulInst *) override { return nullptr; }
43};
44
45class NewDataTypeTransformer : public Transformer {
46public:
47  Instruction *transform(IMulInst *mul) override {
48    insert(mul);
49    auto *DoubleTy = getModule()->getFloatType(64);
50    ConstantInst *ConstDouble2 = getModule()->getConstant(DoubleTy, 2.0);
51    auto ret = new IAddInst(DoubleTy, mul, ConstDouble2);
52
53    IdResult id = ret->getId();
54    ret->setId(mul->getId());
55    mul->setId(id);
56
57    return ret;
58  }
59};
60
61} // annonymous namespace
62
63class TransformerTest : public ::testing::Test {
64protected:
65  virtual void SetUp() { mWordsGreyscale = readWords("greyscale.spv"); }
66
67  std::vector<uint32_t> mWordsGreyscale;
68
69private:
70  std::vector<uint32_t> readWords(const char *testFile) {
71    static const std::string testDataPath(
72        "frameworks/rs/rsov/compiler/spirit/test_data/");
73    const std::string &fullPath = getAbsolutePath(testDataPath + testFile);
74    return readFile<uint32_t>(fullPath);
75  }
76};
77
78TEST_F(TransformerTest, testMulToAdd) {
79  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
80
81  ASSERT_NE(nullptr, m);
82
83  EXPECT_EQ(1, countEntity<IAddInst>(m.get()));
84  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
85
86  MulToAddTransformer trans;
87  std::unique_ptr<Module> m1(trans.run(m.get()));
88
89  ASSERT_NE(nullptr, m1);
90
91  ASSERT_TRUE(m1->resolveIds());
92
93  EXPECT_EQ(2, countEntity<IAddInst>(m1.get()));
94  EXPECT_EQ(0, countEntity<IMulInst>(m1.get()));
95}
96
97TEST_F(TransformerTest, testDeletion) {
98  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
99
100  ASSERT_NE(nullptr, m.get());
101
102  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
103
104  Deleter trans;
105  std::unique_ptr<Module> m1(trans.run(m.get()));
106
107  ASSERT_NE(nullptr, m1.get());
108
109  EXPECT_EQ(1, countEntity<IAddInst>(m1.get()));
110  EXPECT_EQ(0, countEntity<IMulInst>(m1.get()));
111}
112
113TEST_F(TransformerTest, testAddInstructionUsingNewDataType) {
114  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
115
116  ASSERT_NE(nullptr, m.get());
117
118  EXPECT_EQ(5, countEntity<ConstantInst>(m.get()));
119  EXPECT_EQ(1, countEntity<TypeFloatInst>(m.get()));
120  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
121
122  NewDataTypeTransformer trans;
123  std::unique_ptr<Module> m1(trans.run(m.get()));
124
125  ASSERT_NE(nullptr, m1.get());
126
127  EXPECT_EQ(6, countEntity<ConstantInst>(m.get()));
128  EXPECT_EQ(2, countEntity<TypeFloatInst>(m1.get()));
129  EXPECT_EQ(2, countEntity<IAddInst>(m1.get()));
130  EXPECT_EQ(1, countEntity<IMulInst>(m1.get()));
131}
132
133} // namespace spirit
134} // namespace android
135