SPIRV-Tools/test/fuzz/fuzzer_replayer_test.cpp
Alastair Donaldson fcb22ecf0f
spirv-fuzz: Report fresh ids in transformations (#3856)
Adds a virtual method, GetFreshIds(), to Transformation. Every
transformation uses this to indicate which ids in its protobuf message
are fresh ids. This means that when replaying a sequence of
transformations the replayer can obtain a smallest id that is not in
use by the module already and that will not be used by any
transformation by necessity. Ids greater than or equal to this id
can be used as overflow ids.

Fixes #3851.
2020-09-29 22:12:49 +01:00

1748 lines
59 KiB
C++

// Copyright (c) 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "source/fuzz/fuzzer.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/pseudo_random_generator.h"
#include "source/fuzz/replayer.h"
#include "source/fuzz/uniform_buffer_element_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
const uint32_t kNumFuzzerRuns = 20;
// The SPIR-V came from this GLSL:
//
// #version 310 es
//
// void foo() {
// int x;
// x = 2;
// for (int i = 0; i < 100; i++) {
// x += i;
// x = x * 2;
// }
// return;
// }
//
// void main() {
// foo();
// for (int i = 0; i < 10; i++) {
// int j = 20;
// while(j > 0) {
// foo();
// j--;
// }
// do {
// i++;
// } while(i < 4);
// }
// }
const std::string kTestShader1 = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
OpName %4 "main"
OpName %6 "foo("
OpName %10 "x"
OpName %12 "i"
OpName %33 "i"
OpName %42 "j"
OpDecorate %10 RelaxedPrecision
OpDecorate %12 RelaxedPrecision
OpDecorate %19 RelaxedPrecision
OpDecorate %23 RelaxedPrecision
OpDecorate %24 RelaxedPrecision
OpDecorate %25 RelaxedPrecision
OpDecorate %26 RelaxedPrecision
OpDecorate %27 RelaxedPrecision
OpDecorate %28 RelaxedPrecision
OpDecorate %30 RelaxedPrecision
OpDecorate %33 RelaxedPrecision
OpDecorate %39 RelaxedPrecision
OpDecorate %42 RelaxedPrecision
OpDecorate %49 RelaxedPrecision
OpDecorate %52 RelaxedPrecision
OpDecorate %53 RelaxedPrecision
OpDecorate %58 RelaxedPrecision
OpDecorate %59 RelaxedPrecision
OpDecorate %60 RelaxedPrecision
OpDecorate %63 RelaxedPrecision
OpDecorate %64 RelaxedPrecision
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%8 = OpTypeInt 32 1
%9 = OpTypePointer Function %8
%11 = OpConstant %8 2
%13 = OpConstant %8 0
%20 = OpConstant %8 100
%21 = OpTypeBool
%29 = OpConstant %8 1
%40 = OpConstant %8 10
%43 = OpConstant %8 20
%61 = OpConstant %8 4
%4 = OpFunction %2 None %3
%5 = OpLabel
%33 = OpVariable %9 Function
%42 = OpVariable %9 Function
%32 = OpFunctionCall %2 %6
OpStore %33 %13
OpBranch %34
%34 = OpLabel
OpLoopMerge %36 %37 None
OpBranch %38
%38 = OpLabel
%39 = OpLoad %8 %33
%41 = OpSLessThan %21 %39 %40
OpBranchConditional %41 %35 %36
%35 = OpLabel
OpStore %42 %43
OpBranch %44
%44 = OpLabel
OpLoopMerge %46 %47 None
OpBranch %48
%48 = OpLabel
%49 = OpLoad %8 %42
%50 = OpSGreaterThan %21 %49 %13
OpBranchConditional %50 %45 %46
%45 = OpLabel
%51 = OpFunctionCall %2 %6
%52 = OpLoad %8 %42
%53 = OpISub %8 %52 %29
OpStore %42 %53
OpBranch %47
%47 = OpLabel
OpBranch %44
%46 = OpLabel
OpBranch %54
%54 = OpLabel
OpLoopMerge %56 %57 None
OpBranch %55
%55 = OpLabel
%58 = OpLoad %8 %33
%59 = OpIAdd %8 %58 %29
OpStore %33 %59
OpBranch %57
%57 = OpLabel
%60 = OpLoad %8 %33
%62 = OpSLessThan %21 %60 %61
OpBranchConditional %62 %54 %56
%56 = OpLabel
OpBranch %37
%37 = OpLabel
%63 = OpLoad %8 %33
%64 = OpIAdd %8 %63 %29
OpStore %33 %64
OpBranch %34
%36 = OpLabel
OpReturn
OpFunctionEnd
%6 = OpFunction %2 None %3
%7 = OpLabel
%10 = OpVariable %9 Function
%12 = OpVariable %9 Function
OpStore %10 %11
OpStore %12 %13
OpBranch %14
%14 = OpLabel
OpLoopMerge %16 %17 None
OpBranch %18
%18 = OpLabel
%19 = OpLoad %8 %12
%22 = OpSLessThan %21 %19 %20
OpBranchConditional %22 %15 %16
%15 = OpLabel
%23 = OpLoad %8 %12
%24 = OpLoad %8 %10
%25 = OpIAdd %8 %24 %23
OpStore %10 %25
%26 = OpLoad %8 %10
%27 = OpIMul %8 %26 %11
OpStore %10 %27
OpBranch %17
%17 = OpLabel
%28 = OpLoad %8 %12
%30 = OpIAdd %8 %28 %29
OpStore %12 %30
OpBranch %14
%16 = OpLabel
OpReturn
OpFunctionEnd
)";
// The SPIR-V came from this GLSL, which was then optimized using spirv-opt
// with the -O argument:
//
// #version 310 es
//
// precision highp float;
//
// layout(location = 0) out vec4 _GLF_color;
//
// layout(set = 0, binding = 0) uniform buf0 {
// vec2 injectionSwitch;
// };
// layout(set = 0, binding = 1) uniform buf1 {
// vec2 resolution;
// };
// bool checkSwap(float a, float b)
// {
// return gl_FragCoord.y < resolution.y / 2.0 ? a > b : a < b;
// }
// void main()
// {
// float data[10];
// for(int i = 0; i < 10; i++)
// {
// data[i] = float(10 - i) * injectionSwitch.y;
// }
// for(int i = 0; i < 9; i++)
// {
// for(int j = 0; j < 10; j++)
// {
// if(j < i + 1)
// {
// continue;
// }
// bool doSwap = checkSwap(data[i], data[j]);
// if(doSwap)
// {
// float temp = data[i];
// data[i] = data[j];
// data[j] = temp;
// }
// }
// }
// if(gl_FragCoord.x < resolution.x / 2.0)
// {
// _GLF_color = vec4(data[0] / 10.0, data[5] / 10.0, data[9] / 10.0, 1.0);
// }
// else
// {
// _GLF_color = vec4(data[5] / 10.0, data[9] / 10.0, data[0] / 10.0, 1.0);
// }
// }
const std::string kTestShader2 = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main" %16 %139 %25 %68
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
OpName %4 "main"
OpName %16 "gl_FragCoord"
OpName %23 "buf1"
OpMemberName %23 0 "resolution"
OpName %25 ""
OpName %61 "data"
OpName %66 "buf0"
OpMemberName %66 0 "injectionSwitch"
OpName %68 ""
OpName %139 "_GLF_color"
OpDecorate %16 BuiltIn FragCoord
OpMemberDecorate %23 0 Offset 0
OpDecorate %23 Block
OpDecorate %25 DescriptorSet 0
OpDecorate %25 Binding 1
OpDecorate %64 RelaxedPrecision
OpMemberDecorate %66 0 Offset 0
OpDecorate %66 Block
OpDecorate %68 DescriptorSet 0
OpDecorate %68 Binding 0
OpDecorate %75 RelaxedPrecision
OpDecorate %95 RelaxedPrecision
OpDecorate %126 RelaxedPrecision
OpDecorate %128 RelaxedPrecision
OpDecorate %139 Location 0
OpDecorate %182 RelaxedPrecision
OpDecorate %183 RelaxedPrecision
OpDecorate %184 RelaxedPrecision
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypePointer Function %6
%8 = OpTypeBool
%14 = OpTypeVector %6 4
%15 = OpTypePointer Input %14
%16 = OpVariable %15 Input
%17 = OpTypeInt 32 0
%18 = OpConstant %17 1
%19 = OpTypePointer Input %6
%22 = OpTypeVector %6 2
%23 = OpTypeStruct %22
%24 = OpTypePointer Uniform %23
%25 = OpVariable %24 Uniform
%26 = OpTypeInt 32 1
%27 = OpConstant %26 0
%28 = OpTypePointer Uniform %6
%56 = OpConstant %26 10
%58 = OpConstant %17 10
%59 = OpTypeArray %6 %58
%60 = OpTypePointer Function %59
%66 = OpTypeStruct %22
%67 = OpTypePointer Uniform %66
%68 = OpVariable %67 Uniform
%74 = OpConstant %26 1
%83 = OpConstant %26 9
%129 = OpConstant %17 0
%138 = OpTypePointer Output %14
%139 = OpVariable %138 Output
%144 = OpConstant %26 5
%151 = OpConstant %6 1
%194 = OpConstant %6 0.5
%195 = OpConstant %6 0.100000001
%4 = OpFunction %2 None %3
%5 = OpLabel
%61 = OpVariable %60 Function
OpBranch %50
%50 = OpLabel
%182 = OpPhi %26 %27 %5 %75 %51
%57 = OpSLessThan %8 %182 %56
OpLoopMerge %52 %51 None
OpBranchConditional %57 %51 %52
%51 = OpLabel
%64 = OpISub %26 %56 %182
%65 = OpConvertSToF %6 %64
%69 = OpAccessChain %28 %68 %27 %18
%70 = OpLoad %6 %69
%71 = OpFMul %6 %65 %70
%72 = OpAccessChain %7 %61 %182
OpStore %72 %71
%75 = OpIAdd %26 %182 %74
OpBranch %50
%52 = OpLabel
OpBranch %77
%77 = OpLabel
%183 = OpPhi %26 %27 %52 %128 %88
%84 = OpSLessThan %8 %183 %83
OpLoopMerge %79 %88 None
OpBranchConditional %84 %78 %79
%78 = OpLabel
OpBranch %86
%86 = OpLabel
%184 = OpPhi %26 %27 %78 %126 %89
%92 = OpSLessThan %8 %184 %56
OpLoopMerge %1000 %89 None
OpBranchConditional %92 %87 %1000
%87 = OpLabel
%95 = OpIAdd %26 %183 %74
%96 = OpSLessThan %8 %184 %95
OpSelectionMerge %98 None
OpBranchConditional %96 %97 %98
%97 = OpLabel
OpBranch %89
%98 = OpLabel
%104 = OpAccessChain %7 %61 %183
%105 = OpLoad %6 %104
%107 = OpAccessChain %7 %61 %184
%108 = OpLoad %6 %107
%166 = OpAccessChain %19 %16 %18
%167 = OpLoad %6 %166
%168 = OpAccessChain %28 %25 %27 %18
%169 = OpLoad %6 %168
%170 = OpFMul %6 %169 %194
%171 = OpFOrdLessThan %8 %167 %170
OpSelectionMerge %172 None
OpBranchConditional %171 %173 %174
%173 = OpLabel
%177 = OpFOrdGreaterThan %8 %105 %108
OpBranch %172
%174 = OpLabel
%180 = OpFOrdLessThan %8 %105 %108
OpBranch %172
%172 = OpLabel
%186 = OpPhi %8 %177 %173 %180 %174
OpSelectionMerge %112 None
OpBranchConditional %186 %111 %112
%111 = OpLabel
%116 = OpLoad %6 %104
%120 = OpLoad %6 %107
OpStore %104 %120
OpStore %107 %116
OpBranch %112
%112 = OpLabel
OpBranch %89
%89 = OpLabel
%126 = OpIAdd %26 %184 %74
OpBranch %86
%1000 = OpLabel
OpBranch %88
%88 = OpLabel
%128 = OpIAdd %26 %183 %74
OpBranch %77
%79 = OpLabel
%130 = OpAccessChain %19 %16 %129
%131 = OpLoad %6 %130
%132 = OpAccessChain %28 %25 %27 %129
%133 = OpLoad %6 %132
%134 = OpFMul %6 %133 %194
%135 = OpFOrdLessThan %8 %131 %134
OpSelectionMerge %137 None
OpBranchConditional %135 %136 %153
%136 = OpLabel
%140 = OpAccessChain %7 %61 %27
%141 = OpLoad %6 %140
%143 = OpFMul %6 %141 %195
%145 = OpAccessChain %7 %61 %144
%146 = OpLoad %6 %145
%147 = OpFMul %6 %146 %195
%148 = OpAccessChain %7 %61 %83
%149 = OpLoad %6 %148
%150 = OpFMul %6 %149 %195
%152 = OpCompositeConstruct %14 %143 %147 %150 %151
OpStore %139 %152
OpBranch %137
%153 = OpLabel
%154 = OpAccessChain %7 %61 %144
%155 = OpLoad %6 %154
%156 = OpFMul %6 %155 %195
%157 = OpAccessChain %7 %61 %83
%158 = OpLoad %6 %157
%159 = OpFMul %6 %158 %195
%160 = OpAccessChain %7 %61 %27
%161 = OpLoad %6 %160
%162 = OpFMul %6 %161 %195
%163 = OpCompositeConstruct %14 %156 %159 %162 %151
OpStore %139 %163
OpBranch %137
%137 = OpLabel
OpReturn
OpFunctionEnd
)";
// The SPIR-V came from this GLSL, which was then optimized using spirv-opt
// with the -O argument:
//
// #version 310 es
//
// precision highp float;
//
// layout(location = 0) out vec4 _GLF_color;
//
// layout(set = 0, binding = 0) uniform buf0 {
// vec2 resolution;
// };
// void main(void)
// {
// float A[50];
// for(
// int i = 0;
// i < 200;
// i ++
// )
// {
// if(i >= int(resolution.x))
// {
// break;
// }
// if((4 * (i / 4)) == i)
// {
// A[i / 4] = float(i);
// }
// }
// for(
// int i = 0;
// i < 50;
// i ++
// )
// {
// if(i < int(gl_FragCoord.x))
// {
// break;
// }
// if(i > 0)
// {
// A[i] += A[i - 1];
// }
// }
// if(int(gl_FragCoord.x) < 20)
// {
// _GLF_color = vec4(A[0] / resolution.x, A[4] / resolution.y, 1.0, 1.0);
// }
// else
// if(int(gl_FragCoord.x) < 40)
// {
// _GLF_color = vec4(A[5] / resolution.x, A[9] / resolution.y, 1.0, 1.0);
// }
// else
// if(int(gl_FragCoord.x) < 60)
// {
// _GLF_color = vec4(A[10] / resolution.x, A[14] / resolution.y,
// 1.0, 1.0);
// }
// else
// if(int(gl_FragCoord.x) < 80)
// {
// _GLF_color = vec4(A[15] / resolution.x, A[19] / resolution.y,
// 1.0, 1.0);
// }
// else
// if(int(gl_FragCoord.x) < 100)
// {
// _GLF_color = vec4(A[20] / resolution.x, A[24] / resolution.y,
// 1.0, 1.0);
// }
// else
// if(int(gl_FragCoord.x) < 120)
// {
// _GLF_color = vec4(A[25] / resolution.x, A[29] / resolution.y,
// 1.0, 1.0);
// }
// else
// if(int(gl_FragCoord.x) < 140)
// {
// _GLF_color = vec4(A[30] / resolution.x, A[34] / resolution.y,
// 1.0, 1.0);
// }
// else
// if(int(gl_FragCoord.x) < 160)
// {
// _GLF_color = vec4(A[35] / resolution.x, A[39] /
// resolution.y, 1.0, 1.0);
// }
// else
// if(int(gl_FragCoord.x) < 180)
// {
// _GLF_color = vec4(A[40] / resolution.x, A[44] /
// resolution.y, 1.0, 1.0);
// }
// else
// if(int(gl_FragCoord.x) < 180)
// {
// _GLF_color = vec4(A[45] / resolution.x, A[49] /
// resolution.y, 1.0, 1.0);
// }
// else
// {
// discard;
// }
// }
const std::string kTestShader3 = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main" %68 %100 %24
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
OpName %4 "main"
OpName %22 "buf0"
OpMemberName %22 0 "resolution"
OpName %24 ""
OpName %46 "A"
OpName %68 "gl_FragCoord"
OpName %100 "_GLF_color"
OpMemberDecorate %22 0 Offset 0
OpDecorate %22 Block
OpDecorate %24 DescriptorSet 0
OpDecorate %24 Binding 0
OpDecorate %37 RelaxedPrecision
OpDecorate %38 RelaxedPrecision
OpDecorate %55 RelaxedPrecision
OpDecorate %68 BuiltIn FragCoord
OpDecorate %83 RelaxedPrecision
OpDecorate %91 RelaxedPrecision
OpDecorate %100 Location 0
OpDecorate %302 RelaxedPrecision
OpDecorate %304 RelaxedPrecision
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%9 = OpConstant %6 0
%16 = OpConstant %6 200
%17 = OpTypeBool
%20 = OpTypeFloat 32
%21 = OpTypeVector %20 2
%22 = OpTypeStruct %21
%23 = OpTypePointer Uniform %22
%24 = OpVariable %23 Uniform
%25 = OpTypeInt 32 0
%26 = OpConstant %25 0
%27 = OpTypePointer Uniform %20
%35 = OpConstant %6 4
%43 = OpConstant %25 50
%44 = OpTypeArray %20 %43
%45 = OpTypePointer Function %44
%51 = OpTypePointer Function %20
%54 = OpConstant %6 1
%63 = OpConstant %6 50
%66 = OpTypeVector %20 4
%67 = OpTypePointer Input %66
%68 = OpVariable %67 Input
%69 = OpTypePointer Input %20
%95 = OpConstant %6 20
%99 = OpTypePointer Output %66
%100 = OpVariable %99 Output
%108 = OpConstant %25 1
%112 = OpConstant %20 1
%118 = OpConstant %6 40
%122 = OpConstant %6 5
%128 = OpConstant %6 9
%139 = OpConstant %6 60
%143 = OpConstant %6 10
%149 = OpConstant %6 14
%160 = OpConstant %6 80
%164 = OpConstant %6 15
%170 = OpConstant %6 19
%181 = OpConstant %6 100
%190 = OpConstant %6 24
%201 = OpConstant %6 120
%205 = OpConstant %6 25
%211 = OpConstant %6 29
%222 = OpConstant %6 140
%226 = OpConstant %6 30
%232 = OpConstant %6 34
%243 = OpConstant %6 160
%247 = OpConstant %6 35
%253 = OpConstant %6 39
%264 = OpConstant %6 180
%273 = OpConstant %6 44
%287 = OpConstant %6 45
%293 = OpConstant %6 49
%4 = OpFunction %2 None %3
%5 = OpLabel
%46 = OpVariable %45 Function
OpBranch %10
%10 = OpLabel
%302 = OpPhi %6 %9 %5 %55 %42
%18 = OpSLessThan %17 %302 %16
OpLoopMerge %12 %42 None
OpBranchConditional %18 %11 %12
%11 = OpLabel
%28 = OpAccessChain %27 %24 %9 %26
%29 = OpLoad %20 %28
%30 = OpConvertFToS %6 %29
%31 = OpSGreaterThanEqual %17 %302 %30
OpSelectionMerge %33 None
OpBranchConditional %31 %32 %33
%32 = OpLabel
OpBranch %12
%33 = OpLabel
%37 = OpSDiv %6 %302 %35
%38 = OpIMul %6 %35 %37
%40 = OpIEqual %17 %38 %302
OpBranchConditional %40 %41 %42
%41 = OpLabel
%50 = OpConvertSToF %20 %302
%52 = OpAccessChain %51 %46 %37
OpStore %52 %50
OpBranch %42
%42 = OpLabel
%55 = OpIAdd %6 %302 %54
OpBranch %10
%12 = OpLabel
OpBranch %57
%57 = OpLabel
%304 = OpPhi %6 %9 %12 %91 %80
%64 = OpSLessThan %17 %304 %63
OpLoopMerge %59 %80 None
OpBranchConditional %64 %58 %59
%58 = OpLabel
%70 = OpAccessChain %69 %68 %26
%71 = OpLoad %20 %70
%72 = OpConvertFToS %6 %71
%73 = OpSLessThan %17 %304 %72
OpSelectionMerge %75 None
OpBranchConditional %73 %74 %75
%74 = OpLabel
OpBranch %59
%75 = OpLabel
%78 = OpSGreaterThan %17 %304 %9
OpBranchConditional %78 %79 %80
%79 = OpLabel
%83 = OpISub %6 %304 %54
%84 = OpAccessChain %51 %46 %83
%85 = OpLoad %20 %84
%86 = OpAccessChain %51 %46 %304
%87 = OpLoad %20 %86
%88 = OpFAdd %20 %87 %85
OpStore %86 %88
OpBranch %80
%80 = OpLabel
%91 = OpIAdd %6 %304 %54
OpBranch %57
%59 = OpLabel
%92 = OpAccessChain %69 %68 %26
%93 = OpLoad %20 %92
%94 = OpConvertFToS %6 %93
%96 = OpSLessThan %17 %94 %95
OpSelectionMerge %98 None
OpBranchConditional %96 %97 %114
%97 = OpLabel
%101 = OpAccessChain %51 %46 %9
%102 = OpLoad %20 %101
%103 = OpAccessChain %27 %24 %9 %26
%104 = OpLoad %20 %103
%105 = OpFDiv %20 %102 %104
%106 = OpAccessChain %51 %46 %35
%107 = OpLoad %20 %106
%109 = OpAccessChain %27 %24 %9 %108
%110 = OpLoad %20 %109
%111 = OpFDiv %20 %107 %110
%113 = OpCompositeConstruct %66 %105 %111 %112 %112
OpStore %100 %113
OpBranch %98
%114 = OpLabel
%119 = OpSLessThan %17 %94 %118
OpSelectionMerge %121 None
OpBranchConditional %119 %120 %135
%120 = OpLabel
%123 = OpAccessChain %51 %46 %122
%124 = OpLoad %20 %123
%125 = OpAccessChain %27 %24 %9 %26
%126 = OpLoad %20 %125
%127 = OpFDiv %20 %124 %126
%129 = OpAccessChain %51 %46 %128
%130 = OpLoad %20 %129
%131 = OpAccessChain %27 %24 %9 %108
%132 = OpLoad %20 %131
%133 = OpFDiv %20 %130 %132
%134 = OpCompositeConstruct %66 %127 %133 %112 %112
OpStore %100 %134
OpBranch %121
%135 = OpLabel
%140 = OpSLessThan %17 %94 %139
OpSelectionMerge %142 None
OpBranchConditional %140 %141 %156
%141 = OpLabel
%144 = OpAccessChain %51 %46 %143
%145 = OpLoad %20 %144
%146 = OpAccessChain %27 %24 %9 %26
%147 = OpLoad %20 %146
%148 = OpFDiv %20 %145 %147
%150 = OpAccessChain %51 %46 %149
%151 = OpLoad %20 %150
%152 = OpAccessChain %27 %24 %9 %108
%153 = OpLoad %20 %152
%154 = OpFDiv %20 %151 %153
%155 = OpCompositeConstruct %66 %148 %154 %112 %112
OpStore %100 %155
OpBranch %142
%156 = OpLabel
%161 = OpSLessThan %17 %94 %160
OpSelectionMerge %163 None
OpBranchConditional %161 %162 %177
%162 = OpLabel
%165 = OpAccessChain %51 %46 %164
%166 = OpLoad %20 %165
%167 = OpAccessChain %27 %24 %9 %26
%168 = OpLoad %20 %167
%169 = OpFDiv %20 %166 %168
%171 = OpAccessChain %51 %46 %170
%172 = OpLoad %20 %171
%173 = OpAccessChain %27 %24 %9 %108
%174 = OpLoad %20 %173
%175 = OpFDiv %20 %172 %174
%176 = OpCompositeConstruct %66 %169 %175 %112 %112
OpStore %100 %176
OpBranch %163
%177 = OpLabel
%182 = OpSLessThan %17 %94 %181
OpSelectionMerge %184 None
OpBranchConditional %182 %183 %197
%183 = OpLabel
%185 = OpAccessChain %51 %46 %95
%186 = OpLoad %20 %185
%187 = OpAccessChain %27 %24 %9 %26
%188 = OpLoad %20 %187
%189 = OpFDiv %20 %186 %188
%191 = OpAccessChain %51 %46 %190
%192 = OpLoad %20 %191
%193 = OpAccessChain %27 %24 %9 %108
%194 = OpLoad %20 %193
%195 = OpFDiv %20 %192 %194
%196 = OpCompositeConstruct %66 %189 %195 %112 %112
OpStore %100 %196
OpBranch %184
%197 = OpLabel
%202 = OpSLessThan %17 %94 %201
OpSelectionMerge %204 None
OpBranchConditional %202 %203 %218
%203 = OpLabel
%206 = OpAccessChain %51 %46 %205
%207 = OpLoad %20 %206
%208 = OpAccessChain %27 %24 %9 %26
%209 = OpLoad %20 %208
%210 = OpFDiv %20 %207 %209
%212 = OpAccessChain %51 %46 %211
%213 = OpLoad %20 %212
%214 = OpAccessChain %27 %24 %9 %108
%215 = OpLoad %20 %214
%216 = OpFDiv %20 %213 %215
%217 = OpCompositeConstruct %66 %210 %216 %112 %112
OpStore %100 %217
OpBranch %204
%218 = OpLabel
%223 = OpSLessThan %17 %94 %222
OpSelectionMerge %225 None
OpBranchConditional %223 %224 %239
%224 = OpLabel
%227 = OpAccessChain %51 %46 %226
%228 = OpLoad %20 %227
%229 = OpAccessChain %27 %24 %9 %26
%230 = OpLoad %20 %229
%231 = OpFDiv %20 %228 %230
%233 = OpAccessChain %51 %46 %232
%234 = OpLoad %20 %233
%235 = OpAccessChain %27 %24 %9 %108
%236 = OpLoad %20 %235
%237 = OpFDiv %20 %234 %236
%238 = OpCompositeConstruct %66 %231 %237 %112 %112
OpStore %100 %238
OpBranch %225
%239 = OpLabel
%244 = OpSLessThan %17 %94 %243
OpSelectionMerge %246 None
OpBranchConditional %244 %245 %260
%245 = OpLabel
%248 = OpAccessChain %51 %46 %247
%249 = OpLoad %20 %248
%250 = OpAccessChain %27 %24 %9 %26
%251 = OpLoad %20 %250
%252 = OpFDiv %20 %249 %251
%254 = OpAccessChain %51 %46 %253
%255 = OpLoad %20 %254
%256 = OpAccessChain %27 %24 %9 %108
%257 = OpLoad %20 %256
%258 = OpFDiv %20 %255 %257
%259 = OpCompositeConstruct %66 %252 %258 %112 %112
OpStore %100 %259
OpBranch %246
%260 = OpLabel
%265 = OpSLessThan %17 %94 %264
OpSelectionMerge %267 None
OpBranchConditional %265 %266 %280
%266 = OpLabel
%268 = OpAccessChain %51 %46 %118
%269 = OpLoad %20 %268
%270 = OpAccessChain %27 %24 %9 %26
%271 = OpLoad %20 %270
%272 = OpFDiv %20 %269 %271
%274 = OpAccessChain %51 %46 %273
%275 = OpLoad %20 %274
%276 = OpAccessChain %27 %24 %9 %108
%277 = OpLoad %20 %276
%278 = OpFDiv %20 %275 %277
%279 = OpCompositeConstruct %66 %272 %278 %112 %112
OpStore %100 %279
OpBranch %267
%280 = OpLabel
OpSelectionMerge %285 None
OpBranchConditional %265 %285 %300
%285 = OpLabel
%288 = OpAccessChain %51 %46 %287
%289 = OpLoad %20 %288
%290 = OpAccessChain %27 %24 %9 %26
%291 = OpLoad %20 %290
%292 = OpFDiv %20 %289 %291
%294 = OpAccessChain %51 %46 %293
%295 = OpLoad %20 %294
%296 = OpAccessChain %27 %24 %9 %108
%297 = OpLoad %20 %296
%298 = OpFDiv %20 %295 %297
%299 = OpCompositeConstruct %66 %292 %298 %112 %112
OpStore %100 %299
OpBranch %267
%300 = OpLabel
OpKill
%267 = OpLabel
OpBranch %246
%246 = OpLabel
OpBranch %225
%225 = OpLabel
OpBranch %204
%204 = OpLabel
OpBranch %184
%184 = OpLabel
OpBranch %163
%163 = OpLabel
OpBranch %142
%142 = OpLabel
OpBranch %121
%121 = OpLabel
OpBranch %98
%98 = OpLabel
OpReturn
OpFunctionEnd
)";
// The SPIR-V comes from the 'matrices_smart_loops' GLSL shader that ships
// with GraphicsFuzz.
const std::string kTestShader4 = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main" %327 %363 %65 %70 %80 %90 %99 %108 %117 %126 %135 %144 %333
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
OpName %4 "main"
OpName %8 "matrix_number"
OpName %12 "cols"
OpName %23 "rows"
OpName %31 "c"
OpName %41 "r"
OpName %65 "m22"
OpName %68 "buf0"
OpMemberName %68 0 "one"
OpName %70 ""
OpName %80 "m23"
OpName %90 "m24"
OpName %99 "m32"
OpName %108 "m33"
OpName %117 "m34"
OpName %126 "m42"
OpName %135 "m43"
OpName %144 "m44"
OpName %164 "sum_index"
OpName %165 "cols"
OpName %173 "rows"
OpName %184 "sums"
OpName %189 "c"
OpName %198 "r"
OpName %325 "region_x"
OpName %327 "gl_FragCoord"
OpName %331 "buf1"
OpMemberName %331 0 "resolution"
OpName %333 ""
OpName %340 "region_y"
OpName %348 "overall_region"
OpName %363 "_GLF_color"
OpDecorate %8 RelaxedPrecision
OpDecorate %12 RelaxedPrecision
OpDecorate %19 RelaxedPrecision
OpDecorate %23 RelaxedPrecision
OpDecorate %29 RelaxedPrecision
OpDecorate %31 RelaxedPrecision
OpDecorate %38 RelaxedPrecision
OpDecorate %39 RelaxedPrecision
OpDecorate %41 RelaxedPrecision
OpDecorate %47 RelaxedPrecision
OpDecorate %48 RelaxedPrecision
OpDecorate %50 RelaxedPrecision
OpDecorate %66 RelaxedPrecision
OpDecorate %67 RelaxedPrecision
OpMemberDecorate %68 0 Offset 0
OpDecorate %68 Block
OpDecorate %70 DescriptorSet 0
OpDecorate %70 Binding 0
OpDecorate %81 RelaxedPrecision
OpDecorate %82 RelaxedPrecision
OpDecorate %91 RelaxedPrecision
OpDecorate %92 RelaxedPrecision
OpDecorate %100 RelaxedPrecision
OpDecorate %101 RelaxedPrecision
OpDecorate %109 RelaxedPrecision
OpDecorate %110 RelaxedPrecision
OpDecorate %118 RelaxedPrecision
OpDecorate %119 RelaxedPrecision
OpDecorate %127 RelaxedPrecision
OpDecorate %128 RelaxedPrecision
OpDecorate %136 RelaxedPrecision
OpDecorate %137 RelaxedPrecision
OpDecorate %145 RelaxedPrecision
OpDecorate %146 RelaxedPrecision
OpDecorate %152 RelaxedPrecision
OpDecorate %154 RelaxedPrecision
OpDecorate %155 RelaxedPrecision
OpDecorate %156 RelaxedPrecision
OpDecorate %157 RelaxedPrecision
OpDecorate %159 RelaxedPrecision
OpDecorate %160 RelaxedPrecision
OpDecorate %161 RelaxedPrecision
OpDecorate %162 RelaxedPrecision
OpDecorate %163 RelaxedPrecision
OpDecorate %164 RelaxedPrecision
OpDecorate %165 RelaxedPrecision
OpDecorate %171 RelaxedPrecision
OpDecorate %173 RelaxedPrecision
OpDecorate %179 RelaxedPrecision
OpDecorate %185 RelaxedPrecision
OpDecorate %189 RelaxedPrecision
OpDecorate %195 RelaxedPrecision
OpDecorate %196 RelaxedPrecision
OpDecorate %198 RelaxedPrecision
OpDecorate %204 RelaxedPrecision
OpDecorate %205 RelaxedPrecision
OpDecorate %207 RelaxedPrecision
OpDecorate %218 RelaxedPrecision
OpDecorate %219 RelaxedPrecision
OpDecorate %220 RelaxedPrecision
OpDecorate %228 RelaxedPrecision
OpDecorate %229 RelaxedPrecision
OpDecorate %230 RelaxedPrecision
OpDecorate %238 RelaxedPrecision
OpDecorate %239 RelaxedPrecision
OpDecorate %240 RelaxedPrecision
OpDecorate %248 RelaxedPrecision
OpDecorate %249 RelaxedPrecision
OpDecorate %250 RelaxedPrecision
OpDecorate %258 RelaxedPrecision
OpDecorate %259 RelaxedPrecision
OpDecorate %260 RelaxedPrecision
OpDecorate %268 RelaxedPrecision
OpDecorate %269 RelaxedPrecision
OpDecorate %270 RelaxedPrecision
OpDecorate %278 RelaxedPrecision
OpDecorate %279 RelaxedPrecision
OpDecorate %280 RelaxedPrecision
OpDecorate %288 RelaxedPrecision
OpDecorate %289 RelaxedPrecision
OpDecorate %290 RelaxedPrecision
OpDecorate %298 RelaxedPrecision
OpDecorate %299 RelaxedPrecision
OpDecorate %300 RelaxedPrecision
OpDecorate %309 RelaxedPrecision
OpDecorate %310 RelaxedPrecision
OpDecorate %311 RelaxedPrecision
OpDecorate %312 RelaxedPrecision
OpDecorate %313 RelaxedPrecision
OpDecorate %319 RelaxedPrecision
OpDecorate %320 RelaxedPrecision
OpDecorate %321 RelaxedPrecision
OpDecorate %322 RelaxedPrecision
OpDecorate %323 RelaxedPrecision
OpDecorate %324 RelaxedPrecision
OpDecorate %325 RelaxedPrecision
OpDecorate %327 BuiltIn FragCoord
OpMemberDecorate %331 0 Offset 0
OpDecorate %331 Block
OpDecorate %333 DescriptorSet 0
OpDecorate %333 Binding 1
OpDecorate %339 RelaxedPrecision
OpDecorate %340 RelaxedPrecision
OpDecorate %347 RelaxedPrecision
OpDecorate %348 RelaxedPrecision
OpDecorate %349 RelaxedPrecision
OpDecorate %351 RelaxedPrecision
OpDecorate %352 RelaxedPrecision
OpDecorate %353 RelaxedPrecision
OpDecorate %354 RelaxedPrecision
OpDecorate %356 RelaxedPrecision
OpDecorate %363 Location 0
OpDecorate %364 RelaxedPrecision
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 0
%7 = OpTypePointer Function %6
%9 = OpConstant %6 0
%10 = OpTypeInt 32 1
%11 = OpTypePointer Function %10
%13 = OpConstant %10 2
%20 = OpConstant %10 4
%21 = OpTypeBool
%32 = OpConstant %10 0
%61 = OpTypeFloat 32
%62 = OpTypeVector %61 2
%63 = OpTypeMatrix %62 2
%64 = OpTypePointer Private %63
%65 = OpVariable %64 Private
%68 = OpTypeStruct %61
%69 = OpTypePointer Uniform %68
%70 = OpVariable %69 Uniform
%71 = OpTypePointer Uniform %61
%74 = OpTypePointer Private %61
%77 = OpTypeVector %61 3
%78 = OpTypeMatrix %77 2
%79 = OpTypePointer Private %78
%80 = OpVariable %79 Private
%87 = OpTypeVector %61 4
%88 = OpTypeMatrix %87 2
%89 = OpTypePointer Private %88
%90 = OpVariable %89 Private
%97 = OpTypeMatrix %62 3
%98 = OpTypePointer Private %97
%99 = OpVariable %98 Private
%106 = OpTypeMatrix %77 3
%107 = OpTypePointer Private %106
%108 = OpVariable %107 Private
%115 = OpTypeMatrix %87 3
%116 = OpTypePointer Private %115
%117 = OpVariable %116 Private
%124 = OpTypeMatrix %62 4
%125 = OpTypePointer Private %124
%126 = OpVariable %125 Private
%133 = OpTypeMatrix %77 4
%134 = OpTypePointer Private %133
%135 = OpVariable %134 Private
%142 = OpTypeMatrix %87 4
%143 = OpTypePointer Private %142
%144 = OpVariable %143 Private
%153 = OpConstant %10 1
%158 = OpConstant %6 1
%181 = OpConstant %6 9
%182 = OpTypeArray %61 %181
%183 = OpTypePointer Function %182
%186 = OpConstant %61 0
%187 = OpTypePointer Function %61
%314 = OpConstant %61 16
%326 = OpTypePointer Input %87
%327 = OpVariable %326 Input
%328 = OpTypePointer Input %61
%331 = OpTypeStruct %62
%332 = OpTypePointer Uniform %331
%333 = OpVariable %332 Uniform
%336 = OpConstant %61 3
%350 = OpConstant %10 3
%357 = OpConstant %10 9
%362 = OpTypePointer Output %87
%363 = OpVariable %362 Output
%368 = OpConstant %61 1
%374 = OpConstantComposite %87 %186 %186 %186 %368
%4 = OpFunction %2 None %3
%5 = OpLabel
%8 = OpVariable %7 Function
%12 = OpVariable %11 Function
%23 = OpVariable %11 Function
%31 = OpVariable %11 Function
%41 = OpVariable %11 Function
%164 = OpVariable %11 Function
%165 = OpVariable %11 Function
%173 = OpVariable %11 Function
%184 = OpVariable %183 Function
%189 = OpVariable %11 Function
%198 = OpVariable %11 Function
%325 = OpVariable %11 Function
%340 = OpVariable %11 Function
%348 = OpVariable %11 Function
OpStore %8 %9
OpStore %12 %13
OpBranch %14
%14 = OpLabel
OpLoopMerge %16 %17 None
OpBranch %18
%18 = OpLabel
%19 = OpLoad %10 %12
%22 = OpSLessThanEqual %21 %19 %20
OpBranchConditional %22 %15 %16
%15 = OpLabel
OpStore %23 %13
OpBranch %24
%24 = OpLabel
OpLoopMerge %26 %27 None
OpBranch %28
%28 = OpLabel
%29 = OpLoad %10 %23
%30 = OpSLessThanEqual %21 %29 %20
OpBranchConditional %30 %25 %26
%25 = OpLabel
OpStore %31 %32
OpBranch %33
%33 = OpLabel
OpLoopMerge %35 %36 None
OpBranch %37
%37 = OpLabel
%38 = OpLoad %10 %31
%39 = OpLoad %10 %12
%40 = OpSLessThan %21 %38 %39
OpBranchConditional %40 %34 %35
%34 = OpLabel
OpStore %41 %32
OpBranch %42
%42 = OpLabel
OpLoopMerge %44 %45 None
OpBranch %46
%46 = OpLabel
%47 = OpLoad %10 %41
%48 = OpLoad %10 %23
%49 = OpSLessThan %21 %47 %48
OpBranchConditional %49 %43 %44
%43 = OpLabel
%50 = OpLoad %6 %8
OpSelectionMerge %60 None
OpSwitch %50 %60 0 %51 1 %52 2 %53 3 %54 4 %55 5 %56 6 %57 7 %58 8 %59
%51 = OpLabel
%66 = OpLoad %10 %31
%67 = OpLoad %10 %41
%72 = OpAccessChain %71 %70 %32
%73 = OpLoad %61 %72
%75 = OpAccessChain %74 %65 %66 %67
OpStore %75 %73
OpBranch %60
%52 = OpLabel
%81 = OpLoad %10 %31
%82 = OpLoad %10 %41
%83 = OpAccessChain %71 %70 %32
%84 = OpLoad %61 %83
%85 = OpAccessChain %74 %80 %81 %82
OpStore %85 %84
OpBranch %60
%53 = OpLabel
%91 = OpLoad %10 %31
%92 = OpLoad %10 %41
%93 = OpAccessChain %71 %70 %32
%94 = OpLoad %61 %93
%95 = OpAccessChain %74 %90 %91 %92
OpStore %95 %94
OpBranch %60
%54 = OpLabel
%100 = OpLoad %10 %31
%101 = OpLoad %10 %41
%102 = OpAccessChain %71 %70 %32
%103 = OpLoad %61 %102
%104 = OpAccessChain %74 %99 %100 %101
OpStore %104 %103
OpBranch %60
%55 = OpLabel
%109 = OpLoad %10 %31
%110 = OpLoad %10 %41
%111 = OpAccessChain %71 %70 %32
%112 = OpLoad %61 %111
%113 = OpAccessChain %74 %108 %109 %110
OpStore %113 %112
OpBranch %60
%56 = OpLabel
%118 = OpLoad %10 %31
%119 = OpLoad %10 %41
%120 = OpAccessChain %71 %70 %32
%121 = OpLoad %61 %120
%122 = OpAccessChain %74 %117 %118 %119
OpStore %122 %121
OpBranch %60
%57 = OpLabel
%127 = OpLoad %10 %31
%128 = OpLoad %10 %41
%129 = OpAccessChain %71 %70 %32
%130 = OpLoad %61 %129
%131 = OpAccessChain %74 %126 %127 %128
OpStore %131 %130
OpBranch %60
%58 = OpLabel
%136 = OpLoad %10 %31
%137 = OpLoad %10 %41
%138 = OpAccessChain %71 %70 %32
%139 = OpLoad %61 %138
%140 = OpAccessChain %74 %135 %136 %137
OpStore %140 %139
OpBranch %60
%59 = OpLabel
%145 = OpLoad %10 %31
%146 = OpLoad %10 %41
%147 = OpAccessChain %71 %70 %32
%148 = OpLoad %61 %147
%149 = OpAccessChain %74 %144 %145 %146
OpStore %149 %148
OpBranch %60
%60 = OpLabel
OpBranch %45
%45 = OpLabel
%152 = OpLoad %10 %41
%154 = OpIAdd %10 %152 %153
OpStore %41 %154
OpBranch %42
%44 = OpLabel
OpBranch %36
%36 = OpLabel
%155 = OpLoad %10 %31
%156 = OpIAdd %10 %155 %153
OpStore %31 %156
OpBranch %33
%35 = OpLabel
%157 = OpLoad %6 %8
%159 = OpIAdd %6 %157 %158
OpStore %8 %159
OpBranch %27
%27 = OpLabel
%160 = OpLoad %10 %23
%161 = OpIAdd %10 %160 %153
OpStore %23 %161
OpBranch %24
%26 = OpLabel
OpBranch %17
%17 = OpLabel
%162 = OpLoad %10 %12
%163 = OpIAdd %10 %162 %153
OpStore %12 %163
OpBranch %14
%16 = OpLabel
OpStore %164 %32
OpStore %165 %13
OpBranch %166
%166 = OpLabel
OpLoopMerge %168 %169 None
OpBranch %170
%170 = OpLabel
%171 = OpLoad %10 %165
%172 = OpSLessThanEqual %21 %171 %20
OpBranchConditional %172 %167 %168
%167 = OpLabel
OpStore %173 %13
OpBranch %174
%174 = OpLabel
OpLoopMerge %176 %177 None
OpBranch %178
%178 = OpLabel
%179 = OpLoad %10 %173
%180 = OpSLessThanEqual %21 %179 %20
OpBranchConditional %180 %175 %176
%175 = OpLabel
%185 = OpLoad %10 %164
%188 = OpAccessChain %187 %184 %185
OpStore %188 %186
OpStore %189 %32
OpBranch %190
%190 = OpLabel
OpLoopMerge %192 %193 None
OpBranch %194
%194 = OpLabel
%195 = OpLoad %10 %189
%196 = OpLoad %10 %165
%197 = OpSLessThan %21 %195 %196
OpBranchConditional %197 %191 %192
%191 = OpLabel
OpStore %198 %32
OpBranch %199
%199 = OpLabel
OpLoopMerge %201 %202 None
OpBranch %203
%203 = OpLabel
%204 = OpLoad %10 %198
%205 = OpLoad %10 %173
%206 = OpSLessThan %21 %204 %205
OpBranchConditional %206 %200 %201
%200 = OpLabel
%207 = OpLoad %10 %164
OpSelectionMerge %217 None
OpSwitch %207 %217 0 %208 1 %209 2 %210 3 %211 4 %212 5 %213 6 %214 7 %215 8 %216
%208 = OpLabel
%218 = OpLoad %10 %164
%219 = OpLoad %10 %189
%220 = OpLoad %10 %198
%221 = OpAccessChain %74 %65 %219 %220
%222 = OpLoad %61 %221
%223 = OpAccessChain %187 %184 %218
%224 = OpLoad %61 %223
%225 = OpFAdd %61 %224 %222
%226 = OpAccessChain %187 %184 %218
OpStore %226 %225
OpBranch %217
%209 = OpLabel
%228 = OpLoad %10 %164
%229 = OpLoad %10 %189
%230 = OpLoad %10 %198
%231 = OpAccessChain %74 %80 %229 %230
%232 = OpLoad %61 %231
%233 = OpAccessChain %187 %184 %228
%234 = OpLoad %61 %233
%235 = OpFAdd %61 %234 %232
%236 = OpAccessChain %187 %184 %228
OpStore %236 %235
OpBranch %217
%210 = OpLabel
%238 = OpLoad %10 %164
%239 = OpLoad %10 %189
%240 = OpLoad %10 %198
%241 = OpAccessChain %74 %90 %239 %240
%242 = OpLoad %61 %241
%243 = OpAccessChain %187 %184 %238
%244 = OpLoad %61 %243
%245 = OpFAdd %61 %244 %242
%246 = OpAccessChain %187 %184 %238
OpStore %246 %245
OpBranch %217
%211 = OpLabel
%248 = OpLoad %10 %164
%249 = OpLoad %10 %189
%250 = OpLoad %10 %198
%251 = OpAccessChain %74 %99 %249 %250
%252 = OpLoad %61 %251
%253 = OpAccessChain %187 %184 %248
%254 = OpLoad %61 %253
%255 = OpFAdd %61 %254 %252
%256 = OpAccessChain %187 %184 %248
OpStore %256 %255
OpBranch %217
%212 = OpLabel
%258 = OpLoad %10 %164
%259 = OpLoad %10 %189
%260 = OpLoad %10 %198
%261 = OpAccessChain %74 %108 %259 %260
%262 = OpLoad %61 %261
%263 = OpAccessChain %187 %184 %258
%264 = OpLoad %61 %263
%265 = OpFAdd %61 %264 %262
%266 = OpAccessChain %187 %184 %258
OpStore %266 %265
OpBranch %217
%213 = OpLabel
%268 = OpLoad %10 %164
%269 = OpLoad %10 %189
%270 = OpLoad %10 %198
%271 = OpAccessChain %74 %117 %269 %270
%272 = OpLoad %61 %271
%273 = OpAccessChain %187 %184 %268
%274 = OpLoad %61 %273
%275 = OpFAdd %61 %274 %272
%276 = OpAccessChain %187 %184 %268
OpStore %276 %275
OpBranch %217
%214 = OpLabel
%278 = OpLoad %10 %164
%279 = OpLoad %10 %189
%280 = OpLoad %10 %198
%281 = OpAccessChain %74 %126 %279 %280
%282 = OpLoad %61 %281
%283 = OpAccessChain %187 %184 %278
%284 = OpLoad %61 %283
%285 = OpFAdd %61 %284 %282
%286 = OpAccessChain %187 %184 %278
OpStore %286 %285
OpBranch %217
%215 = OpLabel
%288 = OpLoad %10 %164
%289 = OpLoad %10 %189
%290 = OpLoad %10 %198
%291 = OpAccessChain %74 %135 %289 %290
%292 = OpLoad %61 %291
%293 = OpAccessChain %187 %184 %288
%294 = OpLoad %61 %293
%295 = OpFAdd %61 %294 %292
%296 = OpAccessChain %187 %184 %288
OpStore %296 %295
OpBranch %217
%216 = OpLabel
%298 = OpLoad %10 %164
%299 = OpLoad %10 %189
%300 = OpLoad %10 %198
%301 = OpAccessChain %74 %144 %299 %300
%302 = OpLoad %61 %301
%303 = OpAccessChain %187 %184 %298
%304 = OpLoad %61 %303
%305 = OpFAdd %61 %304 %302
%306 = OpAccessChain %187 %184 %298
OpStore %306 %305
OpBranch %217
%217 = OpLabel
OpBranch %202
%202 = OpLabel
%309 = OpLoad %10 %198
%310 = OpIAdd %10 %309 %153
OpStore %198 %310
OpBranch %199
%201 = OpLabel
OpBranch %193
%193 = OpLabel
%311 = OpLoad %10 %189
%312 = OpIAdd %10 %311 %153
OpStore %189 %312
OpBranch %190
%192 = OpLabel
%313 = OpLoad %10 %164
%315 = OpAccessChain %187 %184 %313
%316 = OpLoad %61 %315
%317 = OpFDiv %61 %316 %314
%318 = OpAccessChain %187 %184 %313
OpStore %318 %317
%319 = OpLoad %10 %164
%320 = OpIAdd %10 %319 %153
OpStore %164 %320
OpBranch %177
%177 = OpLabel
%321 = OpLoad %10 %173
%322 = OpIAdd %10 %321 %153
OpStore %173 %322
OpBranch %174
%176 = OpLabel
OpBranch %169
%169 = OpLabel
%323 = OpLoad %10 %165
%324 = OpIAdd %10 %323 %153
OpStore %165 %324
OpBranch %166
%168 = OpLabel
%329 = OpAccessChain %328 %327 %9
%330 = OpLoad %61 %329
%334 = OpAccessChain %71 %333 %32 %9
%335 = OpLoad %61 %334
%337 = OpFDiv %61 %335 %336
%338 = OpFDiv %61 %330 %337
%339 = OpConvertFToS %10 %338
OpStore %325 %339
%341 = OpAccessChain %328 %327 %158
%342 = OpLoad %61 %341
%343 = OpAccessChain %71 %333 %32 %9
%344 = OpLoad %61 %343
%345 = OpFDiv %61 %344 %336
%346 = OpFDiv %61 %342 %345
%347 = OpConvertFToS %10 %346
OpStore %340 %347
%349 = OpLoad %10 %340
%351 = OpIMul %10 %349 %350
%352 = OpLoad %10 %325
%353 = OpIAdd %10 %351 %352
OpStore %348 %353
%354 = OpLoad %10 %348
%355 = OpSGreaterThan %21 %354 %32
%356 = OpLoad %10 %348
%358 = OpSLessThan %21 %356 %357
%359 = OpLogicalAnd %21 %355 %358
OpSelectionMerge %361 None
OpBranchConditional %359 %360 %373
%360 = OpLabel
%364 = OpLoad %10 %348
%365 = OpAccessChain %187 %184 %364
%366 = OpLoad %61 %365
%367 = OpCompositeConstruct %77 %366 %366 %366
%369 = OpCompositeExtract %61 %367 0
%370 = OpCompositeExtract %61 %367 1
%371 = OpCompositeExtract %61 %367 2
%372 = OpCompositeConstruct %87 %369 %370 %371 %368
OpStore %363 %372
OpBranch %361
%373 = OpLabel
OpStore %363 %374
OpBranch %361
%361 = OpLabel
OpReturn
OpFunctionEnd
)";
// The SPIR-V comes from the following GLSL:
//
// #version 310 es
// precision highp float;
//
// layout(location = 0) out vec4 color;
//
// void main()
// {
// color = vec4(1.0, 0.0, 0.0, 1.0);
// }
const std::string kTestShader5 = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main" %9
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
OpName %4 "main"
OpName %9 "color"
OpDecorate %9 Location 0
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeVector %6 4
%8 = OpTypePointer Output %7
%9 = OpVariable %8 Output
%10 = OpConstant %6 1
%11 = OpConstant %6 0
%12 = OpConstantComposite %7 %10 %11 %11 %10
%4 = OpFunction %2 None %3
%5 = OpLabel
OpStore %9 %12
OpReturn
OpFunctionEnd
)";
// Some miscellaneous SPIR-V.
const std::string kTestShader6 = R"(
OpCapability Shader
OpCapability SampledBuffer
OpCapability ImageBuffer
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %2 "main" %40 %41
OpExecutionMode %2 OriginUpperLeft
OpSource GLSL 450
OpDecorate %40 DescriptorSet 0
OpDecorate %40 Binding 69
OpDecorate %41 DescriptorSet 0
OpDecorate %41 Binding 1
%54 = OpTypeFloat 32
%76 = OpTypeVector %54 4
%55 = OpConstant %54 0
%56 = OpTypeVector %54 3
%94 = OpTypeVector %54 2
%112 = OpConstantComposite %94 %55 %55
%57 = OpConstantComposite %56 %55 %55 %55
%15 = OpTypeImage %54 2D 2 0 0 1 Unknown
%114 = OpTypePointer UniformConstant %15
%38 = OpTypeSampler
%125 = OpTypePointer UniformConstant %38
%132 = OpTypeVoid
%133 = OpTypeFunction %132
%45 = OpTypeSampledImage %15
%40 = OpVariable %114 UniformConstant
%41 = OpVariable %125 UniformConstant
%2 = OpFunction %132 None %133
%164 = OpLabel
%184 = OpLoad %15 %40
%213 = OpLoad %38 %41
%216 = OpSampledImage %45 %184 %213
%217 = OpImageSampleImplicitLod %76 %216 %112 Bias %55
OpReturn
OpFunctionEnd
)";
void AddConstantUniformFact(protobufs::FactSequence* facts,
uint32_t descriptor_set, uint32_t binding,
std::vector<uint32_t>&& indices, uint32_t value) {
protobufs::FactConstantUniform fact;
*fact.mutable_uniform_buffer_element_descriptor() =
MakeUniformBufferElementDescriptor(descriptor_set, binding,
std::move(indices));
*fact.mutable_constant_word()->Add() = value;
protobufs::Fact temp;
*temp.mutable_constant_uniform_fact() = fact;
*facts->mutable_fact()->Add() = temp;
}
// Reinterpret the bits of |value| as a 32-bit unsigned int
uint32_t FloatBitsAsUint(float value) {
uint32_t result;
memcpy(&result, &value, sizeof(float));
return result;
}
// Assembles the given |shader| text, and then runs the fuzzer |num_runs|
// times, using successive seeds starting from |initial_seed|. Checks that
// the binary produced after each fuzzer run is valid, and that replaying
// the transformations that were applied during fuzzing leads to an
// identical binary.
void RunFuzzerAndReplayer(const std::string& shader,
const protobufs::FactSequence& initial_facts,
uint32_t initial_seed, uint32_t num_runs) {
const auto env = SPV_ENV_UNIVERSAL_1_5;
std::vector<uint32_t> binary_in;
SpirvTools t(env);
t.SetMessageConsumer(kConsoleMessageConsumer);
ASSERT_TRUE(t.Assemble(shader, &binary_in, kFuzzAssembleOption));
ASSERT_TRUE(t.Validate(binary_in));
std::vector<fuzzerutil::ModuleSupplier> donor_suppliers;
for (auto donor : {&kTestShader1, &kTestShader2, &kTestShader3, &kTestShader4,
&kTestShader5, &kTestShader6}) {
donor_suppliers.emplace_back([donor]() {
return BuildModule(env, kConsoleMessageConsumer, *donor,
kFuzzAssembleOption);
});
}
std::vector<Fuzzer::RepeatedPassStrategy> strategies{
Fuzzer::RepeatedPassStrategy::kSimple,
Fuzzer::RepeatedPassStrategy::kLoopedWithRecommendations,
Fuzzer::RepeatedPassStrategy::kRandomWithRecommendations};
uint32_t strategy_index = 0;
for (uint32_t seed = initial_seed; seed < initial_seed + num_runs; seed++) {
spvtools::ValidatorOptions validator_options;
// Every 4th time we run the fuzzer, enable all fuzzer passes.
bool enable_all_passes = (seed % 4) == 0;
auto fuzzer_result =
Fuzzer(env, kSilentConsumer, binary_in, initial_facts, donor_suppliers,
MakeUnique<PseudoRandomGenerator>(seed), enable_all_passes,
strategies[strategy_index], true, validator_options)
.Run();
// Cycle the repeated pass strategy so that we try a different one next time
// we run the fuzzer.
strategy_index =
(strategy_index + 1) % static_cast<uint32_t>(strategies.size());
ASSERT_EQ(Fuzzer::FuzzerResultStatus::kComplete, fuzzer_result.status);
ASSERT_TRUE(t.Validate(fuzzer_result.transformed_binary));
auto replayer_result =
Replayer(
env, kConsoleMessageConsumer, binary_in, initial_facts,
fuzzer_result.applied_transformations,
static_cast<uint32_t>(
fuzzer_result.applied_transformations.transformation_size()),
false, validator_options)
.Run();
ASSERT_EQ(Replayer::ReplayerResultStatus::kComplete,
replayer_result.status);
// After replaying the transformations applied by the fuzzer, exactly those
// transformations should have been applied, and the binary resulting from
// replay should be identical to that which resulted from fuzzing.
std::string fuzzer_transformations_string;
std::string replayer_transformations_string;
fuzzer_result.applied_transformations.SerializeToString(
&fuzzer_transformations_string);
replayer_result.applied_transformations.SerializeToString(
&replayer_transformations_string);
ASSERT_EQ(fuzzer_transformations_string, replayer_transformations_string);
ASSERT_TRUE(IsEqual(env, fuzzer_result.transformed_binary,
replayer_result.transformed_module.get()));
}
}
TEST(FuzzerReplayerTest, Miscellaneous1) {
// Do some fuzzer runs, starting from an initial seed of 0 (seed value chosen
// arbitrarily).
RunFuzzerAndReplayer(kTestShader1, protobufs::FactSequence(), 0,
kNumFuzzerRuns);
}
TEST(FuzzerReplayerTest, Miscellaneous2) {
// Do some fuzzer runs, starting from an initial seed of 10 (seed value chosen
// arbitrarily).
RunFuzzerAndReplayer(kTestShader2, protobufs::FactSequence(), 10,
kNumFuzzerRuns);
}
TEST(FuzzerReplayerTest, Miscellaneous3) {
// Add the facts "resolution.x == 250" and "resolution.y == 100".
protobufs::FactSequence facts;
AddConstantUniformFact(&facts, 0, 0, {0, 0}, 250);
AddConstantUniformFact(&facts, 0, 0, {0, 1}, 100);
// Do some fuzzer runs, starting from an initial seed of 94 (seed value chosen
// arbitrarily).
RunFuzzerAndReplayer(kTestShader3, facts, 94, kNumFuzzerRuns);
}
TEST(FuzzerReplayerTest, Miscellaneous4) {
// Add the facts:
// - "one == 1.0"
// - "resolution.y == 256.0",
protobufs::FactSequence facts;
AddConstantUniformFact(&facts, 0, 0, {0}, FloatBitsAsUint(1.0));
AddConstantUniformFact(&facts, 0, 1, {0, 0}, FloatBitsAsUint(256.0));
AddConstantUniformFact(&facts, 0, 1, {0, 1}, FloatBitsAsUint(256.0));
// Do some fuzzer runs, starting from an initial seed of 14 (seed value chosen
// arbitrarily).
RunFuzzerAndReplayer(kTestShader4, facts, 14, kNumFuzzerRuns);
}
TEST(FuzzerReplayerTest, Miscellaneous5) {
// Do some fuzzer runs, starting from an initial seed of 29 (seed value chosen
// arbitrarily).
RunFuzzerAndReplayer(kTestShader5, protobufs::FactSequence(), 29,
kNumFuzzerRuns);
}
TEST(FuzzerReplayerTest, Miscellaneous6) {
// Do some fuzzer runs, starting from an initial seed of 57 (seed value chosen
// arbitrarily).
RunFuzzerAndReplayer(kTestShader6, protobufs::FactSequence(), 57,
kNumFuzzerRuns);
}
} // namespace
} // namespace fuzz
} // namespace spvtools