Improve handling of dead blocks.
All tests pass now. Still need to handle OpFunction, atomics, OpPhi, etc ...
This commit is contained in:
parent
dad4a34072
commit
edbe867b74
@ -19,7 +19,6 @@ layout(binding = 1, std430) buffer HeightmapFFT
|
||||
uvec2 workaround_mix(uvec2 a, uvec2 b, bvec2 sel)
|
||||
{
|
||||
uint _137;
|
||||
uint _148;
|
||||
if (sel.x)
|
||||
{
|
||||
_137 = b.x;
|
||||
@ -29,6 +28,7 @@ uvec2 workaround_mix(uvec2 a, uvec2 b, bvec2 sel)
|
||||
_137 = a.x;
|
||||
}
|
||||
uint _147 = _137;
|
||||
uint _148;
|
||||
if (sel.y)
|
||||
{
|
||||
_148 = b.y;
|
||||
|
@ -18,9 +18,6 @@ void main()
|
||||
vec4 idat = _24.in_data[ident];
|
||||
int k = 0;
|
||||
uint i = 0u;
|
||||
uint i_1;
|
||||
uint j;
|
||||
int l;
|
||||
if ((idat.y == 20.0))
|
||||
{
|
||||
do
|
||||
@ -63,10 +60,10 @@ void main()
|
||||
idat = (idat * 2.0);
|
||||
k = (k + 1);
|
||||
}
|
||||
i_1 = 0u;
|
||||
uint i_1 = 0u;
|
||||
for (; (i_1 < 16u); i_1 = (i_1 + uint(1)), k = (k + 1))
|
||||
{
|
||||
j = 0u;
|
||||
uint j = 0u;
|
||||
for (; (j < 30u); j = (j + uint(1)))
|
||||
{
|
||||
idat = (_24.mvp * idat);
|
||||
@ -93,7 +90,7 @@ void main()
|
||||
{
|
||||
k = (k + 1);
|
||||
} while ((k > 10));
|
||||
l = 0;
|
||||
int l = 0;
|
||||
for (;;)
|
||||
{
|
||||
if ((l == 5))
|
||||
|
@ -9,7 +9,6 @@ layout(binding = 1, std430) buffer SSBO2
|
||||
void main()
|
||||
{
|
||||
uint ident = gl_GlobalInvocationID.x;
|
||||
int i;
|
||||
if ((ident == 2u))
|
||||
{
|
||||
_27.out_data[ident] = vec4(20.0);
|
||||
@ -22,7 +21,7 @@ void main()
|
||||
return;
|
||||
}
|
||||
}
|
||||
i = 0;
|
||||
int i = 0;
|
||||
for (; (i < 20); i = (i + 1))
|
||||
{
|
||||
if ((i == 10))
|
||||
|
@ -17,8 +17,6 @@ void main()
|
||||
uint ident = gl_GlobalInvocationID.x;
|
||||
vec4 idat = _24.in_data[ident];
|
||||
int k = 0;
|
||||
uint i;
|
||||
uint j;
|
||||
for (;;)
|
||||
{
|
||||
int _39 = k;
|
||||
@ -35,10 +33,10 @@ void main()
|
||||
break;
|
||||
}
|
||||
}
|
||||
i = 0u;
|
||||
uint i = 0u;
|
||||
for (; (i < 16u); i = (i + uint(1)), k = (k + 1))
|
||||
{
|
||||
j = 0u;
|
||||
uint j = 0u;
|
||||
for (; (j < 30u); j = (j + uint(1)))
|
||||
{
|
||||
idat = (_24.mvp * idat);
|
||||
|
@ -15,7 +15,6 @@ void main()
|
||||
bool f = true;
|
||||
FragColor = vec4(mix(vIn2, vIn3, f));
|
||||
highp vec4 _35;
|
||||
highp float _44;
|
||||
if (f)
|
||||
{
|
||||
_35 = vIn0;
|
||||
@ -25,6 +24,7 @@ void main()
|
||||
_35 = vIn1;
|
||||
}
|
||||
FragColor = _35;
|
||||
highp float _44;
|
||||
if (f)
|
||||
{
|
||||
_44 = vIn2;
|
||||
|
@ -99,7 +99,6 @@ void main()
|
||||
{
|
||||
vec2 p0 = vPatchPosBase[0];
|
||||
vec2 param = p0;
|
||||
vec2 param_1;
|
||||
if ((!frustum_cull(param)))
|
||||
{
|
||||
gl_TessLevelOuter[0] = -1.0;
|
||||
@ -111,7 +110,7 @@ void main()
|
||||
}
|
||||
else
|
||||
{
|
||||
param_1 = p0;
|
||||
vec2 param_1 = p0;
|
||||
compute_tess_levels(param_1);
|
||||
}
|
||||
}
|
||||
|
@ -58,10 +58,7 @@ vec2 warp_position()
|
||||
uint ufloor_lod = uint(floor_lod);
|
||||
uvec2 uPosition = uvec2(Position);
|
||||
uvec2 mask = ((uvec2(1u) << uvec2(ufloor_lod, (ufloor_lod + 1u))) - uvec2(1u));
|
||||
uvec2 rounding;
|
||||
uint _332;
|
||||
uint _343;
|
||||
vec4 lower_upper_snapped;
|
||||
if ((uPosition.x < 32u))
|
||||
{
|
||||
_332 = mask.x;
|
||||
@ -71,6 +68,7 @@ vec2 warp_position()
|
||||
_332 = 0u;
|
||||
}
|
||||
uint _342 = _332;
|
||||
uint _343;
|
||||
if ((uPosition.y < 32u))
|
||||
{
|
||||
_343 = mask.y;
|
||||
@ -79,8 +77,8 @@ vec2 warp_position()
|
||||
{
|
||||
_343 = 0u;
|
||||
}
|
||||
rounding = uvec2(_342, _343);
|
||||
lower_upper_snapped = vec4(((uPosition + rounding).xyxy & (~mask).xxyy));
|
||||
uvec2 rounding = uvec2(_342, _343);
|
||||
vec4 lower_upper_snapped = vec4(((uPosition + rounding).xyxy & (~mask).xxyy));
|
||||
return mix(lower_upper_snapped.xy, lower_upper_snapped.zw, vec2(fract_lod));
|
||||
}
|
||||
|
||||
|
@ -59,12 +59,7 @@ vec2 warp_position()
|
||||
uint ufloor_lod = uint(floor_lod);
|
||||
uvec4 uPosition = uvec4(Position);
|
||||
uvec2 mask = ((uvec2(1u) << uvec2(ufloor_lod, (ufloor_lod + 1u))) - uvec2(1u));
|
||||
uvec4 rounding;
|
||||
uint _333;
|
||||
uint _345;
|
||||
uint _356;
|
||||
uint _368;
|
||||
vec4 lower_upper_snapped;
|
||||
if ((uPosition.x < 32u))
|
||||
{
|
||||
_333 = mask.x;
|
||||
@ -73,7 +68,9 @@ vec2 warp_position()
|
||||
{
|
||||
_333 = 0u;
|
||||
}
|
||||
uvec4 rounding;
|
||||
rounding.x = _333;
|
||||
uint _345;
|
||||
if ((uPosition.y < 32u))
|
||||
{
|
||||
_345 = mask.x;
|
||||
@ -83,6 +80,7 @@ vec2 warp_position()
|
||||
_345 = 0u;
|
||||
}
|
||||
rounding.y = _345;
|
||||
uint _356;
|
||||
if ((uPosition.x < 32u))
|
||||
{
|
||||
_356 = mask.y;
|
||||
@ -92,6 +90,7 @@ vec2 warp_position()
|
||||
_356 = 0u;
|
||||
}
|
||||
rounding.z = _356;
|
||||
uint _368;
|
||||
if ((uPosition.y < 32u))
|
||||
{
|
||||
_368 = mask.y;
|
||||
@ -101,7 +100,7 @@ vec2 warp_position()
|
||||
_368 = 0u;
|
||||
}
|
||||
rounding.w = _368;
|
||||
lower_upper_snapped = vec4(((uPosition.xyxy + rounding) & (~mask).xxyy));
|
||||
vec4 lower_upper_snapped = vec4(((uPosition.xyxy + rounding) & (~mask).xxyy));
|
||||
return mix(lower_upper_snapped.xy, lower_upper_snapped.zw, vec2(fract_lod));
|
||||
}
|
||||
|
||||
|
@ -16,47 +16,21 @@
|
||||
|
||||
#include "spirv_cfg.hpp"
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace spirv_cross
|
||||
{
|
||||
CFG::CFG(Compiler &compiler_, const SPIRFunction &func_)
|
||||
: compiler(compiler_), func(func_)
|
||||
: compiler(compiler_)
|
||||
, func(func_)
|
||||
{
|
||||
preceding_edges.resize(compiler.get_current_id_bound());
|
||||
succeeding_edges.resize(compiler.get_current_id_bound());
|
||||
visit_order.resize(compiler.get_current_id_bound());
|
||||
immediate_dominators.resize(compiler.get_current_id_bound());
|
||||
|
||||
// Set up all edges between blocks.
|
||||
for (auto block_id : func.blocks)
|
||||
{
|
||||
auto &block = compiler.get<SPIRBlock>(block_id);
|
||||
|
||||
switch (block.terminator)
|
||||
{
|
||||
case SPIRBlock::Direct:
|
||||
add_branch(block.self, block.next_block);
|
||||
break;
|
||||
|
||||
case SPIRBlock::Select:
|
||||
add_branch(block.self, block.true_block);
|
||||
add_branch(block.self, block.false_block);
|
||||
break;
|
||||
|
||||
case SPIRBlock::MultiSelect:
|
||||
for (auto &target : block.cases)
|
||||
add_branch(block.self, target.block);
|
||||
if (block.default_block)
|
||||
add_branch(block.self, block.default_block);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
build_post_order_visit_order();
|
||||
build_immediate_dominators();
|
||||
}
|
||||
@ -98,28 +72,58 @@ void CFG::build_immediate_dominators()
|
||||
{
|
||||
if (!immediate_dominators[block])
|
||||
immediate_dominators[block] = edge;
|
||||
else if (immediate_dominators[block] && immediate_dominators[edge])
|
||||
else
|
||||
{
|
||||
assert(immediate_dominators[edge]);
|
||||
immediate_dominators[block] = update_common_dominator(block, edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CFG::post_order_visit(uint32_t block)
|
||||
bool CFG::post_order_visit(uint32_t block_id)
|
||||
{
|
||||
// If we have already branched to this block (back edge), stop recursion.
|
||||
if (visit_order[block] >= 0)
|
||||
return;
|
||||
if (visit_order[block_id] >= 0)
|
||||
return false;
|
||||
|
||||
// Block back-edges from recursively revisiting ourselves.
|
||||
visit_order[block] = 0;
|
||||
visit_order[block_id] = 0;
|
||||
|
||||
// First visit our branch targets.
|
||||
auto &succeeding = succeeding_edges[block];
|
||||
for (auto &id : succeeding)
|
||||
post_order_visit(id);
|
||||
auto &block = compiler.get<SPIRBlock>(block_id);
|
||||
switch (block.terminator)
|
||||
{
|
||||
case SPIRBlock::Direct:
|
||||
if (post_order_visit(block.next_block))
|
||||
add_branch(block_id, block.next_block);
|
||||
break;
|
||||
|
||||
case SPIRBlock::Select:
|
||||
if (post_order_visit(block.true_block))
|
||||
add_branch(block_id, block.true_block);
|
||||
if (post_order_visit(block.false_block))
|
||||
add_branch(block_id, block.false_block);
|
||||
break;
|
||||
|
||||
case SPIRBlock::MultiSelect:
|
||||
for (auto &target : block.cases)
|
||||
{
|
||||
if (post_order_visit(target.block))
|
||||
add_branch(block_id, target.block);
|
||||
}
|
||||
if (block.default_block && post_order_visit(block.default_block))
|
||||
add_branch(block_id, block.default_block);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Then visit ourselves.
|
||||
visit_order[block] = visit_count++;
|
||||
post_order.push_back(block);
|
||||
visit_order[block_id] = visit_count++;
|
||||
post_order.push_back(block_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CFG::build_post_order_visit_order()
|
||||
@ -143,12 +147,18 @@ void CFG::add_branch(uint32_t from, uint32_t to)
|
||||
}
|
||||
|
||||
DominatorBuilder::DominatorBuilder(const CFG &cfg_)
|
||||
: cfg(cfg_)
|
||||
: cfg(cfg_)
|
||||
{
|
||||
}
|
||||
|
||||
void DominatorBuilder::add_block(uint32_t block)
|
||||
{
|
||||
if (!cfg.get_immediate_dominator(block))
|
||||
{
|
||||
// Unreachable block via the CFG, we will never emit this code anyways.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dominator)
|
||||
{
|
||||
dominator = block;
|
||||
|
@ -55,7 +55,7 @@ private:
|
||||
void add_branch(uint32_t from, uint32_t to);
|
||||
void build_post_order_visit_order();
|
||||
void build_immediate_dominators();
|
||||
void post_order_visit(uint32_t block);
|
||||
bool post_order_visit(uint32_t block);
|
||||
uint32_t visit_count = 0;
|
||||
|
||||
uint32_t update_common_dominator(uint32_t a, uint32_t b);
|
||||
|
@ -2734,6 +2734,39 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
|
||||
void set_current_block(const SPIRBlock &block)
|
||||
{
|
||||
current_block = █
|
||||
|
||||
// If we're branching to a block which uses OpPhi, in GLSL
|
||||
// this will be a variable write when we branch,
|
||||
// so we need to track access to these variables as well to
|
||||
// have a complete picture.
|
||||
const auto test_phi = [this, &block](uint32_t to) {
|
||||
auto &next = compiler.get<SPIRBlock>(to);
|
||||
for (auto &phi : next.phi_variables)
|
||||
if (phi.parent == block.self)
|
||||
accessed_variables_to_block[phi.function_variable].insert(block.self);
|
||||
};
|
||||
|
||||
switch (block.terminator)
|
||||
{
|
||||
case SPIRBlock::Direct:
|
||||
test_phi(block.next_block);
|
||||
break;
|
||||
|
||||
case SPIRBlock::Select:
|
||||
test_phi(block.true_block);
|
||||
test_phi(block.false_block);
|
||||
break;
|
||||
|
||||
case SPIRBlock::MultiSelect:
|
||||
for (auto &target : block.cases)
|
||||
test_phi(target.block);
|
||||
if (block.default_block)
|
||||
test_phi(block.default_block);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool handle(spv::Op op, const uint32_t *args, uint32_t length)
|
||||
@ -2808,7 +2841,12 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
|
||||
|
||||
// Add it to a per-block list of variables.
|
||||
uint32_t dominating_block = builder.get_dominator();
|
||||
auto &block = get<SPIRBlock>(dominating_block);
|
||||
block.dominated_variables.push_back(var.first);
|
||||
// If all blocks here are dead code, this will be 0, so the variable in question
|
||||
// will be completely eliminated.
|
||||
if (dominating_block)
|
||||
{
|
||||
auto &block = get<SPIRBlock>(dominating_block);
|
||||
block.dominated_variables.push_back(var.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user