[llvm] [SLP][NFC]Add a test for mixed fma/fmuladd scalars, NFC (PR #211280)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 22 13:55:12 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Alexey Bataev (alexey-bataev)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/211280.diff


1 Files Affected:

- (added) llvm/test/Transforms/SLPVectorizer/X86/fma-fmuladd-mix.ll (+126) 


``````````diff
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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/211280


More information about the llvm-commits mailing list