[llvm] [PhaseOrdering][X86] Copied codegen add/fadd reduction pattern tests to ensure middle-end is creating reduction intrinsics (PR #206101)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 26 07:52:49 PDT 2026
https://github.com/RKSimon created https://github.com/llvm/llvm-project/pull/206101
AVX512 is missing a llvm.vector.reduce.add.v16i32 call - will investigate
>From da944be068ffdba49df4cc0d30f403d0b3f18827 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Fri, 26 Jun 2026 15:51:48 +0100
Subject: [PATCH] [PhaseOrdering][X86] Copied codegen add/fadd reduction
pattern tests to ensure middle-end is creating reduction intrinsics
AVX512 is missing a llvm.vector.reduce.add.v16i32 call - will investigate
---
.../X86/horizontal-reduce-add.ll | 125 ++++++++++++++++++
.../X86/horizontal-reduce-fadd.ll | 98 ++++++++++++++
2 files changed, 223 insertions(+)
create mode 100644 llvm/test/Transforms/PhaseOrdering/X86/horizontal-reduce-add.ll
create mode 100644 llvm/test/Transforms/PhaseOrdering/X86/horizontal-reduce-fadd.ll
diff --git a/llvm/test/Transforms/PhaseOrdering/X86/horizontal-reduce-add.ll b/llvm/test/Transforms/PhaseOrdering/X86/horizontal-reduce-add.ll
new file mode 100644
index 0000000000000..893c12c965ff0
--- /dev/null
+++ b/llvm/test/Transforms/PhaseOrdering/X86/horizontal-reduce-add.ll
@@ -0,0 +1,125 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=i686-- -mcpu=x86-64 | FileCheck %s --check-prefixes=CHECK,SSE
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=i686-- -mcpu=x86-64-v2 | FileCheck %s --check-prefixes=CHECK,SSE
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=i686-- -mcpu=x86-64-v3 | FileCheck %s --check-prefixes=CHECK,AVX2
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=i686-- -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=CHECK,AVX512
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=x86_64-- -mcpu=x86-64 | FileCheck %s --check-prefixes=CHECK,SSE
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=x86_64-- -mcpu=x86-64-v2 | FileCheck %s --check-prefixes=CHECK,SSE
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=x86_64-- -mcpu=x86-64-v3 | FileCheck %s --check-prefixes=CHECK,AVX2
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=CHECK,AVX512
+
+; PR37890 - subvector reduction followed by shuffle reduction
+
+define i32 @PR37890_v4i32(<4 x i32> %a) {
+; CHECK-LABEL: define i32 @PR37890_v4i32(
+; CHECK-SAME: <4 x i32> [[A:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[E:%.*]] = tail call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[A]])
+; CHECK-NEXT: ret i32 [[E]]
+;
+ %hi0 = shufflevector <4 x i32> %a, <4 x i32> undef, <2 x i32> <i32 2, i32 3>
+ %lo0 = shufflevector <4 x i32> %a, <4 x i32> undef, <2 x i32> <i32 0, i32 1>
+ %sum0 = add <2 x i32> %lo0, %hi0
+ %hi1 = shufflevector <2 x i32> %sum0, <2 x i32> undef, <2 x i32> <i32 1, i32 undef>
+ %sum1 = add <2 x i32> %sum0, %hi1
+ %e = extractelement <2 x i32> %sum1, i32 0
+ ret i32 %e
+}
+
+define i16 @PR37890_v8i16(<8 x i16> %a) {
+; CHECK-LABEL: define i16 @PR37890_v8i16(
+; CHECK-SAME: <8 x i16> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT: [[E:%.*]] = tail call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> [[A]])
+; CHECK-NEXT: ret i16 [[E]]
+;
+ %hi0 = shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %lo0 = shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %sum0 = add <4 x i16> %lo0, %hi0
+ %hi1 = shufflevector <4 x i16> %sum0, <4 x i16> undef, <2 x i32> <i32 2, i32 3>
+ %lo1 = shufflevector <4 x i16> %sum0, <4 x i16> undef, <2 x i32> <i32 0, i32 1>
+ %sum1 = add <2 x i16> %lo1, %hi1
+ %hi2 = shufflevector <2 x i16> %sum1, <2 x i16> undef, <2 x i32> <i32 1, i32 undef>
+ %sum2 = add <2 x i16> %sum1, %hi2
+ %e = extractelement <2 x i16> %sum2, i32 0
+ ret i16 %e
+}
+
+define i32 @PR37890_v8i32(<8 x i32> %a) {
+; CHECK-LABEL: define i32 @PR37890_v8i32(
+; CHECK-SAME: <8 x i32> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT: [[E:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[A]])
+; CHECK-NEXT: ret i32 [[E]]
+;
+ %hi0 = shufflevector <8 x i32> %a, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %lo0 = shufflevector <8 x i32> %a, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %sum0 = add <4 x i32> %lo0, %hi0
+ %hi1 = shufflevector <4 x i32> %sum0, <4 x i32> undef, <2 x i32> <i32 2, i32 3>
+ %lo1 = shufflevector <4 x i32> %sum0, <4 x i32> undef, <2 x i32> <i32 0, i32 1>
+ %sum1 = add <2 x i32> %lo1, %hi1
+ %hi2 = shufflevector <2 x i32> %sum1, <2 x i32> undef, <2 x i32> <i32 1, i32 undef>
+ %sum2 = add <2 x i32> %sum1, %hi2
+ %e = extractelement <2 x i32> %sum2, i32 0
+ ret i32 %e
+}
+
+define i16 @PR37890_v16i16(<16 x i16> %a) {
+; CHECK-LABEL: define i16 @PR37890_v16i16(
+; CHECK-SAME: <16 x i16> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT: [[E:%.*]] = tail call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> [[A]])
+; CHECK-NEXT: ret i16 [[E]]
+;
+ %hi0 = shufflevector <16 x i16> %a, <16 x i16> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ %lo0 = shufflevector <16 x i16> %a, <16 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %sum0 = add <8 x i16> %lo0, %hi0
+ %hi1 = shufflevector <8 x i16> %sum0, <8 x i16> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %lo1 = shufflevector <8 x i16> %sum0, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %sum1 = add <4 x i16> %lo1, %hi1
+ %hi2 = shufflevector <4 x i16> %sum1, <4 x i16> undef, <2 x i32> <i32 2, i32 3>
+ %lo2 = shufflevector <4 x i16> %sum1, <4 x i16> undef, <2 x i32> <i32 0, i32 1>
+ %sum2 = add <2 x i16> %lo2, %hi2
+ %hi3 = shufflevector <2 x i16> %sum2, <2 x i16> undef, <2 x i32> <i32 1, i32 undef>
+ %sum3 = add <2 x i16> %sum2, %hi3
+ %e = extractelement <2 x i16> %sum3, i32 0
+ ret i16 %e
+}
+
+define i32 @PR37890_v16i32(<16 x i32> %a) {
+; SSE-LABEL: define i32 @PR37890_v16i32(
+; SSE-SAME: <16 x i32> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; SSE-NEXT: [[E:%.*]] = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> [[A]])
+; SSE-NEXT: ret i32 [[E]]
+;
+; AVX2-LABEL: define i32 @PR37890_v16i32(
+; AVX2-SAME: <16 x i32> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; AVX2-NEXT: [[E:%.*]] = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> [[A]])
+; AVX2-NEXT: ret i32 [[E]]
+;
+; AVX512-LABEL: define i32 @PR37890_v16i32(
+; AVX512-SAME: <16 x i32> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; AVX512-NEXT: [[HI0:%.*]] = shufflevector <16 x i32> [[A]], <16 x i32> poison, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; AVX512-NEXT: [[LO0:%.*]] = shufflevector <16 x i32> [[A]], <16 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; AVX512-NEXT: [[SUM0:%.*]] = add <8 x i32> [[LO0]], [[HI0]]
+; AVX512-NEXT: [[HI1:%.*]] = shufflevector <8 x i32> [[SUM0]], <8 x i32> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; AVX512-NEXT: [[LO1:%.*]] = shufflevector <8 x i32> [[SUM0]], <8 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; AVX512-NEXT: [[SUM1:%.*]] = add <4 x i32> [[LO1]], [[HI1]]
+; AVX512-NEXT: [[HI2:%.*]] = shufflevector <4 x i32> [[SUM1]], <4 x i32> poison, <2 x i32> <i32 2, i32 3>
+; AVX512-NEXT: [[LO2:%.*]] = shufflevector <4 x i32> [[SUM1]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
+; AVX512-NEXT: [[SUM2:%.*]] = add <2 x i32> [[LO2]], [[HI2]]
+; AVX512-NEXT: [[HI3:%.*]] = shufflevector <2 x i32> [[SUM2]], <2 x i32> poison, <2 x i32> <i32 1, i32 poison>
+; AVX512-NEXT: [[SUM3:%.*]] = add <2 x i32> [[HI3]], [[SUM2]]
+; AVX512-NEXT: [[E:%.*]] = extractelement <2 x i32> [[SUM3]], i64 0
+; AVX512-NEXT: ret i32 [[E]]
+;
+ %hi0 = shufflevector <16 x i32> %a, <16 x i32> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ %lo0 = shufflevector <16 x i32> %a, <16 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %sum0 = add <8 x i32> %lo0, %hi0
+ %hi1 = shufflevector <8 x i32> %sum0, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %lo1 = shufflevector <8 x i32> %sum0, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %sum1 = add <4 x i32> %lo1, %hi1
+ %hi2 = shufflevector <4 x i32> %sum1, <4 x i32> undef, <2 x i32> <i32 2, i32 3>
+ %lo2 = shufflevector <4 x i32> %sum1, <4 x i32> undef, <2 x i32> <i32 0, i32 1>
+ %sum2 = add <2 x i32> %lo2, %hi2
+ %hi3 = shufflevector <2 x i32> %sum2, <2 x i32> undef, <2 x i32> <i32 1, i32 undef>
+ %sum3 = add <2 x i32> %sum2, %hi3
+ %e = extractelement <2 x i32> %sum3, i32 0
+ ret i32 %e
+}
diff --git a/llvm/test/Transforms/PhaseOrdering/X86/horizontal-reduce-fadd.ll b/llvm/test/Transforms/PhaseOrdering/X86/horizontal-reduce-fadd.ll
new file mode 100644
index 0000000000000..4b6b2e8207550
--- /dev/null
+++ b/llvm/test/Transforms/PhaseOrdering/X86/horizontal-reduce-fadd.ll
@@ -0,0 +1,98 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=i686-- -mcpu=x86-64 | FileCheck %s
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=i686-- -mcpu=x86-64-v2 | FileCheck %s
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=i686-- -mcpu=x86-64-v3 | FileCheck %s
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=i686-- -mcpu=x86-64-v4 | FileCheck %s
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=x86_64-- -mcpu=x86-64 | FileCheck %s
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=x86_64-- -mcpu=x86-64-v2 | FileCheck %s
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=x86_64-- -mcpu=x86-64-v3 | FileCheck %s
+; RUN: opt < %s -passes="default<O2>" -S -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s
+
+; PR37890 - subvector reduction followed by shuffle reduction
+
+define float @PR37890_v4f32(<4 x float> %a) {
+; CHECK-LABEL: define float @PR37890_v4f32(
+; CHECK-SAME: <4 x float> [[A:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[E:%.*]] = tail call fast float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[A]])
+; CHECK-NEXT: ret float [[E]]
+;
+ %hi0 = shufflevector <4 x float> %a, <4 x float> undef, <2 x i32> <i32 2, i32 3>
+ %lo0 = shufflevector <4 x float> %a, <4 x float> undef, <2 x i32> <i32 0, i32 1>
+ %sum0 = fadd fast <2 x float> %lo0, %hi0
+ %hi1 = shufflevector <2 x float> %sum0, <2 x float> undef, <2 x i32> <i32 1, i32 undef>
+ %sum1 = fadd fast <2 x float> %sum0, %hi1
+ %e = extractelement <2 x float> %sum1, i32 0
+ ret float %e
+}
+
+define double @PR37890_v4f64(<4 x double> %a) {
+; CHECK-LABEL: define double @PR37890_v4f64(
+; CHECK-SAME: <4 x double> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT: [[E:%.*]] = tail call fast double @llvm.vector.reduce.fadd.v4f64(double 0.000000e+00, <4 x double> [[A]])
+; CHECK-NEXT: ret double [[E]]
+;
+ %hi0 = shufflevector <4 x double> %a, <4 x double> undef, <2 x i32> <i32 2, i32 3>
+ %lo0 = shufflevector <4 x double> %a, <4 x double> undef, <2 x i32> <i32 0, i32 1>
+ %sum0 = fadd fast <2 x double> %lo0, %hi0
+ %hi1 = shufflevector <2 x double> %sum0, <2 x double> undef, <2 x i32> <i32 1, i32 undef>
+ %sum1 = fadd fast <2 x double> %sum0, %hi1
+ %e = extractelement <2 x double> %sum1, i32 0
+ ret double %e
+}
+
+define float @PR37890_v8f32(<8 x float> %a) {
+; CHECK-LABEL: define float @PR37890_v8f32(
+; CHECK-SAME: <8 x float> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT: [[E:%.*]] = tail call fast float @llvm.vector.reduce.fadd.v8f32(float 0.000000e+00, <8 x float> [[A]])
+; CHECK-NEXT: ret float [[E]]
+;
+ %hi0 = shufflevector <8 x float> %a, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %lo0 = shufflevector <8 x float> %a, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %sum0 = fadd fast <4 x float> %lo0, %hi0
+ %hi1 = shufflevector <4 x float> %sum0, <4 x float> undef, <2 x i32> <i32 2, i32 3>
+ %lo1 = shufflevector <4 x float> %sum0, <4 x float> undef, <2 x i32> <i32 0, i32 1>
+ %sum1 = fadd fast <2 x float> %lo1, %hi1
+ %hi2 = shufflevector <2 x float> %sum1, <2 x float> undef, <2 x i32> <i32 1, i32 undef>
+ %sum2 = fadd fast <2 x float> %sum1, %hi2
+ %e = extractelement <2 x float> %sum2, i32 0
+ ret float %e
+}
+
+define double @PR37890_v8f64(<8 x double> %a) {
+; CHECK-LABEL: define double @PR37890_v8f64(
+; CHECK-SAME: <8 x double> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT: [[E:%.*]] = tail call fast double @llvm.vector.reduce.fadd.v8f64(double 0.000000e+00, <8 x double> [[A]])
+; CHECK-NEXT: ret double [[E]]
+;
+ %hi0 = shufflevector <8 x double> %a, <8 x double> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %lo0 = shufflevector <8 x double> %a, <8 x double> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %sum0 = fadd fast <4 x double> %lo0, %hi0
+ %hi1 = shufflevector <4 x double> %sum0, <4 x double> undef, <2 x i32> <i32 2, i32 3>
+ %lo1 = shufflevector <4 x double> %sum0, <4 x double> undef, <2 x i32> <i32 0, i32 1>
+ %sum1 = fadd fast <2 x double> %lo1, %hi1
+ %hi2 = shufflevector <2 x double> %sum1, <2 x double> undef, <2 x i32> <i32 1, i32 undef>
+ %sum2 = fadd fast <2 x double> %sum1, %hi2
+ %e = extractelement <2 x double> %sum2, i32 0
+ ret double %e
+}
+
+define float @PR37890_v16f32(<16 x float> %a) {
+; CHECK-LABEL: define float @PR37890_v16f32(
+; CHECK-SAME: <16 x float> [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT: [[E:%.*]] = tail call fast float @llvm.vector.reduce.fadd.v16f32(float 0.000000e+00, <16 x float> [[A]])
+; CHECK-NEXT: ret float [[E]]
+;
+ %hi0 = shufflevector <16 x float> %a, <16 x float> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ %lo0 = shufflevector <16 x float> %a, <16 x float> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %sum0 = fadd fast <8 x float> %lo0, %hi0
+ %hi1 = shufflevector <8 x float> %sum0, <8 x float> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %lo1 = shufflevector <8 x float> %sum0, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %sum1 = fadd fast <4 x float> %lo1, %hi1
+ %hi2 = shufflevector <4 x float> %sum1, <4 x float> undef, <2 x i32> <i32 2, i32 3>
+ %lo2 = shufflevector <4 x float> %sum1, <4 x float> undef, <2 x i32> <i32 0, i32 1>
+ %sum2 = fadd fast <2 x float> %lo2, %hi2
+ %hi3 = shufflevector <2 x float> %sum2, <2 x float> undef, <2 x i32> <i32 1, i32 undef>
+ %sum3 = fadd fast <2 x float> %sum2, %hi3
+ %e = extractelement <2 x float> %sum3, i32 0
+ ret float %e
+}
More information about the llvm-commits
mailing list