[ir] Convert FlowNode to Block where possible.
This CL updates a bunch of uses of FlowNode to use Block instead. The InboundBranches are moved from FlowNode to Block. Bug: tint:1718 Change-Id: Ic1c07dae103e25364a3a6b3333cfcb57d10b30c2 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/134260 Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
0089d5e6e2
commit
f55ef5e48b
|
@ -35,7 +35,7 @@ class Block : public utils::Castable<Block, FlowNode> {
|
|||
~Block() override;
|
||||
|
||||
/// @returns true if this is block has a branch target set
|
||||
bool HasBranchTarget() const override {
|
||||
bool HasBranchTarget() const {
|
||||
return !instructions_.IsEmpty() && instructions_.Back()->Is<ir::Branch>();
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ class Block : public utils::Castable<Block, FlowNode> {
|
|||
|
||||
/// @param target the block to see if we trampoline too
|
||||
/// @returns if this block just branches to the provided target.
|
||||
bool IsTrampoline(const FlowNode* target) const {
|
||||
bool IsTrampoline(const Block* target) const {
|
||||
if (instructions_.Length() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
@ -78,9 +78,26 @@ class Block : public utils::Castable<Block, FlowNode> {
|
|||
/// @returns the params to the block
|
||||
utils::Vector<const BlockParam*, 0>& Params() { return params_; }
|
||||
|
||||
/// @returns true if this node has inbound branches and branches out
|
||||
bool IsConnected() const { return HasBranchTarget(); }
|
||||
|
||||
/// @returns the inbound branch list for the flow node
|
||||
utils::VectorRef<ir::Branch*> InboundBranches() const { return inbound_branches_; }
|
||||
|
||||
/// Adds the given node to the inbound branches
|
||||
/// @param node the node to add
|
||||
void AddInboundBranch(ir::Branch* node) { inbound_branches_.Push(node); }
|
||||
|
||||
private:
|
||||
utils::Vector<const Instruction*, 16> instructions_;
|
||||
utils::Vector<const BlockParam*, 0> params_;
|
||||
|
||||
/// The list of flow nodes which branch into this node. This list maybe empty for several
|
||||
/// reasons:
|
||||
/// - Node is a start node
|
||||
/// - Node is a merge target outside control flow (e.g. an if that returns in both branches)
|
||||
/// - Node is a continue target outside control flow (e.g. a loop that returns)
|
||||
utils::Vector<ir::Branch*, 2> inbound_branches_;
|
||||
};
|
||||
|
||||
} // namespace tint::ir
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#include "src/tint/ir/flow_node.h"
|
||||
#include "src/tint/ir/block.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::ir::Branch);
|
||||
|
||||
namespace tint::ir {
|
||||
|
||||
Branch::Branch(FlowNode* to, utils::VectorRef<Value*> args) : to_(to), args_(std::move(args)) {
|
||||
Branch::Branch(Block* to, utils::VectorRef<Value*> args) : to_(to), args_(std::move(args)) {
|
||||
TINT_ASSERT(IR, to_);
|
||||
to_->AddInboundBranch(this);
|
||||
for (auto* arg : args) {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
// Forward declarations
|
||||
namespace tint::ir {
|
||||
class FlowNode;
|
||||
class Block;
|
||||
} // namespace tint::ir
|
||||
|
||||
namespace tint::ir {
|
||||
|
@ -32,17 +32,17 @@ class Branch : public utils::Castable<Branch, Instruction> {
|
|||
/// Constructor
|
||||
/// @param to the block to branch too
|
||||
/// @param args the branch arguments
|
||||
explicit Branch(FlowNode* to, utils::VectorRef<Value*> args = {});
|
||||
explicit Branch(Block* to, utils::VectorRef<Value*> args = {});
|
||||
~Branch() override;
|
||||
|
||||
/// @returns the block being branched too.
|
||||
const FlowNode* To() const { return to_; }
|
||||
const Block* To() const { return to_; }
|
||||
|
||||
/// @returns the branch arguments
|
||||
utils::VectorRef<Value*> Args() const { return args_; }
|
||||
|
||||
private:
|
||||
FlowNode* to_;
|
||||
Block* to_;
|
||||
utils::Vector<Value*, 2> args_;
|
||||
};
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ ir::Var* Builder::Declare(const type::Type* type) {
|
|||
return ir.values.Create<ir::Var>(type);
|
||||
}
|
||||
|
||||
ir::Branch* Builder::Branch(FlowNode* to, utils::VectorRef<Value*> args) {
|
||||
ir::Branch* Builder::Branch(Block* to, utils::VectorRef<Value*> args) {
|
||||
return ir.values.Create<ir::Branch>(to, args);
|
||||
}
|
||||
|
||||
|
|
|
@ -402,7 +402,7 @@ class Builder {
|
|||
/// @param to the node being branched too
|
||||
/// @param args the branch arguments
|
||||
/// @returns the instruction
|
||||
ir::Branch* Branch(FlowNode* to, utils::VectorRef<Value*> args = {});
|
||||
ir::Branch* Branch(Block* to, utils::VectorRef<Value*> args = {});
|
||||
|
||||
/// Creates a new `BlockParam`
|
||||
/// @param type the parameter type
|
||||
|
|
|
@ -31,8 +31,8 @@ namespace tint::ir {
|
|||
std::string Debug::AsDotGraph(const Module* mod) {
|
||||
size_t node_count = 0;
|
||||
|
||||
std::unordered_set<const FlowNode*> visited;
|
||||
std::unordered_set<const FlowNode*> merge_nodes;
|
||||
std::unordered_set<const Block*> visited;
|
||||
std::unordered_set<const Block*> merge_nodes;
|
||||
std::unordered_map<const FlowNode*, std::string> node_to_name;
|
||||
utils::StringStream out;
|
||||
|
||||
|
@ -48,7 +48,7 @@ std::string Debug::AsDotGraph(const Module* mod) {
|
|||
return name;
|
||||
};
|
||||
|
||||
std::function<void(const FlowNode*)> Graph = [&](const FlowNode* node) {
|
||||
std::function<void(const Block*)> Graph = [&](const Block* node) {
|
||||
if (visited.count(node) > 0) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#define SRC_TINT_IR_FLOW_NODE_H_
|
||||
|
||||
#include "src/tint/utils/castable.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
// Forward Declarations
|
||||
namespace tint::ir {
|
||||
|
@ -30,30 +29,9 @@ class FlowNode : public utils::Castable<FlowNode> {
|
|||
public:
|
||||
~FlowNode() override;
|
||||
|
||||
/// @returns true if this node has inbound branches and branches out
|
||||
bool IsConnected() const { return HasBranchTarget(); }
|
||||
|
||||
/// @returns true if the node has a branch target
|
||||
virtual bool HasBranchTarget() const { return false; }
|
||||
|
||||
/// @returns the inbound branch list for the flow node
|
||||
utils::VectorRef<Branch*> InboundBranches() const { return inbound_branches_; }
|
||||
|
||||
/// Adds the given node to the inbound branches
|
||||
/// @param node the node to add
|
||||
void AddInboundBranch(Branch* node) { inbound_branches_.Push(node); }
|
||||
|
||||
protected:
|
||||
/// Constructor
|
||||
FlowNode();
|
||||
|
||||
private:
|
||||
/// The list of flow nodes which branch into this node. This list maybe empty for several
|
||||
/// reasons:
|
||||
/// - Node is a start node
|
||||
/// - Node is a merge target outside control flow (e.g. an if that returns in both branches)
|
||||
/// - Node is a continue target outside control flow (e.g. a loop that returns)
|
||||
utils::Vector<Branch*, 2> inbound_branches_;
|
||||
};
|
||||
|
||||
} // namespace tint::ir
|
||||
|
|
|
@ -101,11 +101,7 @@ using ResultType = utils::Result<Module, diag::List>;
|
|||
// For an `if` and `switch` block, the merge has a registered incoming branch instruction of the
|
||||
// `if` and `switch. So, to determine if the merge is connected to any of the branches that happend
|
||||
// in the `if` or `switch` we need a `count` value that is larger then 1.
|
||||
bool IsConnected(const FlowNode* b, uint32_t count) {
|
||||
// Function is always connected as it's the start.
|
||||
if (b->Is<ir::Function>()) {
|
||||
return true;
|
||||
}
|
||||
bool IsConnected(const Block* b, uint32_t count) {
|
||||
return b->InboundBranches().Length() > count;
|
||||
}
|
||||
|
||||
|
@ -170,7 +166,7 @@ class Impl {
|
|||
diagnostics_.add_error(tint::diag::System::IR, err, s);
|
||||
}
|
||||
|
||||
void BranchTo(FlowNode* node, utils::VectorRef<Value*> args = {}) {
|
||||
void BranchTo(Block* node, utils::VectorRef<Value*> args = {}) {
|
||||
TINT_ASSERT(IR, current_flow_block_);
|
||||
TINT_ASSERT(IR, !current_flow_block_->HasBranchTarget());
|
||||
|
||||
|
@ -178,7 +174,7 @@ class Impl {
|
|||
current_flow_block_ = nullptr;
|
||||
}
|
||||
|
||||
void BranchToIfNeeded(FlowNode* node) {
|
||||
void BranchToIfNeeded(Block* node) {
|
||||
if (!current_flow_block_ || current_flow_block_->HasBranchTarget()) {
|
||||
return;
|
||||
}
|
||||
|
@ -752,7 +748,7 @@ class Impl {
|
|||
|
||||
// Discard is being treated as an instruction. The semantics in WGSL is demote_to_helper, so
|
||||
// the code has to continue as before it just predicates writes. If WGSL grows some kind of
|
||||
// terminating discard that would probably make sense as a FlowNode but would then require
|
||||
// terminating discard that would probably make sense as a Block but would then require
|
||||
// figuring out the multi-level exit that is triggered.
|
||||
void EmitDiscard(const ast::DiscardStatement*) {
|
||||
auto* inst = builder_.Discard();
|
||||
|
|
|
@ -98,7 +98,7 @@ class State {
|
|||
if (!ret_ty) {
|
||||
return nullptr;
|
||||
}
|
||||
auto* body = FlowNodeGraph(fn->StartTarget());
|
||||
auto* body = BlockGraph(fn->StartTarget());
|
||||
if (!body) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -108,13 +108,13 @@ class State {
|
|||
std::move(ret_attrs));
|
||||
}
|
||||
|
||||
const ast::BlockStatement* FlowNodeGraph(const ir::Block* start_node) {
|
||||
const ast::BlockStatement* BlockGraph(const ir::Block* start_node) {
|
||||
// TODO(crbug.com/tint/1902): Check if the block is dead
|
||||
utils::Vector<const ast::Statement*,
|
||||
decltype(ast::BlockStatement::statements)::static_length>
|
||||
stmts;
|
||||
|
||||
const ir::FlowNode* block = start_node;
|
||||
const ir::Block* block = start_node;
|
||||
|
||||
// TODO(crbug.com/tint/1902): Handle block arguments.
|
||||
|
||||
|
@ -171,7 +171,7 @@ class State {
|
|||
const ast::IfStatement* If(const ir::If* i) {
|
||||
SCOPED_NESTING();
|
||||
auto* cond = Expr(i->Condition());
|
||||
auto* t = FlowNodeGraph(i->True());
|
||||
auto* t = BlockGraph(i->True());
|
||||
if (TINT_UNLIKELY(!t)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ class State {
|
|||
}
|
||||
return b.If(cond, t, b.Else(f));
|
||||
} else {
|
||||
auto* f = FlowNodeGraph(i->False());
|
||||
auto* f = BlockGraph(i->False());
|
||||
if (!f) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ class State {
|
|||
s->Cases(), //
|
||||
[&](const ir::Switch::Case c) -> const tint::ast::CaseStatement* {
|
||||
SCOPED_NESTING();
|
||||
auto* body = FlowNodeGraph(c.start);
|
||||
auto* body = BlockGraph(c.start);
|
||||
if (!body) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ class State {
|
|||
}
|
||||
|
||||
/// @return true if there are no instructions between @p node and and @p stop_at
|
||||
bool IsEmpty(const ir::Block* node, const ir::FlowNode* stop_at) {
|
||||
bool IsEmpty(const ir::Block* node, const ir::Block* stop_at) {
|
||||
if (node->Instructions().IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue