1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 Google Inc. 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include "source/opt/ir_builder.h" 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include <memory> 18fd4e5da5Sopenharmony_ci#include <vector> 19fd4e5da5Sopenharmony_ci 20fd4e5da5Sopenharmony_ci#include "effcee/effcee.h" 21fd4e5da5Sopenharmony_ci#include "gtest/gtest.h" 22fd4e5da5Sopenharmony_ci#include "source/opt/basic_block.h" 23fd4e5da5Sopenharmony_ci#include "source/opt/build_module.h" 24fd4e5da5Sopenharmony_ci#include "source/opt/instruction.h" 25fd4e5da5Sopenharmony_ci#include "source/opt/type_manager.h" 26fd4e5da5Sopenharmony_ci#include "spirv-tools/libspirv.hpp" 27fd4e5da5Sopenharmony_ci 28fd4e5da5Sopenharmony_cinamespace spvtools { 29fd4e5da5Sopenharmony_cinamespace opt { 30fd4e5da5Sopenharmony_cinamespace { 31fd4e5da5Sopenharmony_ci 32fd4e5da5Sopenharmony_ciusing Analysis = IRContext::Analysis; 33fd4e5da5Sopenharmony_ciusing IRBuilderTest = ::testing::Test; 34fd4e5da5Sopenharmony_ci 35fd4e5da5Sopenharmony_cibool Validate(const std::vector<uint32_t>& bin) { 36fd4e5da5Sopenharmony_ci spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; 37fd4e5da5Sopenharmony_ci spv_context spvContext = spvContextCreate(target_env); 38fd4e5da5Sopenharmony_ci spv_diagnostic diagnostic = nullptr; 39fd4e5da5Sopenharmony_ci spv_const_binary_t binary = {bin.data(), bin.size()}; 40fd4e5da5Sopenharmony_ci spv_result_t error = spvValidate(spvContext, &binary, &diagnostic); 41fd4e5da5Sopenharmony_ci if (error != 0) spvDiagnosticPrint(diagnostic); 42fd4e5da5Sopenharmony_ci spvDiagnosticDestroy(diagnostic); 43fd4e5da5Sopenharmony_ci spvContextDestroy(spvContext); 44fd4e5da5Sopenharmony_ci return error == 0; 45fd4e5da5Sopenharmony_ci} 46fd4e5da5Sopenharmony_ci 47fd4e5da5Sopenharmony_civoid Match(const std::string& original, IRContext* context, 48fd4e5da5Sopenharmony_ci bool do_validation = true) { 49fd4e5da5Sopenharmony_ci std::vector<uint32_t> bin; 50fd4e5da5Sopenharmony_ci context->module()->ToBinary(&bin, true); 51fd4e5da5Sopenharmony_ci if (do_validation) { 52fd4e5da5Sopenharmony_ci EXPECT_TRUE(Validate(bin)); 53fd4e5da5Sopenharmony_ci } 54fd4e5da5Sopenharmony_ci std::string assembly; 55fd4e5da5Sopenharmony_ci SpirvTools tools(SPV_ENV_UNIVERSAL_1_2); 56fd4e5da5Sopenharmony_ci EXPECT_TRUE( 57fd4e5da5Sopenharmony_ci tools.Disassemble(bin, &assembly, SpirvTools::kDefaultDisassembleOption)) 58fd4e5da5Sopenharmony_ci << "Disassembling failed for shader:\n" 59fd4e5da5Sopenharmony_ci << assembly << std::endl; 60fd4e5da5Sopenharmony_ci auto match_result = effcee::Match(assembly, original); 61fd4e5da5Sopenharmony_ci EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) 62fd4e5da5Sopenharmony_ci << match_result.message() << "\nChecking result:\n" 63fd4e5da5Sopenharmony_ci << assembly; 64fd4e5da5Sopenharmony_ci} 65fd4e5da5Sopenharmony_ci 66fd4e5da5Sopenharmony_ciTEST_F(IRBuilderTest, TestInsnAddition) { 67fd4e5da5Sopenharmony_ci const std::string text = R"( 68fd4e5da5Sopenharmony_ci; CHECK: %18 = OpLabel 69fd4e5da5Sopenharmony_ci; CHECK: OpPhi %int %int_0 %14 70fd4e5da5Sopenharmony_ci; CHECK: OpPhi %bool %16 %14 71fd4e5da5Sopenharmony_ci; CHECK: OpBranch %17 72fd4e5da5Sopenharmony_ci OpCapability Shader 73fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 74fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 75fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" %3 76fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 77fd4e5da5Sopenharmony_ci OpSource GLSL 330 78fd4e5da5Sopenharmony_ci OpName %2 "main" 79fd4e5da5Sopenharmony_ci OpName %4 "i" 80fd4e5da5Sopenharmony_ci OpName %3 "c" 81fd4e5da5Sopenharmony_ci OpDecorate %3 Location 0 82fd4e5da5Sopenharmony_ci %5 = OpTypeVoid 83fd4e5da5Sopenharmony_ci %6 = OpTypeFunction %5 84fd4e5da5Sopenharmony_ci %7 = OpTypeInt 32 1 85fd4e5da5Sopenharmony_ci %8 = OpTypePointer Function %7 86fd4e5da5Sopenharmony_ci %9 = OpConstant %7 0 87fd4e5da5Sopenharmony_ci %10 = OpTypeBool 88fd4e5da5Sopenharmony_ci %11 = OpTypeFloat 32 89fd4e5da5Sopenharmony_ci %12 = OpTypeVector %11 4 90fd4e5da5Sopenharmony_ci %13 = OpTypePointer Output %12 91fd4e5da5Sopenharmony_ci %3 = OpVariable %13 Output 92fd4e5da5Sopenharmony_ci %2 = OpFunction %5 None %6 93fd4e5da5Sopenharmony_ci %14 = OpLabel 94fd4e5da5Sopenharmony_ci %4 = OpVariable %8 Function 95fd4e5da5Sopenharmony_ci OpStore %4 %9 96fd4e5da5Sopenharmony_ci %15 = OpLoad %7 %4 97fd4e5da5Sopenharmony_ci %16 = OpINotEqual %10 %15 %9 98fd4e5da5Sopenharmony_ci OpSelectionMerge %17 None 99fd4e5da5Sopenharmony_ci OpBranchConditional %16 %18 %17 100fd4e5da5Sopenharmony_ci %18 = OpLabel 101fd4e5da5Sopenharmony_ci OpBranch %17 102fd4e5da5Sopenharmony_ci %17 = OpLabel 103fd4e5da5Sopenharmony_ci OpReturn 104fd4e5da5Sopenharmony_ci OpFunctionEnd 105fd4e5da5Sopenharmony_ci)"; 106fd4e5da5Sopenharmony_ci 107fd4e5da5Sopenharmony_ci { 108fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 109fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 110fd4e5da5Sopenharmony_ci 111fd4e5da5Sopenharmony_ci BasicBlock* bb = context->cfg()->block(18); 112fd4e5da5Sopenharmony_ci 113fd4e5da5Sopenharmony_ci // Build managers. 114fd4e5da5Sopenharmony_ci context->get_def_use_mgr(); 115fd4e5da5Sopenharmony_ci context->get_instr_block(nullptr); 116fd4e5da5Sopenharmony_ci 117fd4e5da5Sopenharmony_ci InstructionBuilder builder(context.get(), &*bb->begin()); 118fd4e5da5Sopenharmony_ci Instruction* phi1 = builder.AddPhi(7, {9, 14}); 119fd4e5da5Sopenharmony_ci Instruction* phi2 = builder.AddPhi(10, {16, 14}); 120fd4e5da5Sopenharmony_ci 121fd4e5da5Sopenharmony_ci // Make sure the InstructionBuilder did not update the def/use manager. 122fd4e5da5Sopenharmony_ci EXPECT_EQ(context->get_def_use_mgr()->GetDef(phi1->result_id()), nullptr); 123fd4e5da5Sopenharmony_ci EXPECT_EQ(context->get_def_use_mgr()->GetDef(phi2->result_id()), nullptr); 124fd4e5da5Sopenharmony_ci EXPECT_EQ(context->get_instr_block(phi1), nullptr); 125fd4e5da5Sopenharmony_ci EXPECT_EQ(context->get_instr_block(phi2), nullptr); 126fd4e5da5Sopenharmony_ci 127fd4e5da5Sopenharmony_ci Match(text, context.get()); 128fd4e5da5Sopenharmony_ci } 129fd4e5da5Sopenharmony_ci 130fd4e5da5Sopenharmony_ci { 131fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 132fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 133fd4e5da5Sopenharmony_ci 134fd4e5da5Sopenharmony_ci // Build managers. 135fd4e5da5Sopenharmony_ci context->get_def_use_mgr(); 136fd4e5da5Sopenharmony_ci context->get_instr_block(nullptr); 137fd4e5da5Sopenharmony_ci 138fd4e5da5Sopenharmony_ci BasicBlock* bb = context->cfg()->block(18); 139fd4e5da5Sopenharmony_ci InstructionBuilder builder( 140fd4e5da5Sopenharmony_ci context.get(), &*bb->begin(), 141fd4e5da5Sopenharmony_ci IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); 142fd4e5da5Sopenharmony_ci Instruction* phi1 = builder.AddPhi(7, {9, 14}); 143fd4e5da5Sopenharmony_ci Instruction* phi2 = builder.AddPhi(10, {16, 14}); 144fd4e5da5Sopenharmony_ci 145fd4e5da5Sopenharmony_ci // Make sure InstructionBuilder updated the def/use manager 146fd4e5da5Sopenharmony_ci EXPECT_NE(context->get_def_use_mgr()->GetDef(phi1->result_id()), nullptr); 147fd4e5da5Sopenharmony_ci EXPECT_NE(context->get_def_use_mgr()->GetDef(phi2->result_id()), nullptr); 148fd4e5da5Sopenharmony_ci EXPECT_NE(context->get_instr_block(phi1), nullptr); 149fd4e5da5Sopenharmony_ci EXPECT_NE(context->get_instr_block(phi2), nullptr); 150fd4e5da5Sopenharmony_ci 151fd4e5da5Sopenharmony_ci Match(text, context.get()); 152fd4e5da5Sopenharmony_ci } 153fd4e5da5Sopenharmony_ci} 154fd4e5da5Sopenharmony_ci 155fd4e5da5Sopenharmony_ciTEST_F(IRBuilderTest, TestCondBranchAddition) { 156fd4e5da5Sopenharmony_ci const std::string text = R"( 157fd4e5da5Sopenharmony_ci; CHECK: %main = OpFunction %void None %6 158fd4e5da5Sopenharmony_ci; CHECK-NEXT: %15 = OpLabel 159fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpSelectionMerge %13 None 160fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranchConditional %true %14 %13 161fd4e5da5Sopenharmony_ci; CHECK-NEXT: %14 = OpLabel 162fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpBranch %13 163fd4e5da5Sopenharmony_ci; CHECK-NEXT: %13 = OpLabel 164fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn 165fd4e5da5Sopenharmony_ci OpCapability Shader 166fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 167fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 168fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" %3 169fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 170fd4e5da5Sopenharmony_ci OpSource GLSL 330 171fd4e5da5Sopenharmony_ci OpName %2 "main" 172fd4e5da5Sopenharmony_ci OpName %4 "i" 173fd4e5da5Sopenharmony_ci OpName %3 "c" 174fd4e5da5Sopenharmony_ci OpDecorate %3 Location 0 175fd4e5da5Sopenharmony_ci %5 = OpTypeVoid 176fd4e5da5Sopenharmony_ci %6 = OpTypeFunction %5 177fd4e5da5Sopenharmony_ci %7 = OpTypeBool 178fd4e5da5Sopenharmony_ci %8 = OpTypePointer Private %7 179fd4e5da5Sopenharmony_ci %9 = OpConstantTrue %7 180fd4e5da5Sopenharmony_ci %10 = OpTypeFloat 32 181fd4e5da5Sopenharmony_ci %11 = OpTypeVector %10 4 182fd4e5da5Sopenharmony_ci %12 = OpTypePointer Output %11 183fd4e5da5Sopenharmony_ci %3 = OpVariable %12 Output 184fd4e5da5Sopenharmony_ci %4 = OpVariable %8 Private 185fd4e5da5Sopenharmony_ci %2 = OpFunction %5 None %6 186fd4e5da5Sopenharmony_ci %13 = OpLabel 187fd4e5da5Sopenharmony_ci OpReturn 188fd4e5da5Sopenharmony_ci OpFunctionEnd 189fd4e5da5Sopenharmony_ci)"; 190fd4e5da5Sopenharmony_ci 191fd4e5da5Sopenharmony_ci { 192fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 193fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 194fd4e5da5Sopenharmony_ci 195fd4e5da5Sopenharmony_ci Function& fn = *context->module()->begin(); 196fd4e5da5Sopenharmony_ci 197fd4e5da5Sopenharmony_ci BasicBlock& bb_merge = *fn.begin(); 198fd4e5da5Sopenharmony_ci 199fd4e5da5Sopenharmony_ci // TODO(1841): Handle id overflow. 200fd4e5da5Sopenharmony_ci fn.begin().InsertBefore(std::unique_ptr<BasicBlock>( 201fd4e5da5Sopenharmony_ci new BasicBlock(std::unique_ptr<Instruction>(new Instruction( 202fd4e5da5Sopenharmony_ci context.get(), spv::Op::OpLabel, 0, context->TakeNextId(), {}))))); 203fd4e5da5Sopenharmony_ci BasicBlock& bb_true = *fn.begin(); 204fd4e5da5Sopenharmony_ci { 205fd4e5da5Sopenharmony_ci InstructionBuilder builder(context.get(), &*bb_true.begin()); 206fd4e5da5Sopenharmony_ci builder.AddBranch(bb_merge.id()); 207fd4e5da5Sopenharmony_ci } 208fd4e5da5Sopenharmony_ci 209fd4e5da5Sopenharmony_ci // TODO(1841): Handle id overflow. 210fd4e5da5Sopenharmony_ci fn.begin().InsertBefore(std::unique_ptr<BasicBlock>( 211fd4e5da5Sopenharmony_ci new BasicBlock(std::unique_ptr<Instruction>(new Instruction( 212fd4e5da5Sopenharmony_ci context.get(), spv::Op::OpLabel, 0, context->TakeNextId(), {}))))); 213fd4e5da5Sopenharmony_ci BasicBlock& bb_cond = *fn.begin(); 214fd4e5da5Sopenharmony_ci 215fd4e5da5Sopenharmony_ci InstructionBuilder builder(context.get(), &bb_cond); 216fd4e5da5Sopenharmony_ci // This also test consecutive instruction insertion: merge selection + 217fd4e5da5Sopenharmony_ci // branch. 218fd4e5da5Sopenharmony_ci builder.AddConditionalBranch(9, bb_true.id(), bb_merge.id(), bb_merge.id()); 219fd4e5da5Sopenharmony_ci 220fd4e5da5Sopenharmony_ci Match(text, context.get()); 221fd4e5da5Sopenharmony_ci } 222fd4e5da5Sopenharmony_ci} 223fd4e5da5Sopenharmony_ci 224fd4e5da5Sopenharmony_ciTEST_F(IRBuilderTest, AddSelect) { 225fd4e5da5Sopenharmony_ci const std::string text = R"( 226fd4e5da5Sopenharmony_ci; CHECK: [[bool:%\w+]] = OpTypeBool 227fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 228fd4e5da5Sopenharmony_ci; CHECK: [[true:%\w+]] = OpConstantTrue [[bool]] 229fd4e5da5Sopenharmony_ci; CHECK: [[u0:%\w+]] = OpConstant [[uint]] 0 230fd4e5da5Sopenharmony_ci; CHECK: [[u1:%\w+]] = OpConstant [[uint]] 1 231fd4e5da5Sopenharmony_ci; CHECK: OpSelect [[uint]] [[true]] [[u0]] [[u1]] 232fd4e5da5Sopenharmony_ciOpCapability Kernel 233fd4e5da5Sopenharmony_ciOpCapability Linkage 234fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL 235fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 236fd4e5da5Sopenharmony_ci%2 = OpTypeBool 237fd4e5da5Sopenharmony_ci%3 = OpTypeInt 32 0 238fd4e5da5Sopenharmony_ci%4 = OpConstantTrue %2 239fd4e5da5Sopenharmony_ci%5 = OpConstant %3 0 240fd4e5da5Sopenharmony_ci%6 = OpConstant %3 1 241fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 242fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7 243fd4e5da5Sopenharmony_ci%9 = OpLabel 244fd4e5da5Sopenharmony_ciOpReturn 245fd4e5da5Sopenharmony_ciOpFunctionEnd 246fd4e5da5Sopenharmony_ci)"; 247fd4e5da5Sopenharmony_ci 248fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 249fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 250fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, context); 251fd4e5da5Sopenharmony_ci 252fd4e5da5Sopenharmony_ci InstructionBuilder builder(context.get(), 253fd4e5da5Sopenharmony_ci &*context->module()->begin()->begin()->begin()); 254fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.AddSelect(3u, 4u, 5u, 6u)); 255fd4e5da5Sopenharmony_ci 256fd4e5da5Sopenharmony_ci Match(text, context.get()); 257fd4e5da5Sopenharmony_ci} 258fd4e5da5Sopenharmony_ci 259fd4e5da5Sopenharmony_ciTEST_F(IRBuilderTest, AddCompositeConstruct) { 260fd4e5da5Sopenharmony_ci const std::string text = R"( 261fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 262fd4e5da5Sopenharmony_ci; CHECK: [[u0:%\w+]] = OpConstant [[uint]] 0 263fd4e5da5Sopenharmony_ci; CHECK: [[u1:%\w+]] = OpConstant [[uint]] 1 264fd4e5da5Sopenharmony_ci; CHECK: [[struct:%\w+]] = OpTypeStruct [[uint]] [[uint]] [[uint]] [[uint]] 265fd4e5da5Sopenharmony_ci; CHECK: OpCompositeConstruct [[struct]] [[u0]] [[u1]] [[u1]] [[u0]] 266fd4e5da5Sopenharmony_ciOpCapability Kernel 267fd4e5da5Sopenharmony_ciOpCapability Linkage 268fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL 269fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 270fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0 271fd4e5da5Sopenharmony_ci%3 = OpConstant %2 0 272fd4e5da5Sopenharmony_ci%4 = OpConstant %2 1 273fd4e5da5Sopenharmony_ci%5 = OpTypeStruct %2 %2 %2 %2 274fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %1 275fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %6 276fd4e5da5Sopenharmony_ci%8 = OpLabel 277fd4e5da5Sopenharmony_ciOpReturn 278fd4e5da5Sopenharmony_ciOpFunctionEnd 279fd4e5da5Sopenharmony_ci)"; 280fd4e5da5Sopenharmony_ci 281fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 282fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 283fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, context); 284fd4e5da5Sopenharmony_ci 285fd4e5da5Sopenharmony_ci InstructionBuilder builder(context.get(), 286fd4e5da5Sopenharmony_ci &*context->module()->begin()->begin()->begin()); 287fd4e5da5Sopenharmony_ci std::vector<uint32_t> ids = {3u, 4u, 4u, 3u}; 288fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.AddCompositeConstruct(5u, ids)); 289fd4e5da5Sopenharmony_ci 290fd4e5da5Sopenharmony_ci Match(text, context.get()); 291fd4e5da5Sopenharmony_ci} 292fd4e5da5Sopenharmony_ci 293fd4e5da5Sopenharmony_ciTEST_F(IRBuilderTest, ConstantAdder) { 294fd4e5da5Sopenharmony_ci const std::string text = R"( 295fd4e5da5Sopenharmony_ci; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 296fd4e5da5Sopenharmony_ci; CHECK: OpConstant [[uint]] 13 297fd4e5da5Sopenharmony_ci; CHECK: [[sint:%\w+]] = OpTypeInt 32 1 298fd4e5da5Sopenharmony_ci; CHECK: OpConstant [[sint]] -1 299fd4e5da5Sopenharmony_ci; CHECK: OpConstant [[uint]] 1 300fd4e5da5Sopenharmony_ci; CHECK: OpConstant [[sint]] 34 301fd4e5da5Sopenharmony_ci; CHECK: OpConstant [[uint]] 0 302fd4e5da5Sopenharmony_ci; CHECK: OpConstant [[sint]] 0 303fd4e5da5Sopenharmony_ciOpCapability Shader 304fd4e5da5Sopenharmony_ciOpCapability Linkage 305fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 306fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 307fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1 308fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2 309fd4e5da5Sopenharmony_ci%4 = OpLabel 310fd4e5da5Sopenharmony_ciOpReturn 311fd4e5da5Sopenharmony_ciOpFunctionEnd 312fd4e5da5Sopenharmony_ci)"; 313fd4e5da5Sopenharmony_ci 314fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 315fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 316fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, context); 317fd4e5da5Sopenharmony_ci 318fd4e5da5Sopenharmony_ci InstructionBuilder builder(context.get(), 319fd4e5da5Sopenharmony_ci &*context->module()->begin()->begin()->begin()); 320fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.GetUintConstant(13)); 321fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.GetSintConstant(-1)); 322fd4e5da5Sopenharmony_ci 323fd4e5da5Sopenharmony_ci // Try adding the same constants again to make sure they aren't added. 324fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.GetUintConstant(13)); 325fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.GetSintConstant(-1)); 326fd4e5da5Sopenharmony_ci 327fd4e5da5Sopenharmony_ci // Try adding different constants to make sure the type is reused. 328fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.GetUintConstant(1)); 329fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.GetSintConstant(34)); 330fd4e5da5Sopenharmony_ci 331fd4e5da5Sopenharmony_ci // Try adding 0 as both signed and unsigned. 332fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.GetUintConstant(0)); 333fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, builder.GetSintConstant(0)); 334fd4e5da5Sopenharmony_ci 335fd4e5da5Sopenharmony_ci Match(text, context.get()); 336fd4e5da5Sopenharmony_ci} 337fd4e5da5Sopenharmony_ci 338fd4e5da5Sopenharmony_ciTEST_F(IRBuilderTest, ConstantAdderTypeAlreadyExists) { 339fd4e5da5Sopenharmony_ci const std::string text = R"( 340fd4e5da5Sopenharmony_ci; CHECK: OpConstant %uint 13 341fd4e5da5Sopenharmony_ci; CHECK: OpConstant %int -1 342fd4e5da5Sopenharmony_ci; CHECK: OpConstant %uint 1 343fd4e5da5Sopenharmony_ci; CHECK: OpConstant %int 34 344fd4e5da5Sopenharmony_ci; CHECK: OpConstant %uint 0 345fd4e5da5Sopenharmony_ci; CHECK: OpConstant %int 0 346fd4e5da5Sopenharmony_ciOpCapability Shader 347fd4e5da5Sopenharmony_ciOpCapability Linkage 348fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 349fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 350fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 351fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1 352fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1 353fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %4 354fd4e5da5Sopenharmony_ci%6 = OpLabel 355fd4e5da5Sopenharmony_ciOpReturn 356fd4e5da5Sopenharmony_ciOpFunctionEnd 357fd4e5da5Sopenharmony_ci)"; 358fd4e5da5Sopenharmony_ci 359fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 360fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 361fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, context); 362fd4e5da5Sopenharmony_ci 363fd4e5da5Sopenharmony_ci InstructionBuilder builder(context.get(), 364fd4e5da5Sopenharmony_ci &*context->module()->begin()->begin()->begin()); 365fd4e5da5Sopenharmony_ci Instruction* const_1 = builder.GetUintConstant(13); 366fd4e5da5Sopenharmony_ci Instruction* const_2 = builder.GetSintConstant(-1); 367fd4e5da5Sopenharmony_ci 368fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, const_1); 369fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, const_2); 370fd4e5da5Sopenharmony_ci 371fd4e5da5Sopenharmony_ci // Try adding the same constants again to make sure they aren't added. 372fd4e5da5Sopenharmony_ci EXPECT_EQ(const_1, builder.GetUintConstant(13)); 373fd4e5da5Sopenharmony_ci EXPECT_EQ(const_2, builder.GetSintConstant(-1)); 374fd4e5da5Sopenharmony_ci 375fd4e5da5Sopenharmony_ci Instruction* const_3 = builder.GetUintConstant(1); 376fd4e5da5Sopenharmony_ci Instruction* const_4 = builder.GetSintConstant(34); 377fd4e5da5Sopenharmony_ci 378fd4e5da5Sopenharmony_ci // Try adding different constants to make sure the type is reused. 379fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, const_3); 380fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, const_4); 381fd4e5da5Sopenharmony_ci 382fd4e5da5Sopenharmony_ci Instruction* const_5 = builder.GetUintConstant(0); 383fd4e5da5Sopenharmony_ci Instruction* const_6 = builder.GetSintConstant(0); 384fd4e5da5Sopenharmony_ci 385fd4e5da5Sopenharmony_ci // Try adding 0 as both signed and unsigned. 386fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, const_5); 387fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, const_6); 388fd4e5da5Sopenharmony_ci 389fd4e5da5Sopenharmony_ci // They have the same value but different types so should be unique. 390fd4e5da5Sopenharmony_ci EXPECT_NE(const_5, const_6); 391fd4e5da5Sopenharmony_ci 392fd4e5da5Sopenharmony_ci // Check the types are correct. 393fd4e5da5Sopenharmony_ci uint32_t type_id_unsigned = const_1->GetSingleWordOperand(0); 394fd4e5da5Sopenharmony_ci uint32_t type_id_signed = const_2->GetSingleWordOperand(0); 395fd4e5da5Sopenharmony_ci 396fd4e5da5Sopenharmony_ci EXPECT_NE(type_id_unsigned, type_id_signed); 397fd4e5da5Sopenharmony_ci 398fd4e5da5Sopenharmony_ci EXPECT_EQ(const_3->GetSingleWordOperand(0), type_id_unsigned); 399fd4e5da5Sopenharmony_ci EXPECT_EQ(const_5->GetSingleWordOperand(0), type_id_unsigned); 400fd4e5da5Sopenharmony_ci 401fd4e5da5Sopenharmony_ci EXPECT_EQ(const_4->GetSingleWordOperand(0), type_id_signed); 402fd4e5da5Sopenharmony_ci EXPECT_EQ(const_6->GetSingleWordOperand(0), type_id_signed); 403fd4e5da5Sopenharmony_ci 404fd4e5da5Sopenharmony_ci Match(text, context.get()); 405fd4e5da5Sopenharmony_ci} 406fd4e5da5Sopenharmony_ci 407fd4e5da5Sopenharmony_ciTEST_F(IRBuilderTest, AccelerationStructureNV) { 408fd4e5da5Sopenharmony_ci const std::string text = R"( 409fd4e5da5Sopenharmony_ci; CHECK: OpTypeAccelerationStructureKHR 410fd4e5da5Sopenharmony_ciOpCapability Shader 411fd4e5da5Sopenharmony_ciOpCapability RayTracingNV 412fd4e5da5Sopenharmony_ciOpExtension "SPV_NV_ray_tracing" 413fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 414fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %8 "main" 415fd4e5da5Sopenharmony_ciOpExecutionMode %8 OriginUpperLeft 416fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 417fd4e5da5Sopenharmony_ci%2 = OpTypeBool 418fd4e5da5Sopenharmony_ci%3 = OpTypeAccelerationStructureNV 419fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 420fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7 421fd4e5da5Sopenharmony_ci%9 = OpLabel 422fd4e5da5Sopenharmony_ciOpReturn 423fd4e5da5Sopenharmony_ciOpFunctionEnd 424fd4e5da5Sopenharmony_ci)"; 425fd4e5da5Sopenharmony_ci 426fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 427fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 428fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, context); 429fd4e5da5Sopenharmony_ci 430fd4e5da5Sopenharmony_ci InstructionBuilder builder(context.get(), 431fd4e5da5Sopenharmony_ci &*context->module()->begin()->begin()->begin()); 432fd4e5da5Sopenharmony_ci Match(text, context.get()); 433fd4e5da5Sopenharmony_ci} 434fd4e5da5Sopenharmony_ci 435fd4e5da5Sopenharmony_ci} // namespace 436fd4e5da5Sopenharmony_ci} // namespace opt 437fd4e5da5Sopenharmony_ci} // namespace spvtools 438