From 92fe420c8a8b8527eb99b9096ad0c29efc696de8 Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Tue, 5 Jul 2022 16:16:50 -0400 Subject: [PATCH] Reduce load size does not work for array with spec const size (#4845) Arrays do not have to have a size that is known at compile time. It could be a spec constant. In these cases, treat the array as if it is arbitrarily long. This commit will treat it like it is an array of size UINT32_MAX. Fixes https://crbug.com/oss-fuzz/47397. --- source/opt/reduce_load_size.cpp | 11 +++++++-- test/opt/reduce_load_size_test.cpp | 39 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/source/opt/reduce_load_size.cpp b/source/opt/reduce_load_size.cpp index e9b808748..56491b2f2 100644 --- a/source/opt/reduce_load_size.cpp +++ b/source/opt/reduce_load_size.cpp @@ -161,8 +161,15 @@ bool ReduceLoadSize::ShouldReplaceExtract(Instruction* inst) { case analysis::Type::kArray: { const analysis::Constant* size_const = const_mgr->FindDeclaredConstant(load_type->AsArray()->LengthId()); - assert(size_const->AsIntConstant()); - total_size = size_const->GetU32(); + + if (size_const) { + assert(size_const->AsIntConstant()); + total_size = size_const->GetU32(); + } else { + // The size is spec constant, so it is unknown at this time. Assume + // it is very large. + total_size = UINT32_MAX; + } } break; case analysis::Type::kStruct: total_size = static_cast( diff --git a/test/opt/reduce_load_size_test.cpp b/test/opt/reduce_load_size_test.cpp index abb5cde67..454675067 100644 --- a/test/opt/reduce_load_size_test.cpp +++ b/test/opt/reduce_load_size_test.cpp @@ -498,6 +498,45 @@ TEST_F(ReduceLoadSizeTest, replace_cbuffer_load_fully_used) { SinglePassRunAndMatch(test, false, 1.1); } +TEST_F(ReduceLoadSizeTest, replace_array_with_spec_constant_size) { + const std::string test = + R"( + OpCapability ClipDistance + OpExtension " " + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %1 " " + OpExecutionMode %1 OriginUpperLeft + %void = OpTypeVoid + %3 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %uint = OpTypeInt 32 0 + %6 = OpSpecConstant %uint 538976288 + %_arr_int_6 = OpTypeArray %int %6 + %_struct_8 = OpTypeStruct %_arr_int_6 + %_struct_9 = OpTypeStruct %_struct_8 +%_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9 +; CHECK: [[var:%\w+]] = OpVariable %_ptr_Uniform__struct_9 Uniform + %11 = OpVariable %_ptr_Uniform__struct_9 Uniform + %int_0 = OpConstant %int 0 +%_ptr_Uniform__arr_int_6 = OpTypePointer Uniform %_arr_int_6 + %1 = OpFunction %void None %3 + %14 = OpLabel +; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Uniform__arr_int_6 [[var]] %int_0 %int_0 +; CHECK: [[new_ac:%\w+]] = OpAccessChain %_ptr_Uniform_int [[ac]] %uint_538976288 +; CHECK: [[ld:%\w+]] = OpLoad %int [[new_ac]] +; CHECK: %18 = OpIAdd %int [[ld]] [[ld]] + %15 = OpAccessChain %_ptr_Uniform__arr_int_6 %11 %int_0 %int_0 + %16 = OpLoad %_arr_int_6 %15 + %17 = OpCompositeExtract %int %16 538976288 + %18 = OpIAdd %int %17 %17 + OpUnreachable + OpFunctionEnd +)"; + + SinglePassRunAndMatch(test, false, + kDefaultLoadReductionThreshold); +} + } // namespace } // namespace opt } // namespace spvtools