Commit Graph

146 Commits

Author SHA1 Message Date
Steven Perron
8cb0aec724 Remove redundant passes from legalization passes
With work that Alan has done, some passes have become redundant.  ADCE
now removed unused variables.  Dead branch elimination removes
unreachable blocks.  This means we can remove CFG Cleanup and dead
variable elimination.
2018-01-12 17:47:50 -05:00
Alan Baker
3a054e1ddc Adding additional functionality to ADCE.
Modified ADCE to remove dead globals.
* Entry point and execution mode instructions are marked as alive
* Reachable functions and their parameters are marked as alive
* Instruction deletion now deferred until the end of the pass
* Eliminated dead insts set, added IsDead to calculate that value
instead
* Ported applicable dead variable elimination tests
* Ported dead constant elim tests

Added dead function elimination to ADCE
* ported dead function elim tests

Added handling of decoration groups in ADCE
* Uses a custom sorter to traverse decorations in a specific order
* Simplifies necessary checks

Updated -O and -Os pass lists.
2018-01-10 08:35:48 -05:00
Diego Novillo
e5560d64de Fix constant propagation of induction variables.
This fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/1143.
When an instruction transitions from constant to bottom (varying) in the
lattice, we were telling the propagator that the instruction was
varying, but never updating the actual value in the values table.

This led to incorrect value substitutions at the end of propagation.

The patch also re-enables CCP in -O and -Os.
2018-01-08 15:34:35 -05:00
David Neto
3fbbd3c772 Remove CCP from size and performance recipes, pending bugfixes
Currently CCP is incorrectly optimizing loops.
See https://github.com/KhronosGroup/SPIRV-Tools/issues/1143
2018-01-05 14:01:18 -05:00
David Neto
c32e79eeef Add --print-all optimizer option
Adds optimizer API to write disassembly to a given output stream
before each pass, and after the last pass.

Adds spirv-opt --print-all option to write disassembly to stderr
before each pass, and after the last pass.
2018-01-04 18:34:18 -05:00
Steven Perron
7834beea80 Update legalization passes
I've a few passes the legalization passes.  The first is to add the
more specialized load-store removal passes to help improve the compile
time, as was suggested in #1118.

I've also added dead branch elimination while we wait for the behaviour
of dead branch elimination to be folded into CFG cleanup.

I did not add CCP because it seems like most of the constant propagation
what is needed is already being done by the load-store removal passes,
which call `ReplaceAllUsesWith`.  We can reconsider this if needed.
2018-01-04 11:04:49 -05:00
Diego Novillo
135150a1a8 Do not insert Phi nodes in CCP propagator.
In CCP we should not need to insert Phi nodes because CCP never looks at
loads/stores.  This required adjusting two tests that relied on Phi
instructions being inserted.  I changed the tests to have the Phi
instructions pre-inserted.

I also added a new test to make sure that CCP does not try to look
through stores and loads.

Finally, given that CCP does not handle loads/stores, it's better to run
mem2reg before it.  I've changed the -O/-Os schedules to run local
multi-store elimination before CCP.

Although this is just an efficiency fix for CCP, it is
also working around a bug in Phi insertion.  When Phi instructions are
inserted, they are never associated a basic block.  This causes a
segfault when the propagator tries to lookup CFG edges when analyzing
Phi instructions.
2018-01-03 15:12:25 -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
7505d24225 Update the legalization passes.
Changes the set of optimizations done for legalization.  While doing
this, I added documentation to explain why we want each optimization.

A new option "--legalize-hlsl" is added so the legalization passes can
be easily run from the command line.
The legalize option implies skip-validation.
2017-12-20 17:56:03 -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
Alan Baker
616908503d Improving the usability of the type manager. The type manager hashes
types. This allows the lookup of type declaration ids from arbitrarily
constructed types. Users should be cautious when dealing with non-unique
types (structs and potentially pointers) to get the exact id if
necessary.

* Changed the spec composite constant folder to handle ambiguous composites
* Added functionality to create necessary instructions for a type
* Added ability to remove ids from the type manager
2017-12-18 08:20:56 -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
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
Lei Zhang
aec60b8158 Add RegisterLegalizationPasses() into the interface
Add note to mention the use scenario.  The original list came
from Glslang.
2017-11-23 17:26:44 -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
Alan Baker
a771713e42 Adding an unique id to Instruction generated by IRContext
Each instruction is given an unique id that can be used for ordering
purposes. The ids are generated via the IRContext.

Major changes:
* Instructions now contain a uint32_t for unique id and a cached context
pointer
 * Most constructors have been modified to take a context as input
 * unfortunately I cannot remove the default and copy constructors, but
 developers should avoid these
* Added accessors to parents of basic block and function
* Removed the copy constructors for BasicBlock and Function and replaced
them with Clone functions
* Reworked BuildModule to return an IRContext owning the built module
 * Since all instructions require a context, the context now becomes the
