Commit Graph

57 Commits

Author SHA1 Message Date
Alan Baker
4f866abfd8 Validate static uses of interfaces
Fixes #1120

Checks that all static uses of the Input and Output variables are listed
as interfaces in each corresponding entry point declaration.
 * Changed validation state to track interface lists
 * updated many tests
* Modified validation state to store entry point names
 * Combined with interface list and called EntryPointDescription
 * Updated uses
* Changed interface validation error messages to output entry point name
in addtion to ID
2018-06-13 10:56:14 -04:00
Steven Perron
fe2fbee294 Delete the insert-extract-elim pass.
Replaces anything that creates an insert-extract-elim pass and create
a simplifiation pass instead.  Then delete the implementation of the
pass.

Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/1570.
2018-06-01 10:13:39 -04:00
Steven Perron
af430ec822 Add pass to fold a load feeding an extract.
We have already disabled common uniform elimination because it created
sequences of loads an entire uniform object, then we extract just a
single element.  This caused problems in some drivers, and is just
generally slow because it loads more memory than needed.

However, there are other way to get into this situation, so I've added
a pass that looks specifically for this pattern and removes it when only
a portion of the load is used.

Fixes #1547.
2018-05-14 15:40:34 -04:00
Toomas Remmelg
1dc2458060 Add a loop fusion pass.
This pass will look for adjacent loops that are compatible and legal to
be fused.

Loops are compatible if:

- they both have one induction variable
- they have the same upper and lower bounds
    - same initial value
    - same condition
- they have the same update step
- they are adjacent
- there are no break/continue in either of them

Fusion is legal if:

- fused loops do not have any dependencies with dependence distance
  greater than 0 that did not exist in the original loops.
- there are no function calls in the loops (could have side-effects)
- there are no barriers in the loops

It will fuse all such loops as long as the number of registers used for
the fused loop stays under the threshold defined by
max_registers_per_loop.
2018-05-01 15:40:37 -04:00
Stephen McGroarty
9a5dd6fe88 Support loop fission.
Adds support for spliting loops whose register pressure exceeds a user
provided level. This pass will split a loop into two or more loops given
that the loop is a top level loop and that spliting the loop is legal.
Control flow is left intact for dead code elimination to remove.

This pass is enabled with the --loop-fission flag to spirv-opt.
2018-05-01 15:15:10 -04:00
Steven Perron
2c0ce87210
Vector DCE (#1512)
Introduce a pass that does a DCE type analysis for vector elements
instead of the whole vector as a single element.

It will then rewrite instructions that are not used with something else.
For example, an instruction whose value are not used, even though it is
referenced, is replaced with an OpUndef.
2018-04-23 11:13:07 -04:00
Victor Lomuller
0ec08c28c1 Add register liveness analysis.
For each function, the analysis determine which SSA registers are live
at the beginning of each basic block and which one are killed at
the end of the basic block.

It also includes utilities to simulate the register pressure for loop
fusion and fission.

The implementation is based on the paper "A non-iterative data-flow
algorithm for computing liveness sets in strict ssa programs" from
Boissinot et al.
2018-04-20 09:45:15 -04:00
Alan Baker
09c206b6fb Fixes #1480. Validate group non-uniform scopes.
* Adds new pass for validating non-uniform group instructions
 * Currently on checks execution scope for Vulkan 1.1 and SPIR-V 1.3
* Added test framework
2018-04-20 09:25:00 -04:00
Alexander Johnston
61b50b3bfa ZIV and SIV loop dependence analysis.
Provides functionality to perform ZIV and SIV dependency analysis tests
between a load and store within the same loop.

Dependency tests rely on scalar analysis to prove and disprove dependencies
with regard to the loop being analysed.

Based on the 1990 paper Practical Dependence Testing by Goff, Kennedy, Tseng

Adds support for marking loops in the loop nest as IRRELEVANT.
Loops are marked IRRELEVANT if the analysed instructions contain
no induction variables for the loops, i.e. the loops induction
variable is not relevent to the dependence of the store and load.
2018-04-11 09:32:42 -04:00
Stephen McGroarty
ad7e4b8401 Initial patch for scalar evolution analysis
This patch adds support for the analysis of scalars in loops. It works
by traversing the defuse chain to build a DAG of scalar operations and
then simplifies the DAG by folding constants and grouping like terms.
It represents induction variables as recurrent expressions with respect
to a given loop and can simplify DAGs containing recurrent expression by
rewritting the entire DAG to be a recurrent expression with respect to
the same loop.
2018-03-28 16:34:23 -04:00
Steven Perron
c4dc046399 Copy propagate arrays
The sprir-v generated from HLSL code contain many copyies of very large
arrays.  Not only are these time consumming, but they also cause
problems for drivers because they require too much space.

To work around this, we will implement an array copy propagation.  Note
that we will not implement a complete array data flow analysis in order
to implement this.  We will be looking for very simple cases:

1) The source must never be stored to.
2) The target must be stored to exactly once.
3) The store to the target must be a store to the entire array, and be a
copy of the entire source.
4) All loads of the target must be dominated by the store.

