Commit Graph

49 Commits

Author SHA1 Message Date
alan-baker
d35a78db57
Switch SPIRV-Tools to use spirv.hpp11 internally (#4981)
Fixes #4960

* Switches to using enum classes with an underlying type to avoid
  undefined behaviour
2022-11-04 17:27:10 -04:00
Steven Perron
d51dc53d2c
Improve algorithm to reorder blocks in a function (#4911)
* Improve algorithm to reorder blocks in a function

In dead branch elimination, blocks can end up in a the wrong order, so
there is code to reorder the blocks in structured order.  The problem is
that the algorithm to do that is very poor.  It involves many searchs in
the function for the correct position to place the block, as well as
moving many block in the vector.

The solution is to write a specialized function in the function class
that will reorder the blocks in structured order.  After computing the
structured order, reordering the block can be done in linear time, with
very little overhead.
2022-08-31 11:06:15 -04:00
Steven Perron
7c5b17d379
Update passes to handle function declarations (#4599)
Spirv-opt has not had to handle module with function declarations.  This
lead many passes to assume that every function has a body.  This is not
always true.  This commit will modify a number of passes to handle
function declarations.

Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/4443
2021-10-28 11:54:37 -04:00
Alastair Donaldson
1f2fcddd39
spirv-opt: Set parent when adding basic block (#4021)
Ensures that the parent of a block is set in Function::AddBasicBlock.
Removes various now unnecessary calls to BasicBlock::SetParent.

Fixes #3912.
2020-11-13 12:33:15 -05:00
Junda Liu
82b378d671
spirv-opt: Add support to prevent functions from being inlined if they have DontInline flag (#3858)
This commit add support for optimizer to not inline functions with DontInline control flag, so that the [noinline] attribute in HLSL will be useful in DXC SPIR-V generation.

This is part of work of github.com/microsoft/DirectXShaderCompiler/issues/3158
2020-10-29 16:38:56 -04:00
André Perez
ee7f0c882f
spirv-opt: Implement opt::Function::HasEarlyReturn function (#3711) 2020-08-18 09:31:24 -04:00
alan-baker
b4c4da3e76
Improve non-semantic instruction handling in the optimizer (#3693)
* 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
2020-08-13 14:54:14 -04:00
Vasyl Teliman
99651228b2
Add RemoveParameter method (#3437) 2020-06-17 10:15:50 -04:00
Jaebaek Seo
50b1557886
Preserve debug info in inline pass (#3349)
Handles the OpenCL100Debug extension in inlining.  It preserves the information that is available while also adding the debug inlined at for all of the inlining that it does.
2020-05-21 13:09:43 -04:00
Steven Perron
63fa9114a9
Do merge return if the return is not at the end of the function. (#3337)
* Do merge return if the return is not at the end of the function.

We will remove the code in inlining to handle a return in the middle of
a function.  To inline those functions, we need to run merge return to
move the return to the end of the function.
2020-05-12 11:56:16 -04:00
Steven Perron
49ca250b44
Delete nullptr in function bb list immedietly (#3326)
When moving blocks around, we ended up with a nullptr for a basic block,
and it was left in the list for a little bit.  However, in that time, it
would end up being dereferenced while traversing the function.

To fix this, we delete it right away.  This was found in an asan build
that runs our current tests.  No new tests are needed, but I did add
extra check asan checks for our asan bot.
2020-04-28 21:54:08 -04:00
Jaebaek Seo
1c8bda3721
Add data structure for DebugScope, DebugDeclare in spirv-opt (#3183)
When DebugScope is given in SPIR-V, each instruction following the
DebugScope is from the lexical scope pointed by the DebugScope in
the high level language. We add DebugScope struction to keep the
scope information in Instruction class. When ir_loader loads
DebugScope/DebugNoScope, it keeps the scope information in
|last_dbg_scope_| and lets following instructions have that scope
information.

In terms of DebugDeclare/DebugValue, if it is in a function body
but outside of a basic block, we keep it in |debug_insts_in_header_|
of Function class. If it is in a basic block, we keep it as a normal
instruction i.e., in a instruction list of BasicBlock.
2020-03-23 11:01:18 -04:00
David Neto
8d0ca43da5 Add method comment for opt::Function::WhileEachInst (#2867)
Also, say that ForEachInst and ForEachParam process instructions/parameters
in order.
2019-09-23 09:36:48 -04:00
Ryan Harrison
f6d9a17843
Add pass to fix some invalid unreachable blocks for WebGPU (#2563)
Attempts to split up unreachable blocks that are used both as a
merge-block and a continue-target.

Fixes #2429
2019-05-09 12:56:10 -04:00
Steven Perron
acd2781952
Handle id overflow in inlining. (#2196)
Have inlining return Failure if the ids overflow.

Part of #1841.
2018-12-18 19:34:03 +00:00
Steven Perron
2d2a512691
Don't inline recursive functions. (#2130)
* Move ProcessFunction* function from pass to the context.

There are a few functions that are used to traverse the call tree.
They currently live in the Pass class, but they have nothing to do with
a pass, and may be needed outside of a pass.  They would be better in
the ir context, or in a specific call tree class if we ever have a need
for it.

* Don't inline recursive functions.

Inlining does not check if a function is recursive or not.  This has
been fine as long as the shader was a Vulkan shader, which forbid
recursive functions.  However, not all shaders are vulkan, so either
we limit inlining to Vulkan shaders or we teach it to look for recursive
functions.

I prefer to keep the passes as general as is reasonable.  The change
does not require much new code in inlining and gives a reason to refactor
some other code.

The changes are to add a member function to the Function class that
checks if that function is recursive or not.

Then this is used in inlining to not inlining a function call if it calls
a recursive function.

* Add id to function analysis

There are a few places that build a map from ids to Function whose
result is that id.  I decided to add an analysis to the context for this
to reduce that code, and simplify some of the functions.

* Add missing file.
2018-11-29 14:24:58 -05:00
greg-lunarg
c37388f1ad Add passes to propagate and eliminate redundant line instructions (#2027). (#2039)
These are bookend passes designed to help preserve line information
across passes which delete, move and clone instructions. The propagation
pass attaches a debug line instruction to every instruction based on
SPIR-V line propagation rules. It should be performed before optimization.
The redundant line elimination pass eliminates all line instructions
which match the previous line instruction. This pass should be performed
at the end of optimization to reduce physical SPIR-V file size.

Fixes #2027.
2018-11-15 14:06:17 -05:00
Diego Novillo
4a4632264e Add IR dumping functions to use during debugging.
When using lldb and/or gdb I frequently get odd std::string failures
when using the IR printing instructions we have now.  This adds the
methods  Instruction::Dump(), BasicBlock::Dump() and Function::Dump() to
emit the output of the pretty print to stderr.

With this I can now reliably print IR from gdb and lldb sessions.
2018-09-14 14:28:34 -04:00
dan sinclair
eda2cfbe12
Cleanup includes. (#1795)
This Cl cleans up the include paths to be relative to the top level
directory. Various include-what-you-use fixes have been added.
2018-08-03 15:06:09 -04:00
dan sinclair
58a6876cee
Rewrite include guards (#1793)
This CL rewrites the include guards to make PRESUBMIT.py include guard
check happy.
2018-08-03 08:05:33 -04:00
dan sinclair
c7da51a085
Cleanup extraneous namespace qualifies in source/opt. (#1716)
This CL follows up on the opt namespacing CLs by removing the
unnecessary opt:: and opt::analysis:: namespace prefixes.
2018-07-12 15:14:43 -04:00
dan sinclair
e477e7573e
Remove the module from opt::Function. (#1717)
The function class provides a {Set|Get}Parent call in order to provide
the context to the LoopDescriptor methods. This CL removes the module
from Function and provides the needed context directly to LoopDescriptor
on creation.
2018-07-12 14:42:05 -04:00
dan sinclair
a5e4a53217
Remove context() method from opt::Function (#1700)
This CL removes the context() method from opt::Function. In the places
where the context() was used we can retrieve, or provide, the context in
another fashion.
2018-07-12 10:16:15 -04:00
dan sinclair
e6b953361d
Move the ir namespace to opt. (#1680)
This CL moves the files in opt/ to consistenly be under the opt::
namespace. This frees up the ir:: namespace so it can be used to make a
shared ir represenation.
2018-07-09 11:32:29 -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
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
Steven Perron
b3daa93b46 Change merge return pass to handle structured cfg.
We are seeing shaders that have multiple returns in a functions.  These
functions must get inlined for legalization purposes; however, the
inliner does not know how to inline functions that have multiple
returns.

The solution we will go with it to improve the merge return pass to
handle structured control flow.

Note that the merge return pass will assume the cfg has been cleanedup
by dead branch elimination.

Fixes #857.
2018-03-19 13:49:04 -04:00
Victor Lomuller
90e1637ce4 Remove Function::GetBlocks pushed by accident 2018-02-27 21:07:10 -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
Alan Baker
672494da13 Adding ostream operators for IR structures
* Added for Instruction, BasicBlock, Function and Module
* Uses new disassembly functionality that can disassemble individual
instructions
 * For debug use only (no caching is done)
 * Each output converts module to binary, parses and outputs an
 individual instruction
* Added a test for whole module output
* Disabling Microsoft checked iterator warnings
* Updated check_copyright.py to accept 2018
2018-01-12 11:19:58 -05:00
Pierre Moreau
7183ad526e Linker code cleanups
Turn `Linker::Link()` into free functions

  As very little information was kept in the Linker class, we can get rid
  of the whole class and have the `Link()` as free functions instead; the
  environment target as well as the consumer are passed along through an
  `spv_context` object.
  The resulting linked_binary is passed as a pointer rather than a
  reference to follow the Google C++ Style guidelines.

  Addresses remaining comments from
  https://github.com/KhronosGroup/SPIRV-Tools/pull/693 about the SPIR-V
  linker.

Fix variable naming in the linker

  Some of the variables were using mixed case, which did not follow the
  Google C++ Style guidelines.

Linker: Use EXPECT_EQ when possible and update some test

* Replace occurrences of ASSERT_EQ by EXPECT_EQ when possible;
* Reformulated some of the error messages;
* Added the symbol name in the error message when there is a type or
  decoration mismatch between the imported and exported declarations.

Opt: List all duplicates removed by RemoveDuplicatePass in the header

Opt: Make the const version of GetLabelInst() return a pointer

  For consistency with the non-const version, as well as other similar
  functions.

Opt: Rename function_end to EndInst()

  As pointed out by dneto0 the previous name was quite confusing and could
  be mistaken with a function returning an end iterator.
  Also change the return type of the const version to a pointer rather
  than a reference, for consistency.

Opt: Add performance comment to RemoveDuplicateTypes and decorations

  This comment was requested during the review of
  https://github.com/KhronosGroup/SPIRV-Tools/pull/693.

Opt: Add comments and fix variable naming in RemoveDuplicatePass

* Add missing comments to private functions;
* Rename variables that were using mixed case;
* Add TODO for moving AreTypesEqual out.

Linker: Remove commented out code and add TODOs

Linker: Merged together strings that were too much splitted

Implement a C++ RAII wrapper around spv_context
2018-01-05 13:28:44 -05:00
Pierre Moreau
f35963588b Opt: Remove commented out duplicated type_id function
This code was wrongly added by #693.
2017-12-18 17:29:21 -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
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
Diego Novillo
d2938e4842 Re-format files in source, source/opt, source/util, source/val and tools.
NFC. This just makes sure every file is formatted following the
formatting definition in .clang-format.

Re-formatted with:

$ clang-format -i $(find source tools include -name '*.cpp')
$ clang-format -i $(find source tools include -name '*.h')
2017-11-08 14:03:08 -05: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
Pierre Moreau
86627f7b3f Implement Linker (module combiner)
Add extra iterators for ir::Module's sections
Add extra getters to ir::Function
Add a const version of BasicBlock::GetLabelInst()

Use the max of all inputs' version as version

Split debug in debug1 and debug2
- Debug1 instructions have to be placed before debug2 instructions.

Error out if different addressing or memory models are found

Exit early if no binaries were given

Error out if entry points are redeclared

Implement copy ctors for Function and BasicBlock
- Visual Studio ends up generating copy constructors that call deleted
  functions while compiling the linker code, while GCC and clang do not.
  So explicitly write those functions to avoid Visual Studio messing up.

Move removing duplicate capabilities to its own pass

Add functions running on all IDs present in an instruction

Remove duplicate SpvOpExtInstImport

Give default options value for link functions

Remove linkage capability if not making a library

Check types before allowing to link

Detect if two types/variables/functions have different decorations

Remove decorations of imported variables/functions and their types

Add a DecorationManager

Add a method for removing all decorations of id

Add methods for removing operands from instructions

Error out if one of the modules has a non-zero schema

Update README.md to talk about the linker

Do not freak out if an imported built-in variable has no export
2017-10-06 18:33:53 -04:00
Greg Fischer
bba812f4e4 Inline: Inline early return function if no returns in loop. 2017-05-12 17:18:00 -04:00
David Neto
4fc930229d opt::Function::cbegin and cend are const 2017-03-31 10:36:10 -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
David Srbecky
b85997a1df Add various accessors needed to read and edit SPIRV code. 2017-03-29 14:38:57 +01:00
David Neto
9fc8658ef3 Relicense SPIRV-Tools under Apache 2.0
Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/383

Finalize v2016.4
2016-09-02 10:00:29 -04:00
David Neto
97fc6aa3b8 ForEachInst optionally runs on attached debug line insts
Also:
- Add const forms of ForEachInst
- Rewrite Module::ToBinary in terms of ForEachInst
- Add Instruction::ToBinaryWithoutAttachedDebugInsts
- Delete the ToBinary method on Function, BasicBlock, and Instruction
  since it can now be implemented with ForEachInst in a less confusing
  way, e.g. without recursion.
- Preserve debug line instructions on OpFunctionEnd (and store that
  instruction as a unique-pointer, for regularity).
2016-08-25 11:43:22 -04:00
Lei Zhang
4b3247feba Avoid non-oneliner definition in class and add missing iterators. 2016-08-12 10:34:47 -04:00
Lei Zhang
645ee1d9e0 Create an iterator class for in-memory representation. 2016-08-11 18:35:12 -04:00
Lei Zhang
80c94a4fa8 Change the interfaces of in-memory representation to use pointers.
Previously we use vectors of objects and move semantics to handle
ownership. That approach has the flaw that inserting an object into
the middle of a vector, which may trigger a vector reallocation,
can invalidate some addresses taken from instructions.

Now the in-memory representation internally uses vector of unique
pointers to handle ownership. Since objects are explicitly heap-
allocated now, pointers to them won't be invalidated by vector
resizing anymore.
2016-08-10 12:11:33 -04:00
Lei Zhang
abf8f6413c Promote ir namespace and create draft libspirv.{h|c}pp. 2016-06-28 14:52:34 -04:00
Lei Zhang
3df8f7cebd Add classes for representing SPIR-V language constructs in memory. 2016-06-24 20:54:06 -04:00