summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/CoalesceLocals.cpp14
-rw-r--r--test/passes/coalesce-locals-learning.txt3
-rw-r--r--test/passes/coalesce-locals.txt3
-rw-r--r--test/unit.asm.js13
-rw-r--r--test/unit.fromasm28
-rw-r--r--test/unit.fromasm.imprecise28
-rw-r--r--test/unit.fromasm.imprecise.no-opts28
-rw-r--r--test/unit.fromasm.no-opts28
8 files changed, 139 insertions, 6 deletions
diff --git a/src/passes/CoalesceLocals.cpp b/src/passes/CoalesceLocals.cpp
index 39c480107..c36371ec0 100644
--- a/src/passes/CoalesceLocals.cpp
+++ b/src/passes/CoalesceLocals.cpp
@@ -183,7 +183,7 @@ struct CoalesceLocals : public WalkerPass<CFGWalker<CoalesceLocals, Visitor<Coal
void calculateInterferences();
- void calculateInterferences(LocalSet& locals);
+ void calculateInterferences(const LocalSet& locals);
// merge starts of a list of blocks, adding new interferences as necessary. return
// whether anything changed vs an old state (which indicates further processing is necessary).
@@ -282,8 +282,6 @@ void CoalesceLocals::flowLiveness() {
queue.insert(in);
}
}
- // live locals at the entry block include params, obviously, but also
- // vars, in which case the 0-init value is actually used.
#ifdef CFG_DEBUG
std::hash<std::vector<bool>> hasher;
std::cout << getFunction()->name << ": interference hash: " << hasher(*(std::vector<bool>*)&interferences) << "\n";
@@ -347,9 +345,17 @@ void CoalesceLocals::calculateInterferences() {
}
}
}
+ // Params have a value on entry, so mark them as live, as variables
+ // live at the entry expect their zero-init value.
+ LocalSet start = entry->contents.start;
+ auto numParams = getFunction()->getNumParams();
+ for (Index i = 0; i < numParams; i++) {
+ start.insert(i);
+ }
+ calculateInterferences(start);
}
-void CoalesceLocals::calculateInterferences(LocalSet& locals) {
+void CoalesceLocals::calculateInterferences(const LocalSet& locals) {
size_t size = locals.size();
for (size_t i = 0; i < size; i++) {
for (size_t j = i + 1; j < size; j++) {
diff --git a/test/passes/coalesce-locals-learning.txt b/test/passes/coalesce-locals-learning.txt
index 14091cb98..aa3c8c9c0 100644
--- a/test/passes/coalesce-locals-learning.txt
+++ b/test/passes/coalesce-locals-learning.txt
@@ -318,9 +318,10 @@
(func $params (param $0 i32) (param $1 f32)
(local $2 i32)
(local $3 i32)
- (get_local $0)
+ (local $4 i32)
(get_local $2)
(get_local $3)
+ (get_local $4)
)
(func $interfere-in-dead
(local $0 i32)
diff --git a/test/passes/coalesce-locals.txt b/test/passes/coalesce-locals.txt
index 3c1632f68..d0edbd71d 100644
--- a/test/passes/coalesce-locals.txt
+++ b/test/passes/coalesce-locals.txt
@@ -318,9 +318,10 @@
(func $params (param $0 i32) (param $1 f32)
(local $2 i32)
(local $3 i32)
- (get_local $0)
+ (local $4 i32)
(get_local $2)
(get_local $3)
+ (get_local $4)
)
(func $interfere-in-dead
(local $0 i32)
diff --git a/test/unit.asm.js b/test/unit.asm.js
index 5b958a111..2f307e085 100644
--- a/test/unit.asm.js
+++ b/test/unit.asm.js
@@ -234,6 +234,19 @@ function asm(global, env, buffer) {
-3.14159;
}
+ function zeroInit(x) {
+ x = x | 0;
+ var y = 0; // reusing this with x is dangerous - x has a value, and y needs to start at 0!
+ if (lb(0) | 0) {
+ if (lb(1) | 0) y = 3;
+ } else {
+ y = 3;
+ }
+ if ((y | 0) == 3) {
+ lb(2) | 0;
+ }
+ }
+
function z() {
}
function w() {
diff --git a/test/unit.fromasm b/test/unit.fromasm
index 7ee15cd05..3fb76981d 100644
--- a/test/unit.fromasm
+++ b/test/unit.fromasm
@@ -425,4 +425,32 @@
)
(i32.const 0)
)
+ (func $zeroInit (param $0 i32)
+ (local $1 i32)
+ (if
+ (call $lb
+ (i32.const 0)
+ )
+ (if
+ (call $lb
+ (i32.const 1)
+ )
+ (set_local $1
+ (i32.const 3)
+ )
+ )
+ (set_local $1
+ (i32.const 3)
+ )
+ )
+ (if
+ (i32.eq
+ (get_local $1)
+ (i32.const 3)
+ )
+ (call $lb
+ (i32.const 2)
+ )
+ )
+ )
)
diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise
index 293fc490a..a4716941d 100644
--- a/test/unit.fromasm.imprecise
+++ b/test/unit.fromasm.imprecise
@@ -417,4 +417,32 @@
)
(i32.const 0)
)
+ (func $zeroInit (param $0 i32)
+ (local $1 i32)
+ (if
+ (call $lb
+ (i32.const 0)
+ )
+ (if
+ (call $lb
+ (i32.const 1)
+ )
+ (set_local $1
+ (i32.const 3)
+ )
+ )
+ (set_local $1
+ (i32.const 3)
+ )
+ )
+ (if
+ (i32.eq
+ (get_local $1)
+ (i32.const 3)
+ )
+ (call $lb
+ (i32.const 2)
+ )
+ )
+ )
)
diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts
index 2f7665622..c3da01359 100644
--- a/test/unit.fromasm.imprecise.no-opts
+++ b/test/unit.fromasm.imprecise.no-opts
@@ -693,6 +693,34 @@
(func $exportMe
(f64.const -3.14159)
)
+ (func $zeroInit (param $x i32)
+ (local $y i32)
+ (if
+ (call $lb
+ (i32.const 0)
+ )
+ (if
+ (call $lb
+ (i32.const 1)
+ )
+ (set_local $y
+ (i32.const 3)
+ )
+ )
+ (set_local $y
+ (i32.const 3)
+ )
+ )
+ (if
+ (i32.eq
+ (get_local $y)
+ (i32.const 3)
+ )
+ (call $lb
+ (i32.const 2)
+ )
+ )
+ )
(func $z
(nop)
)
diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts
index 19c13f29f..92d2d2add 100644
--- a/test/unit.fromasm.no-opts
+++ b/test/unit.fromasm.no-opts
@@ -697,6 +697,34 @@
(func $exportMe
(f64.const -3.14159)
)
+ (func $zeroInit (param $x i32)
+ (local $y i32)
+ (if
+ (call $lb
+ (i32.const 0)
+ )
+ (if
+ (call $lb
+ (i32.const 1)
+ )
+ (set_local $y
+ (i32.const 3)
+ )
+ )
+ (set_local $y
+ (i32.const 3)
+ )
+ )
+ (if
+ (i32.eq
+ (get_local $y)
+ (i32.const 3)
+ )
+ (call $lb
+ (i32.const 2)
+ )
+ )
+ )
(func $z
(nop)
)