The hard part is keeping all of the types correct.  We do not want to
have to do too large a search to update everything, which may not be
possible, do we give up if we see any instruction that might be hard to
update.

Also in types.h, the element decorations are not stored in an std::map.
This change was done so the hashing algorithm for a Struct is
consistent.  With the std::unordered_map, the traversal order was
non-deterministic leading to the same type getting hashed to different
values.  See |Struct::GetExtraHashWords|.

Contributes to #1416.
2018-03-26 14:44:41 -04:00
Andrey Tuganov
fe9121f721 Add Vulkan validation rules for BuiltIn variables
Added a framework for validation of BuiltIn variables. The framework
allows implementation of flexible abstract rules which are required for
built-ins as the information (decoration, definition, reference) is not
in one place, but is scattered all over the module.

Validation rules are implemented as a map
id -> list<functor(instrution)>

Ids which are dependent on built-in types or objects receive a task
list, such as "this id cannot be referenced from function which is
called from entry point with execution model X; propagate this rule
to your descendants in the global scope".

Also refactored test/val/val_fixtures.

All built-ins covered by tests
2018-03-23 14:02:42 -04:00
Jaebaek Seo
3b594e1630 Add --time-report to spirv-opt
This patch adds a new option --time-report to spirv-opt.  For each pass
executed by spirv-opt, the flag prints resource utilization for the pass
(CPU time, wall time, RSS and page faults)

This fixes issue #1378
2018-03-20 21:30:06 -04:00
Diego Novillo
735d8a579e SSA rewrite pass.
This pass replaces the load/store elimination passes.  It implements the
SSA re-writing algorithm proposed in

     Simple and Efficient Construction of Static Single Assignment Form.
     Braun M., Buchwald S., Hack S., Leißa R., Mallon C., Zwinkau A. (2013)
     In: Jhala R., De Bosschere K. (eds)
     Compiler Construction. CC 2013.
     Lecture Notes in Computer Science, vol 7791.
     Springer, Berlin, Heidelberg

     https://link.springer.com/chapter/10.1007/978-3-642-37051-9_6

In contrast to common eager algorithms based on dominance and dominance
frontier information, this algorithm works backwards from load operations.

When a target variable is loaded, it queries the variable's reaching
definition.  If the reaching definition is unknown at the current location,
it searches backwards in the CFG, inserting Phi instructions at join points
in the CFG along the way until it finds the desired store instruction.

The algorithm avoids repeated lookups using memoization.

