[llvm] [SLP]Model gathers of extracted integer sub-fields as bitcast+permute+ext (PR #224919)

Ryan Buchner via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 23:55:48 PDT 2026


================
@@ -1139,6 +1139,139 @@ TargetTransformInfo::TargetCostKind getSLPCostKind(const Function *F) {
   return F->hasOptSize() ? TTI::TCK_CodeSize : TTI::TCK_RecipThroughput;
 }
 
+/// Checks if \p V is a zero-extended sub-field of a wider integer scalar.
+/// Returns the source scalar, the field width and the field offset.
+static std::optional<std::tuple<Value *, unsigned, unsigned>>
+matchExtractedField(Value *V) {
+  if (!V->getType()->isIntegerTy())
+    return std::nullopt;
+  // Field offset for the field-aligned shift amount, if the shifted value of
+  // the given bit width keeps at least one full field.
+  auto GetFieldOffset = [](const APInt *Amt, unsigned BitWidth,
+                           unsigned FieldWidth) -> std::optional<unsigned> {
+    uint64_t ShAmt = Amt->getLimitedValue(BitWidth);
+    if (ShAmt % FieldWidth != 0 || ShAmt + FieldWidth > BitWidth)
+      return std::nullopt;
+    return ShAmt / FieldWidth;
+  };
+  // Checks if the low bits of Val are a sub-field of the given width of a
+  // wider integer scalar. Val is a scalar integer, since V is one, and so is
+  // the matched source.
+  auto MatchLowField =
+      [&](Value *Val,
+          unsigned FieldWidth) -> std::optional<std::pair<Value *, unsigned>> {
+    Value *Src;
+    const APInt *Amt;
+    // Only the low bits of Val are observed, so lshr and ashr are equivalent.
+    if (match(Val, m_Trunc(m_Shr(m_Value(Src), m_APInt(Amt)))) ||
+        match(Val, m_Shr(m_Value(Src), m_APInt(Amt)))) {
+      if (std::optional<unsigned> Offset = GetFieldOffset(
+              Amt, Src->getType()->getIntegerBitWidth(), FieldWidth))
+        return std::make_pair(Src, *Offset);
+      return std::nullopt;
+    }
+    if (match(Val, m_Shr(m_Trunc(m_Value(Src)), m_APInt(Amt)))) {
+      if (std::optional<unsigned> Offset = GetFieldOffset(
+              Amt, Val->getType()->getIntegerBitWidth(), FieldWidth))
+        return std::make_pair(Src, *Offset);
+      return std::nullopt;
+    }
----------------
bababuck wrote:

Dead code? I think will always match on `match(Val, m_Shr(m_Value(Src), m_APInt(Amt))` first.

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


More information about the llvm-commits mailing list