[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