For reducible CFGs, which are a superset of the structured CFGs in SPIRV,
this algorithm is proven to produce minimal SSA.  That is, it inserts the
minimal number of Phi instructions required to ensure the SSA property, but
some Phi instructions may be dead
(https://en.wikipedia.org/wiki/Static_single_assignment_form).
2018-03-20 20:56:55 -04:00
Victor Lomuller
bdf421cf40 Add loop peeling utility
The loop peeler util takes a loop as input and create a new one before.
The iterator of the duplicated loop then set to accommodate the number
of iteration required for the peeling.

The loop peeling pass that decided to do the peeling and profitability
analysis is left for a follow-up PR.
2018-03-20 10:21:10 -04:00
David Neto
844e186cf7 Add --strip-reflect pass
Strips reflection info. This is limited to decorations and
decoration instructions related to the SPV_GOOGLE_hlsl_functionality1
extension.
It will remove the OpExtension for SPV_GOOGLE_hlsl_functionality1.
It will also remove the OpExtension for SPV_GOOGLE_decorate_string
if there are no further remaining uses of OpDecorateStringGOOGLE.

Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/1398
2018-03-15 21:20:42 -04:00
David Neto
00fa39318f Support SPIR-V 1.3 and Vulkan 1.1
The default target is SPIR-V 1.3.

For example, spirv-as will generate a SPIR-V 1.3 binary by default.
Use command line option "--target-env spv1.0" if you want to make a SPIR-V
1.0 binary or validate against SPIR-V 1.0 rules.

Example:
        # Generate a SPIR-V 1.0 binary instead of SPIR-V 1.3
	spirv-as --target-env spv1.0 a.spvasm -o a.spv
	spirv-as --target-env vulkan1.0 a.spvasm -o a.spv

        # Validate as SPIR-V 1.0.
	spirv-val --target-env spv1.0 a.spv
        # Validate as Vulkan 1.0
	spirv-val --target-env vulkan1.0 a.spv
2018-03-06 15:17:31 -05:00
David Neto
a942ff40f5 Android.mk: Generate enum mappings from unified1 grammar
Some tokens are only showing up in the unified1 grammar.
So enum string mappings have to be generated from that grammar, not
the grammar from the (deprecated) include/spirv/1.2 grammar.

Example: capabilities FragmentFullyCovered, Float16ImageAMD
2018-03-02 15:27:22 -05:00
Victor Lomuller
3497a94460 Add loop unswitch pass.
It moves all conditional branching and switch whose conditions are loop
invariant and uniform. Before performing the loop unswitch we check that
the loop does not contain any instruction that would prevent it
(barriers, group instructions etc.).
2018-02-27 08:52:46 -05:00
Stephen McGroarty
dd8400e150 Initial support for loop unrolling.
This patch adds initial support for loop unrolling in the form of a
series of utility classes which perform the unrolling. The pass can
be run with the command spirv-opt --loop-unroll. This will unroll
loops within the module which have the unroll hint set. The unroller
imposes a number of requirements on the loops it can unroll. These are
documented in the comments for the LoopUtils::CanPerformUnroll method in
loop_utils.h. Some of the restrictions will be lifted in future patches.
2018-02-14 15:44:38 -05:00
Steven Perron
1d7b1423f9 Add folding of OpCompositeExtract and OpConstantComposite constant instructions.
Create files for constant folding rules.

Add the rules for OpConstantComposite and OpCompositeExtract.
2018-02-09 17:52:33 -05:00
Alexander Johnston
84ccd0b9ae Loop invariant code motion initial implementation 2018-02-08 22:55:47 -05:00
Steven Perron
06cdb96984 Make use of the instruction folder.
Implementation of the simplification pass.

- Create pass that calls the instruction folder on each instruction and
  propagate instructions that fold to a copy.  This will do copy
  propagation as well.

- Did not use the propagator engine because I want to modify the instruction
  as we go along.

- Change folding to not allocate new instructions, but make changes in
  place.  This change had a big impact on compile time.

- Add simplification pass to the legalization passes in place of
  insert-extract elimination.

- Added test cases for new folding rules.

- Added tests for the simplification pass

- Added a method to the CFG to apply a function to the basic blocks in
  reverse post order.

Contributes to #1164.
2018-02-07 23:01:47 -05:00
Andrey Tuganov
12e6860d07 Add barrier instructions validation pass 2018-02-05 13:14:55 -05:00
Steven Perron
bc1ec9418b Add general folding infrastructure.
Create the folding engine that will

1) attempt to fold an instruction.
2) iterates on the folding so small folding rules can be easily combined.
3) insert new instructions when needed.

I've added the minimum number of rules needed to test the features above.
2018-02-02 12:24:11 -05:00
Steven Perron
61d8c0384b Add pass to reaplce invalid opcodes
Creates a pass that will remove instructions that are invalid for the
current shader stage.  For the instruction to be considered for replacement

1) The opcode must be valid for a shader modules.
2) The opcode must be invalid for the current shader stage.
3) All entry points to the module must be for the same shader stage.
4) The function containing the instruction must be reachable from an entry point.

