summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-11-14 17:18:22 -0800
committerGitHub <noreply@github.com>2022-11-15 01:18:22 +0000
commit8225e485a24c5fa6fffb0c9f0a3ee8615bcfa0d9 (patch)
treed819d652ff357543a31a7e879057afab59e6003a /src
parenta221b01b89ced3aa6335723e68bf17ea97377a08 (diff)
downloadbinaryen-8225e485a24c5fa6fffb0c9f0a3ee8615bcfa0d9.tar.gz
binaryen-8225e485a24c5fa6fffb0c9f0a3ee8615bcfa0d9.tar.bz2
binaryen-8225e485a24c5fa6fffb0c9f0a3ee8615bcfa0d9.zip
Add a pass to lower sign-ext operations to MVP (#5254)
Fixes #5250
Diffstat (limited to 'src')
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/SignExtLowering.cpp75
-rw-r--r--src/passes/pass.cpp3
-rw-r--r--src/passes/passes.h1
4 files changed, 80 insertions, 0 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index 621a8e68a..8204f1070 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -83,6 +83,7 @@ set(passes_SOURCES
StackIR.cpp
SignaturePruning.cpp
SignatureRefining.cpp
+ SignExtLowering.cpp
Strip.cpp
StripTargetFeatures.cpp
RedundantSetElimination.cpp
diff --git a/src/passes/SignExtLowering.cpp b/src/passes/SignExtLowering.cpp
new file mode 100644
index 000000000..7d03046ea
--- /dev/null
+++ b/src/passes/SignExtLowering.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2022 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.
+ */
+
+//
+// Lowers sign-ext operations into wasm MVP operations.
+//
+
+#include "pass.h"
+#include "wasm-builder.h"
+#include "wasm.h"
+
+namespace wasm {
+
+struct SignExtLowering : public WalkerPass<PostWalker<SignExtLowering>> {
+ template<typename T>
+ void lowerToShifts(Expression* value,
+ BinaryOp leftShift,
+ BinaryOp rightShift,
+ T originalBits) {
+ // To sign-extend, we shift all the way left so the effective sign bit is
+ // where the actual sign bit is. For example, when sign-extending i8, the
+ // effective sign bit is at bit 8, and we shift it to the actual place of
+ // the sign bit, which is 32 for i32 or 64 for i64. Then we do a signed
+ // shift in the other direction, which fills with the proper bit all the
+ // way back, so e.g.
+ //
+ // 0x000000ff =(shift left)=> 0xff000000 =(shift right)=> 0xffffffff
+ //
+ T shiftBits = (sizeof(T) * 8) - originalBits;
+ Builder builder(*getModule());
+ replaceCurrent(builder.makeBinary(
+ rightShift,
+ builder.makeBinary(leftShift, value, builder.makeConst(shiftBits)),
+ builder.makeConst(shiftBits)));
+ }
+
+ void visitUnary(Unary* curr) {
+ switch (curr->op) {
+ case ExtendS8Int32:
+ lowerToShifts(curr->value, ShlInt32, ShrSInt32, int32_t(8));
+ break;
+ case ExtendS16Int32:
+ lowerToShifts(curr->value, ShlInt32, ShrSInt32, int32_t(16));
+ break;
+ case ExtendS8Int64:
+ lowerToShifts(curr->value, ShlInt64, ShrSInt64, int64_t(8));
+ break;
+ case ExtendS16Int64:
+ lowerToShifts(curr->value, ShlInt64, ShrSInt64, int64_t(16));
+ break;
+ case ExtendS32Int64:
+ lowerToShifts(curr->value, ShlInt64, ShrSInt64, int64_t(32));
+ break;
+ default: {
+ }
+ }
+ }
+};
+
+Pass* createSignExtLoweringPass() { return new SignExtLowering(); }
+
+} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index b3bf80f8f..7f79313e2 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -394,6 +394,9 @@ void PassRegistry::registerPasses() {
registerPass("signature-refining",
"apply more specific subtypes to signature types where possible",
createSignatureRefiningPass);
+ registerPass("signext-lowering",
+ "lower sign-ext operations to wasm mvp",
+ createSignExtLoweringPass);
registerPass("simplify-globals",
"miscellaneous globals-related optimizations",
createSimplifyGlobalsPass);
diff --git a/src/passes/passes.h b/src/passes/passes.h
index ba60ade6f..65923cd25 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -125,6 +125,7 @@ Pass* createSafeHeapPass();
Pass* createSetGlobalsPass();
Pass* createSignaturePruningPass();
Pass* createSignatureRefiningPass();
+Pass* createSignExtLoweringPass();
Pass* createSimplifyLocalsPass();
Pass* createSimplifyGlobalsPass();
Pass* createSimplifyGlobalsOptimizingPass();