[llvm] [InstCombine] Pull vector reverse through intrinsics (PR #146384)

Luke Lau via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 1 03:30:58 PDT 2025


================
@@ -1456,6 +1456,45 @@ InstCombinerImpl::foldShuffledIntrinsicOperands(IntrinsicInst *II) {
   return new ShuffleVectorInst(NewIntrinsic, Mask);
 }
 
+/// If all arguments of the intrinsic are reverses, try to pull the reverse
+/// after the intrinsic.
+Value *InstCombinerImpl::foldReversedIntrinsicOperands(IntrinsicInst *II) {
+  if (!isTriviallyVectorizable(II->getIntrinsicID()) ||
+      !II->getCalledFunction()->isSpeculatable())
+    return nullptr;
+
+  // At least 1 operand must be a reverse with 1 use because we are creating 2
+  // instructions.
+  if (none_of(II->args(), [](Value *V) {
+        return match(V, m_OneUse(m_VecReverse(m_Value())));
+      }))
+    return nullptr;
+
+  Value *X;
+  Constant *C;
+  SmallVector<Value *> NewArgs;
+  for (Use &Arg : II->args()) {
+    if (isVectorIntrinsicWithScalarOpAtArg(II->getIntrinsicID(),
+                                           Arg.getOperandNo(), nullptr))
+      NewArgs.push_back(Arg);
+    else if (match(&Arg, m_VecReverse(m_Value(X))))
+      NewArgs.push_back(X);
+    else if (Value *Splat = getSplatValue(Arg))
----------------
lukel97 wrote:

I looked at the existing binop combine to see what it was doing and it actually doesn't create new splats, it instead checks `isSplatValue` which doesn't allow undef lanes:

```c++
  if (match(LHS, m_VecReverse(m_Value(V1)))) {
    // Op(rev(V1), rev(V2)) -> rev(Op(V1, V2))
    if (match(RHS, m_VecReverse(m_Value(V2))) &&
        (LHS->hasOneUse() || RHS->hasOneUse() ||
         (LHS == RHS && LHS->hasNUses(2))))
      return createBinOpReverse(V1, V2);

    // Op(rev(V1), RHSSplat)) -> rev(Op(V1, RHSSplat))
    if (LHS->hasOneUse() && isSplatValue(RHS))
      return createBinOpReverse(V1, RHS);
  }
  // Op(LHSSplat, rev(V2)) -> rev(Op(LHSSplat, V2))
  else if (isSplatValue(LHS) && match(RHS, m_OneUse(m_VecReverse(m_Value(V2)))))
    return createBinOpReverse(LHS, V2);
```

So I've done the same here in e0acdf38c5c3dcc021fe1a6ffe34115fb02bc321 to keep it consistent, disallowing poison lanes. I don't think supporting poison lanes is important given that reverse intrinsics are really only used for scalable vectors.

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


More information about the llvm-commits mailing list