Fixes #1247.
2018-02-01 15:25:09 -05:00
Jeremy Hayes
cd68f2b176 Add adjacency validation pass
Validate OpPhi predecessors.
Validate OpLoopMerge successors.
Validate OpSelectionMerge successors.
Fix collateral damage to existing tests.
Remove ValidateIdWithMessage.OpSampledImageUsedInOpPhiBad.
2018-02-01 14:10:55 -05:00
GregF
f28b106173 InsertExtractElim: Split out DeadInsertElim as separate pass 2018-01-30 08:52:14 -05:00
Alan Baker
2e93e806e4 Initial implementation of if conversion
* Handles simple cases only
* Identifies phis in blocks with two predecessors and attempts to
convert the phi to an select
 * does not perform code motion currently so the converted values must
 dominate the join point (e.g. can't be defined in the branches)
 * limited for now to two predecessors, but can be extended to handle
 more cases
* Adding if conversion to -O and -Os
2018-01-25 09:42:00 -08:00
Steven Perron
34d4294c2c Create a pass to work around a driver bug related to OpUnreachable.
We have come across a driver bug where and OpUnreachable inside a loop
is causing the shader to go into an infinite loop.  This commit will try
to avoid this bug by turning OpUnreachable instructions that are
contained in a loop into branches to the loop merge block.

This is not added to "-O" and "-Os" because it should only be used if
the driver being targeted has this problem.

Fixes #1209.
2018-01-18 20:31:46 -05:00
Victor Lomuller
e8ad02f3dd Add loop descriptors and some required dominator tree extensions.
Add post-order tree iterator.

Add DominatorTreeNode extensions:
 - Add begin/end methods to do pre-order and post-order tree traversal from a given DominatorTreeNode

Add DominatorTree extensions:
  - Add begin/end methods to do pre-order and post-order tree traversal
  - Tree traversal ignore by default the pseudo entry block
  - Retrieve a DominatorTreeNode from a basic block

Add loop descriptor:
  - Add a LoopDescriptor class to register all loops in a given function.
  - Add a Loop class to describe a loop:
    - Loop parent
    - Nested loops
    - Loop depth
    - Loop header, merge, continue and preheader
    - Basic blocks that belong to the loop

Correct a bug that forced dominator tree to be constantly rebuilt.
2018-01-08 09:31:13 -05:00
Andrey Tuganov
25d396b4a2 Add ExtInst validation pass (GLSL only for now)
Validates all GLSL.std.450 extended instructions.
2018-01-02 16:53:25 -05:00
David Neto
59de6100b5 Add asm, dis support for DebugInfo extended instruction set
Add grammar file for DebugInfo extended instruction set
- Each new operand enum kind in extinst.debuginfo.grammar.json maps
  to a new value in spv_operand_type_t.
- Add new concrete enum operand types for DebugInfo

Generate a C header for the DebugInfo extended instruction set

Add table lookup of DebugInfo extended instrutions

Handle the debug info operand types in binary parser,
disassembler, and assembler.

Add DebugInfo round trip tests for assembler, disassembler

Android.mk: Support DebugInfo extended instruction set

The extinst.debuginfo.grammar.json file is currently part of
SPIRV-Tools source.

It contributes operand type enums, so it has to be processed
along with the core grammar files.

We also generate a C header DebugInfo.h.

Add necessary grammar file processing to Android.mk.
2017-12-22 09:39:36 -05:00
Diego Novillo
4ba9dcc8a0 Implement SSA CCP (SSA Conditional Constant Propagation).
This implements the conditional constant propagation pass proposed in

Constant propagation with conditional branches,
Wegman and Zadeck, ACM TOPLAS 13(2):181-210.

The main logic resides in CCPPass::VisitInstruction.  Instruction that
may produce a constant value are evaluated with the constant folder. If
they produce a new constant, the instruction is considered interesting.
Otherwise, it's considered varying (for unfoldable instructions) or
just not interesting (when not enough operands have a constant value).

The other main piece of logic is in CCPPass::VisitBranch.  This
evaluates the selector of the branch.  When it's found to be a known
value, it computes the destination basic block and sets it.  This tells
the propagator which branches to follow.

The patch required extensions to the constant manager as well. Instead
of hashing the Constant pointers, this patch changes the constant pool
to hash the contents of the Constant.  This allows the lookups to be
done using the actual values of the Constant, preventing duplicate
definitions.
2017-12-21 14:29:45 -05:00
Steven Perron
b86eb6842b Convert private variables to function scope.
When a private variable is used in a single function, it can be
converted to a function scope variable in that function.  This adds a
pass that does that.  The pass can be enabled using the option
`--private-to-local`.

This transformation allows other transformations to act on these
variables.

Also moved `FindPointerToType` from the inline class to the type manager.
2017-12-19 14:21:04 -05:00
Jesus Carabano
4dbcef62ee validate & test of literal's upper bits
Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/660
2017-12-19 13:19:56 -05:00
Jeremy Hayes
cdfbf26c13 Add primitive instruction validation pass 2017-12-15 09:53:29 -05:00
Andrey Tuganov
af7d5799a5 Refactor include of latest spir-v header versions 2017-12-14 11:18:20 -05:00
Andrey Tuganov
532b327d4d Add validation rules for atomic instructions
Validates all OpAtomicXXX instructions.
2017-12-13 18:29:38 -05:00
Alan Baker
867451f49e Add scalar replacement
Adds a scalar replacement pass. The pass considers all function scope
variables of composite type. If there are accesses to individual
elements (and it is legal) the pass replaces the variable with a
variable for each composite element and updates all the uses.

Added the pass to -O
Added NumUses and NumUsers to DefUseManager
Added some helper methods for the inst to block mapping in context
Added some helper methods for specific constant types

No longer generate duplicate pointer types.

* Now searches for an existing pointer of the appropriate type instead
of failing validation
* Fixed spec constant extracts
* Addressed changes for review
* Changed RunSinglePassAndMatch to be able to run validation
 * current users do not enable it

Added handling of acceptable decorations.

* Decorations are also transfered where appropriate

Refactored extension checking into FeatureManager

* Context now owns a feature manager
 * consciously NOT an analysis
 * added some test
* fixed some minor issues related to decorates
* added some decorate related tests for scalar replacement
2017-12-11 10:51:13 -05:00
Diego Novillo
241dcacc04 Add a new constant manager class.
This patch adds a new constant manager class to interface with
analysis::Constant.  The new constant manager lives in ir::IRContext
together with the type manager (analysis::TypeManager).

The new analysis::ConstantManager is used by the spec constant folder
and the constant propagator (in progress).

Another cleanup introduced by this patch removes the ID management from
the fold spec constant pass, and ir::IRContext and moves it to
ir::Module. SSA IDs were maintained by IRContext and Module.  That's
pointless and leads to mismatch IDs. Fixed by moving all the bookkeeping
to ir::Module.
2017-12-08 14:14:55 -05:00
Steven Perron
5d602abd66 Add global redundancy elimination
Adds a pass that looks for redundant instruction in a function, and
removes them.  The algorithm is a hash table based value numbering
algorithm that traverses the dominator tree.

This pass removes completely redundant instructions, not partially
redundant ones.
2017-12-07 18:35:38 -05:00
Stephen McGroarty
8ba68fa9b9 Dominator Tree Analysis (#3)
Support for dominator and post dominator analysis on ir::Functions. This patch contains a DominatorTree class for building the tree and DominatorAnalysis and DominatorAnalysisPass classes for interfacing and caching the built trees.
2017-12-05 22:59:43 -05:00
Andrey Tuganov
94e3e7b8ef Add composite instruction validation pass
Validates instructions in the opcode range from OpVectorExtractDynamic
to OpTranspose.
2017-12-05 10:15:51 -05:00
Diego Novillo
74327845aa Generic value propagation engine.
This class implements a generic value propagation algorithm based on the
conditional constant propagation algorithm proposed in

     Constant propagation with conditional branches,
     Wegman and Zadeck, ACM TOPLAS 13(2):181-210.

The implementation is based on

     A Propagation Engine for GCC
     Diego Novillo, GCC Summit 2005
     http://ols.fedoraproject.org/GCC/Reprints-2005/novillo-Reprint.pdf

The purpose of this implementation is to act as a common framework for any
transformation that needs to propagate values from statements producing new
values to statements using those values.
2017-11-27 23:32:06 -05:00
Andrey Tuganov
ab892f7bd6 Add derivatives validation pass
Checks operands of instructions in opcode range from OpDPdx to
OpFwidthCoarse.
2017-11-23 14:17:10 -05:00
Steven Perron
28c415500d Create a local value numbering pass
Creates a pass that removes redundant instructions within the same basic
block.  This will be implemented using a hash based value numbering
algorithm.

Added a number of functions that check for the Vulkan descriptor types.
These are used to determine if we are variables are read-only or not.

Implemented a function to check if loads and variables are read-only.
Implemented kernel specific and shader specific versions.

A big change is that the Combinator analysis in ADCE is factored out
into the IRContext as an analysis. This was done because it is being
reused in the value number table.
2017-11-23 11:45:09 -05:00
Andrey Tuganov
f407ae2b50 Validator pass for image instructions
Includes validation rules for OpImageXXX and ImageOperand.

Doesn't include OpTypeImage and OpImageSparseXXX.

Disabled an invalid test.
2017-11-22 14:34:15 -05:00
Alan Baker
a92d69b43d Initial implementation of merge return pass.
Works with current DefUseManager infrastructure.

Added merge return to the standard opts.

Added validation to passes.

Disabled pass for shader capabilty.
2017-11-15 10:27:04 -05:00
Steven Perron
f32d11f74b Add the IRContext (part 2): Add def-use manager
This change will move the instances of the def-use manager to the
IRContext.  This allows it to persists across optimization, and does
not have to be rebuilt multiple times.

Added test to ensure that the IRContext is validating and invalidating
the analyses correctly.
2017-11-08 13:35:34 -05:00