diff options
author | Alon Zakai <azakai@google.com> | 2021-10-04 12:46:03 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-04 12:46:03 -0700 |
commit | debc9ef887869406ed9fcaf53d758ca7529c53bc (patch) | |
tree | 50791fb0ee58e1cb93821e7415396f5fc54d43ab | |
parent | 1183a7ddef3f0597b4547da0af6b6d1a8393f290 (diff) | |
download | binaryen-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.cpp | 13 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-call_ref.wast | 33 |
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) + ) + ) + ) ) |