[llvm] [WebAssembly] Fold constant `i8x16.swizzle` and `i8x16.relaxed.swizzle` to `shufflevector` (PR #169110)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 22 00:56:29 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) {
----------------
valadaptive wrote:
Looked into this a bit further; the non-relaxed swizzle treats indices as unsigned (though in this case it doesn't matter, since the only inbounds values are 0-15) but the relaxed swizzle treats them as signed. For clarity's sake, maybe it'd be better to only interpret the index as signed when doing the "bail out if relaxed swizzle" check?
https://github.com/llvm/llvm-project/pull/169110
More information about the llvm-commits
mailing list