This PR changes the fact manager so that, when calling some of the
functions in submanagers, passes references to other submanagers if
necessary (e.g. to make consistency checks).
In particular:
- DataSynonymAndIdEquationFacts is passed to the AddFactIdIsIrrelevant
function of IrrelevantValueFacts
- IrrelevantValueFacts is passed to the AddFact functions of
DataSynonymAndIdEquationFacts
The IRContext is also passed when necessary and the calls to the
corresponding functions in FactManager were updated to be valid and
always use an updated context.
Fixes#3550.
This transformation, given the header of a selection construct with
branching instruction OpBranchConditional, flattens it.
Side-effecting operations such as OpLoad, OpStore and OpFunctionCall
are enclosed within smaller conditionals.
It is applicable if the construct does not contain inner selection
constructs or loops, or atomic or barrier instructions.
The corresponding fuzzer pass looks for selection headers and
tries to flatten them.
Needed for the issue #3544, but it does not fix it completely.
In #3636, I missed that the instruction folder may create more than a
single constant per call. Since CCP was only checking whether one
constant had been created after folding, it was wrongly thinking that
the IR had not changed.
Fixes#3738.
Adds a transformation that inserts a conditional statement with a
boolean expression of arbitrary value and duplicates a given
single-entry, single-exit region, so that it is present in each
conditional branch and will be executed regardless of which branch will
be taken.
Fixes#3614.
Motivated by integrating spirv-reduce into spirv-fuzz, so that an
added function can be made smaller during shrinking, this adds support
in spirv-reduce for asking reduction to be restricted to the
instructions of a single specified function.
This PR adds the NestingDepth function to StructuredCFGAnalysis.
This function, given a block id, returns the number of merge
constructs containing it.
This is needed by spirv-fuzz, but it makes sense to add it to
StructuredCFGAnalaysis, which contains related functionalities.
This transformation takes an OpSelect instruction and replaces it with
a conditional branch, selecting the correct value using an OpPhi
instruction.
Fixes part of the issue #3544.
The Vulkan 1.2.152 headers/spec now include Valid Usage IDs (VUID)
for every BuiltIn. This change adds labeling to help aid tracking
the coverage gap in Vulkan targeted validation. This is done with
a script in the Validation Layers that parses the source for VUID
strings, both that there is an implementation and a test for it.
There are 2 main changes:
1. A VUID string is added where applicable. It is wrapped in a function
that at runtimes checks if Vulkan is the target so that other targets
will not be effected as the output error only changes for Vulkan and
the overhead only occurs if there is an error at all.
2. For unit test, a new parameter value was added to allow make sure
that for each VUID there is a matching test. There are cases where the
same unit test checks multiple VUs via the parameter feature of gtest.
For this, I added a custom gMock Matcher to simply loop over a list
of VUID strings
Pointer (if VariablePointers is enabled) to find sets of potential
synonyms.
However, some instructions with these types cannot be used in an OpPhi:
- OpFunction cannot be used as a value
- OpUndef should not be used, because it yields an undefined value for
each use
Fixes#3761.
This transformation takes the id of an OpPhi instruction, of a dead
predecessor of the block containing it and a replacement id of
available to use and of the same type as the OpPhi, and changes
the id in the OpPhi corresponding to the given predecessor.
For example, %id = OpPhi %type %v1 %p1 %v2 %p2
becomes %id = OpPhi %type %v3 %p1 %v2 %p2
if the transformation is given %id, %p1 and %v3, %p1 is a dead block,
%v3 is type type and it is available to use at the end of %p1.
The fuzzer pass randomly decides to apply the transformation to OpPhi
instructions for which at least one of the predecessors is dead
Fixes#3726.
A transformation that replaces the use of an irrelevant id with
another id of the same type.
The related fuzzer pass, for every use of an irrelevant id,
checks whether the id can be replaced in that use by another
id of the same type and randomly decides whether to replace
it.
Fixes#3503.
This PR extends CallGraph with functions to return:
- a list of functions in lexicographical order, with respect to
function calls
- the maximum loop nesting depth that a function can be called from
(computed interprocedurally, e.g. if foo() calls bar() at depth 2
and bar() calls baz() at depth 1, the maximum depth of baz() will
be 3).
When we update OpenCL.DebugInfo.100 lexical scopes e.g., DebugFunction,
we have to replace DebugScope of each instruction that uses the lexical
scope correctly.
A transformation that adds new OpPhi instructions to blocks with >=1
predecessors, so that its value depends on previously-defined ids of
the right type, which are all synonymous. This instruction is also
recorded as synonymous to the others.
The related fuzzer pass still needs to be implemented.
Fixes#3592 .
This change adds the notion of "overflow ids", which can be used
during shrinking to facilitate applying transformations that would
otherwise have become inapplicable due to earlier transformations
being removed.
It is possible that the result of a void function call is used. In case
it is used, we need something that still defines its id after inlining.
We use an undef for that purpose.
Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/3704
CCP should mark IR changed if it created new constants.
This fixes#3636.
When CCP is simulating statements, it will sometimes successfully fold
an instruction, which laters switches to varying. The initial fold of
the instruction may generate a new constant K.
The problem we were running into is when K never gets propagated to the
IR. Its definition will still exist, so CCP should mark the IR modified
in this case.
In fixing this bug, I noticed that an existing test was suffering from
the same bug. The change also makes PassTest::SinglePassRunAndMatch()
return the result from the pass, so that we can check that the pass
marks the IR modified in this case.
Adds FuzzerPassAddCompositeInserts, which randomly adds new
OpCompositeInsert instructions. Each OpCompositeInsert instruction
yields a copy of an original composite with one subcomponent replaced
with an existing or newly added object. Synonym facts are added for the
unchanged components in the original and added composite, and for the
replaced subcomponent and the object, if possible.
Fixes#2859
For FuzzerPassAddParameters, adds pointer types (that have the storage
class Function or Private) to the pool of available types for new
parameters. If there are no variables of the chosen pointer type, it
invokes TransformationAddLocalVariable / TransformationAddGlobalVariable
to add one.
Part of #3403
In the existing code, ADCE pass does not check DebugScope of an
instruction when it checks the users of each instruction, which results
in removing OpenCL.Debug.100 instructions that are only used by
DebugScope. This commit lets ADCE pass add DebugScope of an instruction
to the live instruction set when the instruction is added to the live
instruction set.
`TransformationAddDeadBlock` did not check whether the existing block
(that will become a selection header) dominates its successor block (that
will become its merge block).
This change adds the check.
Fixes#3690.
Some OpenCL.DebugInfo.100 instructions such as DebugGlobalVariable
and DebugLocalVariable have the Type operand. This commit allows them to
use DebugTypeTemplate for the Type operand.
Improves the code coverage of tests for the following transformations:
1. TransformationAddRelaxedDecoration
2. TransformationReplaceCopyMemoryWithLoadStore
3. TransformationReplaceCopyObjectWithStoreLoad
4. TransformationReplaceLoadStoreWithCopyMemory
5. TransformationReplaceAddSubMulWithCarryingExtended
Support identical predecessors in TransformationPropagateInstructionUp.
A basic block may have multiple identical predecessors as follows:
%1 = OpLabel
OpSelectionMerge %2 None
OpBranchConditional %true %2 %2
%2 = OpLabel
...
This case wasn't supported before.
* No longer blindly add global non-semantic info instructions to global
types and values
* functions now have a list of non-semantic instructions that succeed
them in the global scope
* global non-semantic instructions go in global types and values if
they appear before any function, otherwise they are attached to the
immediate function predecessor in the module
* changed ADCE to use the function removal utility
* Modified EliminateFunction to have special handling for non-semantic
instructions in the global scope
* non-semantic instructions are moved to an earlier function (or full
global set) if the function they are attached to is eliminated
* Added IRContext::KillNonSemanticInfo to remove the tree of
non-semantic instructions that use an instruction
* this is used in function elimination
* There is still significant work in the optimizer to handle
non-semantic instructions fully in the optimizer
`TransformationAddTypeFloat` and `TransformationAddTypeInt` did not check whether the required capabilities were present when adding 16-bit, 64-bit, and 8-bit types.
This change adds these checks in the `IsApplicable` method of each transformation.
Fixes#3669.
`TransformationReplaceIdWithSynonym` is careful to avoid replacing id uses that index into a struct with synonyms because the indices must only be `OpConstant` instructions. However, the check only considered `OpAccessChain` instructions, even though the same restriction applies to `OpInBoundsAccessChain`, `OpPtrAccessChain`, etc.
This change extends the check to include all access chain instructions.
Fixes#3671.
Given an instruction (that may use an OpPhi result from the same block as an input operand), try to clone the instruction into each predecessor block, replacing the input operand with the corresponding OpPhi input operand in each case, if necessary.
Fixes#3458.
Replaces OpIAdd with OpIAddCarry, OpISub with OpISubBorrow, OpIMul with
OpUMulExtended or OpSMulExtended and stores the result into a fresh_id
representing a structure. Extracts the first element of the result into
the original result_id. This value is the same as the result of the
original instruction.
Fixes#3577