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.
diff --git a/source/opt/reduce_load_size.cpp b/source/opt/reduce_load_size.cpp
index e9b8087..56491b2 100644
--- a/source/opt/reduce_load_size.cpp
+++ b/source/opt/reduce_load_size.cpp
@@ -161,8 +161,15 @@
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<uint32_t>(
diff --git a/test/opt/reduce_load_size_test.cpp b/test/opt/reduce_load_size_test.cpp
index abb5cde..4546750 100644
--- a/test/opt/reduce_load_size_test.cpp
+++ b/test/opt/reduce_load_size_test.cpp
@@ -498,6 +498,45 @@
SinglePassRunAndMatch<ReduceLoadSize>(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<ReduceLoadSize>(test, false,
+ kDefaultLoadReductionThreshold);
+}
+
} // namespace
} // namespace opt
} // namespace spvtools