spirv-fuzz: Add outlining test (#3164)

Adds a test to check that we do outline code that uses pointer
parameters.
diff --git a/test/fuzz/transformation_outline_function_test.cpp b/test/fuzz/transformation_outline_function_test.cpp
index 91e1733..ff3d913 100644
--- a/test/fuzz/transformation_outline_function_test.cpp
+++ b/test/fuzz/transformation_outline_function_test.cpp
@@ -1714,6 +1714,118 @@
   ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
 }
 
+TEST(TransformationOutlineFunctionTest,
+     DoOutlineRegionThatUsesPointerParameter) {
+  // The region being outlined reads from a function parameter of pointer type.
+  // This is OK: the function parameter can itself be passed on as a function
+  // parameter.
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Function %6
+          %8 = OpTypeFunction %2 %7
+         %13 = OpConstant %6 2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %15 = OpVariable %7 Function
+         %16 = OpVariable %7 Function
+         %17 = OpLoad %6 %15
+               OpStore %16 %17
+         %18 = OpFunctionCall %2 %10 %16
+         %19 = OpLoad %6 %16
+               OpStore %15 %19
+               OpReturn
+               OpFunctionEnd
+         %10 = OpFunction %2 None %8
+          %9 = OpFunctionParameter %7
+         %11 = OpLabel
+         %12 = OpLoad %6 %9
+         %14 = OpIAdd %6 %12 %13
+               OpBranch %20
+         %20 = OpLabel
+               OpStore %9 %14
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_5;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+
+  TransformationOutlineFunction transformation(
+      /*entry_block*/ 11,
+      /*exit_block*/ 11,
+      /*new_function_struct_return_type_id*/ 200,
+      /*new_function_type_id*/ 201,
+      /*new_function_id*/ 202,
+      /*new_function_region_entry_block*/ 204,
+      /*new_caller_result_id*/ 205,
+      /*new_callee_result_id*/ 206,
+      /*input_id_to_fresh_id*/ {{9, 207}},
+      /*output_id_to_fresh_id*/ {{14, 208}});
+
+  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
+  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  std::string after_transformation = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Function %6
+          %8 = OpTypeFunction %2 %7
+         %13 = OpConstant %6 2
+        %200 = OpTypeStruct %6
+        %201 = OpTypeFunction %200 %7
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %15 = OpVariable %7 Function
+         %16 = OpVariable %7 Function
+         %17 = OpLoad %6 %15
+               OpStore %16 %17
+         %18 = OpFunctionCall %2 %10 %16
+         %19 = OpLoad %6 %16
+               OpStore %15 %19
+               OpReturn
+               OpFunctionEnd
+         %10 = OpFunction %2 None %8
+          %9 = OpFunctionParameter %7
+         %11 = OpLabel
+        %205 = OpFunctionCall %200 %202 %9
+         %14 = OpCompositeExtract %6 %205 0
+               OpBranch %20
+         %20 = OpLabel
+               OpStore %9 %14
+               OpReturn
+               OpFunctionEnd
+        %202 = OpFunction %200 None %201
+        %207 = OpFunctionParameter %7
+        %204 = OpLabel
+         %12 = OpLoad %6 %207
+        %208 = OpIAdd %6 %12 %13
+        %206 = OpCompositeConstruct %200 %208
+               OpReturnValue %206
+               OpFunctionEnd
+  )";
+  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
 TEST(TransformationOutlineFunctionTest, Miscellaneous1) {
   // This tests outlining of some non-trivial code.