[tint][ir][ToProgram] Emit 'else if' instead of 'else { if'

Bug: tint:1902
Change-Id: If49a7fd71d72cd562fc49957a5715ea7eefc8b4d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/133140
Kokoro: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2023-05-17 10:43:46 +00:00 committed by Dawn LUCI CQ
parent 1ea1e1a375
commit 6ab77f16f0
2 changed files with 35 additions and 25 deletions

View File

@ -116,10 +116,27 @@ class State {
const ast::IfStatement* If(const ir::If* i) {
auto* cond = Expr(i->condition);
auto* t = FlowNodeGraph(i->true_.target, i->merge.target);
if (!t) {
return nullptr;
}
if (!IsEmpty(i->false_.target, i->merge.target)) {
// TODO(crbug.com/tint/1902): Merge if else
auto* f = FlowNodeGraph(i->false_.target, i->merge.target);
return b.If(cond, t, b.Else(f));
// If the else target is an if flow node with the same merge target as this if, then
// emit an 'else if' instead of a block statement for the else.
if (auto* else_if = As<ir::If>(NextNonEmptyNode(i->false_.target));
else_if &&
NextNonEmptyNode(i->merge.target) == NextNonEmptyNode(else_if->merge.target)) {
auto* f = If(else_if);
if (!f) {
return nullptr;
}
return b.If(cond, t, b.Else(f));
} else {
auto* f = FlowNodeGraph(i->false_.target, i->merge.target);
if (!f) {
return nullptr;
}
return b.If(cond, t, b.Else(f));
}
}
return b.If(cond, t);
}
@ -139,6 +156,21 @@ class State {
return true;
}
/// @return the next flow node that isn't an empty block
const ir::FlowNode* NextNonEmptyNode(const ir::FlowNode* node) {
while (node) {
if (auto* block = node->As<ir::Block>()) {
if (block->instructions.Length() > 0) {
return node;
}
node = block->branch.target;
} else {
return node;
}
}
return nullptr;
}
const ast::Statement* Stmt(const ir::Instruction* inst) {
return Switch(
inst, //

View File

@ -152,28 +152,6 @@ fn f() {
b();
}
}
)",
R"(
fn a() {
}
fn b() {
}
fn c() {
}
fn f() {
var cond_a : bool = true;
var cond_b : bool = true;
if (cond_a) {
a();
} else {
if (cond_b) {
b();
}
}
}
)");
}
} // namespace