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 <string> 16fd4e5da5Sopenharmony_ci#include <utility> 17fd4e5da5Sopenharmony_ci#include <vector> 18fd4e5da5Sopenharmony_ci 19fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 20fd4e5da5Sopenharmony_ci#include "source/opt/loop_descriptor.h" 21fd4e5da5Sopenharmony_ci#include "source/opt/loop_peeling.h" 22fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 23fd4e5da5Sopenharmony_ci 24fd4e5da5Sopenharmony_cinamespace spvtools { 25fd4e5da5Sopenharmony_cinamespace opt { 26fd4e5da5Sopenharmony_cinamespace { 27fd4e5da5Sopenharmony_ci 28fd4e5da5Sopenharmony_ciclass PeelingPassTest : public PassTest<::testing::Test> { 29fd4e5da5Sopenharmony_ci public: 30fd4e5da5Sopenharmony_ci // Generic routine to run the loop peeling pass and check 31fd4e5da5Sopenharmony_ci LoopPeelingPass::LoopPeelingStats AssembleAndRunPeelingTest( 32fd4e5da5Sopenharmony_ci const std::string& text_head, const std::string& text_tail, 33fd4e5da5Sopenharmony_ci spv::Op opcode, const std::string& res_id, const std::string& op1, 34fd4e5da5Sopenharmony_ci const std::string& op2) { 35fd4e5da5Sopenharmony_ci std::string opcode_str; 36fd4e5da5Sopenharmony_ci switch (opcode) { 37fd4e5da5Sopenharmony_ci case spv::Op::OpSLessThan: 38fd4e5da5Sopenharmony_ci opcode_str = "OpSLessThan"; 39fd4e5da5Sopenharmony_ci break; 40fd4e5da5Sopenharmony_ci case spv::Op::OpSGreaterThan: 41fd4e5da5Sopenharmony_ci opcode_str = "OpSGreaterThan"; 42fd4e5da5Sopenharmony_ci break; 43fd4e5da5Sopenharmony_ci case spv::Op::OpSLessThanEqual: 44fd4e5da5Sopenharmony_ci opcode_str = "OpSLessThanEqual"; 45fd4e5da5Sopenharmony_ci break; 46fd4e5da5Sopenharmony_ci case spv::Op::OpSGreaterThanEqual: 47fd4e5da5Sopenharmony_ci opcode_str = "OpSGreaterThanEqual"; 48fd4e5da5Sopenharmony_ci break; 49fd4e5da5Sopenharmony_ci case spv::Op::OpIEqual: 50fd4e5da5Sopenharmony_ci opcode_str = "OpIEqual"; 51fd4e5da5Sopenharmony_ci break; 52fd4e5da5Sopenharmony_ci case spv::Op::OpINotEqual: 53fd4e5da5Sopenharmony_ci opcode_str = "OpINotEqual"; 54fd4e5da5Sopenharmony_ci break; 55fd4e5da5Sopenharmony_ci default: 56fd4e5da5Sopenharmony_ci assert(false && "Unhandled"); 57fd4e5da5Sopenharmony_ci break; 58fd4e5da5Sopenharmony_ci } 59fd4e5da5Sopenharmony_ci std::string test_cond = 60fd4e5da5Sopenharmony_ci res_id + " = " + opcode_str + " %bool " + op1 + " " + op2 + "\n"; 61fd4e5da5Sopenharmony_ci 62fd4e5da5Sopenharmony_ci LoopPeelingPass::LoopPeelingStats stats; 63fd4e5da5Sopenharmony_ci SinglePassRunAndDisassemble<LoopPeelingPass>( 64fd4e5da5Sopenharmony_ci text_head + test_cond + text_tail, true, true, &stats); 65fd4e5da5Sopenharmony_ci 66fd4e5da5Sopenharmony_ci return stats; 67fd4e5da5Sopenharmony_ci } 68fd4e5da5Sopenharmony_ci 69fd4e5da5Sopenharmony_ci // Generic routine to run the loop peeling pass and check 70fd4e5da5Sopenharmony_ci LoopPeelingPass::LoopPeelingStats RunPeelingTest( 71fd4e5da5Sopenharmony_ci const std::string& text_head, const std::string& text_tail, 72fd4e5da5Sopenharmony_ci spv::Op opcode, const std::string& res_id, const std::string& op1, 73fd4e5da5Sopenharmony_ci const std::string& op2, size_t nb_of_loops) { 74fd4e5da5Sopenharmony_ci LoopPeelingPass::LoopPeelingStats stats = AssembleAndRunPeelingTest( 75fd4e5da5Sopenharmony_ci text_head, text_tail, opcode, res_id, op1, op2); 76fd4e5da5Sopenharmony_ci 77fd4e5da5Sopenharmony_ci Function& f = *context()->module()->begin(); 78fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context()->GetLoopDescriptor(&f); 79fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), nb_of_loops); 80fd4e5da5Sopenharmony_ci 81fd4e5da5Sopenharmony_ci return stats; 82fd4e5da5Sopenharmony_ci } 83fd4e5da5Sopenharmony_ci 84fd4e5da5Sopenharmony_ci using PeelTraceType = 85fd4e5da5Sopenharmony_ci std::vector<std::pair<LoopPeelingPass::PeelDirection, uint32_t>>; 86fd4e5da5Sopenharmony_ci 87fd4e5da5Sopenharmony_ci void BuildAndCheckTrace(const std::string& text_head, 88fd4e5da5Sopenharmony_ci const std::string& text_tail, spv::Op opcode, 89fd4e5da5Sopenharmony_ci const std::string& res_id, const std::string& op1, 90fd4e5da5Sopenharmony_ci const std::string& op2, 91fd4e5da5Sopenharmony_ci const PeelTraceType& expected_peel_trace, 92fd4e5da5Sopenharmony_ci size_t expected_nb_of_loops) { 93fd4e5da5Sopenharmony_ci auto stats = RunPeelingTest(text_head, text_tail, opcode, res_id, op1, op2, 94fd4e5da5Sopenharmony_ci expected_nb_of_loops); 95fd4e5da5Sopenharmony_ci 96fd4e5da5Sopenharmony_ci EXPECT_EQ(stats.peeled_loops_.size(), expected_peel_trace.size()); 97fd4e5da5Sopenharmony_ci if (stats.peeled_loops_.size() != expected_peel_trace.size()) { 98fd4e5da5Sopenharmony_ci return; 99fd4e5da5Sopenharmony_ci } 100fd4e5da5Sopenharmony_ci 101fd4e5da5Sopenharmony_ci PeelTraceType::const_iterator expected_trace_it = 102fd4e5da5Sopenharmony_ci expected_peel_trace.begin(); 103fd4e5da5Sopenharmony_ci decltype(stats.peeled_loops_)::const_iterator stats_it = 104fd4e5da5Sopenharmony_ci stats.peeled_loops_.begin(); 105fd4e5da5Sopenharmony_ci 106fd4e5da5Sopenharmony_ci while (expected_trace_it != expected_peel_trace.end()) { 107fd4e5da5Sopenharmony_ci EXPECT_EQ(expected_trace_it->first, std::get<1>(*stats_it)); 108fd4e5da5Sopenharmony_ci EXPECT_EQ(expected_trace_it->second, std::get<2>(*stats_it)); 109fd4e5da5Sopenharmony_ci ++expected_trace_it; 110fd4e5da5Sopenharmony_ci ++stats_it; 111fd4e5da5Sopenharmony_ci } 112fd4e5da5Sopenharmony_ci } 113fd4e5da5Sopenharmony_ci}; 114fd4e5da5Sopenharmony_ci 115fd4e5da5Sopenharmony_ci/* 116fd4e5da5Sopenharmony_ciTest are derivation of the following generated test from the following GLSL + 117fd4e5da5Sopenharmony_ci--eliminate-local-multi-store 118fd4e5da5Sopenharmony_ci 119fd4e5da5Sopenharmony_ci#version 330 core 120fd4e5da5Sopenharmony_civoid main() { 121fd4e5da5Sopenharmony_ci int a = 0; 122fd4e5da5Sopenharmony_ci for(int i = 1; i < 10; i += 2) { 123fd4e5da5Sopenharmony_ci if (i < 3) { 124fd4e5da5Sopenharmony_ci a += 2; 125fd4e5da5Sopenharmony_ci } 126fd4e5da5Sopenharmony_ci } 127fd4e5da5Sopenharmony_ci} 128fd4e5da5Sopenharmony_ci 129fd4e5da5Sopenharmony_ciThe condition is interchanged to test < > <= >= == and peel before/after 130fd4e5da5Sopenharmony_ciopportunities. 131fd4e5da5Sopenharmony_ci*/ 132fd4e5da5Sopenharmony_ciTEST_F(PeelingPassTest, PeelingPassBasic) { 133fd4e5da5Sopenharmony_ci const std::string text_head = R"( 134fd4e5da5Sopenharmony_ci OpCapability Shader 135fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 136fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 137fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 138fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginLowerLeft 139fd4e5da5Sopenharmony_ci OpSource GLSL 330 140fd4e5da5Sopenharmony_ci OpName %main "main" 141fd4e5da5Sopenharmony_ci OpName %a "a" 142fd4e5da5Sopenharmony_ci OpName %i "i" 143fd4e5da5Sopenharmony_ci %void = OpTypeVoid 144fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 145fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 146fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 147fd4e5da5Sopenharmony_ci %bool = OpTypeBool 148fd4e5da5Sopenharmony_ci %int_20 = OpConstant %int 20 149fd4e5da5Sopenharmony_ci %int_19 = OpConstant %int 19 150fd4e5da5Sopenharmony_ci %int_18 = OpConstant %int 18 151fd4e5da5Sopenharmony_ci %int_17 = OpConstant %int 17 152fd4e5da5Sopenharmony_ci %int_16 = OpConstant %int 16 153fd4e5da5Sopenharmony_ci %int_15 = OpConstant %int 15 154fd4e5da5Sopenharmony_ci %int_14 = OpConstant %int 14 155fd4e5da5Sopenharmony_ci %int_13 = OpConstant %int 13 156fd4e5da5Sopenharmony_ci %int_12 = OpConstant %int 12 157fd4e5da5Sopenharmony_ci %int_11 = OpConstant %int 11 158fd4e5da5Sopenharmony_ci %int_10 = OpConstant %int 10 159fd4e5da5Sopenharmony_ci %int_9 = OpConstant %int 9 160fd4e5da5Sopenharmony_ci %int_8 = OpConstant %int 8 161fd4e5da5Sopenharmony_ci %int_7 = OpConstant %int 7 162fd4e5da5Sopenharmony_ci %int_6 = OpConstant %int 6 163fd4e5da5Sopenharmony_ci %int_5 = OpConstant %int 5 164fd4e5da5Sopenharmony_ci %int_4 = OpConstant %int 4 165fd4e5da5Sopenharmony_ci %int_3 = OpConstant %int 3 166fd4e5da5Sopenharmony_ci %int_2 = OpConstant %int 2 167fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 168fd4e5da5Sopenharmony_ci %int_0 = OpConstant %int 0 169fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 170fd4e5da5Sopenharmony_ci %5 = OpLabel 171fd4e5da5Sopenharmony_ci %a = OpVariable %_ptr_Function_int Function 172fd4e5da5Sopenharmony_ci %i = OpVariable %_ptr_Function_int Function 173fd4e5da5Sopenharmony_ci OpStore %a %int_0 174fd4e5da5Sopenharmony_ci OpStore %i %int_0 175fd4e5da5Sopenharmony_ci OpBranch %11 176fd4e5da5Sopenharmony_ci %11 = OpLabel 177fd4e5da5Sopenharmony_ci %31 = OpPhi %int %int_0 %5 %33 %14 178fd4e5da5Sopenharmony_ci %32 = OpPhi %int %int_1 %5 %30 %14 179fd4e5da5Sopenharmony_ci OpLoopMerge %13 %14 None 180fd4e5da5Sopenharmony_ci OpBranch %15 181fd4e5da5Sopenharmony_ci %15 = OpLabel 182fd4e5da5Sopenharmony_ci %19 = OpSLessThan %bool %32 %int_20 183fd4e5da5Sopenharmony_ci OpBranchConditional %19 %12 %13 184fd4e5da5Sopenharmony_ci %12 = OpLabel 185fd4e5da5Sopenharmony_ci )"; 186fd4e5da5Sopenharmony_ci const std::string text_tail = R"( 187fd4e5da5Sopenharmony_ci OpSelectionMerge %24 None 188fd4e5da5Sopenharmony_ci OpBranchConditional %22 %23 %24 189fd4e5da5Sopenharmony_ci %23 = OpLabel 190fd4e5da5Sopenharmony_ci %27 = OpIAdd %int %31 %int_2 191fd4e5da5Sopenharmony_ci OpStore %a %27 192fd4e5da5Sopenharmony_ci OpBranch %24 193fd4e5da5Sopenharmony_ci %24 = OpLabel 194fd4e5da5Sopenharmony_ci %33 = OpPhi %int %31 %12 %27 %23 195fd4e5da5Sopenharmony_ci OpBranch %14 196fd4e5da5Sopenharmony_ci %14 = OpLabel 197fd4e5da5Sopenharmony_ci %30 = OpIAdd %int %32 %int_2 198fd4e5da5Sopenharmony_ci OpStore %i %30 199fd4e5da5Sopenharmony_ci OpBranch %11 200fd4e5da5Sopenharmony_ci %13 = OpLabel 201fd4e5da5Sopenharmony_ci OpReturn 202fd4e5da5Sopenharmony_ci OpFunctionEnd 203fd4e5da5Sopenharmony_ci )"; 204fd4e5da5Sopenharmony_ci 205fd4e5da5Sopenharmony_ci auto run_test = [&text_head, &text_tail, this](spv::Op opcode, 206fd4e5da5Sopenharmony_ci const std::string& op1, 207fd4e5da5Sopenharmony_ci const std::string& op2) { 208fd4e5da5Sopenharmony_ci auto stats = 209fd4e5da5Sopenharmony_ci RunPeelingTest(text_head, text_tail, opcode, "%22", op1, op2, 2); 210fd4e5da5Sopenharmony_ci 211fd4e5da5Sopenharmony_ci EXPECT_EQ(stats.peeled_loops_.size(), 1u); 212fd4e5da5Sopenharmony_ci if (stats.peeled_loops_.size() != 1u) 213fd4e5da5Sopenharmony_ci return std::pair<LoopPeelingPass::PeelDirection, uint32_t>{ 214fd4e5da5Sopenharmony_ci LoopPeelingPass::PeelDirection::kNone, 0}; 215fd4e5da5Sopenharmony_ci 216fd4e5da5Sopenharmony_ci return std::pair<LoopPeelingPass::PeelDirection, uint32_t>{ 217fd4e5da5Sopenharmony_ci std::get<1>(*stats.peeled_loops_.begin()), 218fd4e5da5Sopenharmony_ci std::get<2>(*stats.peeled_loops_.begin())}; 219fd4e5da5Sopenharmony_ci }; 220fd4e5da5Sopenharmony_ci 221fd4e5da5Sopenharmony_ci // Test LT 222fd4e5da5Sopenharmony_ci // Peel before by a factor of 2. 223fd4e5da5Sopenharmony_ci { 224fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv < 4"); 225fd4e5da5Sopenharmony_ci 226fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 227fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%32", "%int_4"); 228fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 229fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 230fd4e5da5Sopenharmony_ci } 231fd4e5da5Sopenharmony_ci { 232fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 4 > iv"); 233fd4e5da5Sopenharmony_ci 234fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 235fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%int_4", "%32"); 236fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 237fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 238fd4e5da5Sopenharmony_ci } 239fd4e5da5Sopenharmony_ci { 240fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv < 5"); 241fd4e5da5Sopenharmony_ci 242fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 243fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%32", "%int_5"); 244fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 245fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 246fd4e5da5Sopenharmony_ci } 247fd4e5da5Sopenharmony_ci { 248fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 5 > iv"); 249fd4e5da5Sopenharmony_ci 250fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 251fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%int_5", "%32"); 252fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 253fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 254fd4e5da5Sopenharmony_ci } 255fd4e5da5Sopenharmony_ci 256fd4e5da5Sopenharmony_ci // Peel after by a factor of 2. 257fd4e5da5Sopenharmony_ci { 258fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv < 16"); 259fd4e5da5Sopenharmony_ci 260fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 261fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%32", "%int_16"); 262fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 263fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 264fd4e5da5Sopenharmony_ci } 265fd4e5da5Sopenharmony_ci { 266fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 16 > iv"); 267fd4e5da5Sopenharmony_ci 268fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 269fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%int_16", "%32"); 270fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 271fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 272fd4e5da5Sopenharmony_ci } 273fd4e5da5Sopenharmony_ci { 274fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv < 17"); 275fd4e5da5Sopenharmony_ci 276fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 277fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%32", "%int_17"); 278fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 279fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 280fd4e5da5Sopenharmony_ci } 281fd4e5da5Sopenharmony_ci { 282fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 17 > iv"); 283fd4e5da5Sopenharmony_ci 284fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 285fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%int_17", "%32"); 286fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 287fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 288fd4e5da5Sopenharmony_ci } 289fd4e5da5Sopenharmony_ci 290fd4e5da5Sopenharmony_ci // Test GT 291fd4e5da5Sopenharmony_ci // Peel before by a factor of 2. 292fd4e5da5Sopenharmony_ci { 293fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv > 5"); 294fd4e5da5Sopenharmony_ci 295fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 296fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%32", "%int_5"); 297fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 298fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 299fd4e5da5Sopenharmony_ci } 300fd4e5da5Sopenharmony_ci { 301fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 5 < iv"); 302fd4e5da5Sopenharmony_ci 303fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 304fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%int_5", "%32"); 305fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 306fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 307fd4e5da5Sopenharmony_ci } 308fd4e5da5Sopenharmony_ci { 309fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv > 4"); 310fd4e5da5Sopenharmony_ci 311fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 312fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%32", "%int_4"); 313fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 314fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 315fd4e5da5Sopenharmony_ci } 316fd4e5da5Sopenharmony_ci { 317fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 4 < iv"); 318fd4e5da5Sopenharmony_ci 319fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 320fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%int_4", "%32"); 321fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 322fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 323fd4e5da5Sopenharmony_ci } 324fd4e5da5Sopenharmony_ci 325fd4e5da5Sopenharmony_ci // Peel after by a factor of 2. 326fd4e5da5Sopenharmony_ci { 327fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv > 16"); 328fd4e5da5Sopenharmony_ci 329fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 330fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%32", "%int_16"); 331fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 332fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 333fd4e5da5Sopenharmony_ci } 334fd4e5da5Sopenharmony_ci { 335fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 16 < iv"); 336fd4e5da5Sopenharmony_ci 337fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 338fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%int_16", "%32"); 339fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 340fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 341fd4e5da5Sopenharmony_ci } 342fd4e5da5Sopenharmony_ci { 343fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv > 17"); 344fd4e5da5Sopenharmony_ci 345fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 346fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%32", "%int_17"); 347fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 348fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 349fd4e5da5Sopenharmony_ci } 350fd4e5da5Sopenharmony_ci { 351fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 17 < iv"); 352fd4e5da5Sopenharmony_ci 353fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 354fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%int_17", "%32"); 355fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 356fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 357fd4e5da5Sopenharmony_ci } 358fd4e5da5Sopenharmony_ci 359fd4e5da5Sopenharmony_ci // Test LE 360fd4e5da5Sopenharmony_ci // Peel before by a factor of 2. 361fd4e5da5Sopenharmony_ci { 362fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv <= 4"); 363fd4e5da5Sopenharmony_ci 364fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 365fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%32", "%int_4"); 366fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 367fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 368fd4e5da5Sopenharmony_ci } 369fd4e5da5Sopenharmony_ci { 370fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 4 => iv"); 371fd4e5da5Sopenharmony_ci 372fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 373fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%int_4", "%32"); 374fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 375fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 376fd4e5da5Sopenharmony_ci } 377fd4e5da5Sopenharmony_ci { 378fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv <= 3"); 379fd4e5da5Sopenharmony_ci 380fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 381fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%32", "%int_3"); 382fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 383fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 384fd4e5da5Sopenharmony_ci } 385fd4e5da5Sopenharmony_ci { 386fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 3 => iv"); 387fd4e5da5Sopenharmony_ci 388fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 389fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%int_3", "%32"); 390fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 391fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 392fd4e5da5Sopenharmony_ci } 393fd4e5da5Sopenharmony_ci 394fd4e5da5Sopenharmony_ci // Peel after by a factor of 2. 395fd4e5da5Sopenharmony_ci { 396fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv <= 16"); 397fd4e5da5Sopenharmony_ci 398fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 399fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%32", "%int_16"); 400fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 401fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 402fd4e5da5Sopenharmony_ci } 403fd4e5da5Sopenharmony_ci { 404fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 16 => iv"); 405fd4e5da5Sopenharmony_ci 406fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 407fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%int_16", "%32"); 408fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 409fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 410fd4e5da5Sopenharmony_ci } 411fd4e5da5Sopenharmony_ci { 412fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv <= 15"); 413fd4e5da5Sopenharmony_ci 414fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 415fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%32", "%int_15"); 416fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 417fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 418fd4e5da5Sopenharmony_ci } 419fd4e5da5Sopenharmony_ci { 420fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 15 => iv"); 421fd4e5da5Sopenharmony_ci 422fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 423fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%int_15", "%32"); 424fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 425fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 426fd4e5da5Sopenharmony_ci } 427fd4e5da5Sopenharmony_ci 428fd4e5da5Sopenharmony_ci // Test GE 429fd4e5da5Sopenharmony_ci // Peel before by a factor of 2. 430fd4e5da5Sopenharmony_ci { 431fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv >= 5"); 432fd4e5da5Sopenharmony_ci 433fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 434fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_5"); 435fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 436fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 437fd4e5da5Sopenharmony_ci } 438fd4e5da5Sopenharmony_ci { 439fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 35 >= iv"); 440fd4e5da5Sopenharmony_ci 441fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 442fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%int_5", "%32"); 443fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 444fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 445fd4e5da5Sopenharmony_ci } 446fd4e5da5Sopenharmony_ci { 447fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv >= 4"); 448fd4e5da5Sopenharmony_ci 449fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 450fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_4"); 451fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 452fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 453fd4e5da5Sopenharmony_ci } 454fd4e5da5Sopenharmony_ci { 455fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 4 <= iv"); 456fd4e5da5Sopenharmony_ci 457fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 458fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%int_4", "%32"); 459fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 460fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 461fd4e5da5Sopenharmony_ci } 462fd4e5da5Sopenharmony_ci 463fd4e5da5Sopenharmony_ci // Peel after by a factor of 2. 464fd4e5da5Sopenharmony_ci { 465fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv >= 17"); 466fd4e5da5Sopenharmony_ci 467fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 468fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_17"); 469fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 470fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 471fd4e5da5Sopenharmony_ci } 472fd4e5da5Sopenharmony_ci { 473fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 17 <= iv"); 474fd4e5da5Sopenharmony_ci 475fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 476fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%int_17", "%32"); 477fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 478fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 479fd4e5da5Sopenharmony_ci } 480fd4e5da5Sopenharmony_ci { 481fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv >= 16"); 482fd4e5da5Sopenharmony_ci 483fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 484fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_16"); 485fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 486fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 487fd4e5da5Sopenharmony_ci } 488fd4e5da5Sopenharmony_ci { 489fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 16 <= iv"); 490fd4e5da5Sopenharmony_ci 491fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 492fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%int_16", "%32"); 493fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 494fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 2u); 495fd4e5da5Sopenharmony_ci } 496fd4e5da5Sopenharmony_ci 497fd4e5da5Sopenharmony_ci // Test EQ 498fd4e5da5Sopenharmony_ci // Peel before by a factor of 1. 499fd4e5da5Sopenharmony_ci { 500fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv == 1"); 501fd4e5da5Sopenharmony_ci 502fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 503fd4e5da5Sopenharmony_ci run_test(spv::Op::OpIEqual, "%32", "%int_1"); 504fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 505fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 1u); 506fd4e5da5Sopenharmony_ci } 507fd4e5da5Sopenharmony_ci { 508fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 1 == iv"); 509fd4e5da5Sopenharmony_ci 510fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 511fd4e5da5Sopenharmony_ci run_test(spv::Op::OpIEqual, "%int_1", "%32"); 512fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 513fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 1u); 514fd4e5da5Sopenharmony_ci } 515fd4e5da5Sopenharmony_ci 516fd4e5da5Sopenharmony_ci // Peel after by a factor of 1. 517fd4e5da5Sopenharmony_ci { 518fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv == 19"); 519fd4e5da5Sopenharmony_ci 520fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 521fd4e5da5Sopenharmony_ci run_test(spv::Op::OpIEqual, "%32", "%int_19"); 522fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 523fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 1u); 524fd4e5da5Sopenharmony_ci } 525fd4e5da5Sopenharmony_ci { 526fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 19 == iv"); 527fd4e5da5Sopenharmony_ci 528fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 529fd4e5da5Sopenharmony_ci run_test(spv::Op::OpIEqual, "%int_19", "%32"); 530fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 531fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 1u); 532fd4e5da5Sopenharmony_ci } 533fd4e5da5Sopenharmony_ci 534fd4e5da5Sopenharmony_ci // Test NE 535fd4e5da5Sopenharmony_ci // Peel before by a factor of 1. 536fd4e5da5Sopenharmony_ci { 537fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv != 1"); 538fd4e5da5Sopenharmony_ci 539fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 540fd4e5da5Sopenharmony_ci run_test(spv::Op::OpINotEqual, "%32", "%int_1"); 541fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 542fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 1u); 543fd4e5da5Sopenharmony_ci } 544fd4e5da5Sopenharmony_ci { 545fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 1 != iv"); 546fd4e5da5Sopenharmony_ci 547fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 548fd4e5da5Sopenharmony_ci run_test(spv::Op::OpINotEqual, "%int_1", "%32"); 549fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore); 550fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 1u); 551fd4e5da5Sopenharmony_ci } 552fd4e5da5Sopenharmony_ci 553fd4e5da5Sopenharmony_ci // Peel after by a factor of 1. 554fd4e5da5Sopenharmony_ci { 555fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv != 19"); 556fd4e5da5Sopenharmony_ci 557fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 558fd4e5da5Sopenharmony_ci run_test(spv::Op::OpINotEqual, "%32", "%int_19"); 559fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 560fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 1u); 561fd4e5da5Sopenharmony_ci } 562fd4e5da5Sopenharmony_ci { 563fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 19 != iv"); 564fd4e5da5Sopenharmony_ci 565fd4e5da5Sopenharmony_ci std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info = 566fd4e5da5Sopenharmony_ci run_test(spv::Op::OpINotEqual, "%int_19", "%32"); 567fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter); 568fd4e5da5Sopenharmony_ci EXPECT_EQ(peel_info.second, 1u); 569fd4e5da5Sopenharmony_ci } 570fd4e5da5Sopenharmony_ci 571fd4e5da5Sopenharmony_ci // No peel. 572fd4e5da5Sopenharmony_ci { 573fd4e5da5Sopenharmony_ci SCOPED_TRACE("No Peel: 20 => iv"); 574fd4e5da5Sopenharmony_ci 575fd4e5da5Sopenharmony_ci auto stats = RunPeelingTest(text_head, text_tail, spv::Op::OpSLessThanEqual, 576fd4e5da5Sopenharmony_ci "%22", "%int_20", "%32", 1); 577fd4e5da5Sopenharmony_ci 578fd4e5da5Sopenharmony_ci EXPECT_EQ(stats.peeled_loops_.size(), 0u); 579fd4e5da5Sopenharmony_ci } 580fd4e5da5Sopenharmony_ci} 581fd4e5da5Sopenharmony_ci 582fd4e5da5Sopenharmony_ci/* 583fd4e5da5Sopenharmony_ciTest are derivation of the following generated test from the following GLSL + 584fd4e5da5Sopenharmony_ci--eliminate-local-multi-store 585fd4e5da5Sopenharmony_ci 586fd4e5da5Sopenharmony_ci#version 330 core 587fd4e5da5Sopenharmony_civoid main() { 588fd4e5da5Sopenharmony_ci int a = 0; 589fd4e5da5Sopenharmony_ci for(int i = 0; i < 10; ++i) { 590fd4e5da5Sopenharmony_ci if (i < 3) { 591fd4e5da5Sopenharmony_ci a += 2; 592fd4e5da5Sopenharmony_ci } 593fd4e5da5Sopenharmony_ci if (i < 1) { 594fd4e5da5Sopenharmony_ci a += 2; 595fd4e5da5Sopenharmony_ci } 596fd4e5da5Sopenharmony_ci } 597fd4e5da5Sopenharmony_ci} 598fd4e5da5Sopenharmony_ci 599fd4e5da5Sopenharmony_ciThe condition is interchanged to test < > <= >= == and peel before/after 600fd4e5da5Sopenharmony_ciopportunities. 601fd4e5da5Sopenharmony_ci*/ 602fd4e5da5Sopenharmony_ciTEST_F(PeelingPassTest, MultiplePeelingPass) { 603fd4e5da5Sopenharmony_ci const std::string text_head = R"( 604fd4e5da5Sopenharmony_ci OpCapability Shader 605fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 606fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 607fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 608fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginLowerLeft 609fd4e5da5Sopenharmony_ci OpSource GLSL 330 610fd4e5da5Sopenharmony_ci OpName %main "main" 611fd4e5da5Sopenharmony_ci OpName %a "a" 612fd4e5da5Sopenharmony_ci OpName %i "i" 613fd4e5da5Sopenharmony_ci %void = OpTypeVoid 614fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 615fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 616fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 617fd4e5da5Sopenharmony_ci %bool = OpTypeBool 618fd4e5da5Sopenharmony_ci %int_10 = OpConstant %int 10 619fd4e5da5Sopenharmony_ci %int_9 = OpConstant %int 9 620fd4e5da5Sopenharmony_ci %int_8 = OpConstant %int 8 621fd4e5da5Sopenharmony_ci %int_7 = OpConstant %int 7 622fd4e5da5Sopenharmony_ci %int_6 = OpConstant %int 6 623fd4e5da5Sopenharmony_ci %int_5 = OpConstant %int 5 624fd4e5da5Sopenharmony_ci %int_4 = OpConstant %int 4 625fd4e5da5Sopenharmony_ci %int_3 = OpConstant %int 3 626fd4e5da5Sopenharmony_ci %int_2 = OpConstant %int 2 627fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 628fd4e5da5Sopenharmony_ci %int_0 = OpConstant %int 0 629fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 630fd4e5da5Sopenharmony_ci %5 = OpLabel 631fd4e5da5Sopenharmony_ci %a = OpVariable %_ptr_Function_int Function 632fd4e5da5Sopenharmony_ci %i = OpVariable %_ptr_Function_int Function 633fd4e5da5Sopenharmony_ci OpStore %a %int_0 634fd4e5da5Sopenharmony_ci OpStore %i %int_0 635fd4e5da5Sopenharmony_ci OpBranch %11 636fd4e5da5Sopenharmony_ci %11 = OpLabel 637fd4e5da5Sopenharmony_ci %37 = OpPhi %int %int_0 %5 %40 %14 638fd4e5da5Sopenharmony_ci %38 = OpPhi %int %int_0 %5 %36 %14 639fd4e5da5Sopenharmony_ci OpLoopMerge %13 %14 None 640fd4e5da5Sopenharmony_ci OpBranch %15 641fd4e5da5Sopenharmony_ci %15 = OpLabel 642fd4e5da5Sopenharmony_ci %19 = OpSLessThan %bool %38 %int_10 643fd4e5da5Sopenharmony_ci OpBranchConditional %19 %12 %13 644fd4e5da5Sopenharmony_ci %12 = OpLabel 645fd4e5da5Sopenharmony_ci )"; 646fd4e5da5Sopenharmony_ci const std::string text_tail = R"( 647fd4e5da5Sopenharmony_ci OpSelectionMerge %24 None 648fd4e5da5Sopenharmony_ci OpBranchConditional %22 %23 %24 649fd4e5da5Sopenharmony_ci %23 = OpLabel 650fd4e5da5Sopenharmony_ci %27 = OpIAdd %int %37 %int_2 651fd4e5da5Sopenharmony_ci OpStore %a %27 652fd4e5da5Sopenharmony_ci OpBranch %24 653fd4e5da5Sopenharmony_ci %24 = OpLabel 654fd4e5da5Sopenharmony_ci %39 = OpPhi %int %37 %12 %27 %23 655fd4e5da5Sopenharmony_ci %30 = OpSLessThan %bool %38 %int_1 656fd4e5da5Sopenharmony_ci OpSelectionMerge %32 None 657fd4e5da5Sopenharmony_ci OpBranchConditional %30 %31 %32 658fd4e5da5Sopenharmony_ci %31 = OpLabel 659fd4e5da5Sopenharmony_ci %34 = OpIAdd %int %39 %int_2 660fd4e5da5Sopenharmony_ci OpStore %a %34 661fd4e5da5Sopenharmony_ci OpBranch %32 662fd4e5da5Sopenharmony_ci %32 = OpLabel 663fd4e5da5Sopenharmony_ci %40 = OpPhi %int %39 %24 %34 %31 664fd4e5da5Sopenharmony_ci OpBranch %14 665fd4e5da5Sopenharmony_ci %14 = OpLabel 666fd4e5da5Sopenharmony_ci %36 = OpIAdd %int %38 %int_1 667fd4e5da5Sopenharmony_ci OpStore %i %36 668fd4e5da5Sopenharmony_ci OpBranch %11 669fd4e5da5Sopenharmony_ci %13 = OpLabel 670fd4e5da5Sopenharmony_ci OpReturn 671fd4e5da5Sopenharmony_ci OpFunctionEnd 672fd4e5da5Sopenharmony_ci )"; 673fd4e5da5Sopenharmony_ci 674fd4e5da5Sopenharmony_ci auto run_test = [&text_head, &text_tail, this]( 675fd4e5da5Sopenharmony_ci spv::Op opcode, const std::string& op1, 676fd4e5da5Sopenharmony_ci const std::string& op2, 677fd4e5da5Sopenharmony_ci const PeelTraceType& expected_peel_trace) { 678fd4e5da5Sopenharmony_ci BuildAndCheckTrace(text_head, text_tail, opcode, "%22", op1, op2, 679fd4e5da5Sopenharmony_ci expected_peel_trace, expected_peel_trace.size() + 1); 680fd4e5da5Sopenharmony_ci }; 681fd4e5da5Sopenharmony_ci 682fd4e5da5Sopenharmony_ci // Test LT 683fd4e5da5Sopenharmony_ci // Peel before by a factor of 3. 684fd4e5da5Sopenharmony_ci { 685fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv < 3"); 686fd4e5da5Sopenharmony_ci 687fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%38", "%int_3", 688fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 3u}}); 689fd4e5da5Sopenharmony_ci } 690fd4e5da5Sopenharmony_ci { 691fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 3 > iv"); 692fd4e5da5Sopenharmony_ci 693fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%int_3", "%38", 694fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 3u}}); 695fd4e5da5Sopenharmony_ci } 696fd4e5da5Sopenharmony_ci 697fd4e5da5Sopenharmony_ci // Peel after by a factor of 2. 698fd4e5da5Sopenharmony_ci { 699fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv < 8"); 700fd4e5da5Sopenharmony_ci 701fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%38", "%int_8", 702fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); 703fd4e5da5Sopenharmony_ci } 704fd4e5da5Sopenharmony_ci { 705fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 8 > iv"); 706fd4e5da5Sopenharmony_ci 707fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%int_8", "%38", 708fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); 709fd4e5da5Sopenharmony_ci } 710fd4e5da5Sopenharmony_ci 711fd4e5da5Sopenharmony_ci // Test GT 712fd4e5da5Sopenharmony_ci // Peel before by a factor of 2. 713fd4e5da5Sopenharmony_ci { 714fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv > 2"); 715fd4e5da5Sopenharmony_ci 716fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%38", "%int_2", 717fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); 718fd4e5da5Sopenharmony_ci } 719fd4e5da5Sopenharmony_ci { 720fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 2 < iv"); 721fd4e5da5Sopenharmony_ci 722fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%int_2", "%38", 723fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); 724fd4e5da5Sopenharmony_ci } 725fd4e5da5Sopenharmony_ci 726fd4e5da5Sopenharmony_ci // Peel after by a factor of 3. 727fd4e5da5Sopenharmony_ci { 728fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv > 7"); 729fd4e5da5Sopenharmony_ci 730fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThan, "%38", "%int_7", 731fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 3u}}); 732fd4e5da5Sopenharmony_ci } 733fd4e5da5Sopenharmony_ci { 734fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 7 < iv"); 735fd4e5da5Sopenharmony_ci 736fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%int_7", "%38", 737fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 3u}}); 738fd4e5da5Sopenharmony_ci } 739fd4e5da5Sopenharmony_ci 740fd4e5da5Sopenharmony_ci // Test LE 741fd4e5da5Sopenharmony_ci // Peel before by a factor of 2. 742fd4e5da5Sopenharmony_ci { 743fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv <= 1"); 744fd4e5da5Sopenharmony_ci 745fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%38", "%int_1", 746fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); 747fd4e5da5Sopenharmony_ci } 748fd4e5da5Sopenharmony_ci { 749fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 1 => iv"); 750fd4e5da5Sopenharmony_ci 751fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%int_1", "%38", 752fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); 753fd4e5da5Sopenharmony_ci } 754fd4e5da5Sopenharmony_ci 755fd4e5da5Sopenharmony_ci // Peel after by a factor of 2. 756fd4e5da5Sopenharmony_ci { 757fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv <= 7"); 758fd4e5da5Sopenharmony_ci 759fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%38", "%int_7", 760fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); 761fd4e5da5Sopenharmony_ci } 762fd4e5da5Sopenharmony_ci { 763fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 7 => iv"); 764fd4e5da5Sopenharmony_ci 765fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%int_7", "%38", 766fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); 767fd4e5da5Sopenharmony_ci } 768fd4e5da5Sopenharmony_ci 769fd4e5da5Sopenharmony_ci // Test GE 770fd4e5da5Sopenharmony_ci // Peel before by a factor of 2. 771fd4e5da5Sopenharmony_ci { 772fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv >= 2"); 773fd4e5da5Sopenharmony_ci 774fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%38", "%int_2", 775fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); 776fd4e5da5Sopenharmony_ci } 777fd4e5da5Sopenharmony_ci { 778fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 2 <= iv"); 779fd4e5da5Sopenharmony_ci 780fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%int_2", "%38", 781fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 2u}}); 782fd4e5da5Sopenharmony_ci } 783fd4e5da5Sopenharmony_ci 784fd4e5da5Sopenharmony_ci // Peel after by a factor of 2. 785fd4e5da5Sopenharmony_ci { 786fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv >= 8"); 787fd4e5da5Sopenharmony_ci 788fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSGreaterThanEqual, "%38", "%int_8", 789fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); 790fd4e5da5Sopenharmony_ci } 791fd4e5da5Sopenharmony_ci { 792fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 8 <= iv"); 793fd4e5da5Sopenharmony_ci 794fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThanEqual, "%int_8", "%38", 795fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 2u}}); 796fd4e5da5Sopenharmony_ci } 797fd4e5da5Sopenharmony_ci // Test EQ 798fd4e5da5Sopenharmony_ci // Peel before by a factor of 1. 799fd4e5da5Sopenharmony_ci { 800fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv == 0"); 801fd4e5da5Sopenharmony_ci 802fd4e5da5Sopenharmony_ci run_test(spv::Op::OpIEqual, "%38", "%int_0", 803fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); 804fd4e5da5Sopenharmony_ci } 805fd4e5da5Sopenharmony_ci { 806fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 0 == iv"); 807fd4e5da5Sopenharmony_ci 808fd4e5da5Sopenharmony_ci run_test(spv::Op::OpIEqual, "%int_0", "%38", 809fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); 810fd4e5da5Sopenharmony_ci } 811fd4e5da5Sopenharmony_ci 812fd4e5da5Sopenharmony_ci // Peel after by a factor of 1. 813fd4e5da5Sopenharmony_ci { 814fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv == 9"); 815fd4e5da5Sopenharmony_ci 816fd4e5da5Sopenharmony_ci run_test(spv::Op::OpIEqual, "%38", "%int_9", 817fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); 818fd4e5da5Sopenharmony_ci } 819fd4e5da5Sopenharmony_ci { 820fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 9 == iv"); 821fd4e5da5Sopenharmony_ci 822fd4e5da5Sopenharmony_ci run_test(spv::Op::OpIEqual, "%int_9", "%38", 823fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); 824fd4e5da5Sopenharmony_ci } 825fd4e5da5Sopenharmony_ci 826fd4e5da5Sopenharmony_ci // Test NE 827fd4e5da5Sopenharmony_ci // Peel before by a factor of 1. 828fd4e5da5Sopenharmony_ci { 829fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv != 0"); 830fd4e5da5Sopenharmony_ci 831fd4e5da5Sopenharmony_ci run_test(spv::Op::OpINotEqual, "%38", "%int_0", 832fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); 833fd4e5da5Sopenharmony_ci } 834fd4e5da5Sopenharmony_ci { 835fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before 0 != iv"); 836fd4e5da5Sopenharmony_ci 837fd4e5da5Sopenharmony_ci run_test(spv::Op::OpINotEqual, "%int_0", "%38", 838fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); 839fd4e5da5Sopenharmony_ci } 840fd4e5da5Sopenharmony_ci 841fd4e5da5Sopenharmony_ci // Peel after by a factor of 1. 842fd4e5da5Sopenharmony_ci { 843fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv != 9"); 844fd4e5da5Sopenharmony_ci 845fd4e5da5Sopenharmony_ci run_test(spv::Op::OpINotEqual, "%38", "%int_9", 846fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); 847fd4e5da5Sopenharmony_ci } 848fd4e5da5Sopenharmony_ci { 849fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after 9 != iv"); 850fd4e5da5Sopenharmony_ci 851fd4e5da5Sopenharmony_ci run_test(spv::Op::OpINotEqual, "%int_9", "%38", 852fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 1u}}); 853fd4e5da5Sopenharmony_ci } 854fd4e5da5Sopenharmony_ci} 855fd4e5da5Sopenharmony_ci 856fd4e5da5Sopenharmony_ci/* 857fd4e5da5Sopenharmony_ciTest are derivation of the following generated test from the following GLSL + 858fd4e5da5Sopenharmony_ci--eliminate-local-multi-store 859fd4e5da5Sopenharmony_ci 860fd4e5da5Sopenharmony_ci#version 330 core 861fd4e5da5Sopenharmony_civoid main() { 862fd4e5da5Sopenharmony_ci int a = 0; 863fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) { 864fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; j++) { 865fd4e5da5Sopenharmony_ci if (i < 3) { 866fd4e5da5Sopenharmony_ci a += 2; 867fd4e5da5Sopenharmony_ci } 868fd4e5da5Sopenharmony_ci } 869fd4e5da5Sopenharmony_ci } 870fd4e5da5Sopenharmony_ci} 871fd4e5da5Sopenharmony_ci*/ 872fd4e5da5Sopenharmony_ciTEST_F(PeelingPassTest, PeelingNestedPass) { 873fd4e5da5Sopenharmony_ci const std::string text_head = R"( 874fd4e5da5Sopenharmony_ci OpCapability Shader 875fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 876fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 877fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 878fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginLowerLeft 879fd4e5da5Sopenharmony_ci OpSource GLSL 330 880fd4e5da5Sopenharmony_ci OpName %main "main" 881fd4e5da5Sopenharmony_ci OpName %a "a" 882fd4e5da5Sopenharmony_ci OpName %i "i" 883fd4e5da5Sopenharmony_ci OpName %j "j" 884fd4e5da5Sopenharmony_ci %void = OpTypeVoid 885fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 886fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 887fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 888fd4e5da5Sopenharmony_ci %int_0 = OpConstant %int 0 889fd4e5da5Sopenharmony_ci %int_10 = OpConstant %int 10 890fd4e5da5Sopenharmony_ci %bool = OpTypeBool 891fd4e5da5Sopenharmony_ci %int_7 = OpConstant %int 7 892fd4e5da5Sopenharmony_ci %int_3 = OpConstant %int 3 893fd4e5da5Sopenharmony_ci %int_2 = OpConstant %int 2 894fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 895fd4e5da5Sopenharmony_ci %43 = OpUndef %int 896fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 897fd4e5da5Sopenharmony_ci %5 = OpLabel 898fd4e5da5Sopenharmony_ci %a = OpVariable %_ptr_Function_int Function 899fd4e5da5Sopenharmony_ci %i = OpVariable %_ptr_Function_int Function 900fd4e5da5Sopenharmony_ci %j = OpVariable %_ptr_Function_int Function 901fd4e5da5Sopenharmony_ci OpStore %a %int_0 902fd4e5da5Sopenharmony_ci OpStore %i %int_0 903fd4e5da5Sopenharmony_ci OpBranch %11 904fd4e5da5Sopenharmony_ci %11 = OpLabel 905fd4e5da5Sopenharmony_ci %41 = OpPhi %int %int_0 %5 %45 %14 906fd4e5da5Sopenharmony_ci %42 = OpPhi %int %int_0 %5 %40 %14 907fd4e5da5Sopenharmony_ci %44 = OpPhi %int %43 %5 %46 %14 908fd4e5da5Sopenharmony_ci OpLoopMerge %13 %14 None 909fd4e5da5Sopenharmony_ci OpBranch %15 910fd4e5da5Sopenharmony_ci %15 = OpLabel 911fd4e5da5Sopenharmony_ci %19 = OpSLessThan %bool %42 %int_10 912fd4e5da5Sopenharmony_ci OpBranchConditional %19 %12 %13 913fd4e5da5Sopenharmony_ci %12 = OpLabel 914fd4e5da5Sopenharmony_ci OpStore %j %int_0 915fd4e5da5Sopenharmony_ci OpBranch %21 916fd4e5da5Sopenharmony_ci %21 = OpLabel 917fd4e5da5Sopenharmony_ci %45 = OpPhi %int %41 %12 %47 %24 918fd4e5da5Sopenharmony_ci %46 = OpPhi %int %int_0 %12 %38 %24 919fd4e5da5Sopenharmony_ci OpLoopMerge %23 %24 None 920fd4e5da5Sopenharmony_ci OpBranch %25 921fd4e5da5Sopenharmony_ci %25 = OpLabel 922fd4e5da5Sopenharmony_ci %27 = OpSLessThan %bool %46 %int_10 923fd4e5da5Sopenharmony_ci OpBranchConditional %27 %22 %23 924fd4e5da5Sopenharmony_ci %22 = OpLabel 925fd4e5da5Sopenharmony_ci )"; 926fd4e5da5Sopenharmony_ci 927fd4e5da5Sopenharmony_ci const std::string text_tail = R"( 928fd4e5da5Sopenharmony_ci OpSelectionMerge %32 None 929fd4e5da5Sopenharmony_ci OpBranchConditional %30 %31 %32 930fd4e5da5Sopenharmony_ci %31 = OpLabel 931fd4e5da5Sopenharmony_ci %35 = OpIAdd %int %45 %int_2 932fd4e5da5Sopenharmony_ci OpStore %a %35 933fd4e5da5Sopenharmony_ci OpBranch %32 934fd4e5da5Sopenharmony_ci %32 = OpLabel 935fd4e5da5Sopenharmony_ci %47 = OpPhi %int %45 %22 %35 %31 936fd4e5da5Sopenharmony_ci OpBranch %24 937fd4e5da5Sopenharmony_ci %24 = OpLabel 938fd4e5da5Sopenharmony_ci %38 = OpIAdd %int %46 %int_1 939fd4e5da5Sopenharmony_ci OpStore %j %38 940fd4e5da5Sopenharmony_ci OpBranch %21 941fd4e5da5Sopenharmony_ci %23 = OpLabel 942fd4e5da5Sopenharmony_ci OpBranch %14 943fd4e5da5Sopenharmony_ci %14 = OpLabel 944fd4e5da5Sopenharmony_ci %40 = OpIAdd %int %42 %int_1 945fd4e5da5Sopenharmony_ci OpStore %i %40 946fd4e5da5Sopenharmony_ci OpBranch %11 947fd4e5da5Sopenharmony_ci %13 = OpLabel 948fd4e5da5Sopenharmony_ci OpReturn 949fd4e5da5Sopenharmony_ci OpFunctionEnd 950fd4e5da5Sopenharmony_ci )"; 951fd4e5da5Sopenharmony_ci 952fd4e5da5Sopenharmony_ci auto run_test = 953fd4e5da5Sopenharmony_ci [&text_head, &text_tail, this]( 954fd4e5da5Sopenharmony_ci spv::Op opcode, const std::string& op1, const std::string& op2, 955fd4e5da5Sopenharmony_ci const PeelTraceType& expected_peel_trace, size_t nb_of_loops) { 956fd4e5da5Sopenharmony_ci BuildAndCheckTrace(text_head, text_tail, opcode, "%30", op1, op2, 957fd4e5da5Sopenharmony_ci expected_peel_trace, nb_of_loops); 958fd4e5da5Sopenharmony_ci }; 959fd4e5da5Sopenharmony_ci 960fd4e5da5Sopenharmony_ci // Peeling outer before by a factor of 3. 961fd4e5da5Sopenharmony_ci { 962fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv_i < 3"); 963fd4e5da5Sopenharmony_ci 964fd4e5da5Sopenharmony_ci // Expect peel before by a factor of 3 and 4 loops at the end. 965fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%42", "%int_3", 966fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 3u}}, 4); 967fd4e5da5Sopenharmony_ci } 968fd4e5da5Sopenharmony_ci // Peeling outer loop after by a factor of 3. 969fd4e5da5Sopenharmony_ci { 970fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv_i < 7"); 971fd4e5da5Sopenharmony_ci 972fd4e5da5Sopenharmony_ci // Expect peel after by a factor of 3 and 4 loops at the end. 973fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%42", "%int_7", 974fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 3u}}, 4); 975fd4e5da5Sopenharmony_ci } 976fd4e5da5Sopenharmony_ci 977fd4e5da5Sopenharmony_ci // Peeling inner loop before by a factor of 3. 978fd4e5da5Sopenharmony_ci { 979fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel before iv_j < 3"); 980fd4e5da5Sopenharmony_ci 981fd4e5da5Sopenharmony_ci // Expect peel before by a factor of 3 and 3 loops at the end. 982fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%46", "%int_3", 983fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kBefore, 3u}}, 3); 984fd4e5da5Sopenharmony_ci } 985fd4e5da5Sopenharmony_ci // Peeling inner loop after by a factor of 3. 986fd4e5da5Sopenharmony_ci { 987fd4e5da5Sopenharmony_ci SCOPED_TRACE("Peel after iv_j < 7"); 988fd4e5da5Sopenharmony_ci 989fd4e5da5Sopenharmony_ci // Expect peel after by a factor of 3 and 3 loops at the end. 990fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%46", "%int_7", 991fd4e5da5Sopenharmony_ci {{LoopPeelingPass::PeelDirection::kAfter, 3u}}, 3); 992fd4e5da5Sopenharmony_ci } 993fd4e5da5Sopenharmony_ci 994fd4e5da5Sopenharmony_ci // Not unworkable condition. 995fd4e5da5Sopenharmony_ci { 996fd4e5da5Sopenharmony_ci SCOPED_TRACE("No peel"); 997fd4e5da5Sopenharmony_ci 998fd4e5da5Sopenharmony_ci // Expect no peeling and 2 loops at the end. 999fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%46", "%42", {}, 2); 1000fd4e5da5Sopenharmony_ci } 1001fd4e5da5Sopenharmony_ci 1002fd4e5da5Sopenharmony_ci // Could do a peeling of 3, but the goes over the threshold. 1003fd4e5da5Sopenharmony_ci { 1004fd4e5da5Sopenharmony_ci SCOPED_TRACE("Over threshold"); 1005fd4e5da5Sopenharmony_ci 1006fd4e5da5Sopenharmony_ci size_t current_threshold = LoopPeelingPass::GetLoopPeelingThreshold(); 1007fd4e5da5Sopenharmony_ci LoopPeelingPass::SetLoopPeelingThreshold(1u); 1008fd4e5da5Sopenharmony_ci // Expect no peeling and 2 loops at the end. 1009fd4e5da5Sopenharmony_ci run_test(spv::Op::OpSLessThan, "%46", "%int_7", {}, 2); 1010fd4e5da5Sopenharmony_ci LoopPeelingPass::SetLoopPeelingThreshold(current_threshold); 1011fd4e5da5Sopenharmony_ci } 1012fd4e5da5Sopenharmony_ci} 1013fd4e5da5Sopenharmony_ci/* 1014fd4e5da5Sopenharmony_ciTest are derivation of the following generated test from the following GLSL + 1015fd4e5da5Sopenharmony_ci--eliminate-local-multi-store 1016fd4e5da5Sopenharmony_ci 1017fd4e5da5Sopenharmony_ci#version 330 core 1018fd4e5da5Sopenharmony_civoid main() { 1019fd4e5da5Sopenharmony_ci int a = 0; 1020fd4e5da5Sopenharmony_ci for (int i = 0, j = 0; i < 10; j++, i++) { 1021fd4e5da5Sopenharmony_ci if (i < j) { 1022fd4e5da5Sopenharmony_ci a += 2; 1023fd4e5da5Sopenharmony_ci } 1024fd4e5da5Sopenharmony_ci } 1025fd4e5da5Sopenharmony_ci} 1026fd4e5da5Sopenharmony_ci*/ 1027fd4e5da5Sopenharmony_ciTEST_F(PeelingPassTest, PeelingNoChanges) { 1028fd4e5da5Sopenharmony_ci const std::string text = R"( 1029fd4e5da5Sopenharmony_ci OpCapability Shader 1030fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1031fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1032fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 1033fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginLowerLeft 1034fd4e5da5Sopenharmony_ci OpSource GLSL 330 1035fd4e5da5Sopenharmony_ci OpName %main "main" 1036fd4e5da5Sopenharmony_ci OpName %a "a" 1037fd4e5da5Sopenharmony_ci OpName %i "i" 1038fd4e5da5Sopenharmony_ci OpName %j "j" 1039fd4e5da5Sopenharmony_ci %void = OpTypeVoid 1040fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 1041fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 1042fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 1043fd4e5da5Sopenharmony_ci %int_0 = OpConstant %int 0 1044fd4e5da5Sopenharmony_ci %int_10 = OpConstant %int 10 1045fd4e5da5Sopenharmony_ci %bool = OpTypeBool 1046fd4e5da5Sopenharmony_ci %int_2 = OpConstant %int 2 1047fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 1048fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 1049fd4e5da5Sopenharmony_ci %5 = OpLabel 1050fd4e5da5Sopenharmony_ci %a = OpVariable %_ptr_Function_int Function 1051fd4e5da5Sopenharmony_ci %i = OpVariable %_ptr_Function_int Function 1052fd4e5da5Sopenharmony_ci %j = OpVariable %_ptr_Function_int Function 1053fd4e5da5Sopenharmony_ci OpStore %a %int_0 1054fd4e5da5Sopenharmony_ci OpStore %i %int_0 1055fd4e5da5Sopenharmony_ci OpStore %j %int_0 1056fd4e5da5Sopenharmony_ci OpBranch %12 1057fd4e5da5Sopenharmony_ci %12 = OpLabel 1058fd4e5da5Sopenharmony_ci %34 = OpPhi %int %int_0 %5 %37 %15 1059fd4e5da5Sopenharmony_ci %35 = OpPhi %int %int_0 %5 %33 %15 1060fd4e5da5Sopenharmony_ci %36 = OpPhi %int %int_0 %5 %31 %15 1061fd4e5da5Sopenharmony_ci OpLoopMerge %14 %15 None 1062fd4e5da5Sopenharmony_ci OpBranch %16 1063fd4e5da5Sopenharmony_ci %16 = OpLabel 1064fd4e5da5Sopenharmony_ci %20 = OpSLessThan %bool %35 %int_10 1065fd4e5da5Sopenharmony_ci OpBranchConditional %20 %13 %14 1066fd4e5da5Sopenharmony_ci %13 = OpLabel 1067fd4e5da5Sopenharmony_ci %23 = OpSLessThan %bool %35 %36 1068fd4e5da5Sopenharmony_ci OpSelectionMerge %25 None 1069fd4e5da5Sopenharmony_ci OpBranchConditional %23 %24 %25 1070fd4e5da5Sopenharmony_ci %24 = OpLabel 1071fd4e5da5Sopenharmony_ci %28 = OpIAdd %int %34 %int_2 1072fd4e5da5Sopenharmony_ci OpStore %a %28 1073fd4e5da5Sopenharmony_ci OpBranch %25 1074fd4e5da5Sopenharmony_ci %25 = OpLabel 1075fd4e5da5Sopenharmony_ci %37 = OpPhi %int %34 %13 %28 %24 1076fd4e5da5Sopenharmony_ci OpBranch %15 1077fd4e5da5Sopenharmony_ci %15 = OpLabel 1078fd4e5da5Sopenharmony_ci %31 = OpIAdd %int %36 %int_1 1079fd4e5da5Sopenharmony_ci OpStore %j %31 1080fd4e5da5Sopenharmony_ci %33 = OpIAdd %int %35 %int_1 1081fd4e5da5Sopenharmony_ci OpStore %i %33 1082fd4e5da5Sopenharmony_ci OpBranch %12 1083fd4e5da5Sopenharmony_ci %14 = OpLabel 1084fd4e5da5Sopenharmony_ci OpReturn 1085fd4e5da5Sopenharmony_ci OpFunctionEnd 1086fd4e5da5Sopenharmony_ci )"; 1087fd4e5da5Sopenharmony_ci 1088fd4e5da5Sopenharmony_ci { 1089fd4e5da5Sopenharmony_ci auto result = 1090fd4e5da5Sopenharmony_ci SinglePassRunAndDisassemble<LoopPeelingPass>(text, true, false); 1091fd4e5da5Sopenharmony_ci 1092fd4e5da5Sopenharmony_ci EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 1093fd4e5da5Sopenharmony_ci } 1094fd4e5da5Sopenharmony_ci} 1095fd4e5da5Sopenharmony_ci 1096fd4e5da5Sopenharmony_ci} // namespace 1097fd4e5da5Sopenharmony_ci} // namespace opt 1098fd4e5da5Sopenharmony_ci} // namespace spvtools 1099