summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/CoalesceLocals.cpp34
-rw-r--r--test/lit/passes/coalesce-locals-learning.wast20
-rw-r--r--test/lit/passes/coalesce-locals.wast162
-rw-r--r--test/wasm2js/br_table_temp.2asm.js.opt21
4 files changed, 191 insertions, 46 deletions
diff --git a/src/passes/CoalesceLocals.cpp b/src/passes/CoalesceLocals.cpp
index f9ded9c92..42296b5bf 100644
--- a/src/passes/CoalesceLocals.cpp
+++ b/src/passes/CoalesceLocals.cpp
@@ -30,6 +30,7 @@
#include <unordered_set>
#include "cfg/liveness-traversal.h"
+#include "ir/numbering.h"
#include "ir/utils.h"
#include "pass.h"
#include "support/learning.h"
@@ -155,6 +156,10 @@ void CoalesceLocals::calculateInterferences() {
// loop.
std::vector<Index> values(numLocals);
+ ValueNumbering valueNumbering;
+
+ auto* func = getFunction();
+
for (auto& curr : basicBlocks) {
if (liveBlocks.count(curr.get()) == 0) {
continue; // ignore dead blocks
@@ -196,21 +201,22 @@ void CoalesceLocals::calculateInterferences() {
// around through copies between sets we can see when sets are guaranteed to
// be equal.
- // Give all default values the same value ID, regardless of their type. This
- // is valid since we only coalesce locals of the same type anyhow.
- auto zeroInit = 0;
- Index nextValue = 1;
-
if (curr.get() == entry) {
// Each parameter is assumed to have a different value on entry.
- for (Index i = 0; i < getFunction()->getNumParams(); i++) {
- values[i] = nextValue++;
+ for (Index i = 0; i < func->getNumParams(); i++) {
+ values[i] = valueNumbering.getUniqueValue();
}
- for (Index i = getFunction()->getNumParams();
- i < getFunction()->getNumLocals();
- i++) {
- values[i] = zeroInit;
+ for (Index i = func->getNumParams(); i < func->getNumLocals(); i++) {
+ auto type = func->getLocalType(i);
+ if (type.isNonNullable()) {
+ // A non-nullable value cannot be used anyhow, but we must give it
+ // some value. A unique one seems least likely to result in surprise
+ // during debugging.
+ values[i] = valueNumbering.getUniqueValue();
+ } else {
+ values[i] = valueNumbering.getValue(Literal::makeZeros(type));
+ }
}
} else {
// In any block but the entry, assume that each live local might have a
@@ -218,7 +224,7 @@ void CoalesceLocals::calculateInterferences() {
// TODO: Propagating value IDs across blocks could identify more copies,
// however, it would also be nonlinear.
for (auto index : curr->contents.start) {
- values[index] = nextValue++;
+ values[index] = valueNumbering.getUniqueValue();
}
}
@@ -246,8 +252,8 @@ void CoalesceLocals::calculateInterferences() {
assert(i > 0 && set->value == *actions[i - 1].origin);
newValue = values[actions[i - 1].index];
} else {
- // This is not a copy; assign a new unique value.
- newValue = nextValue++;
+ // This is not a copy.
+ newValue = valueNumbering.getValue(set->value);
}
values[index] = newValue;
diff --git a/test/lit/passes/coalesce-locals-learning.wast b/test/lit/passes/coalesce-locals-learning.wast
index 6e896ae9d..d51a41276 100644
--- a/test/lit/passes/coalesce-locals-learning.wast
+++ b/test/lit/passes/coalesce-locals-learning.wast
@@ -57,7 +57,7 @@
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $0)
@@ -73,7 +73,7 @@
(i32.const 0)
)
(local.set $y
- (i32.const 0)
+ (i32.const 1)
)
(drop
(local.get $x)
@@ -190,7 +190,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $block0
;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
@@ -208,7 +208,7 @@
)
(block $block0
(local.set $y
- (i32.const 0)
+ (i32.const 1)
)
)
(drop
@@ -269,7 +269,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $block
;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $1)
@@ -288,7 +288,7 @@
)
(block $block
(local.set $y
- (i32.const 0)
+ (i32.const 1)
)
(drop
(local.get $y)
@@ -582,7 +582,7 @@
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
@@ -600,7 +600,7 @@
(local $x i32)
(local $y i32)
(local.set $x
- (i32.const 0)
+ (i32.const 1)
)
(if
(i32.const 0)
@@ -619,7 +619,7 @@
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.tee $0
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $block1
;; CHECK-NEXT: (drop
@@ -636,7 +636,7 @@
(local $y i32)
(if
(local.tee $x
- (i32.const 0)
+ (i32.const 1)
)
(block $block1
(drop
diff --git a/test/lit/passes/coalesce-locals.wast b/test/lit/passes/coalesce-locals.wast
index 7846929bc..2cd5948bc 100644
--- a/test/lit/passes/coalesce-locals.wast
+++ b/test/lit/passes/coalesce-locals.wast
@@ -74,7 +74,7 @@
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $0)
@@ -90,7 +90,7 @@
(i32.const 0)
)
(local.set $y
- (i32.const 0)
+ (i32.const 1)
)
(drop
(local.get $x)
@@ -207,7 +207,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $block0
;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
@@ -225,7 +225,7 @@
)
(block $block0
(local.set $y
- (i32.const 0)
+ (i32.const 1)
)
)
(drop
@@ -286,7 +286,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $block
;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $1)
@@ -305,7 +305,7 @@
)
(block $block
(local.set $y
- (i32.const 0)
+ (i32.const 1)
)
(drop
(local.get $y)
@@ -599,7 +599,7 @@
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
@@ -617,7 +617,7 @@
(local $x i32)
(local $y i32)
(local.set $x
- (i32.const 0)
+ (i32.const 1)
)
(if
(i32.const 0)
@@ -636,7 +636,7 @@
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.tee $0
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $block1
;; CHECK-NEXT: (drop
@@ -653,7 +653,7 @@
(local $y i32)
(if
(local.tee $x
- (i32.const 0)
+ (i32.const 1)
)
(block $block1
(drop
@@ -2921,4 +2921,146 @@
)
(local.get $1)
)
+
+ ;; CHECK: (func $equal-constants-zeroinit
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $equal-constants-zeroinit
+ (local $x i32)
+ (local $y i32)
+ ;; $x and $y both have the zero init value, which is identical, and they do
+ ;; not interfere.
+ (drop
+ (local.get $x)
+ )
+ (drop
+ (local.get $y)
+ )
+ )
+
+ ;; CHECK: (func $equal-constants
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $equal-constants
+ (local $x i32)
+ (local $y i32)
+ ;; $x is written the same value as $y, so they do not interfere.
+ (local.set $x
+ (i32.const 0)
+ )
+ (drop
+ (local.get $x)
+ )
+ (drop
+ (local.get $y)
+ )
+ )
+
+ ;; CHECK: (func $different-constants
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (local $1 i32)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $different-constants
+ (local $x i32)
+ (local $y i32)
+ ;; $x is written a different value, so they do interfere.
+ (local.set $x
+ (i32.const 1)
+ )
+ (drop
+ (local.get $x)
+ )
+ (drop
+ (local.get $y)
+ )
+ )
+
+ ;; CHECK: (func $equal-constants-nonzero
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $equal-constants-nonzero
+ (local $x i32)
+ (local $y i32)
+ (local.set $x
+ (i32.const 42)
+ )
+ (local.set $y
+ (i32.const 42)
+ )
+ (drop
+ (local.get $x)
+ )
+ (drop
+ (local.get $y)
+ )
+ )
+
+ ;; CHECK: (func $different-constants-nonzero
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (local $1 i32)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (i32.const 1337)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $different-constants-nonzero
+ (local $x i32)
+ (local $y i32)
+ (local.set $x
+ (i32.const 42)
+ )
+ (local.set $y
+ (i32.const 1337)
+ )
+ (drop
+ (local.get $x)
+ )
+ (drop
+ (local.get $y)
+ )
+ )
)
diff --git a/test/wasm2js/br_table_temp.2asm.js.opt b/test/wasm2js/br_table_temp.2asm.js.opt
index b4198a4dc..5c7d88a16 100644
--- a/test/wasm2js/br_table_temp.2asm.js.opt
+++ b/test/wasm2js/br_table_temp.2asm.js.opt
@@ -12555,15 +12555,14 @@ function asmFunc(env) {
function $60($0) {
$0 = $0 | 0;
- var $1 = 0, $2 = 0;
+ var $1 = 0;
$1 = 16;
- $2 = 16;
block : {
switch ($0 | 0) {
case 0:
- $2 = 18;
+ $1 = 18;
case 1:
- $1 = $2 + 1 | 0;
+ $1 = $1 + 1 | 0;
break;
default:
break block;
@@ -12574,15 +12573,14 @@ function asmFunc(env) {
function $61($0) {
$0 = $0 | 0;
- var $1 = 0, $2 = 0;
+ var $1 = 0;
$1 = 8;
- $2 = 8;
block : {
switch ($0 | 0) {
default:
- $2 = 16;
+ $1 = 16;
case 1:
- $1 = $2 + 1 | 0;
+ $1 = $1 + 1 | 0;
break;
case 0:
break block;
@@ -12593,15 +12591,14 @@ function asmFunc(env) {
function $62($0) {
$0 = $0 | 0;
- var $1 = 0, $2 = 0;
+ var $1 = 0;
$1 = 8;
- $2 = 8;
block : {
switch ($0 | 0) {
case 0:
- $2 = 16;
+ $1 = 16;
case 1:
- $1 = $2 + 1 | 0;
+ $1 = $1 + 1 | 0;
break;
default:
break block;