basic unit for IR
* Added a constructor to context to create an owned module internally
* Replaced uses of Instruction's copy constructor with Clone whereever I
found them
* Reworked the linker functionality to perform clones into a different
context instead of moves
* Updated many tests to be consistent with the above changes
 * Still need to add new tests to cover added functionality
* Added comparison operators to Instruction
* Added an internal option to LinkerOptions to verify merged ids are
unique
* Added a test for the linker to verify merged ids are unique

* Updated MergeReturnPass to supply a context
* Updated DecorationManager to supply a context for cloned decorations

* Reworked several portions of the def use tests in anticipation of next
set of changes
2017-11-20 17:49:10 -05:00
Steven Perron
3214c3b0ca Add dead function elimination to -O and -Os
This pass is very useful in reducing the size of the code, and reducing
the amount of work done by other optimizations.
2017-11-20 09:41:03 -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
GregF
d86c7ce808 Opt: Remove CommonUniformElimination from -O and -Os (for now)
It is causing crashes for some drivers. Will try to re-enable it once
existing drivers are able to deal better with it.
2017-11-07 16:55:12 -05:00
Steven Perron
476cae6f7d Add the IRContext (part 1)
This is the first part of adding the IRContext.  This class is meant to
hold the extra data that is build on top of the module that it
owns.

The first part will simply create the IRContext class and get it passed
to the passes in place of the module.  For now it does not have any
functionality of its own, but it acts more as a wrapper for the module.

The functions that I added to the IRContext are those that either
traverse the headers or add to them.  I did this because we may decide
to have other ways of dealing with these sections (for example adding a
type pool, or use the decoration manager).

I also added the function that add to the header because the IRContext
needs to know when an instruction is added to update other data
structures appropriately.

Note that there is still lots of work that needs to be done.  There are
still many places that change the module, and do not inform the context.
That will be the next step.
2017-10-31 13:46:05 -04:00
Steven Perron
8d6e4dbc72 Run dead variable elimination when using -O and -Os
We want to run the optimization when using -O and -Os, but it was not
added at part of https://github.com/KhronosGroup/SPIRV-Tools/pull/905.
This change will add that a well as some minor formatting changes
requested in that same pull request.
2017-10-23 22:09:12 -04:00
Steven Perron
5834719fc1 Add pass to remove dead variables at the module level.
There does not seem to be any pass that remove global variables.  I
think we could use one.  This pass will look specifically for global
variables that are not referenced and are not exported.  Any decoration
associated with the variable will also be removed.  However, this could
cause types or constants to become unreferenced.  They will not be
removed.  Another pass will have to be called to remove those.
2017-10-23 13:57:05 -04:00
David Neto
8ec62deb23 The reviewed cfg_cleanup optimize pass 2017-10-19 15:28:09 -04:00
Diego Novillo
c75704ec08 CFG cleanup pass - Remove unreachable blocks.
- Adds a new pass CFGCleanupPass.  This serves as an umbrella pass to
  remove unnecessary cruft from a CFG.
- Currently, the only cleanup operation done is the removal of
  unreachable basic blocks.
- Adds unit tests.
- Adds a flag to spirvopt to execute the pass (--cfg-cleanup).
2017-10-19 15:16:29 -04:00
Diego Novillo
c90d7305e7 Add -O, -Os and -Oconfig flags.
These flags are expanded to a series of spirv-opt flags with the
following semantics:

-O: expands to passes that attempt to improve the performance of the
    generated code.

-Os: expands to passes that attempt to reduce the size of the generated
     code.

-Oconfig=<file> expands to the sequence of passes determined by the
                flags specified in the user-provided file.
2017-10-10 12:14:09 -04:00
Steven Perron
e43c91046b Create the dead function elimination pass
Creates a pass called eliminate dead functions that looks for functions
that could never be called, and deletes them from the module.

To support this change a new function was added to the Pass class to
traverse the call trees from diffent starting points.

Includes a test to ensure that annotations are removed when deleting a
dead function.  They were not, so fixed that up as well.

Did some cleanup of the assembly for the test in pass_test.cpp.  Trying
to make them smaller and easier to read.
2017-09-26 11:18:06 -04:00
Steven Perron
e4c7d8e748 Add strength reduction; for now replace multiply by power of 2
Create a new optimization pass, strength reduction, which will replace
integer multiplication by a constant power of 2 with an equivalent bit
shift.  More changes could be added later.

- Does not duplicate constants

- Adds vector |Concat| utility function to a common test header.
2017-09-18 17:01:36 -04:00
GregF
429ca05b3f Opt: Create InlineOpaquePass
Only inline calls to functions with opaque params or return

TODO: Handle parameter type or return type where the opqaue
type is buried within an array.
2017-08-18 18:04:30 -04:00
GregF
e28bd39997 Inline: Split out InlineExhaustivePass from InlinePass 2017-08-04 17:56:46 -04:00
GregF
f4b29f3bf7 Add CommonUniformElim pass
- UniformElim: Only process reachable blocks

