summaryrefslogtreecommitdiff
path: root/src/ir/intrinsics.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/intrinsics.h')
-rw-r--r--src/ir/intrinsics.h95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/ir/intrinsics.h b/src/ir/intrinsics.h
new file mode 100644
index 000000000..9a1356029
--- /dev/null
+++ b/src/ir/intrinsics.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2021 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_ir_intrinsics_h
+#define wasm_ir_intrinsics_h
+
+#include "pass.h"
+#include "wasm-traversal.h"
+
+//
+// See the README.md for background on intrinsic functions.
+//
+// Intrinsics can be recognized by Intrinsics::isFoo() methods, that check if a
+// function is a particular intrinsic, or if a call to a function is so. The
+// latter returns nullptr if the input is not that intrinsic, and otherwise the
+// intrinsic itself cast to a Call*.
+//
+
+namespace wasm {
+
+class Intrinsics {
+ Module& module;
+
+public:
+ Intrinsics(Module& module) : module(module) {}
+
+ //
+ // Check if an instruction is the call.without.effects intrinsic.
+ //
+ // (import "binaryen-intrinsics" "call.without.effects"
+ // (func (..params..) (param $target funcref) (..results..)))
+ //
+ // call.without.effects can take any parameters, and in addition a funcref,
+ // and return any result.
+ //
+ // Precise semantics:
+ //
+ // * The optimizer will assume this instruction has no side effects.
+ // * Final lowering turns a call.without.effects into a call of the given
+ // function with the given parameters. (This will either be a direct call,
+ // or a call_ref; note that either way, the function reference that appears
+ // here must have the proper type - if not, you will get an error.)
+ //
+ // call.without.effects is useful to be able to get rid of an unused result
+ // that has side effects. For example,
+ //
+ // (drop (call $get-something))
+ //
+ // cannot be removed, as a call has side effects. But if a code generator
+ // knows that it is fine to not make the call given that the result is
+ // dropped (perhaps the side effects are to initialize a global cache, for
+ // example) then instead of emitting
+ //
+ // (call $get-something)
+ //
+ // it can emit
+ //
+ // (call $call.without.effects (ref.func $get-something))
+ //
+ // which will have this behavior in the optimizer if it is dropped:
+ //
+ // (drop (call $call.without.effects (ref.func $get-something)))
+ // =>
+ // (drop (ref.func $get-something))
+ //
+ // Later optimizations can remove the dropped ref.func. Or, if the result is
+ // actually used,
+ //
+ // (local.set $x (call $call.without.effects (ref.func $get-something)))
+ // =>
+ // (local.set $x (call $get-something))
+ //
+ // Later passes will then turn that into a direct call and further optimize
+ // things.
+ //
+ bool isCallWithoutEffects(Function* func);
+ Call* isCallWithoutEffects(Expression* curr);
+};
+
+} // namespace wasm
+
+#endif // wasm_ir_intrinsics_h