diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-04-07 18:09:57 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-04-07 18:13:16 +0300 |
commit | 28930a3bba902127d5e8be057024b7d5615c3cdf (patch) | |
tree | 6a92c991e2330bb29379d70975b0bb895945ec07 | |
parent | 2519370a893cd648a313e981cc41e49a13140a64 (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.cpp | 11 | ||||
-rw-r--r-- | dxil_converter.cpp | 7 | ||||
-rw-r--r-- | ir.hpp | 2 | ||||
-rw-r--r-- | node.cpp | 2 | ||||
-rw-r--r-- | spirv_module.cpp | 10 |
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) { @@ -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; }; @@ -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); |