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