Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HansKristian-Work/dxil-spirv.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Kristian Arntzen <post@arntzen-software.no>2022-04-07 18:09:57 +0300
committerHans-Kristian Arntzen <post@arntzen-software.no>2022-04-07 18:13:16 +0300
commit28930a3bba902127d5e8be057024b7d5615c3cdf (patch)
tree6a92c991e2330bb29379d70975b0bb895945ec07
parent2519370a893cd648a313e981cc41e49a13140a64 (diff)
Consider impossible fallthrough scenarios with default blocks as well.
We only checked cases, but default block is also block like any other. Refactor default blocks to be just a normal case label.
-rw-r--r--cfg_structurizer.cpp11
-rw-r--r--dxil_converter.cpp7
-rw-r--r--ir.hpp2
-rw-r--r--node.cpp2
-rw-r--r--spirv_module.cpp10
5 files changed, 21 insertions, 11 deletions
diff --git a/cfg_structurizer.cpp b/cfg_structurizer.cpp
index dcaa2ad..d181834 100644
--- a/cfg_structurizer.cpp
+++ b/cfg_structurizer.cpp
@@ -86,7 +86,6 @@ void CFGStructurizer::log_cfg_graphviz(const char *path) const
case Terminator::Type::Switch:
for (auto &c : node->ir.terminator.cases)
fprintf(file, "%u -> %u;\n", get_node_id(node), get_node_id(c.node));
- fprintf(file, "%u -> %u;\n", get_node_id(node), get_node_id(node->ir.terminator.default_node));
break;
default:
@@ -141,8 +140,12 @@ void CFGStructurizer::log_cfg(const char *tag) const
case Terminator::Type::Switch:
LOGI(" Switch\n");
for (auto &c : node->ir.terminator.cases)
- LOGI(" Case %u -> %s\n", c.value, c.node->name.c_str());
- LOGI(" Default -> %s\n", node->ir.terminator.default_node->name.c_str());
+ {
+ if (c.is_default)
+ LOGI(" Default -> %s\n", c.node->name.c_str());
+ else
+ LOGI(" Case %u -> %s\n", c.value, c.node->name.c_str());
+ }
break;
case Terminator::Type::Kill:
@@ -2946,8 +2949,6 @@ void CFGStructurizer::retarget_pred_from(CFGNode *new_node, CFGNode *old_succ)
p_term.true_block = new_node;
if (p_term.false_block == old_succ)
p_term.false_block = new_node;
- if (p_term.default_node == old_succ)
- p_term.default_node = new_node;
for (auto &c : p_term.cases)
if (c.node == old_succ)
c.node = new_node;
diff --git a/dxil_converter.cpp b/dxil_converter.cpp
index f36052a..4aa567e 100644
--- a/dxil_converter.cpp
+++ b/dxil_converter.cpp
@@ -5360,7 +5360,12 @@ CFGNode *Converter::Impl::convert_function(llvm::Function *func, CFGNodePool &po
else if (auto *inst = llvm::dyn_cast<llvm::SwitchInst>(instruction))
{
node->ir.terminator.type = Terminator::Type::Switch;
- node->ir.terminator.default_node = bb_map[inst->getDefaultDest()]->node;
+
+ Terminator::Case default_case = {};
+ default_case.is_default = true;
+ default_case.node = bb_map[inst->getDefaultDest()]->node;
+ node->ir.terminator.cases.push_back(default_case);
+
node->ir.terminator.conditional_id = get_id_for_value(inst->getCondition());
for (auto itr = inst->case_begin(); itr != inst->case_end(); ++itr)
{
diff --git a/ir.hpp b/ir.hpp
index c154037..f02b9f3 100644
--- a/ir.hpp
+++ b/ir.hpp
@@ -164,9 +164,9 @@ struct Terminator
CFGNode *node = nullptr;
uint64_t global_order = 0;
uint32_t value = 0;
+ bool is_default = false;
};
Vector<Case> cases;
- CFGNode *default_node = nullptr;
uint32_t return_value = 0;
};
diff --git a/node.cpp b/node.cpp
index c077eeb..8581532 100644
--- a/node.cpp
+++ b/node.cpp
@@ -429,8 +429,6 @@ void CFGNode::retarget_branch(CFGNode *to_prev, CFGNode *to_next)
ir.terminator.true_block = to_next;
if (ir.terminator.false_block == to_prev)
ir.terminator.false_block = to_next;
- if (ir.terminator.default_node == to_prev)
- ir.terminator.default_node = to_next;
for (auto &c : ir.terminator.cases)
if (c.node == to_prev)
c.node = to_next;
diff --git a/spirv_module.cpp b/spirv_module.cpp
index 6b4f8d6..c7d56db 100644
--- a/spirv_module.cpp
+++ b/spirv_module.cpp
@@ -987,10 +987,16 @@ void SPIRVModule::Impl::emit_basic_block(CFGNode *node)
{
auto switch_op = std::make_unique<spv::Instruction>(spv::OpSwitch);
switch_op->addIdOperand(ir.terminator.conditional_id);
- switch_op->addIdOperand(ir.terminator.default_node->id);
- get_spv_block(ir.terminator.default_node)->addPredecessor(bb);
+
+ auto default_itr = std::find_if(ir.terminator.cases.begin(), ir.terminator.cases.end(),
+ [](const Terminator::Case &c) { return c.is_default; });
+ assert(default_itr != ir.terminator.cases.end());
+ switch_op->addIdOperand(default_itr->node->id);
+ get_spv_block(default_itr->node)->addPredecessor(bb);
for (auto &switch_case : ir.terminator.cases)
{
+ if (switch_case.is_default)
+ continue;
switch_op->addImmediateOperand(switch_case.value);
switch_op->addIdOperand(switch_case.node->id);
get_spv_block(switch_case.node)->addPredecessor(bb);