Home | History | Annotate | Download | only in opt
      1 // Copyright (c) 2016 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include <memory>
     16 #include <utility>
     17 #include <vector>
     18 
     19 #include "gtest/gtest.h"
     20 #include "source/opt/types.h"
     21 #include "source/util/make_unique.h"
     22 
     23 namespace spvtools {
     24 namespace opt {
     25 namespace analysis {
     26 namespace {
     27 
     28 // Fixture class providing some element types.
     29 class SameTypeTest : public ::testing::Test {
     30  protected:
     31   void SetUp() override {
     32     void_t_ = MakeUnique<Void>();
     33     u32_t_ = MakeUnique<Integer>(32, false);
     34     f64_t_ = MakeUnique<Float>(64);
     35     v3u32_t_ = MakeUnique<Vector>(u32_t_.get(), 3);
     36     image_t_ =
     37         MakeUnique<Image>(f64_t_.get(), SpvDim2D, 1, 1, 0, 0, SpvImageFormatR16,
     38                           SpvAccessQualifierReadWrite);
     39   }
     40 
     41   // Element types to be used for constructing other types for testing.
     42   std::unique_ptr<Type> void_t_;
     43   std::unique_ptr<Type> u32_t_;
     44   std::unique_ptr<Type> f64_t_;
     45   std::unique_ptr<Type> v3u32_t_;
     46   std::unique_ptr<Type> image_t_;
     47 };
     48 
     49 #define TestMultipleInstancesOfTheSameType(ty, ...)                       \
     50   TEST_F(SameTypeTest, MultiSame##ty) {                                   \
     51     std::vector<std::unique_ptr<Type>> types;                             \
     52     for (int i = 0; i < 10; ++i) types.emplace_back(new ty(__VA_ARGS__)); \
     53     for (size_t i = 0; i < types.size(); ++i) {                           \
     54       for (size_t j = 0; j < types.size(); ++j) {                         \
     55         EXPECT_TRUE(types[i]->IsSame(types[j].get()))                     \
     56             << "expected '" << types[i]->str() << "' is the same as '"    \
     57             << types[j]->str() << "'";                                    \
     58         EXPECT_TRUE(*types[i] == *types[j])                               \
     59             << "expected '" << types[i]->str() << "' is the same as '"    \
     60             << types[j]->str() << "'";                                    \
     61       }                                                                   \
     62     }                                                                     \
     63   }
     64 TestMultipleInstancesOfTheSameType(Void);
     65 TestMultipleInstancesOfTheSameType(Bool);
     66 TestMultipleInstancesOfTheSameType(Integer, 32, true);
     67 TestMultipleInstancesOfTheSameType(Float, 64);
     68 TestMultipleInstancesOfTheSameType(Vector, u32_t_.get(), 3);
     69 TestMultipleInstancesOfTheSameType(Matrix, v3u32_t_.get(), 4);
     70 TestMultipleInstancesOfTheSameType(Image, f64_t_.get(), SpvDimCube, 0, 0, 1, 1,
     71                                    SpvImageFormatRgb10A2,
     72                                    SpvAccessQualifierWriteOnly);
     73 TestMultipleInstancesOfTheSameType(Sampler);
     74 TestMultipleInstancesOfTheSameType(SampledImage, image_t_.get());
     75 TestMultipleInstancesOfTheSameType(Array, u32_t_.get(), 10);
     76 TestMultipleInstancesOfTheSameType(RuntimeArray, u32_t_.get());
     77 TestMultipleInstancesOfTheSameType(Struct, std::vector<const Type*>{
     78                                                u32_t_.get(), f64_t_.get()});
     79 TestMultipleInstancesOfTheSameType(Opaque, "testing rocks");
     80 TestMultipleInstancesOfTheSameType(Pointer, u32_t_.get(), SpvStorageClassInput);
     81 TestMultipleInstancesOfTheSameType(Function, u32_t_.get(),
     82                                    {f64_t_.get(), f64_t_.get()});
     83 TestMultipleInstancesOfTheSameType(Event);
     84 TestMultipleInstancesOfTheSameType(DeviceEvent);
     85 TestMultipleInstancesOfTheSameType(ReserveId);
     86 TestMultipleInstancesOfTheSameType(Queue);
     87 TestMultipleInstancesOfTheSameType(Pipe, SpvAccessQualifierReadWrite);
     88 TestMultipleInstancesOfTheSameType(ForwardPointer, 10, SpvStorageClassUniform);
     89 TestMultipleInstancesOfTheSameType(PipeStorage);
     90 TestMultipleInstancesOfTheSameType(NamedBarrier);
     91 TestMultipleInstancesOfTheSameType(AccelerationStructureNV);
     92 #undef TestMultipleInstanceOfTheSameType
     93 
     94 std::vector<std::unique_ptr<Type>> GenerateAllTypes() {
     95   // Types in this test case are only equal to themselves, nothing else.
     96   std::vector<std::unique_ptr<Type>> types;
     97 
     98   // Forward Pointer
     99   types.emplace_back(new ForwardPointer(10000, SpvStorageClassInput));
    100   types.emplace_back(new ForwardPointer(20000, SpvStorageClassInput));
    101 
    102   // Void, Bool
    103   types.emplace_back(new Void());
    104   auto* voidt = types.back().get();
    105   types.emplace_back(new Bool());
    106   auto* boolt = types.back().get();
    107 
    108   // Integer
    109   types.emplace_back(new Integer(32, true));
    110   auto* s32 = types.back().get();
    111   types.emplace_back(new Integer(32, false));
    112   types.emplace_back(new Integer(64, true));
    113   types.emplace_back(new Integer(64, false));
    114   auto* u64 = types.back().get();
    115 
    116   // Float
    117   types.emplace_back(new Float(32));
    118   auto* f32 = types.back().get();
    119   types.emplace_back(new Float(64));
    120 
    121   // Vector
    122   types.emplace_back(new Vector(s32, 2));
    123   types.emplace_back(new Vector(s32, 3));
    124   auto* v3s32 = types.back().get();
    125   types.emplace_back(new Vector(u64, 4));
    126   types.emplace_back(new Vector(f32, 3));
    127   auto* v3f32 = types.back().get();
    128 
    129   // Matrix
    130   types.emplace_back(new Matrix(v3s32, 3));
    131   types.emplace_back(new Matrix(v3s32, 4));
    132   types.emplace_back(new Matrix(v3f32, 4));
    133 
    134   // Images
    135   types.emplace_back(new Image(s32, SpvDim2D, 0, 0, 0, 0, SpvImageFormatRg8,
    136                                SpvAccessQualifierReadOnly));
    137   auto* image1 = types.back().get();
    138   types.emplace_back(new Image(s32, SpvDim2D, 0, 1, 0, 0, SpvImageFormatRg8,
    139                                SpvAccessQualifierReadOnly));
    140   types.emplace_back(new Image(s32, SpvDim3D, 0, 1, 0, 0, SpvImageFormatRg8,
    141                                SpvAccessQualifierReadOnly));
    142   types.emplace_back(new Image(voidt, SpvDim3D, 0, 1, 0, 1, SpvImageFormatRg8,
    143                                SpvAccessQualifierReadWrite));
    144   auto* image2 = types.back().get();
    145 
    146   // Sampler
    147   types.emplace_back(new Sampler());
    148 
    149   // Sampled Image
    150   types.emplace_back(new SampledImage(image1));
    151   types.emplace_back(new SampledImage(image2));
    152 
    153   // Array
    154   types.emplace_back(new Array(f32, 100));
    155   types.emplace_back(new Array(f32, 42));
    156   auto* a42f32 = types.back().get();
    157   types.emplace_back(new Array(u64, 24));
    158 
    159   // RuntimeArray
    160   types.emplace_back(new RuntimeArray(v3f32));
    161   types.emplace_back(new RuntimeArray(v3s32));
    162   auto* rav3s32 = types.back().get();
    163 
    164   // Struct
    165   types.emplace_back(new Struct(std::vector<const Type*>{s32}));
    166   types.emplace_back(new Struct(std::vector<const Type*>{s32, f32}));
    167   auto* sts32f32 = types.back().get();
    168   types.emplace_back(
    169       new Struct(std::vector<const Type*>{u64, a42f32, rav3s32}));
    170 
    171   // Opaque
    172   types.emplace_back(new Opaque(""));
    173   types.emplace_back(new Opaque("hello"));
    174   types.emplace_back(new Opaque("world"));
    175 
    176   // Pointer
    177   types.emplace_back(new Pointer(f32, SpvStorageClassInput));
    178   types.emplace_back(new Pointer(sts32f32, SpvStorageClassFunction));
    179   types.emplace_back(new Pointer(a42f32, SpvStorageClassFunction));
    180   types.emplace_back(new Pointer(voidt, SpvStorageClassFunction));
    181 
    182   // Function
    183   types.emplace_back(new Function(voidt, {}));
    184   types.emplace_back(new Function(voidt, {boolt}));
    185   types.emplace_back(new Function(voidt, {boolt, s32}));
    186   types.emplace_back(new Function(s32, {boolt, s32}));
    187 
    188   // Event, Device Event, Reserve Id, Queue,
    189   types.emplace_back(new Event());
    190   types.emplace_back(new DeviceEvent());
    191   types.emplace_back(new ReserveId());
    192   types.emplace_back(new Queue());
    193 
    194   // Pipe, Forward Pointer, PipeStorage, NamedBarrier
    195   types.emplace_back(new Pipe(SpvAccessQualifierReadWrite));
    196   types.emplace_back(new Pipe(SpvAccessQualifierReadOnly));
    197   types.emplace_back(new ForwardPointer(1, SpvStorageClassInput));
    198   types.emplace_back(new ForwardPointer(2, SpvStorageClassInput));
    199   types.emplace_back(new ForwardPointer(2, SpvStorageClassUniform));
    200   types.emplace_back(new PipeStorage());
    201   types.emplace_back(new NamedBarrier());
    202 
    203   return types;
    204 }
    205 
    206 TEST(Types, AllTypes) {
    207   // Types in this test case are only equal to themselves, nothing else.
    208   std::vector<std::unique_ptr<Type>> types = GenerateAllTypes();
    209 
    210   for (size_t i = 0; i < types.size(); ++i) {
    211     for (size_t j = 0; j < types.size(); ++j) {
    212       if (i == j) {
    213         EXPECT_TRUE(types[i]->IsSame(types[j].get()))
    214             << "expected '" << types[i]->str() << "' is the same as '"
    215             << types[j]->str() << "'";
    216       } else {
    217         EXPECT_FALSE(types[i]->IsSame(types[j].get()))
    218             << "expected '" << types[i]->str() << "' is different to '"
    219             << types[j]->str() << "'";
    220       }
    221     }
    222   }
    223 }
    224 
    225 TEST(Types, IntSignedness) {
    226   std::vector<bool> signednesses = {true, false, false, true};
    227   std::vector<std::unique_ptr<Integer>> types;
    228   for (bool s : signednesses) {
    229     types.emplace_back(new Integer(32, s));
    230   }
    231   for (size_t i = 0; i < signednesses.size(); i++) {
    232     EXPECT_EQ(signednesses[i], types[i]->IsSigned());
    233   }
    234 }
    235 
    236 TEST(Types, IntWidth) {
    237   std::vector<uint32_t> widths = {1, 2, 4, 8, 16, 32, 48, 64, 128};
    238   std::vector<std::unique_ptr<Integer>> types;
    239   for (uint32_t w : widths) {
    240     types.emplace_back(new Integer(w, true));
    241   }
    242   for (size_t i = 0; i < widths.size(); i++) {
    243     EXPECT_EQ(widths[i], types[i]->width());
    244   }
    245 }
    246 
    247 TEST(Types, FloatWidth) {
    248   std::vector<uint32_t> widths = {1, 2, 4, 8, 16, 32, 48, 64, 128};
    249   std::vector<std::unique_ptr<Float>> types;
    250   for (uint32_t w : widths) {
    251     types.emplace_back(new Float(w));
    252   }
    253   for (size_t i = 0; i < widths.size(); i++) {
    254     EXPECT_EQ(widths[i], types[i]->width());
    255   }
    256 }
    257 
    258 TEST(Types, VectorElementCount) {
    259   auto s32 = MakeUnique<Integer>(32, true);
    260   for (uint32_t c : {2, 3, 4}) {
    261     auto s32v = MakeUnique<Vector>(s32.get(), c);
    262     EXPECT_EQ(c, s32v->element_count());
    263   }
    264 }
    265 
    266 TEST(Types, MatrixElementCount) {
    267   auto s32 = MakeUnique<Integer>(32, true);
    268   auto s32v4 = MakeUnique<Vector>(s32.get(), 4);
    269   for (uint32_t c : {1, 2, 3, 4, 10, 100}) {
    270     auto s32m = MakeUnique<Matrix>(s32v4.get(), c);
    271     EXPECT_EQ(c, s32m->element_count());
    272   }
    273 }
    274 
    275 TEST(Types, IsUniqueType) {
    276   std::vector<std::unique_ptr<Type>> types = GenerateAllTypes();
    277 
    278   for (auto& t : types) {
    279     bool expectation = true;
    280     // Disallowing variable pointers.
    281     switch (t->kind()) {
    282       case Type::kArray:
    283       case Type::kRuntimeArray:
    284       case Type::kStruct:
    285         expectation = false;
    286         break;
    287       default:
    288         break;
    289     }
    290     EXPECT_EQ(t->IsUniqueType(false), expectation)
    291         << "expected '" << t->str() << "' to be a "
    292         << (expectation ? "" : "non-") << "unique type";
    293 
    294     // Allowing variables pointers.
    295     if (t->AsPointer()) expectation = false;
    296     EXPECT_EQ(t->IsUniqueType(true), expectation)
    297         << "expected '" << t->str() << "' to be a "
    298         << (expectation ? "" : "non-") << "unique type";
    299   }
    300 }
    301 
    302 std::vector<std::unique_ptr<Type>> GenerateAllTypesWithDecorations() {
    303   std::vector<std::unique_ptr<Type>> types = GenerateAllTypes();
    304   uint32_t elems = 1;
    305   uint32_t decs = 1;
    306   for (auto& t : types) {
    307     for (uint32_t i = 0; i < (decs % 10); ++i) {
    308       std::vector<uint32_t> decoration;
    309       for (uint32_t j = 0; j < (elems % 4) + 1; ++j) {
    310         decoration.push_back(j);
    311       }
    312       t->AddDecoration(std::move(decoration));
    313       ++elems;
    314       ++decs;
    315     }
    316   }
    317 
    318   return types;
    319 }
    320 
    321 TEST(Types, Clone) {
    322   std::vector<std::unique_ptr<Type>> types = GenerateAllTypesWithDecorations();
    323   for (auto& t : types) {
    324     auto clone = t->Clone();
    325     EXPECT_TRUE(*t == *clone);
    326     EXPECT_TRUE(t->HasSameDecorations(clone.get()));
    327     EXPECT_NE(clone.get(), t.get());
    328   }
    329 }
    330 
    331 TEST(Types, RemoveDecorations) {
    332   std::vector<std::unique_ptr<Type>> types = GenerateAllTypesWithDecorations();
    333   for (auto& t : types) {
    334     auto decorationless = t->RemoveDecorations();
    335     EXPECT_EQ(*t == *decorationless, t->decoration_empty());
    336     EXPECT_EQ(t->HasSameDecorations(decorationless.get()),
    337               t->decoration_empty());
    338     EXPECT_NE(t.get(), decorationless.get());
    339   }
    340 }
    341 
    342 }  // namespace
    343 }  // namespace analysis
    344 }  // namespace opt
    345 }  // namespace spvtools
    346