summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-10-04 12:46:03 -0700
committerGitHub <noreply@github.com>2021-10-04 12:46:03 -0700
commitdebc9ef887869406ed9fcaf53d758ca7529c53bc (patch)
tree50791fb0ee58e1cb93821e7415396f5fc54d43ab
parent1183a7ddef3f0597b4547da0af6b6d1a8393f290 (diff)
downloadbinaryen-debc9ef887869406ed9fcaf53d758ca7529c53bc.tar.gz
binaryen-debc9ef887869406ed9fcaf53d758ca7529c53bc.tar.bz2
binaryen-debc9ef887869406ed9fcaf53d758ca7529c53bc.zip
Optimize call_ref+table.get => call_indirect (#4207)
Rather than load from the table and call that reference, call using the table.
-rw-r--r--src/passes/OptimizeInstructions.cpp13
-rw-r--r--test/lit/passes/optimize-instructions-call_ref.wast33
2 files changed, 41 insertions, 5 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index cb656ceaf..3153af200 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1190,6 +1190,19 @@ struct OptimizeInstructions
return;
}
+ if (auto* get = curr->target->dynCast<TableGet>()) {
+ // (call_ref ..args.. (table.get $table (index))
+ // =>
+ // (call_indirect $table ..args.. (index))
+ replaceCurrent(Builder(*getModule())
+ .makeCallIndirect(get->table,
+ get->index,
+ curr->operands,
+ get->type.getHeapType().getSignature(),
+ curr->isReturn));
+ return;
+ }
+
auto features = getModule()->features;
// It is possible the target is not a function reference, but we can infer
diff --git a/test/lit/passes/optimize-instructions-call_ref.wast b/test/lit/passes/optimize-instructions-call_ref.wast
index 320237d1e..553f8d07b 100644
--- a/test/lit/passes/optimize-instructions-call_ref.wast
+++ b/test/lit/passes/optimize-instructions-call_ref.wast
@@ -5,21 +5,27 @@
;; remove-unused-names is to allow fallthrough computations to work on blocks
(module
- ;; CHECK: (type $none_=>_i32 (func (result i32)))
- (type $none_=>_i32 (func (result i32)))
-
;; CHECK: (type $i32_i32_=>_none (func (param i32 i32)))
(type $i32_i32_=>_none (func (param i32 i32)))
+ ;; CHECK: (type $none_=>_i32 (func (result i32)))
+ (type $none_=>_i32 (func (result i32)))
+
;; CHECK: (type $none_=>_none (func))
(type $none_=>_none (func))
+ ;; CHECK: (type $i32_=>_none (func (param i32)))
+
;; CHECK: (type $data_=>_none (func (param dataref)))
(type $data_=>_none (func (param (ref data))))
- ;; CHECK: (type $i32_=>_none (func (param i32)))
+ ;; CHECK: (table $table-1 10 (ref null $i32_i32_=>_none))
+ (table $table-1 10 (ref null $i32_i32_=>_none))
+ ;; CHECK: (elem $elem-1 (table $table-1) (i32.const 0) (ref null $i32_i32_=>_none) (ref.func $foo))
+ (elem $elem-1 (table $table-1) (i32.const 0) (ref null $i32_i32_=>_none)
+ (ref.func $foo))
- ;; CHECK: (elem declare func $fallthrough-no-params $fallthrough-non-nullable $foo $return-nothing)
+ ;; CHECK: (elem declare func $fallthrough-no-params $fallthrough-non-nullable $return-nothing)
;; CHECK: (func $foo (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (unreachable)
@@ -206,4 +212,21 @@
(unreachable)
)
)
+
+ ;; CHECK: (func $call-table-get (param $x i32)
+ ;; CHECK-NEXT: (call_indirect $table-1 (type $i32_i32_=>_none)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $call-table-get (param $x i32)
+ (call_ref
+ (i32.const 1)
+ (i32.const 2)
+ (table.get $table-1
+ (local.get $x)
+ )
+ )
+ )
)