[llvm] [SLP]Look through truncation of shifted extracted sub-fields (PR #226803)

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 27 09:05:07 PDT 2026


https://github.com/alexey-bataev created https://github.com/llvm/llvm-project/pull/226803

The masked sub-field of the shifted truncation of a wider scalar was
matched with the truncation as its source, while the other fields
matched the scalar itself, so the gather of the fields was rejected.
The field is within the truncated bits, look through the truncation.

Fixes #74380


>From dffb567130839f0388fa662894dc9f130ca7bd96 Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Sun, 27 Sep 2026 09:04:56 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7
---
 .../Vectorize/SLPVectorizer/SLPUtils.cpp           |  5 ++++-
 .../X86/extracted-subfields-shifted-trunc.ll       | 14 ++------------
 2 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.cpp
index a764dec5ad0e7..d639e0d9c7d63 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.cpp
@@ -1166,8 +1166,11 @@ matchExtractedField(Value *V) {
     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))
+              Amt, Src->getType()->getIntegerBitWidth(), FieldWidth)) {
+        // The truncation of the shifted value keeps the field, look through it.
+        match(Src, m_Trunc(m_Value(Src)));
         return std::make_pair(Src, *Offset);
+      }
       return std::nullopt;
     }
     if (match(Val, m_Trunc(m_Value(Src))) &&
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/extracted-subfields-shifted-trunc.ll b/llvm/test/Transforms/SLPVectorizer/X86/extracted-subfields-shifted-trunc.ll
index 82e231326d0d1..56bb1404087f1 100644
--- a/llvm/test/Transforms/SLPVectorizer/X86/extracted-subfields-shifted-trunc.ll
+++ b/llvm/test/Transforms/SLPVectorizer/X86/extracted-subfields-shifted-trunc.ll
@@ -8,18 +8,8 @@ define void @store_bytes_i64(i64 %x, ptr %out) {
 ; CHECK-LABEL: define void @store_bytes_i64(
 ; CHECK-SAME: i64 [[X:%.*]], ptr [[OUT:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[T:%.*]] = trunc i64 [[X]] to i32
-; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[T]], i64 0
-; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> poison, <4 x i32> zeroinitializer
-; CHECK-NEXT:    [[TMP2:%.*]] = lshr <4 x i32> [[TMP10]], <i32 0, i32 8, i32 16, i32 24>
-; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <4 x i64> poison, i64 [[X]], i64 0
-; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <4 x i64> [[TMP3]], <4 x i64> poison, <4 x i32> zeroinitializer
-; CHECK-NEXT:    [[TMP5:%.*]] = lshr <4 x i64> [[TMP4]], <i64 32, i64 40, i64 48, i64 56>
-; CHECK-NEXT:    [[TMP6:%.*]] = trunc <4 x i64> [[TMP5]] to <4 x i32>
-; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <4 x i32> [[TMP2]], <4 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
-; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <4 x i32> [[TMP6]], <4 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
-; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <8 x i32> [[TMP7]], <8 x i32> [[TMP8]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
-; CHECK-NEXT:    [[TMP1:%.*]] = and <8 x i32> [[TMP9]], <i32 255, i32 255, i32 255, i32 -1, i32 255, i32 255, i32 255, i32 -1>
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast i64 [[X]] to <8 x i8>
+; CHECK-NEXT:    [[TMP1:%.*]] = zext <8 x i8> [[TMP0]] to <8 x i32>
 ; CHECK-NEXT:    store <8 x i32> [[TMP1]], ptr [[OUT]], align 4
 ; CHECK-NEXT:    ret void
 ;



More information about the llvm-commits mailing list