1// Copyright (c) 2018 Google LLC. 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 <string> 16 17#include "gmock/gmock.h" 18#include "source/opt/licm_pass.h" 19#include "test/opt/pass_fixture.h" 20 21namespace spvtools { 22namespace opt { 23namespace { 24 25using ::testing::UnorderedElementsAre; 26using PassClassTest = PassTest<::testing::Test>; 27 28/* 29 A simple test for the LICM pass 30 31 Generated from the following GLSL fragment shader 32--eliminate-local-multi-store has also been run on the spv binary 33#version 440 core 34void main(){ 35 int a = 1; 36 int b = 2; 37 int hoist = 0; 38 for (int i = 0; i < 10; i++) { 39 // invariant 40 hoist = a + b; 41 } 42} 43*/ 44TEST_F(PassClassTest, SimpleHoist) { 45 const std::string before_hoist = R"(OpCapability Shader 46%1 = OpExtInstImport "GLSL.std.450" 47OpMemoryModel Logical GLSL450 48OpEntryPoint Fragment %main "main" 49OpExecutionMode %main OriginUpperLeft 50OpSource GLSL 440 51OpName %main "main" 52%void = OpTypeVoid 53%4 = OpTypeFunction %void 54%int = OpTypeInt 32 1 55%_ptr_Function_int = OpTypePointer Function %int 56%int_1 = OpConstant %int 1 57%int_2 = OpConstant %int 2 58%int_0 = OpConstant %int 0 59%int_10 = OpConstant %int 10 60%bool = OpTypeBool 61%main = OpFunction %void None %4 62%12 = OpLabel 63OpBranch %13 64%13 = OpLabel 65%14 = OpPhi %int %int_0 %12 %15 %16 66%17 = OpPhi %int %int_0 %12 %18 %16 67OpLoopMerge %19 %16 None 68OpBranch %20 69%20 = OpLabel 70%21 = OpSLessThan %bool %17 %int_10 71OpBranchConditional %21 %22 %19 72%22 = OpLabel 73%15 = OpIAdd %int %int_1 %int_2 74OpBranch %16 75%16 = OpLabel 76%18 = OpIAdd %int %17 %int_1 77OpBranch %13 78%19 = OpLabel 79OpReturn 80OpFunctionEnd 81)"; 82 83 const std::string after_hoist = R"(OpCapability Shader 84%1 = OpExtInstImport "GLSL.std.450" 85OpMemoryModel Logical GLSL450 86OpEntryPoint Fragment %main "main" 87OpExecutionMode %main OriginUpperLeft 88OpSource GLSL 440 89OpName %main "main" 90%void = OpTypeVoid 91%4 = OpTypeFunction %void 92%int = OpTypeInt 32 1 93%_ptr_Function_int = OpTypePointer Function %int 94%int_1 = OpConstant %int 1 95%int_2 = OpConstant %int 2 96%int_0 = OpConstant %int 0 97%int_10 = OpConstant %int 10 98%bool = OpTypeBool 99%main = OpFunction %void None %4 100%12 = OpLabel 101%15 = OpIAdd %int %int_1 %int_2 102OpBranch %13 103%13 = OpLabel 104%14 = OpPhi %int %int_0 %12 %15 %16 105%17 = OpPhi %int %int_0 %12 %18 %16 106OpLoopMerge %19 %16 None 107OpBranch %20 108%20 = OpLabel 109%21 = OpSLessThan %bool %17 %int_10 110OpBranchConditional %21 %22 %19 111%22 = OpLabel 112OpBranch %16 113%16 = OpLabel 114%18 = OpIAdd %int %17 %int_1 115OpBranch %13 116%19 = OpLabel 117OpReturn 118OpFunctionEnd 119)"; 120 121 SinglePassRunAndCheck<LICMPass>(before_hoist, after_hoist, true); 122} 123 124} // namespace 125} // namespace opt 126} // namespace spvtools 127