1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 Google LLC 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/reduce/operand_to_const_reduction_opportunity_finder.h" 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "source/opt/build_module.h" 18fd4e5da5Sopenharmony_ci#include "source/reduce/reduction_opportunity.h" 19fd4e5da5Sopenharmony_ci#include "test/reduce/reduce_test_util.h" 20fd4e5da5Sopenharmony_ci 21fd4e5da5Sopenharmony_cinamespace spvtools { 22fd4e5da5Sopenharmony_cinamespace reduce { 23fd4e5da5Sopenharmony_cinamespace { 24fd4e5da5Sopenharmony_ci 25fd4e5da5Sopenharmony_ciTEST(OperandToConstantReductionPassTest, BasicCheck) { 26fd4e5da5Sopenharmony_ci std::string prologue = R"( 27fd4e5da5Sopenharmony_ci OpCapability Shader 28fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 29fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 30fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %37 31fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 32fd4e5da5Sopenharmony_ci OpSource ESSL 310 33fd4e5da5Sopenharmony_ci OpName %4 "main" 34fd4e5da5Sopenharmony_ci OpName %9 "buf1" 35fd4e5da5Sopenharmony_ci OpMemberName %9 0 "f" 36fd4e5da5Sopenharmony_ci OpName %11 "" 37fd4e5da5Sopenharmony_ci OpName %24 "buf2" 38fd4e5da5Sopenharmony_ci OpMemberName %24 0 "i" 39fd4e5da5Sopenharmony_ci OpName %26 "" 40fd4e5da5Sopenharmony_ci OpName %37 "_GLF_color" 41fd4e5da5Sopenharmony_ci OpMemberDecorate %9 0 Offset 0 42fd4e5da5Sopenharmony_ci OpDecorate %9 Block 43fd4e5da5Sopenharmony_ci OpDecorate %11 DescriptorSet 0 44fd4e5da5Sopenharmony_ci OpDecorate %11 Binding 1 45fd4e5da5Sopenharmony_ci OpMemberDecorate %24 0 Offset 0 46fd4e5da5Sopenharmony_ci OpDecorate %24 Block 47fd4e5da5Sopenharmony_ci OpDecorate %26 DescriptorSet 0 48fd4e5da5Sopenharmony_ci OpDecorate %26 Binding 2 49fd4e5da5Sopenharmony_ci OpDecorate %37 Location 0 50fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 51fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 52fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 53fd4e5da5Sopenharmony_ci %9 = OpTypeStruct %6 54fd4e5da5Sopenharmony_ci %10 = OpTypePointer Uniform %9 55fd4e5da5Sopenharmony_ci %11 = OpVariable %10 Uniform 56fd4e5da5Sopenharmony_ci %12 = OpTypeInt 32 1 57fd4e5da5Sopenharmony_ci %13 = OpConstant %12 0 58fd4e5da5Sopenharmony_ci %14 = OpTypePointer Uniform %6 59fd4e5da5Sopenharmony_ci %20 = OpConstant %6 2 60fd4e5da5Sopenharmony_ci %24 = OpTypeStruct %12 61fd4e5da5Sopenharmony_ci %25 = OpTypePointer Uniform %24 62fd4e5da5Sopenharmony_ci %26 = OpVariable %25 Uniform 63fd4e5da5Sopenharmony_ci %27 = OpTypePointer Uniform %12 64fd4e5da5Sopenharmony_ci %33 = OpConstant %12 3 65fd4e5da5Sopenharmony_ci %35 = OpTypeVector %6 4 66fd4e5da5Sopenharmony_ci %36 = OpTypePointer Output %35 67fd4e5da5Sopenharmony_ci %37 = OpVariable %36 Output 68fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 69fd4e5da5Sopenharmony_ci %5 = OpLabel 70fd4e5da5Sopenharmony_ci %15 = OpAccessChain %14 %11 %13 71fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %15 72fd4e5da5Sopenharmony_ci %19 = OpFAdd %6 %16 %16 73fd4e5da5Sopenharmony_ci %21 = OpFAdd %6 %19 %20 74fd4e5da5Sopenharmony_ci %28 = OpAccessChain %27 %26 %13 75fd4e5da5Sopenharmony_ci %29 = OpLoad %12 %28 76fd4e5da5Sopenharmony_ci )"; 77fd4e5da5Sopenharmony_ci 78fd4e5da5Sopenharmony_ci std::string epilogue = R"( 79fd4e5da5Sopenharmony_ci %45 = OpConvertSToF %6 %34 80fd4e5da5Sopenharmony_ci %46 = OpCompositeConstruct %35 %16 %21 %43 %45 81fd4e5da5Sopenharmony_ci OpStore %37 %46 82fd4e5da5Sopenharmony_ci OpReturn 83fd4e5da5Sopenharmony_ci OpFunctionEnd 84fd4e5da5Sopenharmony_ci )"; 85fd4e5da5Sopenharmony_ci 86fd4e5da5Sopenharmony_ci std::string original = prologue + R"( 87fd4e5da5Sopenharmony_ci %32 = OpIAdd %12 %29 %29 88fd4e5da5Sopenharmony_ci %34 = OpIAdd %12 %32 %33 89fd4e5da5Sopenharmony_ci %43 = OpConvertSToF %6 %29 90fd4e5da5Sopenharmony_ci )" + epilogue; 91fd4e5da5Sopenharmony_ci 92fd4e5da5Sopenharmony_ci std::string expected = prologue + R"( 93fd4e5da5Sopenharmony_ci %32 = OpIAdd %12 %13 %13 ; %29 -> %13 x 2 94fd4e5da5Sopenharmony_ci %34 = OpIAdd %12 %13 %33 ; %32 -> %13 95fd4e5da5Sopenharmony_ci %43 = OpConvertSToF %6 %13 ; %29 -> %13 96fd4e5da5Sopenharmony_ci )" + epilogue; 97fd4e5da5Sopenharmony_ci 98fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 99fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 100fd4e5da5Sopenharmony_ci const auto context = 101fd4e5da5Sopenharmony_ci BuildModule(env, consumer, original, kReduceAssembleOption); 102fd4e5da5Sopenharmony_ci const auto ops = 103fd4e5da5Sopenharmony_ci OperandToConstReductionOpportunityFinder().GetAvailableOpportunities( 104fd4e5da5Sopenharmony_ci context.get(), 0); 105fd4e5da5Sopenharmony_ci ASSERT_EQ(17, ops.size()); 106fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[0]->PreconditionHolds()); 107fd4e5da5Sopenharmony_ci ops[0]->TryToApply(); 108fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[1]->PreconditionHolds()); 109fd4e5da5Sopenharmony_ci ops[1]->TryToApply(); 110fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[2]->PreconditionHolds()); 111fd4e5da5Sopenharmony_ci ops[2]->TryToApply(); 112fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[3]->PreconditionHolds()); 113fd4e5da5Sopenharmony_ci ops[3]->TryToApply(); 114fd4e5da5Sopenharmony_ci 115fd4e5da5Sopenharmony_ci CheckEqual(env, expected, context.get()); 116fd4e5da5Sopenharmony_ci} 117fd4e5da5Sopenharmony_ci 118fd4e5da5Sopenharmony_ciTEST(OperandToConstantReductionPassTest, WithCalledFunction) { 119fd4e5da5Sopenharmony_ci std::string shader = R"( 120fd4e5da5Sopenharmony_ci OpCapability Shader 121fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 122fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 123fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %10 %12 124fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 125fd4e5da5Sopenharmony_ci OpSource ESSL 310 126fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 127fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 128fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 129fd4e5da5Sopenharmony_ci %7 = OpTypeVector %6 4 130fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %7 131fd4e5da5Sopenharmony_ci %9 = OpTypePointer Output %7 132fd4e5da5Sopenharmony_ci %10 = OpVariable %9 Output 133fd4e5da5Sopenharmony_ci %11 = OpTypePointer Input %7 134fd4e5da5Sopenharmony_ci %12 = OpVariable %11 Input 135fd4e5da5Sopenharmony_ci %13 = OpConstant %6 0 136fd4e5da5Sopenharmony_ci %14 = OpConstantComposite %7 %13 %13 %13 %13 137fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 138fd4e5da5Sopenharmony_ci %5 = OpLabel 139fd4e5da5Sopenharmony_ci %15 = OpFunctionCall %7 %16 140fd4e5da5Sopenharmony_ci OpReturn 141fd4e5da5Sopenharmony_ci OpFunctionEnd 142fd4e5da5Sopenharmony_ci %16 = OpFunction %7 None %8 143fd4e5da5Sopenharmony_ci %17 = OpLabel 144fd4e5da5Sopenharmony_ci OpReturnValue %14 145fd4e5da5Sopenharmony_ci OpFunctionEnd 146fd4e5da5Sopenharmony_ci )"; 147fd4e5da5Sopenharmony_ci 148fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 149fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 150fd4e5da5Sopenharmony_ci const auto context = 151fd4e5da5Sopenharmony_ci BuildModule(env, consumer, shader, kReduceAssembleOption); 152fd4e5da5Sopenharmony_ci const auto ops = 153fd4e5da5Sopenharmony_ci OperandToConstReductionOpportunityFinder().GetAvailableOpportunities( 154fd4e5da5Sopenharmony_ci context.get(), 0); 155fd4e5da5Sopenharmony_ci ASSERT_EQ(0, ops.size()); 156fd4e5da5Sopenharmony_ci} 157fd4e5da5Sopenharmony_ci 158fd4e5da5Sopenharmony_ciTEST(OperandToConstantReductionPassTest, TargetSpecificFunction) { 159fd4e5da5Sopenharmony_ci std::string shader = R"( 160fd4e5da5Sopenharmony_ci OpCapability Shader 161fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 162fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 163fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 164fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 165fd4e5da5Sopenharmony_ci OpSource ESSL 320 166fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 167fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 168fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 169fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 170fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %6 %7 171fd4e5da5Sopenharmony_ci %17 = OpConstant %6 1 172fd4e5da5Sopenharmony_ci %20 = OpConstant %6 2 173fd4e5da5Sopenharmony_ci %23 = OpConstant %6 0 174fd4e5da5Sopenharmony_ci %24 = OpTypeBool 175fd4e5da5Sopenharmony_ci %35 = OpConstant %6 3 176fd4e5da5Sopenharmony_ci %53 = OpConstant %6 10 177fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 178fd4e5da5Sopenharmony_ci %5 = OpLabel 179fd4e5da5Sopenharmony_ci %65 = OpVariable %7 Function 180fd4e5da5Sopenharmony_ci %68 = OpVariable %7 Function 181fd4e5da5Sopenharmony_ci %73 = OpVariable %7 Function 182fd4e5da5Sopenharmony_ci OpStore %65 %35 183fd4e5da5Sopenharmony_ci %66 = OpLoad %6 %65 184fd4e5da5Sopenharmony_ci %67 = OpIAdd %6 %66 %17 185fd4e5da5Sopenharmony_ci OpStore %65 %67 186fd4e5da5Sopenharmony_ci %69 = OpLoad %6 %65 187fd4e5da5Sopenharmony_ci OpStore %68 %69 188fd4e5da5Sopenharmony_ci %70 = OpFunctionCall %6 %13 %68 189fd4e5da5Sopenharmony_ci %71 = OpLoad %6 %65 190fd4e5da5Sopenharmony_ci %72 = OpIAdd %6 %71 %70 191fd4e5da5Sopenharmony_ci OpStore %65 %72 192fd4e5da5Sopenharmony_ci %74 = OpLoad %6 %65 193fd4e5da5Sopenharmony_ci OpStore %73 %74 194fd4e5da5Sopenharmony_ci %75 = OpFunctionCall %6 %10 %73 195fd4e5da5Sopenharmony_ci %76 = OpLoad %6 %65 196fd4e5da5Sopenharmony_ci %77 = OpIAdd %6 %76 %75 197fd4e5da5Sopenharmony_ci OpStore %65 %77 198fd4e5da5Sopenharmony_ci OpReturn 199fd4e5da5Sopenharmony_ci OpFunctionEnd 200fd4e5da5Sopenharmony_ci %10 = OpFunction %6 None %8 201fd4e5da5Sopenharmony_ci %9 = OpFunctionParameter %7 202fd4e5da5Sopenharmony_ci %11 = OpLabel 203fd4e5da5Sopenharmony_ci %15 = OpVariable %7 Function 204fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %9 205fd4e5da5Sopenharmony_ci %18 = OpIAdd %6 %16 %17 206fd4e5da5Sopenharmony_ci OpStore %15 %18 207fd4e5da5Sopenharmony_ci %19 = OpLoad %6 %15 208fd4e5da5Sopenharmony_ci %21 = OpIAdd %6 %19 %20 209fd4e5da5Sopenharmony_ci OpStore %15 %21 210fd4e5da5Sopenharmony_ci %22 = OpLoad %6 %15 211fd4e5da5Sopenharmony_ci %25 = OpSGreaterThan %24 %22 %23 212fd4e5da5Sopenharmony_ci OpSelectionMerge %27 None 213fd4e5da5Sopenharmony_ci OpBranchConditional %25 %26 %27 214fd4e5da5Sopenharmony_ci %26 = OpLabel 215fd4e5da5Sopenharmony_ci %28 = OpLoad %6 %9 216fd4e5da5Sopenharmony_ci OpReturnValue %28 217fd4e5da5Sopenharmony_ci %27 = OpLabel 218fd4e5da5Sopenharmony_ci %30 = OpLoad %6 %9 219fd4e5da5Sopenharmony_ci %31 = OpIAdd %6 %30 %17 220fd4e5da5Sopenharmony_ci OpReturnValue %31 221fd4e5da5Sopenharmony_ci OpFunctionEnd 222fd4e5da5Sopenharmony_ci %13 = OpFunction %6 None %8 223fd4e5da5Sopenharmony_ci %12 = OpFunctionParameter %7 224fd4e5da5Sopenharmony_ci %14 = OpLabel 225fd4e5da5Sopenharmony_ci %41 = OpVariable %7 Function 226fd4e5da5Sopenharmony_ci %46 = OpVariable %7 Function 227fd4e5da5Sopenharmony_ci %55 = OpVariable %7 Function 228fd4e5da5Sopenharmony_ci %34 = OpLoad %6 %12 229fd4e5da5Sopenharmony_ci %36 = OpIEqual %24 %34 %35 230fd4e5da5Sopenharmony_ci OpSelectionMerge %38 None 231fd4e5da5Sopenharmony_ci OpBranchConditional %36 %37 %38 232fd4e5da5Sopenharmony_ci %37 = OpLabel 233fd4e5da5Sopenharmony_ci %39 = OpLoad %6 %12 234fd4e5da5Sopenharmony_ci %40 = OpIMul %6 %20 %39 235fd4e5da5Sopenharmony_ci OpStore %41 %40 236fd4e5da5Sopenharmony_ci %42 = OpFunctionCall %6 %10 %41 237fd4e5da5Sopenharmony_ci OpReturnValue %42 238fd4e5da5Sopenharmony_ci %38 = OpLabel 239fd4e5da5Sopenharmony_ci %44 = OpLoad %6 %12 240fd4e5da5Sopenharmony_ci %45 = OpIAdd %6 %44 %17 241fd4e5da5Sopenharmony_ci OpStore %12 %45 242fd4e5da5Sopenharmony_ci OpStore %46 %23 243fd4e5da5Sopenharmony_ci OpBranch %47 244fd4e5da5Sopenharmony_ci %47 = OpLabel 245fd4e5da5Sopenharmony_ci OpLoopMerge %49 %50 None 246fd4e5da5Sopenharmony_ci OpBranch %51 247fd4e5da5Sopenharmony_ci %51 = OpLabel 248fd4e5da5Sopenharmony_ci %52 = OpLoad %6 %46 249fd4e5da5Sopenharmony_ci %54 = OpSLessThan %24 %52 %53 250fd4e5da5Sopenharmony_ci OpBranchConditional %54 %48 %49 251fd4e5da5Sopenharmony_ci %48 = OpLabel 252fd4e5da5Sopenharmony_ci %56 = OpLoad %6 %12 253fd4e5da5Sopenharmony_ci OpStore %55 %56 254fd4e5da5Sopenharmony_ci %57 = OpFunctionCall %6 %10 %55 255fd4e5da5Sopenharmony_ci %58 = OpLoad %6 %12 256fd4e5da5Sopenharmony_ci %59 = OpIAdd %6 %58 %57 257fd4e5da5Sopenharmony_ci OpStore %12 %59 258fd4e5da5Sopenharmony_ci OpBranch %50 259fd4e5da5Sopenharmony_ci %50 = OpLabel 260fd4e5da5Sopenharmony_ci %60 = OpLoad %6 %46 261fd4e5da5Sopenharmony_ci %61 = OpIAdd %6 %60 %17 262fd4e5da5Sopenharmony_ci OpStore %46 %61 263fd4e5da5Sopenharmony_ci OpBranch %47 264fd4e5da5Sopenharmony_ci %49 = OpLabel 265fd4e5da5Sopenharmony_ci %62 = OpLoad %6 %12 266fd4e5da5Sopenharmony_ci OpReturnValue %62 267fd4e5da5Sopenharmony_ci OpFunctionEnd 268fd4e5da5Sopenharmony_ci )"; 269fd4e5da5Sopenharmony_ci 270fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 271fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 272fd4e5da5Sopenharmony_ci const auto context = 273fd4e5da5Sopenharmony_ci BuildModule(env, consumer, shader, kReduceAssembleOption); 274fd4e5da5Sopenharmony_ci 275fd4e5da5Sopenharmony_ci // Targeting all functions, there are quite a few opportunities. To avoid 276fd4e5da5Sopenharmony_ci // making the test too sensitive, we check that there are more than a number 277fd4e5da5Sopenharmony_ci // somewhat lower than the real number. 278fd4e5da5Sopenharmony_ci const auto all_ops = 279fd4e5da5Sopenharmony_ci OperandToConstReductionOpportunityFinder().GetAvailableOpportunities( 280fd4e5da5Sopenharmony_ci context.get(), 0); 281fd4e5da5Sopenharmony_ci ASSERT_TRUE(all_ops.size() > 100); 282fd4e5da5Sopenharmony_ci 283fd4e5da5Sopenharmony_ci // Targeting individual functions, there are fewer opportunities. Again, we 284fd4e5da5Sopenharmony_ci // avoid checking against an exact number so that the test is not too 285fd4e5da5Sopenharmony_ci // sensitive. 286fd4e5da5Sopenharmony_ci const auto ops_for_function_4 = 287fd4e5da5Sopenharmony_ci OperandToConstReductionOpportunityFinder().GetAvailableOpportunities( 288fd4e5da5Sopenharmony_ci context.get(), 4); 289fd4e5da5Sopenharmony_ci const auto ops_for_function_10 = 290fd4e5da5Sopenharmony_ci OperandToConstReductionOpportunityFinder().GetAvailableOpportunities( 291fd4e5da5Sopenharmony_ci context.get(), 10); 292fd4e5da5Sopenharmony_ci const auto ops_for_function_13 = 293fd4e5da5Sopenharmony_ci OperandToConstReductionOpportunityFinder().GetAvailableOpportunities( 294fd4e5da5Sopenharmony_ci context.get(), 13); 295fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops_for_function_4.size() < 60); 296fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops_for_function_10.size() < 50); 297fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops_for_function_13.size() < 80); 298fd4e5da5Sopenharmony_ci 299fd4e5da5Sopenharmony_ci // The total number of opportunities should be the sum of the per-function 300fd4e5da5Sopenharmony_ci // opportunities. 301fd4e5da5Sopenharmony_ci ASSERT_EQ(all_ops.size(), ops_for_function_4.size() + 302fd4e5da5Sopenharmony_ci ops_for_function_10.size() + 303fd4e5da5Sopenharmony_ci ops_for_function_13.size()); 304fd4e5da5Sopenharmony_ci} 305fd4e5da5Sopenharmony_ci 306fd4e5da5Sopenharmony_ci} // namespace 307fd4e5da5Sopenharmony_ci} // namespace reduce 308fd4e5da5Sopenharmony_ci} // namespace spvtools 309