1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 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 <string> 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 18fd4e5da5Sopenharmony_ci#include "test/opt/assembly_builder.h" 19fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 20fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h" 21fd4e5da5Sopenharmony_ci 22fd4e5da5Sopenharmony_cinamespace spvtools { 23fd4e5da5Sopenharmony_cinamespace opt { 24fd4e5da5Sopenharmony_cinamespace { 25fd4e5da5Sopenharmony_ci 26fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr; 27fd4e5da5Sopenharmony_ciusing ::testing::MatchesRegex; 28fd4e5da5Sopenharmony_ciusing RedundancyEliminationTest = PassTest<::testing::Test>; 29fd4e5da5Sopenharmony_ci 30fd4e5da5Sopenharmony_ci// Test that it can get a simple case of local redundancy elimination. 31fd4e5da5Sopenharmony_ci// The rest of the test check for extra functionality. 32fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantLocalAdd) { 33fd4e5da5Sopenharmony_ci const std::string text = R"( 34fd4e5da5Sopenharmony_ci OpCapability Shader 35fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 36fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 37fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 38fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 39fd4e5da5Sopenharmony_ci OpSource GLSL 430 40fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 41fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 42fd4e5da5Sopenharmony_ci %5 = OpTypeFloat 32 43fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 44fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 45fd4e5da5Sopenharmony_ci %7 = OpLabel 46fd4e5da5Sopenharmony_ci %8 = OpVariable %6 Function 47fd4e5da5Sopenharmony_ci %9 = OpLoad %5 %8 48fd4e5da5Sopenharmony_ci %10 = OpFAdd %5 %9 %9 49fd4e5da5Sopenharmony_ci; CHECK: OpFAdd 50fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd 51fd4e5da5Sopenharmony_ci %11 = OpFAdd %5 %9 %9 52fd4e5da5Sopenharmony_ci OpReturn 53fd4e5da5Sopenharmony_ci OpFunctionEnd 54fd4e5da5Sopenharmony_ci )"; 55fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<RedundancyEliminationPass>(text, false); 56fd4e5da5Sopenharmony_ci} 57fd4e5da5Sopenharmony_ci 58fd4e5da5Sopenharmony_ci// Remove a redundant add across basic blocks. 59fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantAdd) { 60fd4e5da5Sopenharmony_ci const std::string text = R"( 61fd4e5da5Sopenharmony_ci OpCapability Shader 62fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 63fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 64fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 65fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 66fd4e5da5Sopenharmony_ci OpSource GLSL 430 67fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 68fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 69fd4e5da5Sopenharmony_ci %5 = OpTypeFloat 32 70fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 71fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 72fd4e5da5Sopenharmony_ci %7 = OpLabel 73fd4e5da5Sopenharmony_ci %8 = OpVariable %6 Function 74fd4e5da5Sopenharmony_ci %9 = OpLoad %5 %8 75fd4e5da5Sopenharmony_ci %10 = OpFAdd %5 %9 %9 76fd4e5da5Sopenharmony_ci OpBranch %11 77fd4e5da5Sopenharmony_ci %11 = OpLabel 78fd4e5da5Sopenharmony_ci; CHECK: OpFAdd 79fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd 80fd4e5da5Sopenharmony_ci %12 = OpFAdd %5 %9 %9 81fd4e5da5Sopenharmony_ci OpReturn 82fd4e5da5Sopenharmony_ci OpFunctionEnd 83fd4e5da5Sopenharmony_ci )"; 84fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<RedundancyEliminationPass>(text, false); 85fd4e5da5Sopenharmony_ci} 86fd4e5da5Sopenharmony_ci 87fd4e5da5Sopenharmony_ci// Remove a redundant add going through a multiple basic blocks. 88fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantAddDiamond) { 89fd4e5da5Sopenharmony_ci const std::string text = R"( 90fd4e5da5Sopenharmony_ci OpCapability Shader 91fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 92fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 93fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 94fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 95fd4e5da5Sopenharmony_ci OpSource GLSL 430 96fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 97fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 98fd4e5da5Sopenharmony_ci %5 = OpTypeFloat 32 99fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 100fd4e5da5Sopenharmony_ci %7 = OpTypeBool 101fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %7 102fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 103fd4e5da5Sopenharmony_ci %9 = OpLabel 104fd4e5da5Sopenharmony_ci %10 = OpVariable %6 Function 105fd4e5da5Sopenharmony_ci %11 = OpLoad %5 %10 106fd4e5da5Sopenharmony_ci %12 = OpFAdd %5 %11 %11 107fd4e5da5Sopenharmony_ci; CHECK: OpFAdd 108fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd 109fd4e5da5Sopenharmony_ci OpBranchConditional %8 %13 %14 110fd4e5da5Sopenharmony_ci %13 = OpLabel 111fd4e5da5Sopenharmony_ci OpBranch %15 112fd4e5da5Sopenharmony_ci %14 = OpLabel 113fd4e5da5Sopenharmony_ci OpBranch %15 114fd4e5da5Sopenharmony_ci %15 = OpLabel 115fd4e5da5Sopenharmony_ci %16 = OpFAdd %5 %11 %11 116fd4e5da5Sopenharmony_ci OpReturn 117fd4e5da5Sopenharmony_ci OpFunctionEnd 118fd4e5da5Sopenharmony_ci 119fd4e5da5Sopenharmony_ci )"; 120fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<RedundancyEliminationPass>(text, false); 121fd4e5da5Sopenharmony_ci} 122fd4e5da5Sopenharmony_ci 123fd4e5da5Sopenharmony_ci// Remove a redundant add in a side node. 124fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantAddInSideNode) { 125fd4e5da5Sopenharmony_ci const std::string text = R"( 126fd4e5da5Sopenharmony_ci OpCapability Shader 127fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 128fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 129fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 130fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 131fd4e5da5Sopenharmony_ci OpSource GLSL 430 132fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 133fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 134fd4e5da5Sopenharmony_ci %5 = OpTypeFloat 32 135fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 136fd4e5da5Sopenharmony_ci %7 = OpTypeBool 137fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %7 138fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 139fd4e5da5Sopenharmony_ci %9 = OpLabel 140fd4e5da5Sopenharmony_ci %10 = OpVariable %6 Function 141fd4e5da5Sopenharmony_ci %11 = OpLoad %5 %10 142fd4e5da5Sopenharmony_ci %12 = OpFAdd %5 %11 %11 143fd4e5da5Sopenharmony_ci; CHECK: OpFAdd 144fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd 145fd4e5da5Sopenharmony_ci OpBranchConditional %8 %13 %14 146fd4e5da5Sopenharmony_ci %13 = OpLabel 147fd4e5da5Sopenharmony_ci OpBranch %15 148fd4e5da5Sopenharmony_ci %14 = OpLabel 149fd4e5da5Sopenharmony_ci %16 = OpFAdd %5 %11 %11 150fd4e5da5Sopenharmony_ci OpBranch %15 151fd4e5da5Sopenharmony_ci %15 = OpLabel 152fd4e5da5Sopenharmony_ci OpReturn 153fd4e5da5Sopenharmony_ci OpFunctionEnd 154fd4e5da5Sopenharmony_ci 155fd4e5da5Sopenharmony_ci )"; 156fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<RedundancyEliminationPass>(text, false); 157fd4e5da5Sopenharmony_ci} 158fd4e5da5Sopenharmony_ci 159fd4e5da5Sopenharmony_ci// Remove a redundant add whose value is in the result of a phi node. 160fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantAddWithPhi) { 161fd4e5da5Sopenharmony_ci const std::string text = R"( 162fd4e5da5Sopenharmony_ci OpCapability Shader 163fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 164fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 165fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 166fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 167fd4e5da5Sopenharmony_ci OpSource GLSL 430 168fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 169fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 170fd4e5da5Sopenharmony_ci %5 = OpTypeFloat 32 171fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 172fd4e5da5Sopenharmony_ci %7 = OpTypeBool 173fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %7 174fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 175fd4e5da5Sopenharmony_ci %9 = OpLabel 176fd4e5da5Sopenharmony_ci %10 = OpVariable %6 Function 177fd4e5da5Sopenharmony_ci %11 = OpLoad %5 %10 178fd4e5da5Sopenharmony_ci OpBranchConditional %8 %13 %14 179fd4e5da5Sopenharmony_ci %13 = OpLabel 180fd4e5da5Sopenharmony_ci %add1 = OpFAdd %5 %11 %11 181fd4e5da5Sopenharmony_ci; CHECK: OpFAdd 182fd4e5da5Sopenharmony_ci OpBranch %15 183fd4e5da5Sopenharmony_ci %14 = OpLabel 184fd4e5da5Sopenharmony_ci %add2 = OpFAdd %5 %11 %11 185fd4e5da5Sopenharmony_ci; CHECK: OpFAdd 186fd4e5da5Sopenharmony_ci OpBranch %15 187fd4e5da5Sopenharmony_ci %15 = OpLabel 188fd4e5da5Sopenharmony_ci; CHECK: OpPhi 189fd4e5da5Sopenharmony_ci %phi = OpPhi %5 %add1 %13 %add2 %14 190fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd 191fd4e5da5Sopenharmony_ci %16 = OpFAdd %5 %11 %11 192fd4e5da5Sopenharmony_ci OpReturn 193fd4e5da5Sopenharmony_ci OpFunctionEnd 194fd4e5da5Sopenharmony_ci 195fd4e5da5Sopenharmony_ci )"; 196fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<RedundancyEliminationPass>(text, false); 197fd4e5da5Sopenharmony_ci} 198fd4e5da5Sopenharmony_ci 199fd4e5da5Sopenharmony_ci// Keep the add because it is redundant on some paths, but not all paths. 200fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, KeepPartiallyRedundantAdd) { 201fd4e5da5Sopenharmony_ci const std::string text = R"( 202fd4e5da5Sopenharmony_ci OpCapability Shader 203fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 204fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 205fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 206fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 207fd4e5da5Sopenharmony_ci OpSource GLSL 430 208fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 209fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 210fd4e5da5Sopenharmony_ci %5 = OpTypeFloat 32 211fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 212fd4e5da5Sopenharmony_ci %7 = OpTypeBool 213fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %7 214fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 215fd4e5da5Sopenharmony_ci %9 = OpLabel 216fd4e5da5Sopenharmony_ci %10 = OpVariable %6 Function 217fd4e5da5Sopenharmony_ci %11 = OpLoad %5 %10 218fd4e5da5Sopenharmony_ci OpBranchConditional %8 %13 %14 219fd4e5da5Sopenharmony_ci %13 = OpLabel 220fd4e5da5Sopenharmony_ci %add = OpFAdd %5 %11 %11 221fd4e5da5Sopenharmony_ci OpBranch %15 222fd4e5da5Sopenharmony_ci %14 = OpLabel 223fd4e5da5Sopenharmony_ci OpBranch %15 224fd4e5da5Sopenharmony_ci %15 = OpLabel 225fd4e5da5Sopenharmony_ci %16 = OpFAdd %5 %11 %11 226fd4e5da5Sopenharmony_ci OpReturn 227fd4e5da5Sopenharmony_ci OpFunctionEnd 228fd4e5da5Sopenharmony_ci 229fd4e5da5Sopenharmony_ci )"; 230fd4e5da5Sopenharmony_ci auto result = SinglePassRunAndDisassemble<RedundancyEliminationPass>( 231fd4e5da5Sopenharmony_ci text, /* skip_nop = */ true, /* do_validation = */ false); 232fd4e5da5Sopenharmony_ci EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 233fd4e5da5Sopenharmony_ci} 234fd4e5da5Sopenharmony_ci 235fd4e5da5Sopenharmony_ci// Keep the add. Even if it is redundant on all paths, there is no single id 236fd4e5da5Sopenharmony_ci// whose definition dominates the add and contains the same value. 237fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, KeepRedundantAddWithoutPhi) { 238fd4e5da5Sopenharmony_ci const std::string text = R"( 239fd4e5da5Sopenharmony_ci OpCapability Shader 240fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 241fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 242fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 243fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 244fd4e5da5Sopenharmony_ci OpSource GLSL 430 245fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 246fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 247fd4e5da5Sopenharmony_ci %5 = OpTypeFloat 32 248fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 249fd4e5da5Sopenharmony_ci %7 = OpTypeBool 250fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %7 251fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 252fd4e5da5Sopenharmony_ci %9 = OpLabel 253fd4e5da5Sopenharmony_ci %10 = OpVariable %6 Function 254fd4e5da5Sopenharmony_ci %11 = OpLoad %5 %10 255fd4e5da5Sopenharmony_ci OpBranchConditional %8 %13 %14 256fd4e5da5Sopenharmony_ci %13 = OpLabel 257fd4e5da5Sopenharmony_ci %add1 = OpFAdd %5 %11 %11 258fd4e5da5Sopenharmony_ci OpBranch %15 259fd4e5da5Sopenharmony_ci %14 = OpLabel 260fd4e5da5Sopenharmony_ci %add2 = OpFAdd %5 %11 %11 261fd4e5da5Sopenharmony_ci OpBranch %15 262fd4e5da5Sopenharmony_ci %15 = OpLabel 263fd4e5da5Sopenharmony_ci %16 = OpFAdd %5 %11 %11 264fd4e5da5Sopenharmony_ci OpReturn 265fd4e5da5Sopenharmony_ci OpFunctionEnd 266fd4e5da5Sopenharmony_ci 267fd4e5da5Sopenharmony_ci )"; 268fd4e5da5Sopenharmony_ci auto result = SinglePassRunAndDisassemble<RedundancyEliminationPass>( 269fd4e5da5Sopenharmony_ci text, /* skip_nop = */ true, /* do_validation = */ false); 270fd4e5da5Sopenharmony_ci EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 271fd4e5da5Sopenharmony_ci} 272fd4e5da5Sopenharmony_ci 273fd4e5da5Sopenharmony_ci// Test that it can get a simple case of local redundancy elimination 274fd4e5da5Sopenharmony_ci// when it has OpenCL.DebugInfo.100 instructions. 275fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, OpenCLDebugInfo100) { 276fd4e5da5Sopenharmony_ci // When three redundant DebugValues exist, only one DebugValue must remain. 277fd4e5da5Sopenharmony_ci const std::string text = R"( 278fd4e5da5Sopenharmony_ci OpCapability Shader 279fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "OpenCL.DebugInfo.100" 280fd4e5da5Sopenharmony_ci %2 = OpExtInstImport "GLSL.std.450" 281fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 282fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %3 "main" 283fd4e5da5Sopenharmony_ci OpExecutionMode %3 OriginUpperLeft 284fd4e5da5Sopenharmony_ci OpSource GLSL 430 285fd4e5da5Sopenharmony_ci %4 = OpString "ps.hlsl" 286fd4e5da5Sopenharmony_ci %5 = OpString "float" 287fd4e5da5Sopenharmony_ci %6 = OpString "s0" 288fd4e5da5Sopenharmony_ci %7 = OpString "main" 289fd4e5da5Sopenharmony_ci %void = OpTypeVoid 290fd4e5da5Sopenharmony_ci %9 = OpTypeFunction %void 291fd4e5da5Sopenharmony_ci %float = OpTypeFloat 32 292fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 293fd4e5da5Sopenharmony_ci %uint_0 = OpConstant %uint 0 294fd4e5da5Sopenharmony_ci %uint_32 = OpConstant %uint 32 295fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float 296fd4e5da5Sopenharmony_ci %15 = OpExtInst %void %1 DebugExpression 297fd4e5da5Sopenharmony_ci %16 = OpExtInst %void %1 DebugSource %4 298fd4e5da5Sopenharmony_ci %17 = OpExtInst %void %1 DebugCompilationUnit 1 4 %16 HLSL 299fd4e5da5Sopenharmony_ci %18 = OpExtInst %void %1 DebugTypeBasic %5 %uint_32 Float 300fd4e5da5Sopenharmony_ci %19 = OpExtInst %void %1 DebugTypeVector %18 4 301fd4e5da5Sopenharmony_ci %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %19 302fd4e5da5Sopenharmony_ci %21 = OpExtInst %void %1 DebugFunction %7 %20 %16 4 1 %17 %7 FlagIsProtected|FlagIsPrivate 4 %3 303fd4e5da5Sopenharmony_ci; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void {{%\w+}} DebugLocalVariable 304fd4e5da5Sopenharmony_ci %22 = OpExtInst %void %1 DebugLocalVariable %6 %19 %16 0 0 %21 FlagIsLocal 305fd4e5da5Sopenharmony_ci %14 = OpExtInst %void %1 DebugLocalVariable %6 %19 %16 0 0 %21 FlagIsLocal 306fd4e5da5Sopenharmony_ci %3 = OpFunction %void None %9 307fd4e5da5Sopenharmony_ci %23 = OpLabel 308fd4e5da5Sopenharmony_ci %24 = OpExtInst %void %1 DebugScope %21 309fd4e5da5Sopenharmony_ci %25 = OpVariable %_ptr_Function_float Function 310fd4e5da5Sopenharmony_ci %26 = OpLoad %float %25 311fd4e5da5Sopenharmony_ci OpLine %4 0 0 312fd4e5da5Sopenharmony_ci; Two `OpFAdd %float %26 %26` are the same. One must be removed. 313fd4e5da5Sopenharmony_ci; After removing one `OpFAdd %float %26 %26`, two DebugValues are the same. 314fd4e5da5Sopenharmony_ci; One must be removed. 315fd4e5da5Sopenharmony_ci; 316fd4e5da5Sopenharmony_ci; CHECK: OpLine {{%\w+}} 0 0 317fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[add:%\w+]] = OpFAdd %float [[value:%\w+]] 318fd4e5da5Sopenharmony_ci; CHECK-NEXT: DebugValue [[dbg_local_var]] [[add]] 319fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLine {{%\w+}} 1 0 320fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFAdd %float [[add]] [[value]] 321fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn 322fd4e5da5Sopenharmony_ci %27 = OpFAdd %float %26 %26 323fd4e5da5Sopenharmony_ci %28 = OpExtInst %void %1 DebugValue %22 %27 %15 %uint_0 324fd4e5da5Sopenharmony_ci OpLine %4 1 0 325fd4e5da5Sopenharmony_ci %29 = OpFAdd %float %26 %26 326fd4e5da5Sopenharmony_ci %30 = OpExtInst %void %1 DebugValue %14 %29 %15 %uint_0 327fd4e5da5Sopenharmony_ci %31 = OpExtInst %void %1 DebugValue %22 %29 %15 %uint_0 328fd4e5da5Sopenharmony_ci %32 = OpFAdd %float %29 %26 329fd4e5da5Sopenharmony_ci %33 = OpFAdd %float %27 %26 330fd4e5da5Sopenharmony_ci OpReturn 331fd4e5da5Sopenharmony_ci OpFunctionEnd 332fd4e5da5Sopenharmony_ci )"; 333fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<RedundancyEliminationPass>(text, false); 334fd4e5da5Sopenharmony_ci} 335fd4e5da5Sopenharmony_ci 336fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, FunctionDeclaration) { 337fd4e5da5Sopenharmony_ci // Make sure the pass works with a function declaration that is called. 338fd4e5da5Sopenharmony_ci const std::string text = R"(OpCapability Addresses 339fd4e5da5Sopenharmony_ciOpCapability Linkage 340fd4e5da5Sopenharmony_ciOpCapability Kernel 341fd4e5da5Sopenharmony_ciOpCapability Int8 342fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.std" 343fd4e5da5Sopenharmony_ciOpMemoryModel Physical64 OpenCL 344fd4e5da5Sopenharmony_ciOpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool" 345fd4e5da5Sopenharmony_ciOpExecutionMode %2 ContractionOff 346fd4e5da5Sopenharmony_ciOpSource Unknown 0 347fd4e5da5Sopenharmony_ciOpDecorate %3 LinkageAttributes "julia_error_7712" Import 348fd4e5da5Sopenharmony_ci%void = OpTypeVoid 349fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void 350fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %5 351fd4e5da5Sopenharmony_ciOpFunctionEnd 352fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %5 353fd4e5da5Sopenharmony_ci%6 = OpLabel 354fd4e5da5Sopenharmony_ci%7 = OpFunctionCall %void %3 355fd4e5da5Sopenharmony_ciOpReturn 356fd4e5da5Sopenharmony_ciOpFunctionEnd 357fd4e5da5Sopenharmony_ci)"; 358fd4e5da5Sopenharmony_ci 359fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<RedundancyEliminationPass>(text, text, false); 360fd4e5da5Sopenharmony_ci} 361fd4e5da5Sopenharmony_ci 362fd4e5da5Sopenharmony_ci} // namespace 363fd4e5da5Sopenharmony_ci} // namespace opt 364fd4e5da5Sopenharmony_ci} // namespace spvtools