[ir] Convert tests to use disassembler.

This Cl updates the flow node tests to compare against a disassembled
output instead of explicit expect statements. This makes it easier to
see the structure of the IR and to determine any changes.

Bug: tint:1718
Change-Id: I5b8ab42ada4ba902e8937099c7058a39533f2010
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/116548
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
dan sinclair 2023-01-08 01:29:03 +00:00 committed by Dawn LUCI CQ
parent e3992f2408
commit 97b98619e8
6 changed files with 616 additions and 433 deletions

View File

@ -31,6 +31,10 @@ class Block : public Castable<Block, FlowNode> {
Block(); Block();
~Block() override; ~Block() override;
/// @returns true if this is a dead block. This can happen in the case like a loop merge block
/// which is never reached.
bool IsDead() const { return branch.target == nullptr; }
/// The node this block branches too. /// The node this block branches too.
Branch branch = {}; Branch branch = {};

File diff suppressed because it is too large Load Diff

View File

@ -68,6 +68,8 @@ void Disassembler::EmitBlockInstructions(const Block* b) {
} }
size_t Disassembler::GetIdForNode(const FlowNode* node) { size_t Disassembler::GetIdForNode(const FlowNode* node) {
TINT_ASSERT(IR, node);
auto it = flow_node_to_id_.find(node); auto it = flow_node_to_id_.find(node);
if (it != flow_node_to_id_.end()) { if (it != flow_node_to_id_.end()) {
return it->second; return it->second;
@ -97,6 +99,12 @@ void Disassembler::Walk(const FlowNode* node) {
Walk(f->end_target); Walk(f->end_target);
}, },
[&](const ir::Block* b) { [&](const ir::Block* b) {
// If this block is dead, nothing to do
if (b->IsDead()) {
Indent() << "# Dead" << std::endl;
return;
}
Indent() << "%bb" << GetIdForNode(b) << " = Block" << std::endl; Indent() << "%bb" << GetIdForNode(b) << " = Block" << std::endl;
EmitBlockInstructions(b); EmitBlockInstructions(b);
@ -113,7 +121,11 @@ void Disassembler::Walk(const FlowNode* node) {
} }
v->ToString(out_, mod_.symbols); v->ToString(out_, mod_.symbols);
} }
out_ << ")" << std::endl << std::endl; out_ << ")" << std::endl;
if (!b->branch.target->Is<Terminator>()) {
out_ << std::endl;
}
Walk(b->branch.target); Walk(b->branch.target);
}, },
@ -128,14 +140,17 @@ void Disassembler::Walk(const FlowNode* node) {
for (const auto& c : s->cases) { for (const auto& c : s->cases) {
Indent() << "# Case "; Indent() << "# Case ";
for (const auto& selector : c.selectors) { for (const auto& selector : c.selectors) {
if (&selector != &c.selectors.Front()) {
out_ << " ";
}
if (selector.IsDefault()) { if (selector.IsDefault()) {
out_ << "default "; out_ << "default";
} else { } else {
selector.val->ToString(out_, mod_.symbols); selector.val->ToString(out_, mod_.symbols);
} }
} }
out_ << std::endl; out_ << std::endl;
ScopedIndent case_indent(&indent_size_);
Walk(c.start.target); Walk(c.start.target);
} }
} }
@ -159,8 +174,10 @@ void Disassembler::Walk(const FlowNode* node) {
Walk(i->false_.target); Walk(i->false_.target);
} }
Indent() << "# if merge" << std::endl; if (!i->merge.target->IsDisconnected()) {
Walk(i->merge.target); Indent() << "# if merge" << std::endl;
Walk(i->merge.target);
}
}, },
[&](const ir::Loop* l) { [&](const ir::Loop* l) {
Indent() << "%bb" << GetIdForNode(l) << " = loop" << std::endl; Indent() << "%bb" << GetIdForNode(l) << " = loop" << std::endl;
@ -174,7 +191,6 @@ void Disassembler::Walk(const FlowNode* node) {
} }
Indent() << "# loop continuing" << std::endl; Indent() << "# loop continuing" << std::endl;
ScopedIndent continuing_indent(&indent_size_);
Walk(l->continuing.target); Walk(l->continuing.target);
} }

View File

@ -32,6 +32,9 @@ class FlowNode : public Castable<FlowNode> {
/// - Node is a continue target outside control flow (loop that returns) /// - Node is a continue target outside control flow (loop that returns)
utils::Vector<FlowNode*, 2> inbound_branches; utils::Vector<FlowNode*, 2> inbound_branches;
/// @returns true if this node has no inbound branches
bool IsDisconnected() const { return inbound_branches.IsEmpty(); }
protected: protected:
/// Constructor /// Constructor
FlowNode(); FlowNode();

View File

@ -37,7 +37,7 @@ class If : public Castable<If, FlowNode> {
Branch true_ = {}; Branch true_ = {};
/// The false branch block /// The false branch block
Branch false_ = {}; Branch false_ = {};
/// An block to reconvert the true/false barnches. The block always exists, but there maybe no /// An block to converge the true/false branches. The block always exists, but there maybe no
/// branches into it. (e.g. if both branches `return`) /// branches into it. (e.g. if both branches `return`)
Branch merge = {}; Branch merge = {};
/// Value holding the condition result /// Value holding the condition result

View File

@ -92,6 +92,13 @@ class TestHelperBase : public BASE, public ProgramBuilder {
return gen_->FlowNodeForAstNode(node); return gen_->FlowNodeForAstNode(node);
} }
/// @param mod the module
/// @returns the disassembly string of the module
std::string Disassemble(Module& mod) const {
Disassembler d(mod);
return d.Disassemble();
}
/// @returns the error generated during build, if any /// @returns the error generated during build, if any
std::string Error() const { return error_; } std::string Error() const { return error_; }