[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
Thu Nov 27 22:29:43 PST 2025


================
@@ -493,3 +496,86 @@ bool WebAssemblyTTIImpl::isProfitableToSinkOperands(
 
   return false;
 }
+
+/// 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:

Non-relaxed swizzle treats indices as unsigned, I don't think you can apply same logic to both

Continuing from https://github.com/llvm/llvm-project/pull/169110#discussion_r2570587819

https://github.com/llvm/llvm-project/pull/169110


More information about the llvm-commits mailing list