namespace r600_sb {
+int dce_cleanup::run() {
+ int r;
+
+ // Run cleanup for as long as there are unused nodes.
+ do {
+ nodes_changed = false;
+ r = vpass::run();
+ } while (r == 0 && nodes_changed);
+
+ return r;
+}
+
bool dce_cleanup::visit(node& n, bool enter) {
if (enter) {
} else {
void dce_cleanup::cleanup_dst(node& n) {
if (!cleanup_dst_vec(n.dst) && remove_unused &&
!n.dst.empty() && !(n.flags & NF_DONT_KILL) && n.parent)
+ {
+ // Delete use references to the removed node from the src values.
+ for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; ++I) {
+ value* v = *I;
+ if (v && v->def && v->uses.size())
+ {
+ v->remove_use(&n);
+ }
+ }
n.remove();
+ nodes_changed = true;
+ }
}
bool dce_cleanup::visit(container_node& n, bool enter) {
if (v->gvn_source && v->gvn_source->is_dead())
v->gvn_source = NULL;
- if (v->is_dead() || (remove_unused && !v->is_rel() && !v->uses))
+ if (v->is_dead() || (remove_unused && !v->is_rel() && !v->uses.size()))
v = NULL;
else
alive = true;
sblog << "\n";
);
- use_info *u = v->uses;
- while (u) {
+ for (uselist::iterator I = v->uses.begin(), E = v->uses.end(); I != E; ++I) {
+ use_info *u = *I;
if (u->op->parent != &pending) {
- u = u->next;
continue;
}
sblog << "\n";
);
+ assert(uses[u->op] > 0);
if (--uses[u->op] == 0) {
GCM_DUMP(
sblog << "td released : ";
pending.remove_node(u->op);
ready.push_back(u->op);
}
- u = u->next;
}
}
void node::remove() {parent->remove_node(this);
}
-value_hash node::hash_src() {
+value_hash node::hash_src() const {
value_hash h = 12345;
}
-value_hash node::hash() {
+value_hash node::hash() const {
if (parent && parent->subtype == NST_LOOP_PHI_CONTAINER)
return 47451;
};
struct use_info {
- use_info *next;
node *op;
use_kind kind;
int arg;
- use_info(node *n, use_kind kind, int arg, use_info* next)
- : next(next), op(n), kind(kind), arg(arg) {}
+ use_info(node *n, use_kind kind, int arg)
+ : op(n), kind(kind), arg(arg) {}
};
+typedef std::list< use_info * > uselist;
+
enum constraint_kind {
CK_SAME_REG,
CK_PACKED_BS,
value_hash ghash;
node *def, *adef;
- use_info *uses;
+ uselist uses;
ra_constraint *constraint;
ra_chunk *chunk;
}
void add_use(node *n, use_kind kind, int arg);
+ void remove_use(const node *n);
value_hash hash();
value_hash rel_hash();
void replace_with(node *n);
void remove();
- virtual value_hash hash();
- value_hash hash_src();
+ virtual value_hash hash() const;
+ value_hash hash_src() const;
virtual bool fold_dispatch(expr_handler *ex);
public:
dce_cleanup(shader &s) : vpass(s),
- remove_unused(s.dce_flags & DF_REMOVE_UNUSED) {}
+ remove_unused(s.dce_flags & DF_REMOVE_UNUSED), nodes_changed(false) {}
+
+ virtual int run();
virtual bool visit(node &n, bool enter);
virtual bool visit(alu_group_node &n, bool enter);
void cleanup_dst(node &n);
bool cleanup_dst_vec(vvec &vv);
+ // Did we alter/remove nodes during a single pass?
+ bool nodes_changed;
};
dump::dump_op(n);
sblog << " kind " << kind << " arg " << arg << "\n";
}
- uses = new use_info(n, kind, arg, uses);
+ uses.push_back(new use_info(n, kind, arg));
}
-unsigned value::use_count() {
- use_info *u = uses;
- unsigned c = 0;
- while (u) {
- ++c;
- u = u->next;
+struct use_node_comp {
+ explicit use_node_comp(const node *n) : n(n) {}
+ bool operator() (const use_info *u) {
+ return u->op->hash() == n->hash();
+ }
+
+ private:
+ const node *n;
+};
+
+void value::remove_use(const node *n) {
+ uselist::iterator it =
+ std::find_if(uses.begin(), uses.end(), use_node_comp(n));
+
+ if (it != uses.end())
+ {
+ // TODO assert((*it)->kind == kind) ?
+ // TODO assert((*it)->arg == arg) ?
+ uses.erase(it);
}
- return c;
+}
+
+unsigned value::use_count() {
+ return uses.size();
}
bool value::is_global() {
}
void value::delete_uses() {
- use_info *u, *c = uses;
- while (c) {
- u = c->next;
- delete c;
- c = u;
- }
- uses = NULL;
+ uses.erase(uses.begin(), uses.end());
}
void ra_constraint::update_values() {
bool r600_sb::sb_value_set::contains(value* v) {
unsigned b = v->uid - 1;
if (b < bs.size())
- return bs.get(v->uid - 1);
+ return bs.get(b);
else
return false;
}