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 <sstream>
     17 #include <string>
     18 #include <vector>
     19 
     20 #include "gmock/gmock.h"
     21 #include "gtest/gtest.h"
     22 #include "source/opt/build_module.h"
     23 #include "source/opt/module.h"
     24 #include "spirv-tools/libspirv.hpp"
     25 #include "test/opt/module_utils.h"
     26 
     27 namespace spvtools {
     28 namespace opt {
     29 namespace {
     30 
     31 using ::testing::Eq;
     32 using spvtest::GetIdBound;
     33 
     34 TEST(ModuleTest, SetIdBound) {
     35   Module m;
     36   // It's initialized to 0.
     37   EXPECT_EQ(0u, GetIdBound(m));
     38 
     39   m.SetIdBound(19);
     40   EXPECT_EQ(19u, GetIdBound(m));
     41 
     42   m.SetIdBound(102);
     43   EXPECT_EQ(102u, GetIdBound(m));
     44 }
     45 
     46 // Returns an IRContext owning the module formed by assembling the given text,
     47 // then loading the result.
     48 inline std::unique_ptr<IRContext> BuildModule(std::string text) {
     49   return spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
     50                                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
     51 }
     52 
     53 TEST(ModuleTest, ComputeIdBound) {
     54   // Emtpy module case.
     55   EXPECT_EQ(1u, BuildModule("")->module()->ComputeIdBound());
     56   // Sensitive to result id
     57   EXPECT_EQ(2u, BuildModule("%void = OpTypeVoid")->module()->ComputeIdBound());
     58   // Sensitive to type id
     59   EXPECT_EQ(1000u,
     60             BuildModule("%a = OpTypeArray !999 3")->module()->ComputeIdBound());
     61   // Sensitive to a regular Id parameter
     62   EXPECT_EQ(2000u,
     63             BuildModule("OpDecorate !1999 0")->module()->ComputeIdBound());
     64   // Sensitive to a scope Id parameter.
     65   EXPECT_EQ(3000u,
     66             BuildModule("%f = OpFunction %void None %fntype %a = OpLabel "
     67                         "OpMemoryBarrier !2999 %b\n")
     68                 ->module()
     69                 ->ComputeIdBound());
     70   // Sensitive to a semantics Id parameter
     71   EXPECT_EQ(4000u,
     72             BuildModule("%f = OpFunction %void None %fntype %a = OpLabel "
     73                         "OpMemoryBarrier %b !3999\n")
     74                 ->module()
     75                 ->ComputeIdBound());
     76 }
     77 
     78 TEST(ModuleTest, OstreamOperator) {
     79   const std::string text = R"(OpCapability Shader
     80 OpCapability Linkage
     81 OpMemoryModel Logical GLSL450
     82 OpName %7 "restrict"
     83 OpDecorate %8 Restrict
     84 %9 = OpTypeVoid
     85 %10 = OpTypeInt 32 0
     86 %11 = OpTypeStruct %10 %10
     87 %12 = OpTypePointer Function %10
     88 %13 = OpTypePointer Function %11
     89 %14 = OpConstant %10 0
     90 %15 = OpConstant %10 1
     91 %7 = OpTypeFunction %9
     92 %1 = OpFunction %9 None %7
     93 %2 = OpLabel
     94 %8 = OpVariable %13 Function
     95 %3 = OpAccessChain %12 %8 %14
     96 %4 = OpLoad %10 %3
     97 %5 = OpAccessChain %12 %8 %15
     98 %6 = OpLoad %10 %5
     99 OpReturn
    100 OpFunctionEnd)";
    101 
    102   std::string s;
    103   std::ostringstream str(s);
    104   str << *BuildModule(text)->module();
    105   EXPECT_EQ(text, str.str());
    106 }
    107 
    108 TEST(ModuleTest, OstreamOperatorInt64) {
    109   const std::string text = R"(OpCapability Shader
    110 OpCapability Linkage
    111 OpCapability Int64
    112 OpMemoryModel Logical GLSL450
    113 OpName %7 "restrict"
    114 OpDecorate %5 Restrict
    115 %9 = OpTypeVoid
    116 %10 = OpTypeInt 64 0
    117 %11 = OpTypeStruct %10 %10
    118 %12 = OpTypePointer Function %10
    119 %13 = OpTypePointer Function %11
    120 %14 = OpConstant %10 0
    121 %15 = OpConstant %10 1
    122 %16 = OpConstant %10 4294967297
    123 %7 = OpTypeFunction %9
    124 %1 = OpFunction %9 None %7
    125 %2 = OpLabel
    126 %5 = OpVariable %12 Function
    127 %6 = OpLoad %10 %5
    128 OpSelectionMerge %3 None
    129 OpSwitch %6 %3 4294967297 %4
    130 %4 = OpLabel
    131 OpBranch %3
    132 %3 = OpLabel
    133 OpReturn
    134 OpFunctionEnd)";
    135 
    136   std::string s;
    137   std::ostringstream str(s);
    138   str << *BuildModule(text)->module();
    139   EXPECT_EQ(text, str.str());
    140 }
    141 
    142 TEST(ModuleTest, IdBoundTestAtLimit) {
    143   const std::string text = R"(
    144 OpCapability Shader
    145 OpCapability Linkage
    146 OpMemoryModel Logical GLSL450
    147 %1 = OpTypeVoid
    148 %2 = OpTypeFunction %1
    149 %3 = OpFunction %1 None %2
    150 %4 = OpLabel
    151 OpReturn
    152 OpFunctionEnd)";
    153 
    154   std::unique_ptr<IRContext> context = BuildModule(text);
    155   uint32_t current_bound = context->module()->id_bound();
    156   context->set_max_id_bound(current_bound);
    157   uint32_t next_id_bound = context->module()->TakeNextIdBound();
    158   EXPECT_EQ(next_id_bound, 0);
    159   EXPECT_EQ(current_bound, context->module()->id_bound());
    160   next_id_bound = context->module()->TakeNextIdBound();
    161   EXPECT_EQ(next_id_bound, 0);
    162 }
    163 
    164 TEST(ModuleTest, IdBoundTestBelowLimit) {
    165   const std::string text = R"(
    166 OpCapability Shader
    167 OpCapability Linkage
    168 OpMemoryModel Logical GLSL450
    169 %1 = OpTypeVoid
    170 %2 = OpTypeFunction %1
    171 %3 = OpFunction %1 None %2
    172 %4 = OpLabel
    173 OpReturn
    174 OpFunctionEnd)";
    175 
    176   std::unique_ptr<IRContext> context = BuildModule(text);
    177   uint32_t current_bound = context->module()->id_bound();
    178   context->set_max_id_bound(current_bound + 100);
    179   uint32_t next_id_bound = context->module()->TakeNextIdBound();
    180   EXPECT_EQ(next_id_bound, current_bound);
    181   EXPECT_EQ(current_bound + 1, context->module()->id_bound());
    182   next_id_bound = context->module()->TakeNextIdBound();
    183   EXPECT_EQ(next_id_bound, current_bound + 1);
    184 }
    185 
    186 TEST(ModuleTest, IdBoundTestNearLimit) {
    187   const std::string text = R"(
    188 OpCapability Shader
    189 OpCapability Linkage
    190 OpMemoryModel Logical GLSL450
    191 %1 = OpTypeVoid
    192 %2 = OpTypeFunction %1
    193 %3 = OpFunction %1 None %2
    194 %4 = OpLabel
    195 OpReturn
    196 OpFunctionEnd)";
    197 
    198   std::unique_ptr<IRContext> context = BuildModule(text);
    199   uint32_t current_bound = context->module()->id_bound();
    200   context->set_max_id_bound(current_bound + 1);
    201   uint32_t next_id_bound = context->module()->TakeNextIdBound();
    202   EXPECT_EQ(next_id_bound, current_bound);
    203   EXPECT_EQ(current_bound + 1, context->module()->id_bound());
    204   next_id_bound = context->module()->TakeNextIdBound();
    205   EXPECT_EQ(next_id_bound, 0);
    206 }
    207 
    208 TEST(ModuleTest, IdBoundTestUIntMax) {
    209   const std::string text = R"(
    210 OpCapability Shader
    211 OpCapability Linkage
    212 OpMemoryModel Logical GLSL450
    213 %1 = OpTypeVoid
    214 %2 = OpTypeFunction %1
    215 %3 = OpFunction %1 None %2
    216 %4294967294 = OpLabel ; ID is UINT_MAX-1
    217 OpReturn
    218 OpFunctionEnd)";
    219 
    220   std::unique_ptr<IRContext> context = BuildModule(text);
    221   uint32_t current_bound = context->module()->id_bound();
    222 
    223   // Expecting |BuildModule| to preserve the numeric ids.
    224   EXPECT_EQ(current_bound, std::numeric_limits<uint32_t>::max());
    225 
    226   context->set_max_id_bound(current_bound);
    227   uint32_t next_id_bound = context->module()->TakeNextIdBound();
    228   EXPECT_EQ(next_id_bound, 0);
    229   EXPECT_EQ(current_bound, context->module()->id_bound());
    230 }
    231 }  // namespace
    232 }  // namespace opt
    233 }  // namespace spvtools
    234