- UniformElim: Don't reuse loads of samplers and images across blocks.
  Added a second phase which only reuses loads within a block for samplers
  and images.

- UniformElim: Upgrade CopyObject skipping in GetPtr

- UniformElim: Add extensions whitelist
  Currently disallowing SPV_KHR_variable_pointers because it doesn't
  handle extended pointer forms.

- UniformElim: Do not process shaders with GroupDecorate

- UniformElim: Bail on shaders with non-32-bit ints.

- UniformElim: Document support for only single index and add TODO.
2017-08-03 11:34:58 -04:00
GregF
9de4e69856 Add AggressiveDCEPass
Create aggressive dead code elimination pass
This pass eliminates unused code from functions. In addition,
it detects and eliminates code which may have spurious uses but which do
not contribute to the output of the function. The most common cause of
such code sequences is summations in loops whose result is no longer used
due to dead code elimination. This optimization has additional compile
time cost over standard dead code elimination.

This pass only processes entry point functions. It also only processes
shaders with logical addressing. It currently will not process functions
with function calls. It currently only supports the GLSL.std.450 extended
instruction set. It currently does not support any extensions.

This pass will be made more effective by first running passes that remove
dead control flow and inlines function calls.

This pass can be especially useful after running Local Access Chain
Conversion, which tends to cause cycles of dead code to be left after
Store/Load elimination passes are completed. These cycles cannot be
eliminated with standard dead code elimination.

Additionally: This transform uses a whitelist of instructions that it
knows do have side effects, (a.k.a. combinators).  It assumes other
instructions have side effects: it will not remove them, and assumes
they have side effects via their ID operands.
2017-07-10 11:30:25 -04:00
GregF
cc8bad3a5b Add LocalMultiStoreElim pass
A SSA local variable load/store elimination pass.
For every entry point function, eliminate all loads and stores of function
scope variables only referenced with non-access-chain loads and stores.
Eliminate the variables as well.

The presence of access chain references and function calls can inhibit
the above optimization.

Only shader modules with logical addressing are currently processed.
Currently modules with any extensions enabled are not processed. This
is left for future work.

This pass is most effective if preceeded by Inlining and
LocalAccessChainConvert. LocalSingleStoreElim and LocalSingleBlockElim
will reduce the work that this pass has to do.
2017-07-07 17:54:21 -04:00
GregF
52e247f221 DeadBranchElim: Add DeadBranchElimPass 2017-07-07 15:16:25 -04:00
GregF
ad1d0351a0 BlockMerge: Add BlockMergePass
Also, add BasicBlock::tail()
2017-06-27 11:31:33 -04:00
GregF
6136bf9e0b mem2reg: Add InsertExtractElimPass 2017-06-21 08:13:15 -04:00
GregF
0c5722fc01 mem2reg: Add LocalSingleStoreElimPass
Eliminate function scope variables with one store, if possible.
2017-06-19 10:43:02 -04:00
GregF
7c8da66bc2 mem2reg: Add pass to eliminate local loads and stores in single block. 2017-06-12 17:03:47 -04:00
GregF
aa7e687ef0 Mem2Reg: Add Local Access Chain Convert pass
- Supports OpAccessChain and OpInBoundsAccessChain
- Does not process modules with non-32-bit integer types.
2017-06-04 12:49:27 -04:00
qining
144f59e451 Add bit pattern interface for setting default value for spec constants 2017-04-21 11:22:47 -04:00
Andrey Tuganov
1e309af80a Added --compact-ids to /tools/opt
The pass remaps ids to a compact set which starts with %1 and
has no gaps.
2017-04-20 10:54:39 -04:00
David Neto
11a867f412 Add FlattenDecoration transform
Add --flatten-decorations to spirv-opt

Flattens decoration groups.  That is, replace OpDecorationGroup
and its uses in OpGroupDecorate and OpGroupMemberDecorate with
ordinary OpDecorate and OpMemberDecorate instructions.

Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/602
2017-04-06 11:19:56 -04:00
David Neto
afc60bbebf Fix optimizer on when to write the binary
The spvtools::Optimizer::Run method should also write the output binary
if optimization succeeds without changes but the output binary vector
does not have exactly the same contents as the input binary.
We have to check both the base pointer of the storage and the size of
the vector

Added a test for this too.

Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/611
2017-04-03 15:48:50 -04:00
Greg Fischer
04fcc66743 Add exhaustive function call inlining to spirv-opt
Inlining is done for all functions designated as entry points.

Add optional validation to test fixture method SinglePassRunAndCheck.
2017-03-29 18:02:40 -04:00
Lei Zhang
620f05e679 Publish the C++ interface. 2016-09-21 14:41:47 -04:00
Lei Zhang
f18e1f293b Add a C++ interface to the optimization functionalities. 2016-09-20 16:52:05 -04:00