[llvm] [WebAssembly] Fold constant `i8x16.swizzle` and `i8x16.relaxed.swizzle` to `shufflevector` (PR #169110)
Petr Penzin via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 25 17:01:31 PST 2025
================
@@ -0,0 +1,107 @@
+//=== WebAssemblyInstCombineIntrinsic.cpp -
+// WebAssembly specific InstCombine pass ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file implements a TargetTransformInfo analysis pass specific to
+/// WebAssembly. It uses the target's detailed information to provide more
+/// precise answers to certain TTI queries, while letting the target independent
+/// and default TTI implementations handle the rest.
+///
+//===----------------------------------------------------------------------===//
+
+#include "WebAssemblyTargetTransformInfo.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IntrinsicsWebAssembly.h"
+#include "llvm/Transforms/InstCombine/InstCombiner.h"
+#include <optional>
+
+using namespace llvm;
+using namespace llvm::PatternMatch;
+
+/// Attempt to convert [relaxed_]swizzle to shufflevector if the mask is
+/// constant.
+static Value *simplifyWasmSwizzle(const IntrinsicInst &II,
+ InstCombiner::BuilderTy &Builder,
+ bool IsRelaxed) {
+ auto *V = dyn_cast<Constant>(II.getArgOperand(1));
+ if (!V)
+ return nullptr;
+
+ auto *VecTy = cast<FixedVectorType>(II.getType());
+ unsigned NumElts = VecTy->getNumElements();
+ assert(NumElts == 16);
+
+ // Construct a shuffle mask from constant integers or UNDEFs.
+ int Indexes[16];
+ bool AnyOutOfBounds = false;
+
+ for (unsigned I = 0; I < NumElts; ++I) {
+ Constant *COp = V->getAggregateElement(I);
+ if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp)))
+ return nullptr;
+
+ if (isa<UndefValue>(COp)) {
+ Indexes[I] = -1;
+ continue;
+ }
+
+ int64_t Index = cast<ConstantInt>(COp)->getSExtValue();
+
+ if (Index >= NumElts && IsRelaxed) {
+ // For lane indices above 15, the relaxed_swizzle operation can choose
+ // between returning 0 or the lane at `Index % 16`. However, the choice
+ // must be made consistently. As the WebAssembly spec states:
+ //
+ // "The result of relaxed operators are implementation-dependent, because
+ // the set of possible results may depend on properties of the host
+ // environment, such as its hardware. Technically, their behaviour is
+ // controlled by a set of global parameters to the semantics that an
+ // implementation can instantiate in different ways. These choices are
+ // fixed, that is, parameters are constant during the execution of any
+ // given program."
+ //
+ // The WebAssembly runtime may choose differently from us, so we can't
+ // optimize a relaxed swizzle with lane indices above 15.
+ return nullptr;
+ }
+
+ if (Index >= NumElts || Index < 0) {
----------------
ppenzin wrote:
I think [relaxed swizzle](https://github.com/WebAssembly/relaxed-simd/blob/main/proposals/relaxed-simd/Overview.md#relaxed-swizzle) still treats indices as unsigned (the link is to the proposal, not the final spec - take that with a grain of salt). I don't think negative indices should be valid.
https://github.com/llvm/llvm-project/pull/169110
More information about the llvm-commits
mailing list