Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
glslang
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
glslang
Commits
44bfb0d0
Commit
44bfb0d0
authored
Jan 18, 2016
by
Dejan Mircevski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement inReadableOrder().
parent
454796e0
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
87 additions
and
4 deletions
+87
-4
CMakeLists.txt
SPIRV/CMakeLists.txt
+1
-0
InReadableOrder.cpp
SPIRV/InReadableOrder.cpp
+64
-0
spvIR.h
SPIRV/spvIR.h
+22
-4
No files found.
SPIRV/CMakeLists.txt
View file @
44bfb0d0
...
...
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.8)
set
(
SOURCES
GlslangToSpv.cpp
InReadableOrder.cpp
SpvBuilder.cpp
SPVRemapper.cpp
doc.cpp
...
...
SPIRV/InReadableOrder.cpp
0 → 100644
View file @
44bfb0d0
// The SPIR-V spec requires code blocks to appear in an order satisfying the
// dominator-tree direction (ie, dominator before the dominated). This is,
// actually, easy to achieve: any pre-order CFG traversal algorithm will do it.
// Because such algorithms visit a block only after traversing some path to it
// from the root, they necessarily visit the block's idom first.
//
// But not every graph-traversal algorithm outputs blocks in an order that
// appears logical to human readers. The problem is that unrelated branches may
// be interspersed with each other, and merge blocks may come before some of the
// branches being merged.
//
// A good, human-readable order of blocks may be achieved by performing
// depth-first search but delaying merge nodes until after all their branches
// have been visited. This is implemented below by the inReadableOrder()
// function.
#include "spvIR.h"
#include <algorithm>
#include <deque>
#include <unordered_map>
#include <unordered_set>
using
spv
::
Block
;
using
spv
::
Id
;
using
BlockSet
=
std
::
unordered_set
<
Id
>
;
using
IdToBool
=
std
::
unordered_map
<
Id
,
bool
>
;
namespace
{
// True if any of prerequisites have not yet been visited.
bool
delay
(
const
BlockSet
&
prereqs
,
const
IdToBool
&
visited
)
{
return
std
::
any_of
(
prereqs
.
begin
(),
prereqs
.
end
(),
[
&
visited
](
Id
b
)
{
return
!
visited
.
count
(
b
);
});
}
}
void
spv
::
inReadableOrder
(
Block
*
root
,
std
::
function
<
void
(
Block
*
)
>
callback
)
{
// Prerequisites for a merge block; must be completed prior to visiting the
// merge block.
std
::
unordered_map
<
Id
,
BlockSet
>
prereqs
;
IdToBool
visited
;
// Whether a block has already been visited.
std
::
deque
<
Block
*>
worklist
;
// DFS worklist
worklist
.
push_back
(
root
);
while
(
!
worklist
.
empty
())
{
Block
*
current
=
worklist
.
front
();
worklist
.
pop_front
();
// Nodes may be pushed repeadetly (before they're first visited) if they
// have multiple predecessors. Skip the already-visited ones.
if
(
visited
[
current
->
getId
()])
continue
;
callback
(
current
);
visited
[
current
->
getId
()]
=
true
;
if
(
auto
merge
=
current
->
getMergeInstruction
())
{
auto
&
mergePrereqs
=
prereqs
[
merge
->
getIdOperand
(
0
)];
// Delay visiting merge blocks until all branches are visited.
for
(
const
auto
succ
:
current
->
getSuccessors
())
mergePrereqs
.
insert
(
succ
->
getId
());
}
for
(
auto
succ
:
current
->
getSuccessors
())
{
if
(
!
visited
[
succ
->
getId
()]
&&
!
delay
(
prereqs
[
succ
->
getId
()],
visited
))
{
worklist
.
push_back
(
succ
);
}
}
}
}
SPIRV/spvIR.h
View file @
44bfb0d0
...
...
@@ -52,10 +52,11 @@
#include "spirv.hpp"
#include <vector>
#include <cassert>
#include <functional>
#include <iostream>
#include <memory>
#include <
assert.h
>
#include <
vector
>
namespace
spv
{
...
...
@@ -168,6 +169,19 @@ public:
const
std
::
vector
<
Block
*>
getSuccessors
()
const
{
return
successors
;
}
void
setUnreachable
()
{
unreachable
=
true
;
}
bool
isUnreachable
()
const
{
return
unreachable
;
}
// Returns the block's merge instruction, if one exists (otherwise null).
const
Instruction
*
getMergeInstruction
()
const
{
if
(
instructions
.
size
()
<
2
)
return
nullptr
;
const
Instruction
*
nextToLast
=
*
(
instructions
.
cend
()
-
2
);
switch
(
nextToLast
->
getOpCode
())
{
case
OpSelectionMerge
:
case
OpLoopMerge
:
return
nextToLast
;
default
:
return
nullptr
;
}
return
nullptr
;
}
bool
isTerminated
()
const
{
...
...
@@ -217,6 +231,11 @@ protected:
bool
unreachable
;
};
// Traverses the control-flow graph rooted at root in an order suited for
// readable code generation. Invokes callback at every node in the traversal
// order.
void
inReadableOrder
(
Block
*
root
,
std
::
function
<
void
(
Block
*
)
>
callback
);
//
// SPIR-V IR Function.
//
...
...
@@ -253,8 +272,7 @@ public:
parameterInstructions
[
p
]
->
dump
(
out
);
// Blocks
for
(
int
b
=
0
;
b
<
(
int
)
blocks
.
size
();
++
b
)
blocks
[
b
]
->
dump
(
out
);
inReadableOrder
(
blocks
[
0
],
[
&
out
](
const
Block
*
b
)
{
b
->
dump
(
out
);
});
Instruction
end
(
0
,
0
,
OpFunctionEnd
);
end
.
dump
(
out
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment