[llvm] 958f9ff - [SLP][NFC]Add a test for mixed fma/fmuladd scalars, NFC
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 22 07:53:28 PDT 2026
Author: Alexey Bataev
Date: 2026-07-22T10:53:24-04:00
New Revision: 958f9ff83ea9aa071df1c84c6a467b17d6b8dadf
URL: https://github.com/llvm/llvm-project/commit/958f9ff83ea9aa071df1c84c6a467b17d6b8dadf
DIFF: https://github.com/llvm/llvm-project/commit/958f9ff83ea9aa071df1c84c6a467b17d6b8dadf.diff
LOG: [SLP][NFC]Add a test for mixed fma/fmuladd scalars, NFC
Reviewers:
Pull Request: https://github.com/llvm/llvm-project/pull/211280
Added:
llvm/test/Transforms/SLPVectorizer/X86/fma-fmuladd-mix.ll
Modified:
Removed:
################################################################################
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/fma-fmuladd-mix.ll b/llvm/test/Transforms/SLPVectorizer/X86/fma-fmuladd-mix.ll
new file mode 100644
index 0000000000000..3179f53823941
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/fma-fmuladd-mix.ll
@@ -0,0 +1,126 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -mtriple=x86_64-unknown -passes=slp-vectorizer -S | FileCheck %s --check-prefix=NO-FMA
+; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -passes=slp-vectorizer -S | FileCheck %s --check-prefix=FMA
+
+ at srcA64 = common global [8 x double] zeroinitializer, align 64
+ at srcB64 = common global [8 x double] zeroinitializer, align 64
+ at srcC64 = common global [8 x double] zeroinitializer, align 64
+ at dst64 = common global [8 x double] zeroinitializer, align 64
+
+declare double @llvm.fma.f64(double, double, double)
+declare double @llvm.fmuladd.f64(double, double, double)
+
+; A bundle mixing fma and fmuladd widens to a single vector fma on an FMA
+; target; the fmuladd lane is fused, which is one of its permitted lowerings.
+define void @fma_fmuladd_2f64() {
+; NO-FMA-LABEL: @fma_fmuladd_2f64(
+; NO-FMA-NEXT: [[A0:%.*]] = load double, ptr @srcA64, align 8
+; NO-FMA-NEXT: [[A1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcA64, i32 0, i64 1), align 8
+; NO-FMA-NEXT: [[B0:%.*]] = load double, ptr @srcB64, align 8
+; NO-FMA-NEXT: [[B1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcB64, i32 0, i64 1), align 8
+; NO-FMA-NEXT: [[C0:%.*]] = load double, ptr @srcC64, align 8
+; NO-FMA-NEXT: [[C1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcC64, i32 0, i64 1), align 8
+; NO-FMA-NEXT: [[FMA0:%.*]] = call double @llvm.fma.f64(double [[A0]], double [[B0]], double [[C0]])
+; NO-FMA-NEXT: [[FMA1:%.*]] = call double @llvm.fmuladd.f64(double [[A1]], double [[B1]], double [[C1]])
+; NO-FMA-NEXT: store double [[FMA0]], ptr @dst64, align 8
+; NO-FMA-NEXT: store double [[FMA1]], ptr getelementptr inbounds ([8 x double], ptr @dst64, i32 0, i64 1), align 8
+; NO-FMA-NEXT: ret void
+;
+; FMA-LABEL: @fma_fmuladd_2f64(
+; FMA-NEXT: [[A0:%.*]] = load double, ptr @srcA64, align 8
+; FMA-NEXT: [[A1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcA64, i32 0, i64 1), align 8
+; FMA-NEXT: [[B0:%.*]] = load double, ptr @srcB64, align 8
+; FMA-NEXT: [[B1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcB64, i32 0, i64 1), align 8
+; FMA-NEXT: [[C0:%.*]] = load double, ptr @srcC64, align 8
+; FMA-NEXT: [[C1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcC64, i32 0, i64 1), align 8
+; FMA-NEXT: [[FMA0:%.*]] = call double @llvm.fma.f64(double [[A0]], double [[B0]], double [[C0]])
+; FMA-NEXT: [[FMA1:%.*]] = call double @llvm.fmuladd.f64(double [[A1]], double [[B1]], double [[C1]])
+; FMA-NEXT: store double [[FMA0]], ptr @dst64, align 8
+; FMA-NEXT: store double [[FMA1]], ptr getelementptr inbounds ([8 x double], ptr @dst64, i32 0, i64 1), align 8
+; FMA-NEXT: ret void
+;
+ %a0 = load double, ptr @srcA64, align 8
+ %a1 = load double, ptr getelementptr inbounds ([8 x double], ptr @srcA64, i32 0, i64 1), align 8
+ %b0 = load double, ptr @srcB64, align 8
+ %b1 = load double, ptr getelementptr inbounds ([8 x double], ptr @srcB64, i32 0, i64 1), align 8
+ %c0 = load double, ptr @srcC64, align 8
+ %c1 = load double, ptr getelementptr inbounds ([8 x double], ptr @srcC64, i32 0, i64 1), align 8
+ %fma0 = call double @llvm.fma.f64(double %a0, double %b0, double %c0)
+ %fma1 = call double @llvm.fmuladd.f64(double %a1, double %b1, double %c1)
+ store double %fma0, ptr @dst64, align 8
+ store double %fma1, ptr getelementptr inbounds ([8 x double], ptr @dst64, i32 0, i64 1), align 8
+ ret void
+}
+
+; Reversed lane order: the fmuladd appears first, so the representative must be
+; switched to the fma to emit the always-fused vector form.
+define void @fmuladd_fma_2f64() {
+; NO-FMA-LABEL: @fmuladd_fma_2f64(
+; NO-FMA-NEXT: [[A0:%.*]] = load double, ptr @srcA64, align 8
+; NO-FMA-NEXT: [[A1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcA64, i32 0, i64 1), align 8
+; NO-FMA-NEXT: [[B0:%.*]] = load double, ptr @srcB64, align 8
+; NO-FMA-NEXT: [[B1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcB64, i32 0, i64 1), align 8
+; NO-FMA-NEXT: [[C0:%.*]] = load double, ptr @srcC64, align 8
+; NO-FMA-NEXT: [[C1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcC64, i32 0, i64 1), align 8
+; NO-FMA-NEXT: [[FMA0:%.*]] = call double @llvm.fmuladd.f64(double [[A0]], double [[B0]], double [[C0]])
+; NO-FMA-NEXT: [[FMA1:%.*]] = call double @llvm.fma.f64(double [[A1]], double [[B1]], double [[C1]])
+; NO-FMA-NEXT: store double [[FMA0]], ptr @dst64, align 8
+; NO-FMA-NEXT: store double [[FMA1]], ptr getelementptr inbounds ([8 x double], ptr @dst64, i32 0, i64 1), align 8
+; NO-FMA-NEXT: ret void
+;
+; FMA-LABEL: @fmuladd_fma_2f64(
+; FMA-NEXT: [[A0:%.*]] = load double, ptr @srcA64, align 8
+; FMA-NEXT: [[A1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcA64, i32 0, i64 1), align 8
+; FMA-NEXT: [[B0:%.*]] = load double, ptr @srcB64, align 8
+; FMA-NEXT: [[B1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcB64, i32 0, i64 1), align 8
+; FMA-NEXT: [[C0:%.*]] = load double, ptr @srcC64, align 8
+; FMA-NEXT: [[C1:%.*]] = load double, ptr getelementptr inbounds ([8 x double], ptr @srcC64, i32 0, i64 1), align 8
+; FMA-NEXT: [[FMA0:%.*]] = call double @llvm.fmuladd.f64(double [[A0]], double [[B0]], double [[C0]])
+; FMA-NEXT: [[FMA1:%.*]] = call double @llvm.fma.f64(double [[A1]], double [[B1]], double [[C1]])
+; FMA-NEXT: store double [[FMA0]], ptr @dst64, align 8
+; FMA-NEXT: store double [[FMA1]], ptr getelementptr inbounds ([8 x double], ptr @dst64, i32 0, i64 1), align 8
+; FMA-NEXT: ret void
+;
+ %a0 = load double, ptr @srcA64, align 8
+ %a1 = load double, ptr getelementptr inbounds ([8 x double], ptr @srcA64, i32 0, i64 1), align 8
+ %b0 = load double, ptr @srcB64, align 8
+ %b1 = load double, ptr getelementptr inbounds ([8 x double], ptr @srcB64, i32 0, i64 1), align 8
+ %c0 = load double, ptr @srcC64, align 8
+ %c1 = load double, ptr getelementptr inbounds ([8 x double], ptr @srcC64, i32 0, i64 1), align 8
+ %fma0 = call double @llvm.fmuladd.f64(double %a0, double %b0, double %c0)
+ %fma1 = call double @llvm.fma.f64(double %a1, double %b1, double %c1)
+ store double %fma0, ptr @dst64, align 8
+ store double %fma1, ptr getelementptr inbounds ([8 x double], ptr @dst64, i32 0, i64 1), align 8
+ ret void
+}
+
+; Control: a pure fmuladd bundle stays fmuladd, keeping the freedom to split.
+define void @fmuladd_2f64() {
+; NO-FMA-LABEL: @fmuladd_2f64(
+; NO-FMA-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr @srcA64, align 8
+; NO-FMA-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr @srcB64, align 8
+; NO-FMA-NEXT: [[TMP3:%.*]] = load <2 x double>, ptr @srcC64, align 8
+; NO-FMA-NEXT: [[TMP4:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[TMP1]], <2 x double> [[TMP2]], <2 x double> [[TMP3]])
+; NO-FMA-NEXT: store <2 x double> [[TMP4]], ptr @dst64, align 8
+; NO-FMA-NEXT: ret void
+;
+; FMA-LABEL: @fmuladd_2f64(
+; FMA-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr @srcA64, align 8
+; FMA-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr @srcB64, align 8
+; FMA-NEXT: [[TMP3:%.*]] = load <2 x double>, ptr @srcC64, align 8
+; FMA-NEXT: [[TMP4:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[TMP1]], <2 x double> [[TMP2]], <2 x double> [[TMP3]])
+; FMA-NEXT: store <2 x double> [[TMP4]], ptr @dst64, align 8
+; FMA-NEXT: ret void
+;
+ %a0 = load double, ptr @srcA64, align 8
+ %a1 = load double, ptr getelementptr inbounds ([8 x double], ptr @srcA64, i32 0, i64 1), align 8
+ %b0 = load double, ptr @srcB64, align 8
+ %b1 = load double, ptr getelementptr inbounds ([8 x double], ptr @srcB64, i32 0, i64 1), align 8
+ %c0 = load double, ptr @srcC64, align 8
+ %c1 = load double, ptr getelementptr inbounds ([8 x double], ptr @srcC64, i32 0, i64 1), align 8
+ %fma0 = call double @llvm.fmuladd.f64(double %a0, double %b0, double %c0)
+ %fma1 = call double @llvm.fmuladd.f64(double %a1, double %b1, double %c1)
+ store double %fma0, ptr @dst64, align 8
+ store double %fma1, ptr getelementptr inbounds ([8 x double], ptr @dst64, i32 0, i64 1), align 8
+ ret void
+}
More information about the llvm-commits
mailing list