[llvm] [AMDGPU][InstCombine] Optimize constant shuffle patterns (PR #192246)

Juan Manuel Martinez CaamaƱo via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 16 00:41:38 PDT 2026


================
@@ -718,6 +720,288 @@ GCNTTIImpl::hoistLaneIntrinsicThroughOperand(InstCombiner &IC,
   return nullptr;
 }
 
+static std::optional<unsigned> evalLaneExpr(Value *V, unsigned Lane,
+                                            const GCNSubtarget &ST,
+                                            const DataLayout &DL,
+                                            unsigned Depth = 0) {
+  if (Depth > 16)
+    return std::nullopt;
+
+  if (isThreadID(ST, V))
+    return Lane;
+
+  if (const auto *CI = dyn_cast<ConstantInt>(V))
+    return CI->getZExtValue();
+
+  auto *BO = dyn_cast<BinaryOperator>(V);
+  if (!BO)
+    return std::nullopt;
+
+  auto LHS = evalLaneExpr(BO->getOperand(0), Lane, ST, DL, Depth + 1);
+  auto RHS = evalLaneExpr(BO->getOperand(1), Lane, ST, DL, Depth + 1);
+  if (!LHS || !RHS)
+    return std::nullopt;
+
+  Type *Ty = BO->getType();
+  Constant *LC = ConstantInt::get(Ty, *LHS);
+  Constant *RC = ConstantInt::get(Ty, *RHS);
+  Constant *Result = ConstantFoldBinaryOpOperands(BO->getOpcode(), LC, RC, DL);
+  auto *CI = dyn_cast_or_null<ConstantInt>(Result);
+  if (!CI)
+    return std::nullopt;
+  return CI->getZExtValue();
+}
+
+static bool tryBuildShuffleMap(Value *Index, const GCNSubtarget &ST,
+                               SmallVectorImpl<uint8_t> &Ids,
+                               const DataLayout &DL) {
+  unsigned WaveSize = ST.getWavefrontSize();
+  Ids.resize(WaveSize);
+  for (unsigned Lane = 0; Lane < WaveSize; ++Lane) {
+    auto Val = evalLaneExpr(Index, Lane, ST, DL);
+    if (!Val || *Val >= WaveSize)
+      return false;
+    Ids[Lane] = static_cast<uint8_t>(*Val);
+  }
+  return true;
+}
+
+static bool isHalfRowPattern(ArrayRef<uint8_t> Ids) {
----------------
jmmartinez wrote:

These 3 functions repeat the same pattern, if I'm not mistaken:

```cpp
template<unsigned N>
bool isRowPattern(ArrayRef<uint8_t> Ids) {
  for (unsigned i = 0; i < N; ++i)
    if (Ids[i] >= N)
      return false;
  for (unsigned i = N, E = Ids.size(); i < E; ++i)
    if (Ids[i] != Ids[i % N] + (i % N))
      return false;
  return true;
}
```

Can we refactor it to avoid repetition?

Then

```cpp
static constexpr auto isHalfRowPattern = isRowPattern<8>;
static constexpr auto isFullRowPattern = isRowPattern<16>;

// for matchQuad we have to deal with the return separately
```

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


More information about the llvm-commits mailing list