aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2016-02-25 11:15:17 +0100
committerErik Verbruggen <erik.verbruggen@theqtcompany.com>2016-03-06 14:25:53 +0000
commit30ab43463c4b70f0ca9643d163e4e46c62133415 (patch)
tree217151b9f4e9542afbbc3a94e99dd2d23fd8bf3d
parentc020bc671b30ea90f6bacd8bf6cd26ce5e808a6b (diff)
V4: tweak Phi node data destruction.
Phi nodes can only occur at the start of a basic block. If there are any, they need to be subsequent to eachother, and the first phi node should be the first statement in the basic-block. A number of loops rely on this behavior, so they don't need to walk through the whole list of instructions in a basic-block (e.g. the calls to destroyData in BasicBlock::~BasicBlock). Change-Id: I57763bc6abae271337b0b169cccd26e10ecd9b2d Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
-rw-r--r--src/qml/compiler/qv4jsir.cpp33
-rw-r--r--src/qml/compiler/qv4jsir_p.h4
2 files changed, 22 insertions, 15 deletions
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index e383d1432b..a9f8df7748 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -514,9 +514,11 @@ void Function::setStatementCount(int cnt)
BasicBlock::~BasicBlock()
{
for (Stmt *s : qAsConst(_statements)) {
- Phi *p = s->asPhi();
- if (p)
+ if (Phi *p = s->asPhi()) {
p->destroyData();
+ } else {
+ break;
+ }
}
}
@@ -769,14 +771,15 @@ void BasicBlock::setStatements(const QVector<Stmt *> &newStatements)
{
Q_ASSERT(!isRemoved());
Q_ASSERT(newStatements.size() >= _statements.size());
- // FIXME: this gets quite inefficient for large basic-blocks, so this function/case should be re-worked.
for (Stmt *s : qAsConst(_statements)) {
- Phi *p = s->asPhi();
- if (!p)
- continue;
-
- if (!newStatements.contains(p))
- p->destroyData();
+ if (Phi *p = s->asPhi()) {
+ if (!newStatements.contains(p)) {
+ // phi-node was not copied over, so:
+ p->destroyData();
+ }
+ } else {
+ break;
+ }
}
_statements = newStatements;
}
@@ -825,27 +828,27 @@ void BasicBlock::insertStatementBeforeTerminator(Stmt *stmt)
void BasicBlock::replaceStatement(int index, Stmt *newStmt)
{
Q_ASSERT(!isRemoved());
- Phi *p = _statements[index]->asPhi();
- if (p)
+ if (Phi *p = _statements[index]->asPhi()) {
p->destroyData();
+ }
_statements[index] = newStmt;
}
void BasicBlock::removeStatement(Stmt *stmt)
{
Q_ASSERT(!isRemoved());
- Phi *p = stmt->asPhi();
- if (p)
+ if (Phi *p = stmt->asPhi()) {
p->destroyData();
+ }
_statements.remove(_statements.indexOf(stmt));
}
void BasicBlock::removeStatement(int idx)
{
Q_ASSERT(!isRemoved());
- Phi *p = _statements[idx]->asPhi();
- if (p)
+ if (Phi *p = _statements[idx]->asPhi()) {
p->destroyData();
+ }
_statements.remove(idx);
}
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 0189ff4a23..baa338ed52 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -751,6 +751,10 @@ struct Ret: Stmt {
virtual Ret *asRet() { return this; }
};
+// Phi nodes can only occur at the start of a basic block. If there are any, they need to be
+// subsequent to eachother, and the first phi node should be the first statement in the basic-block.
+// A number of loops rely on this behavior, so they don't need to walk through the whole list
+// of instructions in a basic-block (e.g. the calls to destroyData in BasicBlock::~BasicBlock).
struct Phi: Stmt {
Temp *targetTemp;
VarLengthArray<Expr *, 4> incoming;