summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/maxwell/control_flow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell/control_flow.cpp')
-rw-r--r--src/shader_recompiler/frontend/maxwell/control_flow.cpp31
1 files changed, 23 insertions, 8 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.cpp b/src/shader_recompiler/frontend/maxwell/control_flow.cpp
index 715c0e92d..4f6707fae 100644
--- a/src/shader_recompiler/frontend/maxwell/control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/control_flow.cpp
@@ -104,6 +104,7 @@ bool HasFlowTest(Opcode opcode) {
104 case Opcode::EXIT: 104 case Opcode::EXIT:
105 case Opcode::JMP: 105 case Opcode::JMP:
106 case Opcode::JMX: 106 case Opcode::JMX:
107 case Opcode::KIL:
107 case Opcode::BRK: 108 case Opcode::BRK:
108 case Opcode::CONT: 109 case Opcode::CONT:
109 case Opcode::LONGJMP: 110 case Opcode::LONGJMP:
@@ -287,6 +288,13 @@ CFG::AnalysisState CFG::AnalyzeInst(Block* block, FunctionId function_id, Locati
287 block->end = pc; 288 block->end = pc;
288 return AnalysisState::Branch; 289 return AnalysisState::Branch;
289 } 290 }
291 case Opcode::KIL: {
292 const Predicate pred{inst.Pred()};
293 const auto ir_pred{static_cast<IR::Pred>(pred.index)};
294 const IR::Condition cond{inst.branch.flow_test, ir_pred, pred.negated};
295 AnalyzeCondInst(block, function_id, pc, EndClass::Kill, cond);
296 return AnalysisState::Branch;
297 }
290 case Opcode::PBK: 298 case Opcode::PBK:
291 case Opcode::PCNT: 299 case Opcode::PCNT:
292 case Opcode::PEXIT: 300 case Opcode::PEXIT:
@@ -324,13 +332,12 @@ CFG::AnalysisState CFG::AnalyzeInst(Block* block, FunctionId function_id, Locati
324 return AnalysisState::Continue; 332 return AnalysisState::Continue;
325 } 333 }
326 const IR::Condition cond{static_cast<IR::Pred>(pred.index), pred.negated}; 334 const IR::Condition cond{static_cast<IR::Pred>(pred.index), pred.negated};
327 AnalyzeCondInst(block, function_id, pc, EndClass::Branch, cond, true); 335 AnalyzeCondInst(block, function_id, pc, EndClass::Branch, cond);
328 return AnalysisState::Branch; 336 return AnalysisState::Branch;
329} 337}
330 338
331void CFG::AnalyzeCondInst(Block* block, FunctionId function_id, Location pc, 339void CFG::AnalyzeCondInst(Block* block, FunctionId function_id, Location pc,
332 EndClass insn_end_class, IR::Condition cond, 340 EndClass insn_end_class, IR::Condition cond) {
333 bool visit_conditional_inst) {
334 if (block->begin != pc) { 341 if (block->begin != pc) {
335 // If the block doesn't start in the conditional instruction 342 // If the block doesn't start in the conditional instruction
336 // mark it as a label to visit it later 343 // mark it as a label to visit it later
@@ -356,14 +363,16 @@ void CFG::AnalyzeCondInst(Block* block, FunctionId function_id, Location pc,
356 // Impersonate the visited block with a virtual block 363 // Impersonate the visited block with a virtual block
357 *block = std::move(virtual_block); 364 *block = std::move(virtual_block);
358 // Set the end properties of the conditional instruction 365 // Set the end properties of the conditional instruction
359 conditional_block->end = visit_conditional_inst ? (pc + 1) : pc; 366 conditional_block->end = pc + 1;
360 conditional_block->end_class = insn_end_class; 367 conditional_block->end_class = insn_end_class;
361 // Add a label to the instruction after the conditional instruction 368 // Add a label to the instruction after the conditional instruction
362 Block* const endif_block{AddLabel(conditional_block, block->stack, pc + 1, function_id)}; 369 Block* const endif_block{AddLabel(conditional_block, block->stack, pc + 1, function_id)};
363 // Branch to the next instruction from the virtual block 370 // Branch to the next instruction from the virtual block
364 block->branch_false = endif_block; 371 block->branch_false = endif_block;
365 // And branch to it from the conditional instruction if it is a branch 372 // And branch to it from the conditional instruction if it is a branch or a kill instruction
366 if (insn_end_class == EndClass::Branch) { 373 // Kill instructions are considered a branch because they demote to a helper invocation and
374 // execution may continue.
375 if (insn_end_class == EndClass::Branch || insn_end_class == EndClass::Kill) {
367 conditional_block->cond = IR::Condition{true}; 376 conditional_block->cond = IR::Condition{true};
368 conditional_block->branch_true = endif_block; 377 conditional_block->branch_true = endif_block;
369 conditional_block->branch_false = nullptr; 378 conditional_block->branch_false = nullptr;
@@ -415,7 +424,7 @@ CFG::AnalysisState CFG::AnalyzeEXIT(Block* block, FunctionId function_id, Locati
415 throw NotImplementedException("Conditional EXIT with PEXIT token"); 424 throw NotImplementedException("Conditional EXIT with PEXIT token");
416 } 425 }
417 const IR::Condition cond{flow_test, static_cast<IR::Pred>(pred.index), pred.negated}; 426 const IR::Condition cond{flow_test, static_cast<IR::Pred>(pred.index), pred.negated};
418 AnalyzeCondInst(block, function_id, pc, EndClass::Exit, cond, false); 427 AnalyzeCondInst(block, function_id, pc, EndClass::Exit, cond);
419 return AnalysisState::Branch; 428 return AnalysisState::Branch;
420 } 429 }
421 if (const std::optional<Location> exit_pc{block->stack.Peek(Token::PEXIT)}) { 430 if (const std::optional<Location> exit_pc{block->stack.Peek(Token::PEXIT)}) {
@@ -425,7 +434,7 @@ CFG::AnalysisState CFG::AnalyzeEXIT(Block* block, FunctionId function_id, Locati
425 block->branch_false = nullptr; 434 block->branch_false = nullptr;
426 return AnalysisState::Branch; 435 return AnalysisState::Branch;
427 } 436 }
428 block->end = pc; 437 block->end = pc + 1;
429 block->end_class = EndClass::Exit; 438 block->end_class = EndClass::Exit;
430 return AnalysisState::Branch; 439 return AnalysisState::Branch;
431} 440}
@@ -505,6 +514,12 @@ std::string CFG::Dot() const {
505 node_uid); 514 node_uid);
506 ++node_uid; 515 ++node_uid;
507 break; 516 break;
517 case EndClass::Kill:
518 dot += fmt::format("\t\t{}->N{};\n", name, node_uid);
519 dot += fmt::format("\t\tN{} [label=\"Kill\"][shape=square][style=stripped];\n",
520 node_uid);
521 ++node_uid;
522 break;
508 } 523 }
509 } 524 }
510 if (function.entrypoint == 8) { 525 if (function.entrypoint == 8) {