r600g/sb: Fix memory leak by reworking uses list (rebased)
The author is Heiko Przybyl(CC'ing), the patch is rebased on top of Bartosz Tomczyk's one per Dieter Nützel's comment. Tested-by: Constantine Charlamov <Hi-Angel@yandex.ru> v2: Resend the patch again through git-email. The prev. rebase was sent through Thunderbird, which screwed up tab characters, making the patch not apply. -------------- When fixing the stalls on evergreen I introduced leaking of the useinfo structure(s). Sorry. Instead of allocating a new object to hold 3 values where only one is actually used, rework the list to just store the node pointer. Thus no allocating and deallocation is needed. Since use_info and use_kind aren't used anywhere, drop them and reduce code complexity. This might also save some small amount of cycles. Thanks to Bartosz Tomczyk for finding the bug. Reported-by: Bartosz Tomczyk <bartosz.tomczyk86 at gmail.com <https://lists.freedesktop.org/mailman/listinfo/mesa-dev>> Signed-off-by: Heiko Przybyl <lil_tux at web.de <https://lists.freedesktop.org/mailman/listinfo/mesa-dev>> Supersedes: https://patchwork.freedesktop.org/patch/135852 Signed-off-by: Marek Olšák <marek.olsak@amd.com> Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
This commit is contained in:
parent
827ae79b2c
commit
99d400b78f
|
@ -106,58 +106,51 @@ void def_use::process_defs(node *n, vvec &vv, bool arr_def) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void def_use::process_uses(node* n) {
|
void def_use::process_uses(node* n) {
|
||||||
unsigned k = 0;
|
for (vvec::iterator I = n->src.begin(), E = n->src.end(); I != E; ++I) {
|
||||||
|
|
||||||
for (vvec::iterator I = n->src.begin(), E = n->src.end(); I != E;
|
|
||||||
++I, ++k) {
|
|
||||||
value *v = *I;
|
value *v = *I;
|
||||||
if (!v || v->is_readonly())
|
if (!v || v->is_readonly())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (v->is_rel()) {
|
if (v->is_rel()) {
|
||||||
if (!v->rel->is_readonly())
|
if (!v->rel->is_readonly())
|
||||||
v->rel->add_use(n, UK_SRC_REL, k);
|
v->rel->add_use(n);
|
||||||
|
|
||||||
unsigned k2 = 0;
|
|
||||||
for (vvec::iterator I = v->muse.begin(), E = v->muse.end();
|
for (vvec::iterator I = v->muse.begin(), E = v->muse.end();
|
||||||
I != E; ++I, ++k2) {
|
I != E; ++I) {
|
||||||
value *v = *I;
|
value *v = *I;
|
||||||
if (!v)
|
if (!v)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
v->add_use(n, UK_MAYUSE, k2);
|
v->add_use(n);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
v->add_use(n, UK_SRC, k);
|
v->add_use(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
k = 0;
|
for (vvec::iterator I = n->dst.begin(), E = n->dst.end(); I != E; ++I) {
|
||||||
for (vvec::iterator I = n->dst.begin(), E = n->dst.end(); I != E;
|
|
||||||
++I, ++k) {
|
|
||||||
value *v = *I;
|
value *v = *I;
|
||||||
if (!v || !v->is_rel())
|
if (!v || !v->is_rel())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!v->rel->is_readonly())
|
if (!v->rel->is_readonly())
|
||||||
v->rel->add_use(n, UK_DST_REL, k);
|
v->rel->add_use(n);
|
||||||
unsigned k2 = 0;
|
|
||||||
for (vvec::iterator I = v->muse.begin(), E = v->muse.end();
|
for (vvec::iterator I = v->muse.begin(), E = v->muse.end();
|
||||||
I != E; ++I, ++k2) {
|
I != E; ++I) {
|
||||||
value *v = *I;
|
value *v = *I;
|
||||||
if (!v)
|
if (!v)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
v->add_use(n, UK_MAYDEF, k2);
|
v->add_use(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n->pred)
|
if (n->pred)
|
||||||
n->pred->add_use(n, UK_PRED, 0);
|
n->pred->add_use(n);
|
||||||
|
|
||||||
if (n->type == NT_IF) {
|
if (n->type == NT_IF) {
|
||||||
if_node *i = static_cast<if_node*>(n);
|
if_node *i = static_cast<if_node*>(n);
|
||||||
if (i->cond)
|
if (i->cond)
|
||||||
i->cond->add_use(i, UK_COND, 0);
|
i->cond->add_use(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,27 +200,27 @@ void gcm::td_release_val(value *v) {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (uselist::iterator I = v->uses.begin(), E = v->uses.end(); I != E; ++I) {
|
for (uselist::iterator I = v->uses.begin(), E = v->uses.end(); I != E; ++I) {
|
||||||
use_info *u = *I;
|
node *op = *I;
|
||||||
if (u->op->parent != &pending) {
|
if (op->parent != &pending) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
GCM_DUMP(
|
GCM_DUMP(
|
||||||
sblog << "td used in ";
|
sblog << "td used in ";
|
||||||
dump::dump_op(u->op);
|
dump::dump_op(op);
|
||||||
sblog << "\n";
|
sblog << "\n";
|
||||||
);
|
);
|
||||||
|
|
||||||
assert(uses[u->op] > 0);
|
assert(uses[op] > 0);
|
||||||
if (--uses[u->op] == 0) {
|
if (--uses[op] == 0) {
|
||||||
GCM_DUMP(
|
GCM_DUMP(
|
||||||
sblog << "td released : ";
|
sblog << "td released : ";
|
||||||
dump::dump_op(u->op);
|
dump::dump_op(op);
|
||||||
sblog << "\n";
|
sblog << "\n";
|
||||||
);
|
);
|
||||||
|
|
||||||
pending.remove_node(u->op);
|
pending.remove_node(op);
|
||||||
ready.push_back(u->op);
|
ready.push_back(op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -435,26 +435,7 @@ sb_ostream& operator << (sb_ostream &o, value &v);
|
||||||
|
|
||||||
typedef uint32_t value_hash;
|
typedef uint32_t value_hash;
|
||||||
|
|
||||||
enum use_kind {
|
typedef std::list< node * > uselist;
|
||||||
UK_SRC,
|
|
||||||
UK_SRC_REL,
|
|
||||||
UK_DST_REL,
|
|
||||||
UK_MAYDEF,
|
|
||||||
UK_MAYUSE,
|
|
||||||
UK_PRED,
|
|
||||||
UK_COND
|
|
||||||
};
|
|
||||||
|
|
||||||
struct use_info {
|
|
||||||
node *op;
|
|
||||||
use_kind kind;
|
|
||||||
int 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 {
|
enum constraint_kind {
|
||||||
CK_SAME_REG,
|
CK_SAME_REG,
|
||||||
|
@ -585,7 +566,7 @@ public:
|
||||||
&& literal_value != literal(1.0);
|
&& literal_value != literal(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_use(node *n, use_kind kind, int arg);
|
void add_use(node *n);
|
||||||
void remove_use(const node *n);
|
void remove_use(const node *n);
|
||||||
|
|
||||||
value_hash hash();
|
value_hash hash();
|
||||||
|
|
|
@ -212,21 +212,20 @@ void value_table::get_values(vvec& v) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void value::add_use(node* n, use_kind kind, int arg) {
|
void value::add_use(node* n) {
|
||||||
if (0) {
|
if (0) {
|
||||||
sblog << "add_use ";
|
sblog << "add_use ";
|
||||||
dump::dump_val(this);
|
dump::dump_val(this);
|
||||||
sblog << " => ";
|
sblog << " => ";
|
||||||
dump::dump_op(n);
|
dump::dump_op(n);
|
||||||
sblog << " kind " << kind << " arg " << arg << "\n";
|
|
||||||
}
|
}
|
||||||
uses.push_back(new use_info(n, kind, arg));
|
uses.push_back(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct use_node_comp {
|
struct use_node_comp {
|
||||||
explicit use_node_comp(const node *n) : n(n) {}
|
explicit use_node_comp(const node *n) : n(n) {}
|
||||||
bool operator() (const use_info *u) {
|
bool operator() (const node *o) {
|
||||||
return u->op->hash() == n->hash();
|
return o->hash() == n->hash();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -239,9 +238,7 @@ void value::remove_use(const node *n) {
|
||||||
|
|
||||||
if (it != uses.end())
|
if (it != uses.end())
|
||||||
{
|
{
|
||||||
// TODO assert((*it)->kind == kind) ?
|
// We only ever had a pointer, so don't delete it here
|
||||||
// TODO assert((*it)->arg == arg) ?
|
|
||||||
delete *it;
|
|
||||||
uses.erase(it);
|
uses.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,12 +288,8 @@ bool value::is_prealloc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void value::delete_uses() {
|
void value::delete_uses() {
|
||||||
for (uselist::iterator it = uses.begin(); it != uses.end(); ++it)
|
// We only ever had pointers, so don't delete them here
|
||||||
{
|
uses.erase(uses.begin(), uses.end());
|
||||||
delete *it;
|
|
||||||
}
|
|
||||||
|
|
||||||
uses.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ra_constraint::update_values() {
|
void ra_constraint::update_values() {
|
||||||
|
|
Loading…
Reference in New Issue