[llvm] [SLP][NFC]Add tests with non-profitable GEPs vectorization, NFC (PR #228916)

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 4 09:45:20 PDT 2026


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

None

>From a7fbb68ad08e76715d9aad2ec827c068884fa01d Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Sun, 4 Oct 2026 09:45:06 -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
---
 .../X86/gather-gep-addressing-cost.ll         | 69 ++++++++++++++
 .../X86/once-used-gep-index-seeds.ll          | 92 +++++++++++++++++++
 2 files changed, 161 insertions(+)
 create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/gather-gep-addressing-cost.ll
 create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/once-used-gep-index-seeds.ll

diff --git a/llvm/test/Transforms/SLPVectorizer/X86/gather-gep-addressing-cost.ll b/llvm/test/Transforms/SLPVectorizer/X86/gather-gep-addressing-cost.ll
new file mode 100644
index 0000000000000..8e0f3bb8d4a20
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/gather-gep-addressing-cost.ll
@@ -0,0 +1,69 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=slp-vectorizer -S < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=graniterapids | FileCheck %s
+
+; The table lookups use different constant bases of the same global, so their
+; addresses do not form a chain of one base pointer and are priced separately
+; for the loaded type.
+
+ at tbl = external local_unnamed_addr constant [8 x [256 x i32]], align 16
+
+define i32 @crc_step(ptr %words, i32 %crc) {
+; CHECK-LABEL: define i32 @crc_step(
+; CHECK-SAME: ptr [[WORDS:%.*]], i32 [[CRC:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CONV:%.*]] = zext i32 [[CRC]] to i64
+; CHECK-NEXT:    [[W:%.*]] = load i64, ptr [[WORDS]], align 8
+; CHECK-NEXT:    [[XOR:%.*]] = xor i64 [[W]], [[CONV]]
+; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <8 x i64> poison, i64 [[XOR]], i64 0
+; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <8 x i64> [[TMP0]], i64 [[W]], i64 1
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> poison, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 1, i32 1, i32 1, i32 1>
+; CHECK-NEXT:    [[TMP3:%.*]] = lshr <8 x i64> [[TMP2]], <i64 8, i64 0, i64 16, i64 24, i64 32, i64 40, i64 48, i64 56>
+; CHECK-NEXT:    [[TMP4:%.*]] = and <8 x i64> [[TMP3]], <i64 255, i64 255, i64 255, i64 255, i64 255, i64 255, i64 255, i64 -1>
+; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds nuw [4 x i8], <8 x ptr> <ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 1024), ptr @tbl, ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 2048), ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 3072), ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 4096), ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 5120), ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 6144), ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 7168)>, <8 x i64> [[TMP4]]
+; CHECK-NEXT:    [[TMP6:%.*]] = call <8 x i32> @llvm.masked.gather.v8i32.v8p0(<8 x ptr> align 4 [[TMP5]], <8 x i1> splat (i1 true), <8 x i32> poison)
+; CHECK-NEXT:    [[TMP7:%.*]] = call i32 @llvm.vector.reduce.xor.v8i32(<8 x i32> [[TMP6]])
+; CHECK-NEXT:    ret i32 [[TMP7]]
+;
+entry:
+  %conv = zext i32 %crc to i64
+  %w = load i64, ptr %words, align 8
+  %xor = xor i64 %w, %conv
+  %and = and i64 %xor, 255
+  %p0 = getelementptr inbounds nuw [4 x i8], ptr @tbl, i64 %and
+  %l0 = load i32, ptr %p0, align 4
+  %shr = lshr i64 %xor, 8
+  %and1 = and i64 %shr, 255
+  %p1 = getelementptr inbounds nuw [4 x i8], ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 1024), i64 %and1
+  %l1 = load i32, ptr %p1, align 4
+  %x1 = xor i32 %l1, %l0
+  %shr.1 = lshr i64 %xor, 16
+  %and.1 = and i64 %shr.1, 255
+  %p2 = getelementptr inbounds nuw [4 x i8], ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 2048), i64 %and.1
+  %l2 = load i32, ptr %p2, align 4
+  %x2 = xor i32 %l2, %x1
+  %shr.2 = lshr i64 %xor, 24
+  %and.2 = and i64 %shr.2, 255
+  %p3 = getelementptr inbounds nuw [4 x i8], ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 3072), i64 %and.2
+  %l3 = load i32, ptr %p3, align 4
+  %x3 = xor i32 %l3, %x2
+  %shr.3 = lshr i64 %w, 32
+  %and.3 = and i64 %shr.3, 255
+  %p4 = getelementptr inbounds nuw [4 x i8], ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 4096), i64 %and.3
+  %l4 = load i32, ptr %p4, align 4
+  %x4 = xor i32 %l4, %x3
+  %shr.4 = lshr i64 %w, 40
+  %and.4 = and i64 %shr.4, 255
+  %p5 = getelementptr inbounds nuw [4 x i8], ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 5120), i64 %and.4
+  %l5 = load i32, ptr %p5, align 4
+  %x5 = xor i32 %l5, %x4
+  %shr.5 = lshr i64 %w, 48
+  %and.5 = and i64 %shr.5, 255
+  %p6 = getelementptr inbounds nuw [4 x i8], ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 6144), i64 %and.5
+  %l6 = load i32, ptr %p6, align 4
+  %x6 = xor i32 %l6, %x5
+  %shr.6 = lshr i64 %w, 56
+  %p7 = getelementptr inbounds nuw [4 x i8], ptr getelementptr inbounds nuw (i8, ptr @tbl, i64 7168), i64 %shr.6
+  %l7 = load i32, ptr %p7, align 4
+  %x7 = xor i32 %l7, %x6
+  ret i32 %x7
+}
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/once-used-gep-index-seeds.ll b/llvm/test/Transforms/SLPVectorizer/X86/once-used-gep-index-seeds.ll
new file mode 100644
index 0000000000000..dd7b07a7c1b8b
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/once-used-gep-index-seeds.ll
@@ -0,0 +1,92 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=slp-vectorizer -S < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=x86-64-v3 | FileCheck %s
+
+; The single-use index computations of the scalar addresses are not used as
+; the standalone seeds, all the vector lanes would be extracted for the
+; addresses.
+
+define void @index_pair(ptr %idx, ptr %t, ptr %u, ptr %o) {
+; CHECK-LABEL: define void @index_pair(
+; CHECK-SAME: ptr [[IDX:%.*]], ptr [[T:%.*]], ptr [[U:%.*]], ptr [[O:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x i64>, ptr [[IDX]], align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = xor <2 x i64> [[TMP1]], splat (i64 1234)
+; CHECK-NEXT:    [[TMP3:%.*]] = and <2 x i64> [[TMP2]], splat (i64 1023)
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x i64> [[TMP3]], i64 0
+; CHECK-NEXT:    [[G0:%.*]] = getelementptr inbounds i32, ptr [[T]], i64 [[TMP4]]
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x i64> [[TMP3]], i64 1
+; CHECK-NEXT:    [[G1:%.*]] = getelementptr inbounds i32, ptr [[U]], i64 [[TMP5]]
+; CHECK-NEXT:    [[L0:%.*]] = load i32, ptr [[G0]], align 4
+; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[G1]], align 4
+; CHECK-NEXT:    [[R:%.*]] = add i32 [[L0]], [[L1]]
+; CHECK-NEXT:    store i32 [[R]], ptr [[O]], align 4
+; CHECK-NEXT:    ret void
+;
+  %a = load i64, ptr %idx, align 8
+  %idx1 = getelementptr inbounds i8, ptr %idx, i64 8
+  %b = load i64, ptr %idx1, align 8
+  %x0 = xor i64 %a, 1234
+  %x1 = xor i64 %b, 1234
+  %i0 = and i64 %x0, 1023
+  %i1 = and i64 %x1, 1023
+  %g0 = getelementptr inbounds i32, ptr %t, i64 %i0
+  %g1 = getelementptr inbounds i32, ptr %u, i64 %i1
+  %l0 = load i32, ptr %g0, align 4
+  %l1 = load i32, ptr %g1, align 4
+  %r = add i32 %l0, %l1
+  store i32 %r, ptr %o, align 4
+  ret void
+}
+
+define void @index_quad(ptr %idx, ptr %t, ptr %u, ptr %v, ptr %w, ptr %o) {
+; CHECK-LABEL: define void @index_quad(
+; CHECK-SAME: ptr [[IDX:%.*]], ptr [[T:%.*]], ptr [[U:%.*]], ptr [[V:%.*]], ptr [[W:%.*]], ptr [[O:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[TMP1:%.*]] = load <4 x i64>, ptr [[IDX]], align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = xor <4 x i64> [[TMP1]], splat (i64 1234)
+; CHECK-NEXT:    [[TMP3:%.*]] = and <4 x i64> [[TMP2]], splat (i64 1023)
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x i64> [[TMP3]], i64 0
+; CHECK-NEXT:    [[G0:%.*]] = getelementptr inbounds i32, ptr [[T]], i64 [[TMP4]]
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x i64> [[TMP3]], i64 1
+; CHECK-NEXT:    [[G1:%.*]] = getelementptr inbounds i32, ptr [[U]], i64 [[TMP5]]
+; CHECK-NEXT:    [[TMP6:%.*]] = extractelement <4 x i64> [[TMP3]], i64 2
+; CHECK-NEXT:    [[G2:%.*]] = getelementptr inbounds i32, ptr [[V]], i64 [[TMP6]]
+; CHECK-NEXT:    [[TMP7:%.*]] = extractelement <4 x i64> [[TMP3]], i64 3
+; CHECK-NEXT:    [[G3:%.*]] = getelementptr inbounds i32, ptr [[W]], i64 [[TMP7]]
+; CHECK-NEXT:    [[L0:%.*]] = load i32, ptr [[G0]], align 4
+; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[G1]], align 4
+; CHECK-NEXT:    [[L2:%.*]] = load i32, ptr [[G2]], align 4
+; CHECK-NEXT:    [[L3:%.*]] = load i32, ptr [[G3]], align 4
+; CHECK-NEXT:    [[R0:%.*]] = add i32 [[L0]], [[L1]]
+; CHECK-NEXT:    [[R1:%.*]] = add i32 [[L2]], [[L3]]
+; CHECK-NEXT:    [[R:%.*]] = mul i32 [[R0]], [[R1]]
+; CHECK-NEXT:    store i32 [[R]], ptr [[O]], align 4
+; CHECK-NEXT:    ret void
+;
+  %a = load i64, ptr %idx, align 8
+  %p1 = getelementptr inbounds i8, ptr %idx, i64 8
+  %b = load i64, ptr %p1, align 8
+  %p2 = getelementptr inbounds i8, ptr %idx, i64 16
+  %c = load i64, ptr %p2, align 8
+  %p3 = getelementptr inbounds i8, ptr %idx, i64 24
+  %d = load i64, ptr %p3, align 8
+  %x0 = xor i64 %a, 1234
+  %x1 = xor i64 %b, 1234
+  %x2 = xor i64 %c, 1234
+  %x3 = xor i64 %d, 1234
+  %i0 = and i64 %x0, 1023
+  %i1 = and i64 %x1, 1023
+  %i2 = and i64 %x2, 1023
+  %i3 = and i64 %x3, 1023
+  %g0 = getelementptr inbounds i32, ptr %t, i64 %i0
+  %g1 = getelementptr inbounds i32, ptr %u, i64 %i1
+  %g2 = getelementptr inbounds i32, ptr %v, i64 %i2
+  %g3 = getelementptr inbounds i32, ptr %w, i64 %i3
+  %l0 = load i32, ptr %g0, align 4
+  %l1 = load i32, ptr %g1, align 4
+  %l2 = load i32, ptr %g2, align 4
+  %l3 = load i32, ptr %g3, align 4
+  %r0 = add i32 %l0, %l1
+  %r1 = add i32 %l2, %l3
+  %r = mul i32 %r0, %r1
+  store i32 %r, ptr %o, align 4
+  ret void
+}



More information about the llvm-commits mailing list