Commit Graph

57 Commits

Author SHA1 Message Date
Alastair Donaldson
dcb7169bbd
spirv-fuzz: Transformation to add a new function to a module (#3114)
This adds a large transformation that can add a new function to a
SPIR-V module.  This paves the way for donation of code from one
module to another.
2019-12-19 21:15:09 +00:00
Alastair Donaldson
2e41d5ece7
spirv-fuzz: Avoid passing access chains as parameters (#3112)
This change prevents the spirv-fuzz function outliner from outlining a
region that uses the result of an OpAccessChain not defined inside the
region.  Such accesses were turning into parameters to the outlined
function, and the result of an OpAccessChain cannot be passed as a
function parameter according to the SPIR-V specification.
2019-12-19 17:34:36 +00:00
Alastair Donaldson
38d7fbaad0
spirv-fuzz: Transformations to add types, constants and variables (#3101)
This change adds several transformations that allow types, constants,
undefined values and global variables to be added to a module.
2019-12-16 23:54:13 +00:00
Alastair Donaldson
96354f5047
spirv-fuzz: Fuzzer pass to merge blocks (#3097)
This change adds a transformation and associated fuzzer pass for
merging adjacent blocks in a module, re-using block merging code from
the optimizer.
2019-12-12 15:27:40 +00:00
Alastair Donaldson
0a2b38d082
spirv-fuzz: function outlining fuzzer pass (#3078)
A new transformation and associated fuzzer pass in spirv-fuzz that
selects single-entry single-exit control flow graph regions and for
each selected region outlines the region into a new function and
replaces the original region with a call to this function.
2019-12-10 14:47:42 +00:00
Alastair Donaldson
983b5b4fcc
spirv-fuzz: Use validator to check break/continue dominance conditions (#3089)
The passes that add dead breaks and continues suffer from the
challenge that a new control flow graph edge can change dominance
information, leading to the potenital for definitions to no longer
dominate their uses.  The attempt at guarding against this was known
to be incomplete.  This change calls on the SPIR-V validator to do the
necessary checking: in deciding whether adding such an edge would be
legitimate, we clone the module, add the edge, and use the validator
to check whether the transformed clone is valid.

This strategy is heavy-weight, and should be used sparingly, but seems
like a good option when the validity of transformations is intricate,
to avoid reimplementing swathes of validation logic in the fuzzer.

Fixes #2919.
2019-12-06 16:38:17 +00:00
Alastair Donaldson
47f3eb4264
spirv-fuzz: Fix invalid tests (#3079)
This change fixes some tests that turned out to be invalid; recent
improvements to the validator in #3068 exposed them as such.
2019-11-29 15:48:13 +00:00
alan-baker
b334829a91 Validate nested constructs (#3068)
* Validate that if a construct contains a header and it's merge is
reachable, the construct also contains the merge
* updated block merging to not merge into the continue
* update inlining to mark the original block of a single block loop as
the continue
* updated some tests
* remove dead code
* rename kBlockTypeHeader to kBlockTypeSelection for clarity
2019-11-27 16:45:57 -05:00
Alastair Donaldson
52e9cc9301
spirv-fuzz: Improve debugging facilities (#3074)
Adds an option to run the validator on the SPIR-V binary after each
fuzzer pass has been applied, to help identify when the fuzzer has
made the module invalid.  Also adds a helper method to allow dumping
of the sequence of transformations that have been applied to a JSON
file.
2019-11-27 18:05:56 +00:00
Alastair Donaldson
041f0a0249
spirv-fuzz: simplify transformation for replacing an id with a synonym (#3020)
Prior to this change, TransformationReplaceIdWithSynonym was designed
to be able to replace an id with some synonymous data descriptor,
possibly necessitating extracting from a composite into a fresh id in
order to get at the synonymous data.  This change simplifies things so
that TransformationReplaceIdWithSynonym just allows one id to be
replaced by another id.  It is the responsibility of the associated
fuzzer pass - FuzzerPassApplyIdSynonyms - to perform the extraction
operations, using e.g. TransformationCompositeExtract.
2019-11-07 16:19:06 +00:00
Alastair Donaldson
dc59b4b075
spirv-fuzz: vector shuffle transformation (#3015)
Inroduces a new transformation that adds a vector shuffle instruction
to the module, with associated facts about how the result vector of
the shuffle relates to the input vectors.

A fuzzer pass to add such transformations is not yet in place.
2019-11-06 17:11:54 +00:00
Alastair Donaldson
3724cfbea8
spirv-fuzz: better computation of data synonym facts (#3010)
When a data synonym fact about two composites is added, data synonym
facts between all sub-components of the composites are also added.

Furthermore, when data synonym facts been all sub-components of two
composites are known, a data synonym fact relating the two composites
is added. Identification of this case is done in a lazy manner, when
questions about data synonym facts are asked.

The change introduces helper methods to get the size of an array type
and the number of elements of a struct type, and fixes
TransformationCompositeExtract to invalidate analyses appropriately.
2019-11-05 16:45:14 +00:00
Alastair Donaldson
fb6bac889e
spirv-fuzz: make equivalence classes deterministic (#3011)
An equivalence relation is computed by traversing the tree of values
rooted at the class's representative. Children were represented by
unordered sets, meaning that the order of values in an equivalence
class could be nondeterministic. This change makes things
deterministic by representing children using a vector.

The path compression optimization employed in the implementation of
the underlying union-find data structure has the potential to change
the order in which elements appear in an equivalence class by changing
the structure of the tree, so the guarantee of determinism is limited
to being a deterministic function of the manner in which the
equivalence relation is updated and inspected.
2019-11-05 15:34:05 +00:00
Alastair Donaldson
f1e5cd73f6
spirv-fuzz: improvements to representation of data synonym facts (#3006)
This change fixes a bug in EquivalenceRelation, changes the interface
of EquivalenceRelation to avoid exposing (potentially
nondeterministic) unordered sets, and changes the interface of
FactManager to allow querying data synonyms directly. These interface
changes have required a lot of corresponding changes to client code
and tests.
2019-11-01 17:50:01 +00:00
Alastair Donaldson
fac166162f
spirv-fuzz: Transformation to extract from a composite object (#2991)
At present, TransformationReplaceIdWithSynonym both extracts elements
from composite objects and replaces uses of ids with synonyms.  This
new TransformationCompositeExtract class will allow that
transformation to be broken into smaller transformations.
2019-10-28 09:33:08 +00:00
Alastair Donaldson
ec12de9131
spirv-fuzz: rename class, and fix bug related to dominance (#2990)
Class TransformationConstructComposite has been renamed to
TransformationCompositeConstruct, to correspond to the name of the
SPIR-V instruction (as is done with e.g. TransformationCopyObject).
Running tests revealed an issue related to checking dominance in
TransformationReplaceIdWithSynonym, which is also fixed here.
2019-10-27 18:11:07 +00:00
Alastair Donaldson
0dbd4e358a
spirv-fuzz: Rework management of data synonyms (#2989)
This change uses the recently-added equivalence relation class to
re-work the way synonyms between data values are managed by the fact
manager.

The tests for 'transformation_replace_id_with_synonym' have been
temporarily removed.  This is because those tests are going to be
split into a number of test classes in an upcoming PR, once some other
refactorings have been applied, and it would be burdensome to
temporarily refactor all the tests to be in a working state for this
intermediate change.
2019-10-25 17:37:55 +01:00
Alastair Donaldson
b34fa73193
spirv-fuzz: add class to represent equivalence relation (#2988)
Adds a templated class for representing an equivalence relation on a
value data type.  This will be used by spirv-fuzz for representing
sets of distinct pieces of data in a shader that are known to have
equal values.
2019-10-25 12:46:52 +01:00
Alastair Donaldson
570582d8d6
spirv-fuzz: fuzzer pass to adjust memory access operands (#2968)
A new pass that gives spirv-fuzz the ability to adjust the memory
operand masks associated with memory access instructions (such as
OpLoad and OpCopy Memory).

Fixes #2940.
2019-10-22 18:05:35 +01:00
Alastair Donaldson
8357b878d1
spirv-fuzz: add missing functionality for matrix composites (#2974)
Support for matrix composites had been omitted in a previous PR; this
change adds the support that was missing.

Fixes #2971.
2019-10-22 14:23:13 +01:00
Alastair Donaldson
00170cc5e6
spirv-fuzz: Refactor 'copy object' and 'construct composite' transformations (#2966)
Rework these transformations to identify instructions via (base,
opcode, skip-count) triples, rather than (base, offset) pairs.
2019-10-15 20:00:17 +01:00
Alastair Donaldson
1b6fd37fa6
spirv-fuzz: Refactor 'split blocks' to identify instructions differently (#2961)
This change refactors the 'split blocks' transformation so that an
instruction is identified via a base, opcode, and number of those
opcodes to be skipped when searching from the base, as opposed to the
previous design which used a base and offset.
2019-10-14 17:00:46 +01:00
Alastair Donaldson
3eda1b9ff1
spirv-fuzz: Rework id descriptors (#2959)
A refactoring that separates the identification of an instruction from
the identification of a use in an instruction, to enable the former to
be used independently of the latter.
2019-10-11 10:13:06 +01:00
Alastair Donaldson
eba98c4eb7
spirv-fuzz: Add fuzzer pass to add NoContraction decorations (#2950)
A new pass that allows the fuzzer to add NoContraction decorations to
arithmetic instructions.

Fixes #2936.
2019-10-11 09:15:47 +01:00
Alastair Donaldson
91232f7f75
spirv-fuzz: Add fuzzer pass to change function controls (#2951)
A new pass that allows the fuzzer to change the 'function control'
operand of OpFunction instructions.

Fixes #2939.
2019-10-11 07:10:47 +01:00
Alastair Donaldson
253806adc4
spirv-fuzz: Add fuzzer pass to change loop controls (#2949)
A new pass that allows the fuzzer to change the 'loop control' operand
(and associated literal operands) of OpLoopMerge instructions.

Fixes #2938.
Fixes #2943.
2019-10-10 13:34:38 +01:00
Alastair Donaldson
5910bb8e94
spirv-fuzz: add transformation and pass to construct composites (#2941)
Adds a fuzzer pass and transformation to create a composite (array,
matrix, struct or vector) from available constituent components, and
inform the fact manager that each component of the new composite is
synonymous with the id that was used to construct it. This allows the
"replace id with synonym" pass to then replace uses of said ids with
uses of elements extracted from the composite.

Fixes #2858.
2019-10-08 14:04:10 +01:00
Alastair Donaldson
81d227f36b
spirv-fuzz: add disabled test to document known issue (#2942)
Issue #2919 identifies a problem in spirv-fuzz's ability to determine
when it is safe to add a new control flow edge without breaking
dominance rules.  This change adds a (currently disabled) test to
expose the issue, and a comment to document that the current solution
is incomplete.
2019-10-08 11:26:08 +01:00
Alastair Donaldson
26dba32c43
spirv-fuzz: Add fuzzer pass to change selection controls (#2944)
A new pass that allows the fuzzer to change the 'selection control'
operand of OpSelectionControl instructions.

Fixes #2937.
2019-10-08 11:25:34 +01:00
Alastair Donaldson
84b1976061
spirv-fuzz: do not allow a dead break to target an unreachable block (#2917)
Because dominance information becomes a bit unreliable when blocks are
unreachable, this change makes it so that the 'dead break'
transformation will not introduce a break to an unreachable block.

Fixes #2907.
2019-09-26 10:57:05 +01:00
Alastair Donaldson
70097c7761
spirv-fuzz: do not replace struct indices with synonyms (#2915)
This change introduces a robust check for whether an index in an
access chain is indexing into a struct, in which case the index needs
to be an OpConstant and cannot be replaced with a synonym.

Fixes #2906.
2019-09-25 16:52:35 +01:00
Alastair Donaldson
c1e03834e3
spirv-fuzz: Fixes to preconditions for adding dead break/continue edges (#2904)
Issues #2898 and #2900 identify some cases where adding a dead
continue would lead to an invalid module, and these turned out to be
due to the lack of sensible dominance information when a continue
target is unreachable. This change requires that the header of a loop
dominates the loop's continue target if a dead continue is to be
added.

Furthermore, issue #2905 identified a shortcoming in the algorithm
being used to identify when it is OK, from a dominance point of view,
to add a new break/continue edge to a control flow graph. This change
replaces that algorithm with a simpler and more obviously correct
algorithm (that incidentally does not require the new edge to be a
break/continue edge in particular).

Fixes #2898.
Fixes #2900.
Fixes #2905.
2019-09-25 16:51:41 +01:00
Alastair Donaldson
7bc114ba2f
spirv-fuzz: do not replace a pointer argument to a function call with a synonym (#2901)
Before this change, spirv-fuzz would replace a pointer argument to a
function call with a synonym, which is problematic when the synonym is
not a memory object declaration, since function call arguments are
required to be memory object declarations. This change adds a check
to ensure that such a replacement is not made.

Fixes #2896.
2019-09-25 12:17:29 +01:00
Alastair Donaldson
290f6a820d
spirv-fuzz: do not replace boolean constant argument to OpPhi instruction (#2903)
Before this change, spirv-fuzz would replace a constant boolean
argument to an OpPhi with the result of a binary operation, inserting
the instruction to compute the binary operation right before the
OpPhi, leading to an invalid module. This change conservatively
disallows replacing OpPhi arguments. Issue #2902 notes that there is
scope for being less conservative.

Fixes #2897.
2019-09-25 12:16:25 +01:00
Alastair Donaldson
958f7e72a7
Employ the "swarm testing" idea in spirv-fuzz (#2890)
This change to spirv-fuzz uses ideas from "Swarm Testing" (Groce et al. 2012), so that a random subset of fuzzer passes are enabled. These passes are then applied repeatedly in a randomized fashion, with the aggression with which they are applied being randomly chosen per pass.

There is plenty of scope for refining the probabilities introduce in this change; this is just meant to be a reasonable first effort.
2019-09-23 16:29:19 +01:00
Alastair Donaldson
4653127262
Fix to CMakeLists for spirv-fuzz tests (#2888)
A previous change that disabled long-running tests by default failed
to enable short-running tests when long-running tests are enabled.
This change fixes that problem.
2019-09-20 15:23:25 +01:00
Alastair Donaldson
7275a71654
Allow validation during spirv-fuzz replay (#2873)
To aid in debugging issues in spirv-fuzz, this change adds an option whereby the SPIR-V module is validated after each transformation is applied during replay.  This can assist in finding a transformation that erroneously makes the module invalid, so that said transformation can be debugged.
2019-09-20 10:54:09 +01:00
Alastair Donaldson
4eee71e78f
Disable long-running fuzzer tests by default (#2887)
spirv-fuzz has useful tests that run the fuzzer and shrinker, to give
the whole tool a good shake up, effectively "fuzzing the fuzzer".  The
problems that this detects are sensitive to the source of randomness
that is used, which can change from test platform to test platform.
It is thus not a good idea to run these tests by default during
continuous integration - they may end up failing due to environtal
factors, making it look like an unrelated change has broken the fuzzer
when really the fuzzer has revealed an already-existing bug in itself.

This change makes the tests disabled by default; they can enabled
during dedicated testing of the fuzzer.
2019-09-20 09:43:26 +01:00
Alastair Donaldson
e59b60de07
Fix detection of blocks bypassed by new edge (#2874)
Fixes an issue where the blocks that would be bypassed by a new break
or continue control flow edge were not properly detected.

Fixes #2871.
2019-09-18 20:50:08 +01:00
Alastair Donaldson
0a07cd1c9a
Add fuzzer pass to replace ids with synonyms (#2857)
If the fuzzer's fact manager knows that ids A and B are synonymous, it
can replace a use of A with a use of B, so long as various conditions
hold (e.g. the definition of B must dominate the use of A, and it is
not legal to replace a use of an OpConstant in a struct's access chain
with a synonym that is not an OpConstant).

This change adds a fuzzer pass to sprinke such synonym replacements
through the module.
2019-09-18 20:47:08 +01:00
Alastair Donaldson
7ee8f443ea
Fix add-dead-break and add-dead-continue passes to respect dominance (#2838)
The implementation of these passes had overlooked the fact that adding
a new edge to a control flow graph can change dominance information.
Adding a dead break/continue risks causing uses to no longer be
dominated by their definitions.  This change introduces various tests
to expose such scenarios, and augments the preconditions for these
transformations with checks to guard against the situation.
2019-09-10 14:48:27 +01:00
Alastair Donaldson
698b56a8f0
Add 'copy object' transformation (#2766)
This transformation can introduce an instruction that uses
OpCopyObject to make a copy of some other result id.  This change
introduces the transformation, but does not yet introduce a fuzzer
pass to actually apply it.
2019-08-05 18:00:13 +01:00
Alastair Donaldson
f54b8653dd Limit fuzzer tests so that they take less time to run (#2763)
The recently added fuzzer_replayer and fuzzer_shrinker tests were
rather heavyweight and were leading to CI timeouts.  This change
reduces the runtime of those tests by having them do fewer iterations.
2019-07-25 13:09:49 -04:00
Alastair Donaldson
1a89ac8b28
Transformation and fuzzer pass to add dead continues (#2758)
Similar to the existing 'add dead breaks' pass, this adds a pass to
add dead continues to blocks in loops where such a transformation is
viable.  Various functionality common to this new pass and 'add dead
breaks' has been factored into 'fuzzer_util', and some small
improvements to 'add dead breaks' that were identified while reviewing
that code again have been applied.

Fixes #2719.
2019-07-25 13:50:33 +01:00
Alastair Donaldson
b8ab80843f
Shrinker for spirv-fuzz (#2708)
Adds to spirv-fuzz the option to shrink a sequence of transformations
that lead to an interesting binary to be generated, to find a smaller
sub-sequence of transformations that still lead to an interesting (but
hopefully simpler) binary being generated. The notion of what counts
as "interesting" comes from a user-provided script, the
"interestingness function", similar to the way the spirv-reduce tool
works. The shrinking process will give up after a maximum number of
steps, which can be configured on the command line.

Tests for the combination of fuzzing and shrinking are included, using
a variety of interestingness functions.
2019-07-07 08:55:30 +01:00
Alastair Donaldson
efde682369
Disallow movement of unreachable blocks. (#2700)
Fixes #2695.  Allowing unreachable blocks to be moved can lead to an
unreachable block A getting placed after an unreachable successor B,
which is a problem if B uses ids that A generates.
2019-06-26 15:32:25 +01:00
Alastair Donaldson
dfcb5a1e10
Refactor fuzzer transformations (#2694)
Introduced abstract class for transformations, and refactored all transformations to inherit from this abstract class.
2019-06-25 20:49:46 +01:00
Alastair Donaldson
51b0d5ce50
Represent uniform facts via descriptor set and binding. (#2681)
* Represent uniform facts via descriptor set and binding.

Previously uniform facts were expressed with resepect to the id of a
uniform variable.  Describing them with respect to a descriptor set
and binding is more convenient from the point of view of expressing
facts about a shader without requiring analysis of its SPIR-V.

* Fix equality testing for uniform buffer element descriptors.

The equality test now checks that the lengths of the index vectors
match.  Added a test that exposes the previous omission.
2019-06-19 20:45:14 +01:00
Alastair Donaldson
001e823b65
Add fuzzer pass to obfuscate constants. (#2671)
Adds a new transformation that can replace a constant with a uniform known to have the same value, and adds a fuzzer pass that (a) replaces a boolean with a comparison of literals (e.g. replacing "true" with "42 > 24"), and then (b) obfuscates the literals appearing in this comparison by replacing them with identically-valued uniforms, if available.

The fuzzer_replayer test file has also been updated to allow initial facts to be provided, and to do error checking of the status results returned by the fuzzer and replayer components.
2019-06-18 18:41:08 +01:00
Alastair Donaldson
42830e5a68
Add replayer tool for spirv-fuzz. (#2664)
The replayer takes an existing sequence of transformations and applies
them to a module.  Replaying a sequence of transformations that were
obtained via fuzzing should lead to an identical module to the module
that was fuzzed.  Tests have been added to check for this.
2019-06-13 14:08:33 +01:00