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
8548bab1
Commit
8548bab1
authored
Feb 01, 2016
by
GregF
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
spirv-remap: Fixed strings not at end of operands, fixed L/S defect
Also added new op classes.
parent
036a7944
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
90 additions
and
32 deletions
+90
-32
SPVRemapper.cpp
SPIRV/SPVRemapper.cpp
+88
-30
SPVRemapper.h
SPIRV/SPVRemapper.h
+2
-2
No files found.
SPIRV/SPVRemapper.cpp
View file @
8548bab1
...
...
@@ -140,20 +140,17 @@ namespace spv {
}
}
bool
spirvbin_t
::
isFlowCtrl
Open
(
spv
::
Op
opCode
)
const
bool
spirvbin_t
::
isFlowCtrl
(
spv
::
Op
opCode
)
const
{
switch
(
opCode
)
{
case
spv
:
:
OpBranchConditional
:
case
spv
:
:
OpSwitch
:
return
true
;
default
:
return
false
;
}
}
bool
spirvbin_t
::
isFlowCtrlClose
(
spv
::
Op
opCode
)
const
{
switch
(
opCode
)
{
case
spv
:
:
OpBranch
:
case
spv
:
:
OpSwitch
:
case
spv
:
:
OpLoopMerge
:
case
spv
:
:
OpSelectionMerge
:
return
true
;
case
spv
:
:
OpSelectionMerge
:
case
spv
:
:
OpLabel
:
case
spv
:
:
OpFunction
:
case
spv
:
:
OpFunctionEnd
:
return
true
;
default
:
return
false
;
}
}
...
...
@@ -468,20 +465,36 @@ namespace spv {
}
return
nextInst
;
case
spv
:
:
OperandLiteralString
:
// word += literalStringWords(literalString(word)); // for clarity
case
spv
:
:
OperandLiteralString
:
{
const
int
stringWordCount
=
literalStringWords
(
literalString
(
word
));
word
+=
stringWordCount
;
numOperands
-=
(
stringWordCount
-
1
);
// -1 because for() header post-decrements
break
;
}
// Execution mode might have extra literal operands. Skip them.
case
spv
:
:
OperandExecutionMode
:
return
nextInst
;
// Single word operands we simply ignore, as they hold no IDs
// Single word operands we simply ignore, as they hold no IDs
case
spv
:
:
OperandLiteralNumber
:
case
spv
:
:
OperandSource
:
case
spv
:
:
OperandExecutionModel
:
case
spv
:
:
OperandAddressing
:
case
spv
:
:
OperandMemory
:
case
spv
:
:
OperandExecutionMode
:
case
spv
:
:
OperandStorage
:
case
spv
:
:
OperandDimensionality
:
case
spv
:
:
OperandSamplerAddressingMode
:
case
spv
:
:
OperandSamplerFilterMode
:
case
spv
:
:
OperandSamplerImageFormat
:
case
spv
:
:
OperandImageChannelOrder
:
case
spv
:
:
OperandImageChannelDataType
:
case
spv
:
:
OperandImageOperands
:
case
spv
:
:
OperandFPFastMath
:
case
spv
:
:
OperandFPRoundingMode
:
case
spv
:
:
OperandLinkageType
:
case
spv
:
:
OperandAccessQualifier
:
case
spv
:
:
OperandFuncParamAttr
:
case
spv
:
:
OperandDecoration
:
case
spv
:
:
OperandBuiltIn
:
case
spv
:
:
OperandSelect
:
...
...
@@ -493,6 +506,7 @@ namespace spv {
case
spv
:
:
OperandGroupOperation
:
case
spv
:
:
OperandKernelEnqueueFlags
:
case
spv
:
:
OperandKernelProfilingInfo
:
case
spv
:
:
OperandCapability
:
++
word
;
break
;
...
...
@@ -560,7 +574,7 @@ namespace spv {
// Window size for context-sensitive canonicalization values
// Emperical best size from a single data set. TODO: Would be a good tunable.
// We essentially perform
a
a little convolution around each instruction,
// We essentially perform a little convolution around each instruction,
// to capture the flavor of nearby code, to hopefully match to similar
// code in other modules.
static
const
unsigned
windowSize
=
2
;
...
...
@@ -715,18 +729,23 @@ namespace spv {
strip
();
// strip out data we decided to eliminate
}
//
remove bodies of uncalled function
s
//
optimize loads and store
s
void
spirvbin_t
::
optLoadStore
()
{
idset_t
fnLocalVars
;
// Map of load result IDs to what they load
idmap_t
idMap
;
idset_t
fnLocalVars
;
// candidates for removal (only locals)
idmap_t
idMap
;
// Map of load result IDs to what they load
blockmap_t
blockMap
;
// Map of IDs to blocks they first appear in
int
blockNum
=
0
;
// block count, to avoid crossing flow control
// Find all the function local pointers stored at most once, and not via access chains
process
(
[
&
](
spv
::
Op
opCode
,
unsigned
start
)
{
const
int
wordCount
=
asWordCount
(
start
);
// Count blocks, so we can avoid crossing flow control
if
(
isFlowCtrl
(
opCode
))
++
blockNum
;
// Add local variables to the map
if
((
opCode
==
spv
::
OpVariable
&&
spv
[
start
+
3
]
==
spv
::
StorageClassFunction
&&
asWordCount
(
start
)
==
4
))
{
fnLocalVars
.
insert
(
asId
(
start
+
2
));
...
...
@@ -741,27 +760,40 @@ namespace spv {
}
if
(
opCode
==
spv
::
OpLoad
&&
fnLocalVars
.
count
(
asId
(
start
+
3
))
>
0
)
{
// Avoid loads before stores (TODO: why? Crashes driver, but seems like it shouldn't).
if
(
idMap
.
find
(
asId
(
start
+
3
))
==
idMap
.
end
())
{
fnLocalVars
.
erase
(
asId
(
start
+
3
));
idMap
.
erase
(
asId
(
start
+
3
));
const
spv
::
Id
varId
=
asId
(
start
+
3
);
// Avoid loads before stores
if
(
idMap
.
find
(
varId
)
==
idMap
.
end
())
{
fnLocalVars
.
erase
(
varId
);
idMap
.
erase
(
varId
);
}
// don't do for volatile references
if
(
wordCount
>
4
&&
(
spv
[
start
+
4
]
&
spv
::
MemoryAccessVolatileMask
))
{
fnLocalVars
.
erase
(
asId
(
start
+
3
));
idMap
.
erase
(
asId
(
start
+
3
));
fnLocalVars
.
erase
(
varId
);
idMap
.
erase
(
varId
);
}
// Handle flow control
if
(
blockMap
.
find
(
varId
)
==
blockMap
.
end
())
{
blockMap
[
varId
]
=
blockNum
;
// track block we found it in.
}
else
if
(
blockMap
[
varId
]
!=
blockNum
)
{
fnLocalVars
.
erase
(
varId
);
// Ignore if crosses flow control
idMap
.
erase
(
varId
);
}
return
true
;
}
if
(
opCode
==
spv
::
OpStore
&&
fnLocalVars
.
count
(
asId
(
start
+
1
))
>
0
)
{
if
(
idMap
.
find
(
asId
(
start
+
1
))
==
idMap
.
end
())
{
idMap
[
asId
(
start
+
1
)]
=
asId
(
start
+
2
);
const
spv
::
Id
varId
=
asId
(
start
+
1
);
if
(
idMap
.
find
(
varId
)
==
idMap
.
end
())
{
idMap
[
varId
]
=
asId
(
start
+
2
);
}
else
{
// Remove if it has more than one store to the same pointer
fnLocalVars
.
erase
(
asId
(
start
+
1
)
);
idMap
.
erase
(
asId
(
start
+
1
)
);
fnLocalVars
.
erase
(
varId
);
idMap
.
erase
(
varId
);
}
// don't do for volatile references
...
...
@@ -769,6 +801,15 @@ namespace spv {
fnLocalVars
.
erase
(
asId
(
start
+
3
));
idMap
.
erase
(
asId
(
start
+
3
));
}
// Handle flow control
if
(
blockMap
.
find
(
varId
)
==
blockMap
.
end
())
{
blockMap
[
varId
]
=
blockNum
;
// track block we found it in.
}
else
if
(
blockMap
[
varId
]
!=
blockNum
)
{
fnLocalVars
.
erase
(
varId
);
// Ignore if crosses flow control
idMap
.
erase
(
varId
);
}
return
true
;
}
...
...
@@ -792,12 +833,27 @@ namespace spv {
},
op_fn_nop
);
// Chase replacements to their origins, in case there is a chain such as:
// 2 = store 1
// 3 = load 2
// 4 = store 3
// 5 = load 4
// We want to replace uses of 5 with 1.
for
(
const
auto
&
idPair
:
idMap
)
{
spv
::
Id
id
=
idPair
.
first
;
while
(
idMap
.
find
(
id
)
!=
idMap
.
end
())
// Chase to end of chain
id
=
idMap
[
id
];
idMap
[
idPair
.
first
]
=
id
;
// replace with final result
}
// Remove the load/store/variables for the ones we've discovered
process
(
[
&
](
spv
::
Op
opCode
,
unsigned
start
)
{
if
((
opCode
==
spv
::
OpLoad
&&
fnLocalVars
.
count
(
asId
(
start
+
3
))
>
0
)
||
(
opCode
==
spv
::
OpStore
&&
fnLocalVars
.
count
(
asId
(
start
+
1
))
>
0
)
||
(
opCode
==
spv
::
OpVariable
&&
fnLocalVars
.
count
(
asId
(
start
+
2
))
>
0
))
{
stripInst
(
start
);
return
true
;
}
...
...
@@ -805,7 +861,9 @@ namespace spv {
return
false
;
},
[
&
](
spv
::
Id
&
id
)
{
if
(
idMap
.
find
(
id
)
!=
idMap
.
end
())
id
=
idMap
[
id
];
}
[
&
](
spv
::
Id
&
id
)
{
if
(
idMap
.
find
(
id
)
!=
idMap
.
end
())
id
=
idMap
[
id
];
}
);
strip
();
// strip out data we decided to eliminate
...
...
SPIRV/SPVRemapper.h
View file @
8548bab1
...
...
@@ -131,6 +131,7 @@ private:
// Local to global, or global to local ID map
typedef
std
::
unordered_map
<
spv
::
Id
,
spv
::
Id
>
idmap_t
;
typedef
std
::
unordered_set
<
spv
::
Id
>
idset_t
;
typedef
std
::
unordered_map
<
spv
::
Id
,
int
>
blockmap_t
;
void
remap
(
std
::
uint32_t
opts
=
DO_EVERYTHING
);
...
...
@@ -164,8 +165,7 @@ private:
bool
isConstOp
(
spv
::
Op
opCode
)
const
;
bool
isTypeOp
(
spv
::
Op
opCode
)
const
;
bool
isStripOp
(
spv
::
Op
opCode
)
const
;
bool
isFlowCtrlOpen
(
spv
::
Op
opCode
)
const
;
bool
isFlowCtrlClose
(
spv
::
Op
opCode
)
const
;
bool
isFlowCtrl
(
spv
::
Op
opCode
)
const
;
range_t
literalRange
(
spv
::
Op
opCode
)
const
;
range_t
typeRange
(
spv
::
Op
opCode
)
const
;
range_t
constRange
(
spv
::
Op
opCode
)
const
;
...
...
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