[llvm] [AArch64] Add FMIN/FMAX clustering (PR #210906)
Tomer Shafir via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 21 01:19:19 PDT 2026
https://github.com/tomershafir updated https://github.com/llvm/llvm-project/pull/210906
>From b07160ef27a5908fed183f8f8e85e9526dd1feea Mon Sep 17 00:00:00 2001
From: tomershafir <tomer.shafir8 at gmail.com>
Date: Tue, 21 Jul 2026 11:16:00 +0300
Subject: [PATCH] [AArch64] Add FMIN/FMAX clustering
This patch adds a subtarget feature that controls scheduling FMIN/FMAX instructions back to back. Enabled on Apple CPU.
---
llvm/lib/Target/AArch64/AArch64Features.td | 5 +
.../lib/Target/AArch64/AArch64MacroFusion.cpp | 44 +
llvm/lib/Target/AArch64/AArch64Processors.td | 4 +-
llvm/lib/Target/AArch64/AArch64Subtarget.h | 2 +-
.../misched-fusion-fmin-fmax-post-ra.mir | 968 ++++++++++++++++++
.../misched-fusion-fmin-fmax-pre-ra.mir | 456 +++++++++
.../AArch64/misched-fusion-fmin-fmax.ll | 411 ++++++++
.../TableGen/aarch64-apple-tuning-features.td | 1 +
8 files changed, 1889 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax-post-ra.mir
create mode 100644 llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax-pre-ra.mir
create mode 100644 llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax.ll
diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td
index 7cb7cd32f673b..d67ef1b176df6 100644
--- a/llvm/lib/Target/AArch64/AArch64Features.td
+++ b/llvm/lib/Target/AArch64/AArch64Features.td
@@ -831,6 +831,11 @@ def FeatureFuseFCmpFCSel : SubtargetFeature<
"CPU can fuse FCMP and FCSEL operations",
[], InlineIgnore>;
+def FeatureFuseFMinFMax : SubtargetFeature<
+ "fuse-fmin-fmax", "HasFuseFMinFMax", "true",
+ "CPU can fuse FMIN and FMAX operations",
+ [], InlineIgnore>;
+
def FeatureAlignCmpCSelPairs : SubtargetFeature<
"align-cmp-csel-pairs", "HasAlignCmpCSelPairs", "true",
"Align certain CMP/FCMP and CSEL/FCSEL instruction pairs",
diff --git a/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp b/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp
index 31b3e097de8ca..698412ff7afd0 100644
--- a/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MacroFusion.cpp
@@ -537,6 +537,48 @@ static bool isAddSub2RegAndConstOnePair(const MachineInstr *FirstMI,
return false;
}
+// Floating-point minimum or maximum, scalar (H/S/D) or vector (Vd).
+static bool isFMinFMax(unsigned Opcode) {
+ switch (Opcode) {
+ // Scalar.
+ case AArch64::FMAXHrr:
+ case AArch64::FMAXSrr:
+ case AArch64::FMAXDrr:
+ case AArch64::FMINHrr:
+ case AArch64::FMINSrr:
+ case AArch64::FMINDrr:
+ // Vector.
+ case AArch64::FMAXv4f16:
+ case AArch64::FMAXv8f16:
+ case AArch64::FMAXv2f32:
+ case AArch64::FMAXv4f32:
+ case AArch64::FMAXv2f64:
+ case AArch64::FMINv4f16:
+ case AArch64::FMINv8f16:
+ case AArch64::FMINv2f32:
+ case AArch64::FMINv4f32:
+ case AArch64::FMINv2f64:
+ return true;
+ }
+ return false;
+}
+
+// FMIN + FMAX.
+static bool isFMinFMaxPair(const MachineInstr *FirstMI,
+ const MachineInstr &SecondMI) {
+ if (!isFMinFMax(SecondMI.getOpcode()))
+ return false;
+
+ // Assume the 1st instr to be a wildcard if it is unspecified.
+ if (FirstMI == nullptr)
+ return true;
+
+ if (!isFMinFMax(FirstMI->getOpcode()))
+ return false;
+
+ return mayHaveWAWDependency(*FirstMI, SecondMI);
+}
+
/// \brief Check if the instr pair, FirstMI and SecondMI, should be fused
/// together. Given SecondMI, when FirstMI is unspecified, then check if
/// SecondMI may be part of a fused pair at all.
@@ -576,6 +618,8 @@ static bool shouldScheduleAdjacent(const TargetInstrInfo &TII,
if (ST.hasFuseAddSub2RegAndConstOne() &&
isAddSub2RegAndConstOnePair(FirstMI, SecondMI))
return true;
+ if (ST.hasFuseFMinFMax() && isFMinFMaxPair(FirstMI, SecondMI))
+ return true;
return false;
}
diff --git a/llvm/lib/Target/AArch64/AArch64Processors.td b/llvm/lib/Target/AArch64/AArch64Processors.td
index a8e7e897265e4..7d5927de6f02d 100644
--- a/llvm/lib/Target/AArch64/AArch64Processors.td
+++ b/llvm/lib/Target/AArch64/AArch64Processors.td
@@ -451,7 +451,9 @@ def TuneAppleM4 : SubtargetFeature<"apple-m4", "ARMProcFamily", "AppleM4",
[FeatureStorePairSuppress])>;
def TuneAppleM5 : SubtargetFeature<"apple-m5", "ARMProcFamily", "AppleM5",
- "Apple M5", TuneAppleM4.Implies>;
+ "Apple M5",
+ !listconcat(TuneAppleM4.Implies,
+ [FeatureFuseFMinFMax])>;
def TuneExynosM3 : SubtargetFeature<"exynosm3", "ARMProcFamily", "ExynosM3",
"Samsung Exynos-M3 processors",
diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h
index b8303224a8976..b61dfd2f9de9e 100644
--- a/llvm/lib/Target/AArch64/AArch64Subtarget.h
+++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h
@@ -266,7 +266,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
return hasArithmeticBccFusion() || hasArithmeticCbzFusion() ||
hasFuseAES() || hasFuseArithmeticLogic() || hasFuseCmpCSel() ||
hasFuseFCmpFCSel() || hasFuseCmpCSet() || hasFuseAdrpAdd() ||
- hasFuseLiterals();
+ hasFuseLiterals() || hasFuseFMinFMax();
}
unsigned getEpilogueVectorizationMinVF() const {
diff --git a/llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax-post-ra.mir b/llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax-post-ra.mir
new file mode 100644
index 0000000000000..9dd770310abea
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax-post-ra.mir
@@ -0,0 +1,968 @@
+# REQUIRES: asserts
+
+# RUN: llc -o /dev/null %s -mtriple=aarch64-linux-gnu -mattr=+fuse-fmin-fmax -passes=machine-scheduler -misched-print-dags -print-before=machine-scheduler 2>&1 | FileCheck %s --check-prefixes=FUSE
+# RUN: llc -o /dev/null %s -mtriple=arm64-apple-macosx -mcpu=apple-m5 -passes=machine-scheduler -misched-print-dags -print-before=machine-scheduler 2>&1 | FileCheck %s --check-prefixes=FUSE
+
+# RUN: llc -o /dev/null %s -mtriple=aarch64-linux-gnu -passes=machine-scheduler -misched-print-dags -print-before=machine-scheduler 2>&1 | FileCheck %s --check-prefixes=NOFUSE
+# RUN: llc -o /dev/null %s -mtriple=arm64-apple-macosx -mcpu=apple-m5 -mattr=-fuse-fmin-fmax -passes=machine-scheduler -misched-print-dags -print-before=machine-scheduler 2>&1 | FileCheck %s --check-prefixes=NOFUSE
+
+---
+name: fmax_fmax_h_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $h0, $h1, $h2, $h3, $h4
+ ; CHECK: SU(0): $h5 = FMAXHrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $h5 = FMAXHrr
+ $h5 = FMAXHrr $h0, $h1, implicit $fpcr
+ $h6 = FADDHrr $h3, $h4, implicit $fpcr
+ $h5 = FMAXHrr $h5, $h2, implicit $fpcr
+...
+---
+name: fmax_fmax_h_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $h0, $h1, $h2, $h3, $h4
+ ; CHECK: SU(0): $h5 = FMAXHrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $h7 = FMAXHrr
+ $h5 = FMAXHrr $h0, $h1, implicit $fpcr
+ $h6 = FADDHrr $h3, $h4, implicit $fpcr
+ $h7 = FMAXHrr $h5, $h2, implicit $fpcr
+...
+---
+name: fmax_fmin_h_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $h0, $h1, $h2, $h3, $h4
+ ; CHECK: SU(0): $h5 = FMAXHrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $h5 = FMINHrr
+ $h5 = FMAXHrr $h0, $h1, implicit $fpcr
+ $h6 = FADDHrr $h3, $h4, implicit $fpcr
+ $h5 = FMINHrr $h5, $h2, implicit $fpcr
+...
+---
+name: fmax_fmin_h_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $h0, $h1, $h2, $h3, $h4
+ ; CHECK: SU(0): $h5 = FMAXHrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $h7 = FMINHrr
+ $h5 = FMAXHrr $h0, $h1, implicit $fpcr
+ $h6 = FADDHrr $h3, $h4, implicit $fpcr
+ $h7 = FMINHrr $h5, $h2, implicit $fpcr
+...
+---
+name: fmin_fmax_h_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $h0, $h1, $h2, $h3, $h4
+ ; CHECK: SU(0): $h5 = FMINHrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $h5 = FMAXHrr
+ $h5 = FMINHrr $h0, $h1, implicit $fpcr
+ $h6 = FADDHrr $h3, $h4, implicit $fpcr
+ $h5 = FMAXHrr $h5, $h2, implicit $fpcr
+...
+---
+name: fmin_fmax_h_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $h0, $h1, $h2, $h3, $h4
+ ; CHECK: SU(0): $h5 = FMINHrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $h7 = FMAXHrr
+ $h5 = FMINHrr $h0, $h1, implicit $fpcr
+ $h6 = FADDHrr $h3, $h4, implicit $fpcr
+ $h7 = FMAXHrr $h5, $h2, implicit $fpcr
+...
+---
+name: fmin_fmin_h_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $h0, $h1, $h2, $h3, $h4
+ ; CHECK: SU(0): $h5 = FMINHrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $h5 = FMINHrr
+ $h5 = FMINHrr $h0, $h1, implicit $fpcr
+ $h6 = FADDHrr $h3, $h4, implicit $fpcr
+ $h5 = FMINHrr $h5, $h2, implicit $fpcr
+...
+---
+name: fmin_fmin_h_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $h0, $h1, $h2, $h3, $h4
+ ; CHECK: SU(0): $h5 = FMINHrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $h7 = FMINHrr
+ $h5 = FMINHrr $h0, $h1, implicit $fpcr
+ $h6 = FADDHrr $h3, $h4, implicit $fpcr
+ $h7 = FMINHrr $h5, $h2, implicit $fpcr
+...
+---
+name: fmax_fmax_s_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $s0, $s1, $s2, $s3, $s4
+ ; CHECK: SU(0): $s5 = FMAXSrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $s5 = FMAXSrr
+ $s5 = FMAXSrr $s0, $s1, implicit $fpcr
+ $s6 = FADDSrr $s3, $s4, implicit $fpcr
+ $s5 = FMAXSrr $s5, $s2, implicit $fpcr
+...
+---
+name: fmax_fmax_s_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $s0, $s1, $s2, $s3, $s4
+ ; CHECK: SU(0): $s5 = FMAXSrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $s7 = FMAXSrr
+ $s5 = FMAXSrr $s0, $s1, implicit $fpcr
+ $s6 = FADDSrr $s3, $s4, implicit $fpcr
+ $s7 = FMAXSrr $s5, $s2, implicit $fpcr
+...
+---
+name: fmax_fmin_s_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $s0, $s1, $s2, $s3, $s4
+ ; CHECK: SU(0): $s5 = FMAXSrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $s5 = FMINSrr
+ $s5 = FMAXSrr $s0, $s1, implicit $fpcr
+ $s6 = FADDSrr $s3, $s4, implicit $fpcr
+ $s5 = FMINSrr $s5, $s2, implicit $fpcr
+...
+---
+name: fmax_fmin_s_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $s0, $s1, $s2, $s3, $s4
+ ; CHECK: SU(0): $s5 = FMAXSrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $s7 = FMINSrr
+ $s5 = FMAXSrr $s0, $s1, implicit $fpcr
+ $s6 = FADDSrr $s3, $s4, implicit $fpcr
+ $s7 = FMINSrr $s5, $s2, implicit $fpcr
+...
+---
+name: fmin_fmax_s_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $s0, $s1, $s2, $s3, $s4
+ ; CHECK: SU(0): $s5 = FMINSrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $s5 = FMAXSrr
+ $s5 = FMINSrr $s0, $s1, implicit $fpcr
+ $s6 = FADDSrr $s3, $s4, implicit $fpcr
+ $s5 = FMAXSrr $s5, $s2, implicit $fpcr
+...
+---
+name: fmin_fmax_s_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $s0, $s1, $s2, $s3, $s4
+ ; CHECK: SU(0): $s5 = FMINSrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $s7 = FMAXSrr
+ $s5 = FMINSrr $s0, $s1, implicit $fpcr
+ $s6 = FADDSrr $s3, $s4, implicit $fpcr
+ $s7 = FMAXSrr $s5, $s2, implicit $fpcr
+...
+---
+name: fmin_fmin_s_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $s0, $s1, $s2, $s3, $s4
+ ; CHECK: SU(0): $s5 = FMINSrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $s5 = FMINSrr
+ $s5 = FMINSrr $s0, $s1, implicit $fpcr
+ $s6 = FADDSrr $s3, $s4, implicit $fpcr
+ $s5 = FMINSrr $s5, $s2, implicit $fpcr
+...
+---
+name: fmin_fmin_s_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $s0, $s1, $s2, $s3, $s4
+ ; CHECK: SU(0): $s5 = FMINSrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $s7 = FMINSrr
+ $s5 = FMINSrr $s0, $s1, implicit $fpcr
+ $s6 = FADDSrr $s3, $s4, implicit $fpcr
+ $s7 = FMINSrr $s5, $s2, implicit $fpcr
+...
+---
+name: fmax_fmax_d_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXDrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMAXDrr
+ $d5 = FMAXDrr $d0, $d1, implicit $fpcr
+ $d6 = FADDDrr $d3, $d4, implicit $fpcr
+ $d5 = FMAXDrr $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmax_d_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXDrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMAXDrr
+ $d5 = FMAXDrr $d0, $d1, implicit $fpcr
+ $d6 = FADDDrr $d3, $d4, implicit $fpcr
+ $d7 = FMAXDrr $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmin_d_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXDrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMINDrr
+ $d5 = FMAXDrr $d0, $d1, implicit $fpcr
+ $d6 = FADDDrr $d3, $d4, implicit $fpcr
+ $d5 = FMINDrr $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmin_d_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXDrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMINDrr
+ $d5 = FMAXDrr $d0, $d1, implicit $fpcr
+ $d6 = FADDDrr $d3, $d4, implicit $fpcr
+ $d7 = FMINDrr $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmax_d_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINDrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMAXDrr
+ $d5 = FMINDrr $d0, $d1, implicit $fpcr
+ $d6 = FADDDrr $d3, $d4, implicit $fpcr
+ $d5 = FMAXDrr $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmax_d_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINDrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMAXDrr
+ $d5 = FMINDrr $d0, $d1, implicit $fpcr
+ $d6 = FADDDrr $d3, $d4, implicit $fpcr
+ $d7 = FMAXDrr $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmin_d_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINDrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMINDrr
+ $d5 = FMINDrr $d0, $d1, implicit $fpcr
+ $d6 = FADDDrr $d3, $d4, implicit $fpcr
+ $d5 = FMINDrr $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmin_d_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINDrr
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMINDrr
+ $d5 = FMINDrr $d0, $d1, implicit $fpcr
+ $d6 = FADDDrr $d3, $d4, implicit $fpcr
+ $d7 = FMINDrr $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmax_v4f16_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXv4f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMAXv4f16
+ $d5 = FMAXv4f16 $d0, $d1, implicit $fpcr
+ $d6 = FADDv4f16 $d3, $d4, implicit $fpcr
+ $d5 = FMAXv4f16 $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmax_v4f16_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXv4f16
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMAXv4f16
+ $d5 = FMAXv4f16 $d0, $d1, implicit $fpcr
+ $d6 = FADDv4f16 $d3, $d4, implicit $fpcr
+ $d7 = FMAXv4f16 $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmin_v4f16_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXv4f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMINv4f16
+ $d5 = FMAXv4f16 $d0, $d1, implicit $fpcr
+ $d6 = FADDv4f16 $d3, $d4, implicit $fpcr
+ $d5 = FMINv4f16 $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmin_v4f16_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXv4f16
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMINv4f16
+ $d5 = FMAXv4f16 $d0, $d1, implicit $fpcr
+ $d6 = FADDv4f16 $d3, $d4, implicit $fpcr
+ $d7 = FMINv4f16 $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmax_v4f16_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINv4f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMAXv4f16
+ $d5 = FMINv4f16 $d0, $d1, implicit $fpcr
+ $d6 = FADDv4f16 $d3, $d4, implicit $fpcr
+ $d5 = FMAXv4f16 $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmax_v4f16_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINv4f16
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMAXv4f16
+ $d5 = FMINv4f16 $d0, $d1, implicit $fpcr
+ $d6 = FADDv4f16 $d3, $d4, implicit $fpcr
+ $d7 = FMAXv4f16 $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmin_v4f16_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINv4f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMINv4f16
+ $d5 = FMINv4f16 $d0, $d1, implicit $fpcr
+ $d6 = FADDv4f16 $d3, $d4, implicit $fpcr
+ $d5 = FMINv4f16 $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmin_v4f16_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINv4f16
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMINv4f16
+ $d5 = FMINv4f16 $d0, $d1, implicit $fpcr
+ $d6 = FADDv4f16 $d3, $d4, implicit $fpcr
+ $d7 = FMINv4f16 $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmax_v8f16_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv8f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMAXv8f16
+ $q5 = FMAXv8f16 $q0, $q1, implicit $fpcr
+ $q6 = FADDv8f16 $q3, $q4, implicit $fpcr
+ $q5 = FMAXv8f16 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmax_v8f16_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv8f16
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMAXv8f16
+ $q5 = FMAXv8f16 $q0, $q1, implicit $fpcr
+ $q6 = FADDv8f16 $q3, $q4, implicit $fpcr
+ $q7 = FMAXv8f16 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmin_v8f16_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv8f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMINv8f16
+ $q5 = FMAXv8f16 $q0, $q1, implicit $fpcr
+ $q6 = FADDv8f16 $q3, $q4, implicit $fpcr
+ $q5 = FMINv8f16 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmin_v8f16_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv8f16
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMINv8f16
+ $q5 = FMAXv8f16 $q0, $q1, implicit $fpcr
+ $q6 = FADDv8f16 $q3, $q4, implicit $fpcr
+ $q7 = FMINv8f16 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmax_v8f16_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv8f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMAXv8f16
+ $q5 = FMINv8f16 $q0, $q1, implicit $fpcr
+ $q6 = FADDv8f16 $q3, $q4, implicit $fpcr
+ $q5 = FMAXv8f16 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmax_v8f16_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv8f16
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMAXv8f16
+ $q5 = FMINv8f16 $q0, $q1, implicit $fpcr
+ $q6 = FADDv8f16 $q3, $q4, implicit $fpcr
+ $q7 = FMAXv8f16 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmin_v8f16_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv8f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMINv8f16
+ $q5 = FMINv8f16 $q0, $q1, implicit $fpcr
+ $q6 = FADDv8f16 $q3, $q4, implicit $fpcr
+ $q5 = FMINv8f16 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmin_v8f16_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv8f16
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMINv8f16
+ $q5 = FMINv8f16 $q0, $q1, implicit $fpcr
+ $q6 = FADDv8f16 $q3, $q4, implicit $fpcr
+ $q7 = FMINv8f16 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmax_v2f32_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXv2f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMAXv2f32
+ $d5 = FMAXv2f32 $d0, $d1, implicit $fpcr
+ $d6 = FADDv2f32 $d3, $d4, implicit $fpcr
+ $d5 = FMAXv2f32 $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmax_v2f32_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXv2f32
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMAXv2f32
+ $d5 = FMAXv2f32 $d0, $d1, implicit $fpcr
+ $d6 = FADDv2f32 $d3, $d4, implicit $fpcr
+ $d7 = FMAXv2f32 $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmin_v2f32_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXv2f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMINv2f32
+ $d5 = FMAXv2f32 $d0, $d1, implicit $fpcr
+ $d6 = FADDv2f32 $d3, $d4, implicit $fpcr
+ $d5 = FMINv2f32 $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmin_v2f32_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMAXv2f32
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMINv2f32
+ $d5 = FMAXv2f32 $d0, $d1, implicit $fpcr
+ $d6 = FADDv2f32 $d3, $d4, implicit $fpcr
+ $d7 = FMINv2f32 $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmax_v2f32_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINv2f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMAXv2f32
+ $d5 = FMINv2f32 $d0, $d1, implicit $fpcr
+ $d6 = FADDv2f32 $d3, $d4, implicit $fpcr
+ $d5 = FMAXv2f32 $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmax_v2f32_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINv2f32
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMAXv2f32
+ $d5 = FMINv2f32 $d0, $d1, implicit $fpcr
+ $d6 = FADDv2f32 $d3, $d4, implicit $fpcr
+ $d7 = FMAXv2f32 $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmin_v2f32_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINv2f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d5 = FMINv2f32
+ $d5 = FMINv2f32 $d0, $d1, implicit $fpcr
+ $d6 = FADDv2f32 $d3, $d4, implicit $fpcr
+ $d5 = FMINv2f32 $d5, $d2, implicit $fpcr
+...
+---
+name: fmin_fmin_v2f32_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1, $d2, $d3, $d4
+ ; CHECK: SU(0): $d5 = FMINv2f32
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $d7 = FMINv2f32
+ $d5 = FMINv2f32 $d0, $d1, implicit $fpcr
+ $d6 = FADDv2f32 $d3, $d4, implicit $fpcr
+ $d7 = FMINv2f32 $d5, $d2, implicit $fpcr
+...
+---
+name: fmax_fmax_v4f32_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv4f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMAXv4f32
+ $q5 = FMAXv4f32 $q0, $q1, implicit $fpcr
+ $q6 = FADDv4f32 $q3, $q4, implicit $fpcr
+ $q5 = FMAXv4f32 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmax_v4f32_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv4f32
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMAXv4f32
+ $q5 = FMAXv4f32 $q0, $q1, implicit $fpcr
+ $q6 = FADDv4f32 $q3, $q4, implicit $fpcr
+ $q7 = FMAXv4f32 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmin_v4f32_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv4f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMINv4f32
+ $q5 = FMAXv4f32 $q0, $q1, implicit $fpcr
+ $q6 = FADDv4f32 $q3, $q4, implicit $fpcr
+ $q5 = FMINv4f32 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmin_v4f32_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv4f32
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMINv4f32
+ $q5 = FMAXv4f32 $q0, $q1, implicit $fpcr
+ $q6 = FADDv4f32 $q3, $q4, implicit $fpcr
+ $q7 = FMINv4f32 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmax_v4f32_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv4f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMAXv4f32
+ $q5 = FMINv4f32 $q0, $q1, implicit $fpcr
+ $q6 = FADDv4f32 $q3, $q4, implicit $fpcr
+ $q5 = FMAXv4f32 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmax_v4f32_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv4f32
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMAXv4f32
+ $q5 = FMINv4f32 $q0, $q1, implicit $fpcr
+ $q6 = FADDv4f32 $q3, $q4, implicit $fpcr
+ $q7 = FMAXv4f32 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmin_v4f32_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv4f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMINv4f32
+ $q5 = FMINv4f32 $q0, $q1, implicit $fpcr
+ $q6 = FADDv4f32 $q3, $q4, implicit $fpcr
+ $q5 = FMINv4f32 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmin_v4f32_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv4f32
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMINv4f32
+ $q5 = FMINv4f32 $q0, $q1, implicit $fpcr
+ $q6 = FADDv4f32 $q3, $q4, implicit $fpcr
+ $q7 = FMINv4f32 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmax_v2f64_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv2f64
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMAXv2f64
+ $q5 = FMAXv2f64 $q0, $q1, implicit $fpcr
+ $q6 = FADDv2f64 $q3, $q4, implicit $fpcr
+ $q5 = FMAXv2f64 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmax_v2f64_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv2f64
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMAXv2f64
+ $q5 = FMAXv2f64 $q0, $q1, implicit $fpcr
+ $q6 = FADDv2f64 $q3, $q4, implicit $fpcr
+ $q7 = FMAXv2f64 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmin_v2f64_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv2f64
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMINv2f64
+ $q5 = FMAXv2f64 $q0, $q1, implicit $fpcr
+ $q6 = FADDv2f64 $q3, $q4, implicit $fpcr
+ $q5 = FMINv2f64 $q5, $q2, implicit $fpcr
+...
+---
+name: fmax_fmin_v2f64_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMAXv2f64
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMINv2f64
+ $q5 = FMAXv2f64 $q0, $q1, implicit $fpcr
+ $q6 = FADDv2f64 $q3, $q4, implicit $fpcr
+ $q7 = FMINv2f64 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmax_v2f64_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv2f64
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMAXv2f64
+ $q5 = FMINv2f64 $q0, $q1, implicit $fpcr
+ $q6 = FADDv2f64 $q3, $q4, implicit $fpcr
+ $q5 = FMAXv2f64 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmax_v2f64_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv2f64
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMAXv2f64
+ $q5 = FMINv2f64 $q0, $q1, implicit $fpcr
+ $q6 = FADDv2f64 $q3, $q4, implicit $fpcr
+ $q7 = FMAXv2f64 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmin_v2f64_waw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv2f64
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q5 = FMINv2f64
+ $q5 = FMINv2f64 $q0, $q1, implicit $fpcr
+ $q6 = FADDv2f64 $q3, $q4, implicit $fpcr
+ $q5 = FMINv2f64 $q5, $q2, implicit $fpcr
+...
+---
+name: fmin_fmin_v2f64_nowaw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1, $q2, $q3, $q4
+ ; CHECK: SU(0): $q5 = FMINv2f64
+ ; CHECK: Successors:
+ ; FUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): $q7 = FMINv2f64
+ $q5 = FMINv2f64 $q0, $q1, implicit $fpcr
+ $q6 = FADDv2f64 $q3, $q4, implicit $fpcr
+ $q7 = FMINv2f64 $q5, $q2, implicit $fpcr
+...
diff --git a/llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax-pre-ra.mir b/llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax-pre-ra.mir
new file mode 100644
index 0000000000000..a7e5244352209
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax-pre-ra.mir
@@ -0,0 +1,456 @@
+# REQUIRES: asserts
+
+# RUN: llc -o /dev/null %s -mtriple=aarch64-linux-gnu -mattr=+fuse-fmin-fmax -passes=machine-scheduler -misched-print-dags -print-before=machine-scheduler 2>&1 | FileCheck %s --check-prefixes=FUSE
+# RUN: llc -o /dev/null %s -mtriple=arm64-apple-macosx -mcpu=apple-m5 -passes=machine-scheduler -misched-print-dags -print-before=machine-scheduler 2>&1 | FileCheck %s --check-prefixes=FUSE
+
+# RUN: llc -o /dev/null %s -mtriple=aarch64-linux-gnu -passes=machine-scheduler -misched-print-dags -print-before=machine-scheduler 2>&1 | FileCheck %s --check-prefixes=NOFUSE
+# RUN: llc -o /dev/null %s -mtriple=arm64-apple-macosx -mcpu=apple-m5 -mattr=-fuse-fmin-fmax -passes=machine-scheduler -misched-print-dags -print-before=machine-scheduler 2>&1 | FileCheck %s --check-prefixes=NOFUSE
+
+---
+name: fmax_fmax_h
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr16 = FMAXHrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr16 = FMAXHrr
+ %0:fpr16 = FMAXHrr undef $h0, undef $h1, implicit $fpcr
+ %1:fpr16 = FADDHrr undef $h3, undef $h4, implicit $fpcr
+ %2:fpr16 = FMAXHrr %0, undef $h2, implicit $fpcr
+...
+---
+name: fmax_fmin_h
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr16 = FMAXHrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr16 = FMINHrr
+ %0:fpr16 = FMAXHrr undef $h0, undef $h1, implicit $fpcr
+ %1:fpr16 = FADDHrr undef $h3, undef $h4, implicit $fpcr
+ %2:fpr16 = FMINHrr %0, undef $h2, implicit $fpcr
+...
+---
+name: fmin_fmax_h
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr16 = FMINHrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr16 = FMAXHrr
+ %0:fpr16 = FMINHrr undef $h0, undef $h1, implicit $fpcr
+ %1:fpr16 = FADDHrr undef $h3, undef $h4, implicit $fpcr
+ %2:fpr16 = FMAXHrr %0, undef $h2, implicit $fpcr
+...
+---
+name: fmin_fmin_h
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr16 = FMINHrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr16 = FMINHrr
+ %0:fpr16 = FMINHrr undef $h0, undef $h1, implicit $fpcr
+ %1:fpr16 = FADDHrr undef $h3, undef $h4, implicit $fpcr
+ %2:fpr16 = FMINHrr %0, undef $h2, implicit $fpcr
+...
+---
+name: fmax_fmax_s
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr32 = FMAXSrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr32 = FMAXSrr
+ %0:fpr32 = FMAXSrr undef $s0, undef $s1, implicit $fpcr
+ %1:fpr32 = FADDSrr undef $s3, undef $s4, implicit $fpcr
+ %2:fpr32 = FMAXSrr %0, undef $s2, implicit $fpcr
+...
+---
+name: fmax_fmin_s
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr32 = FMAXSrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr32 = FMINSrr
+ %0:fpr32 = FMAXSrr undef $s0, undef $s1, implicit $fpcr
+ %1:fpr32 = FADDSrr undef $s3, undef $s4, implicit $fpcr
+ %2:fpr32 = FMINSrr %0, undef $s2, implicit $fpcr
+...
+---
+name: fmin_fmax_s
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr32 = FMINSrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr32 = FMAXSrr
+ %0:fpr32 = FMINSrr undef $s0, undef $s1, implicit $fpcr
+ %1:fpr32 = FADDSrr undef $s3, undef $s4, implicit $fpcr
+ %2:fpr32 = FMAXSrr %0, undef $s2, implicit $fpcr
+...
+---
+name: fmin_fmin_s
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr32 = FMINSrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr32 = FMINSrr
+ %0:fpr32 = FMINSrr undef $s0, undef $s1, implicit $fpcr
+ %1:fpr32 = FADDSrr undef $s3, undef $s4, implicit $fpcr
+ %2:fpr32 = FMINSrr %0, undef $s2, implicit $fpcr
+...
+---
+name: fmax_fmax_d
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMAXDrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMAXDrr
+ %0:fpr64 = FMAXDrr undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDDrr undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMAXDrr %0, undef $d2, implicit $fpcr
+...
+---
+name: fmax_fmin_d
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMAXDrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMINDrr
+ %0:fpr64 = FMAXDrr undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDDrr undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMINDrr %0, undef $d2, implicit $fpcr
+...
+---
+name: fmin_fmax_d
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMINDrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMAXDrr
+ %0:fpr64 = FMINDrr undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDDrr undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMAXDrr %0, undef $d2, implicit $fpcr
+...
+---
+name: fmin_fmin_d
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMINDrr
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMINDrr
+ %0:fpr64 = FMINDrr undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDDrr undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMINDrr %0, undef $d2, implicit $fpcr
+...
+---
+name: fmax_fmax_v4f16
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMAXv4f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMAXv4f16
+ %0:fpr64 = FMAXv4f16 undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDv4f16 undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMAXv4f16 %0, undef $d2, implicit $fpcr
+...
+---
+name: fmax_fmin_v4f16
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMAXv4f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMINv4f16
+ %0:fpr64 = FMAXv4f16 undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDv4f16 undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMINv4f16 %0, undef $d2, implicit $fpcr
+...
+---
+name: fmin_fmax_v4f16
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMINv4f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMAXv4f16
+ %0:fpr64 = FMINv4f16 undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDv4f16 undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMAXv4f16 %0, undef $d2, implicit $fpcr
+...
+---
+name: fmin_fmin_v4f16
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMINv4f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMINv4f16
+ %0:fpr64 = FMINv4f16 undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDv4f16 undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMINv4f16 %0, undef $d2, implicit $fpcr
+...
+---
+name: fmax_fmax_v8f16
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMAXv8f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMAXv8f16
+ %0:fpr128 = FMAXv8f16 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv8f16 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMAXv8f16 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmax_fmin_v8f16
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMAXv8f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMINv8f16
+ %0:fpr128 = FMAXv8f16 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv8f16 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMINv8f16 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmin_fmax_v8f16
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMINv8f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMAXv8f16
+ %0:fpr128 = FMINv8f16 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv8f16 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMAXv8f16 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmin_fmin_v8f16
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMINv8f16
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMINv8f16
+ %0:fpr128 = FMINv8f16 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv8f16 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMINv8f16 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmax_fmax_v2f32
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMAXv2f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMAXv2f32
+ %0:fpr64 = FMAXv2f32 undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDv2f32 undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMAXv2f32 %0, undef $d2, implicit $fpcr
+...
+---
+name: fmax_fmin_v2f32
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMAXv2f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMINv2f32
+ %0:fpr64 = FMAXv2f32 undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDv2f32 undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMINv2f32 %0, undef $d2, implicit $fpcr
+...
+---
+name: fmin_fmax_v2f32
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMINv2f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMAXv2f32
+ %0:fpr64 = FMINv2f32 undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDv2f32 undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMAXv2f32 %0, undef $d2, implicit $fpcr
+...
+---
+name: fmin_fmin_v2f32
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr64 = FMINv2f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr64 = FMINv2f32
+ %0:fpr64 = FMINv2f32 undef $d0, undef $d1, implicit $fpcr
+ %1:fpr64 = FADDv2f32 undef $d3, undef $d4, implicit $fpcr
+ %2:fpr64 = FMINv2f32 %0, undef $d2, implicit $fpcr
+...
+---
+name: fmax_fmax_v4f32
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMAXv4f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMAXv4f32
+ %0:fpr128 = FMAXv4f32 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv4f32 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMAXv4f32 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmax_fmin_v4f32
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMAXv4f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMINv4f32
+ %0:fpr128 = FMAXv4f32 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv4f32 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMINv4f32 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmin_fmax_v4f32
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMINv4f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMAXv4f32
+ %0:fpr128 = FMINv4f32 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv4f32 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMAXv4f32 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmin_fmin_v4f32
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMINv4f32
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMINv4f32
+ %0:fpr128 = FMINv4f32 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv4f32 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMINv4f32 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmax_fmax_v2f64
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMAXv2f64
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMAXv2f64
+ %0:fpr128 = FMAXv2f64 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv2f64 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMAXv2f64 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmax_fmin_v2f64
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMAXv2f64
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMINv2f64
+ %0:fpr128 = FMAXv2f64 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv2f64 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMINv2f64 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmin_fmax_v2f64
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMINv2f64
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMAXv2f64
+ %0:fpr128 = FMINv2f64 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv2f64 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMAXv2f64 %0, undef $q2, implicit $fpcr
+...
+---
+name: fmin_fmin_v2f64
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: SU(0): %0:fpr128 = FMINv2f64
+ ; CHECK: Successors:
+ ; FUSE: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; NOFUSE-NOT: SU(2): Ord Latency={{[0-9]+}} Cluster
+ ; CHECK: SU(2): %2:fpr128 = FMINv2f64
+ %0:fpr128 = FMINv2f64 undef $q0, undef $q1, implicit $fpcr
+ %1:fpr128 = FADDv2f64 undef $q3, undef $q4, implicit $fpcr
+ %2:fpr128 = FMINv2f64 %0, undef $q2, implicit $fpcr
+...
diff --git a/llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax.ll b/llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax.ll
new file mode 100644
index 0000000000000..98ef57497f9c9
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/misched-fusion-fmin-fmax.ll
@@ -0,0 +1,411 @@
+; RUN: llc %s -o - -mtriple=aarch64-linux-gnu -mattr=+fullfp16,+neon,+fuse-fmin-fmax | FileCheck %s --check-prefixes=CHECK,LINUX
+; RUN: llc %s -o - -mtriple=arm64-apple-macosx -mcpu=apple-m5 | FileCheck %s --check-prefixes=CHECK,APPLE
+
+declare half @llvm.maximum.f16(half, half)
+declare half @llvm.minimum.f16(half, half)
+declare float @llvm.maximum.f32(float, float)
+declare float @llvm.minimum.f32(float, float)
+declare double @llvm.maximum.f64(double, double)
+declare double @llvm.minimum.f64(double, double)
+declare <4 x half> @llvm.maximum.v4f16(<4 x half>, <4 x half>)
+declare <4 x half> @llvm.minimum.v4f16(<4 x half>, <4 x half>)
+declare <8 x half> @llvm.maximum.v8f16(<8 x half>, <8 x half>)
+declare <8 x half> @llvm.minimum.v8f16(<8 x half>, <8 x half>)
+declare <2 x float> @llvm.maximum.v2f32(<2 x float>, <2 x float>)
+declare <2 x float> @llvm.minimum.v2f32(<2 x float>, <2 x float>)
+declare <4 x float> @llvm.maximum.v4f32(<4 x float>, <4 x float>)
+declare <4 x float> @llvm.minimum.v4f32(<4 x float>, <4 x float>)
+declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)
+declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>)
+
+; CHECK-LABEL: fmax_fmax_h:
+; CHECK: fmax [[R:h[0-9]+]], h{{[0-9]+}}, h{{[0-9]+}}
+; CHECK-NEXT: fmax h{{[0-9]+}}, [[R]], h{{[0-9]+}}
+define half @fmax_fmax_h(half %a, half %b, half %c, half %x, half %y) {
+ %v0 = call half @llvm.maximum.f16(half %a, half %b)
+ %d = fadd half %x, %y
+ %v1 = call half @llvm.maximum.f16(half %v0, half %c)
+ %r = fadd half %v1, %d
+ ret half %r
+}
+
+; CHECK-LABEL: fmax_fmin_h:
+; CHECK: fmax [[R:h[0-9]+]], h{{[0-9]+}}, h{{[0-9]+}}
+; CHECK-NEXT: fmin h{{[0-9]+}}, [[R]], h{{[0-9]+}}
+define half @fmax_fmin_h(half %a, half %b, half %c, half %x, half %y) {
+ %v0 = call half @llvm.maximum.f16(half %a, half %b)
+ %d = fadd half %x, %y
+ %v1 = call half @llvm.minimum.f16(half %v0, half %c)
+ %r = fadd half %v1, %d
+ ret half %r
+}
+
+; CHECK-LABEL: fmin_fmax_h:
+; CHECK: fmin [[R:h[0-9]+]], h{{[0-9]+}}, h{{[0-9]+}}
+; CHECK-NEXT: fmax h{{[0-9]+}}, [[R]], h{{[0-9]+}}
+define half @fmin_fmax_h(half %a, half %b, half %c, half %x, half %y) {
+ %v0 = call half @llvm.minimum.f16(half %a, half %b)
+ %d = fadd half %x, %y
+ %v1 = call half @llvm.maximum.f16(half %v0, half %c)
+ %r = fadd half %v1, %d
+ ret half %r
+}
+
+; CHECK-LABEL: fmin_fmin_h:
+; CHECK: fmin [[R:h[0-9]+]], h{{[0-9]+}}, h{{[0-9]+}}
+; CHECK-NEXT: fmin h{{[0-9]+}}, [[R]], h{{[0-9]+}}
+define half @fmin_fmin_h(half %a, half %b, half %c, half %x, half %y) {
+ %v0 = call half @llvm.minimum.f16(half %a, half %b)
+ %d = fadd half %x, %y
+ %v1 = call half @llvm.minimum.f16(half %v0, half %c)
+ %r = fadd half %v1, %d
+ ret half %r
+}
+
+; CHECK-LABEL: fmax_fmax_s:
+; CHECK: fmax [[R:s[0-9]+]], s{{[0-9]+}}, s{{[0-9]+}}
+; CHECK-NEXT: fmax s{{[0-9]+}}, [[R]], s{{[0-9]+}}
+define float @fmax_fmax_s(float %a, float %b, float %c, float %x, float %y) {
+ %v0 = call float @llvm.maximum.f32(float %a, float %b)
+ %d = fadd float %x, %y
+ %v1 = call float @llvm.maximum.f32(float %v0, float %c)
+ %r = fadd float %v1, %d
+ ret float %r
+}
+
+; CHECK-LABEL: fmax_fmin_s:
+; CHECK: fmax [[R:s[0-9]+]], s{{[0-9]+}}, s{{[0-9]+}}
+; CHECK-NEXT: fmin s{{[0-9]+}}, [[R]], s{{[0-9]+}}
+define float @fmax_fmin_s(float %a, float %b, float %c, float %x, float %y) {
+ %v0 = call float @llvm.maximum.f32(float %a, float %b)
+ %d = fadd float %x, %y
+ %v1 = call float @llvm.minimum.f32(float %v0, float %c)
+ %r = fadd float %v1, %d
+ ret float %r
+}
+
+; CHECK-LABEL: fmin_fmax_s:
+; CHECK: fmin [[R:s[0-9]+]], s{{[0-9]+}}, s{{[0-9]+}}
+; CHECK-NEXT: fmax s{{[0-9]+}}, [[R]], s{{[0-9]+}}
+define float @fmin_fmax_s(float %a, float %b, float %c, float %x, float %y) {
+ %v0 = call float @llvm.minimum.f32(float %a, float %b)
+ %d = fadd float %x, %y
+ %v1 = call float @llvm.maximum.f32(float %v0, float %c)
+ %r = fadd float %v1, %d
+ ret float %r
+}
+
+; CHECK-LABEL: fmin_fmin_s:
+; CHECK: fmin [[R:s[0-9]+]], s{{[0-9]+}}, s{{[0-9]+}}
+; CHECK-NEXT: fmin s{{[0-9]+}}, [[R]], s{{[0-9]+}}
+define float @fmin_fmin_s(float %a, float %b, float %c, float %x, float %y) {
+ %v0 = call float @llvm.minimum.f32(float %a, float %b)
+ %d = fadd float %x, %y
+ %v1 = call float @llvm.minimum.f32(float %v0, float %c)
+ %r = fadd float %v1, %d
+ ret float %r
+}
+
+; CHECK-LABEL: fmax_fmax_d:
+; CHECK: fmax [[R:d[0-9]+]], d{{[0-9]+}}, d{{[0-9]+}}
+; CHECK-NEXT: fmax d{{[0-9]+}}, [[R]], d{{[0-9]+}}
+define double @fmax_fmax_d(double %a, double %b, double %c, double %x, double %y) {
+ %v0 = call double @llvm.maximum.f64(double %a, double %b)
+ %d = fadd double %x, %y
+ %v1 = call double @llvm.maximum.f64(double %v0, double %c)
+ %r = fadd double %v1, %d
+ ret double %r
+}
+
+; CHECK-LABEL: fmax_fmin_d:
+; CHECK: fmax [[R:d[0-9]+]], d{{[0-9]+}}, d{{[0-9]+}}
+; CHECK-NEXT: fmin d{{[0-9]+}}, [[R]], d{{[0-9]+}}
+define double @fmax_fmin_d(double %a, double %b, double %c, double %x, double %y) {
+ %v0 = call double @llvm.maximum.f64(double %a, double %b)
+ %d = fadd double %x, %y
+ %v1 = call double @llvm.minimum.f64(double %v0, double %c)
+ %r = fadd double %v1, %d
+ ret double %r
+}
+
+; CHECK-LABEL: fmin_fmax_d:
+; CHECK: fmin [[R:d[0-9]+]], d{{[0-9]+}}, d{{[0-9]+}}
+; CHECK-NEXT: fmax d{{[0-9]+}}, [[R]], d{{[0-9]+}}
+define double @fmin_fmax_d(double %a, double %b, double %c, double %x, double %y) {
+ %v0 = call double @llvm.minimum.f64(double %a, double %b)
+ %d = fadd double %x, %y
+ %v1 = call double @llvm.maximum.f64(double %v0, double %c)
+ %r = fadd double %v1, %d
+ ret double %r
+}
+
+; CHECK-LABEL: fmin_fmin_d:
+; CHECK: fmin [[R:d[0-9]+]], d{{[0-9]+}}, d{{[0-9]+}}
+; CHECK-NEXT: fmin d{{[0-9]+}}, [[R]], d{{[0-9]+}}
+define double @fmin_fmin_d(double %a, double %b, double %c, double %x, double %y) {
+ %v0 = call double @llvm.minimum.f64(double %a, double %b)
+ %d = fadd double %x, %y
+ %v1 = call double @llvm.minimum.f64(double %v0, double %c)
+ %r = fadd double %v1, %d
+ ret double %r
+}
+
+; CHECK-LABEL: fmax_fmax_v4f16:
+; LINUX: fmax [[R:v[0-9]+]].4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h
+; LINUX-NEXT: fmax v{{[0-9]+}}.4h, [[R]].4h, v{{[0-9]+}}.4h
+; APPLE: fmax.4h [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.4h v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <4 x half> @fmax_fmax_v4f16(<4 x half> %a, <4 x half> %b, <4 x half> %c, <4 x half> %x, <4 x half> %y) {
+ %v0 = call <4 x half> @llvm.maximum.v4f16(<4 x half> %a, <4 x half> %b)
+ %d = fadd <4 x half> %x, %y
+ %v1 = call <4 x half> @llvm.maximum.v4f16(<4 x half> %v0, <4 x half> %c)
+ %r = fadd <4 x half> %v1, %d
+ ret <4 x half> %r
+}
+
+; CHECK-LABEL: fmax_fmin_v4f16:
+; LINUX: fmax [[R:v[0-9]+]].4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h
+; LINUX-NEXT: fmin v{{[0-9]+}}.4h, [[R]].4h, v{{[0-9]+}}.4h
+; APPLE: fmax.4h [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.4h v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <4 x half> @fmax_fmin_v4f16(<4 x half> %a, <4 x half> %b, <4 x half> %c, <4 x half> %x, <4 x half> %y) {
+ %v0 = call <4 x half> @llvm.maximum.v4f16(<4 x half> %a, <4 x half> %b)
+ %d = fadd <4 x half> %x, %y
+ %v1 = call <4 x half> @llvm.minimum.v4f16(<4 x half> %v0, <4 x half> %c)
+ %r = fadd <4 x half> %v1, %d
+ ret <4 x half> %r
+}
+
+; CHECK-LABEL: fmin_fmax_v4f16:
+; LINUX: fmin [[R:v[0-9]+]].4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h
+; LINUX-NEXT: fmax v{{[0-9]+}}.4h, [[R]].4h, v{{[0-9]+}}.4h
+; APPLE: fmin.4h [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.4h v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <4 x half> @fmin_fmax_v4f16(<4 x half> %a, <4 x half> %b, <4 x half> %c, <4 x half> %x, <4 x half> %y) {
+ %v0 = call <4 x half> @llvm.minimum.v4f16(<4 x half> %a, <4 x half> %b)
+ %d = fadd <4 x half> %x, %y
+ %v1 = call <4 x half> @llvm.maximum.v4f16(<4 x half> %v0, <4 x half> %c)
+ %r = fadd <4 x half> %v1, %d
+ ret <4 x half> %r
+}
+
+; CHECK-LABEL: fmin_fmin_v4f16:
+; LINUX: fmin [[R:v[0-9]+]].4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h
+; LINUX-NEXT: fmin v{{[0-9]+}}.4h, [[R]].4h, v{{[0-9]+}}.4h
+; APPLE: fmin.4h [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.4h v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <4 x half> @fmin_fmin_v4f16(<4 x half> %a, <4 x half> %b, <4 x half> %c, <4 x half> %x, <4 x half> %y) {
+ %v0 = call <4 x half> @llvm.minimum.v4f16(<4 x half> %a, <4 x half> %b)
+ %d = fadd <4 x half> %x, %y
+ %v1 = call <4 x half> @llvm.minimum.v4f16(<4 x half> %v0, <4 x half> %c)
+ %r = fadd <4 x half> %v1, %d
+ ret <4 x half> %r
+}
+
+; CHECK-LABEL: fmax_fmax_v8f16:
+; LINUX: fmax [[R:v[0-9]+]].8h, v{{[0-9]+}}.8h, v{{[0-9]+}}.8h
+; LINUX-NEXT: fmax v{{[0-9]+}}.8h, [[R]].8h, v{{[0-9]+}}.8h
+; APPLE: fmax.8h [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.8h v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <8 x half> @fmax_fmax_v8f16(<8 x half> %a, <8 x half> %b, <8 x half> %c, <8 x half> %x, <8 x half> %y) {
+ %v0 = call <8 x half> @llvm.maximum.v8f16(<8 x half> %a, <8 x half> %b)
+ %d = fadd <8 x half> %x, %y
+ %v1 = call <8 x half> @llvm.maximum.v8f16(<8 x half> %v0, <8 x half> %c)
+ %r = fadd <8 x half> %v1, %d
+ ret <8 x half> %r
+}
+
+; CHECK-LABEL: fmax_fmin_v8f16:
+; LINUX: fmax [[R:v[0-9]+]].8h, v{{[0-9]+}}.8h, v{{[0-9]+}}.8h
+; LINUX-NEXT: fmin v{{[0-9]+}}.8h, [[R]].8h, v{{[0-9]+}}.8h
+; APPLE: fmax.8h [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.8h v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <8 x half> @fmax_fmin_v8f16(<8 x half> %a, <8 x half> %b, <8 x half> %c, <8 x half> %x, <8 x half> %y) {
+ %v0 = call <8 x half> @llvm.maximum.v8f16(<8 x half> %a, <8 x half> %b)
+ %d = fadd <8 x half> %x, %y
+ %v1 = call <8 x half> @llvm.minimum.v8f16(<8 x half> %v0, <8 x half> %c)
+ %r = fadd <8 x half> %v1, %d
+ ret <8 x half> %r
+}
+
+; CHECK-LABEL: fmin_fmax_v8f16:
+; LINUX: fmin [[R:v[0-9]+]].8h, v{{[0-9]+}}.8h, v{{[0-9]+}}.8h
+; LINUX-NEXT: fmax v{{[0-9]+}}.8h, [[R]].8h, v{{[0-9]+}}.8h
+; APPLE: fmin.8h [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.8h v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <8 x half> @fmin_fmax_v8f16(<8 x half> %a, <8 x half> %b, <8 x half> %c, <8 x half> %x, <8 x half> %y) {
+ %v0 = call <8 x half> @llvm.minimum.v8f16(<8 x half> %a, <8 x half> %b)
+ %d = fadd <8 x half> %x, %y
+ %v1 = call <8 x half> @llvm.maximum.v8f16(<8 x half> %v0, <8 x half> %c)
+ %r = fadd <8 x half> %v1, %d
+ ret <8 x half> %r
+}
+
+; CHECK-LABEL: fmin_fmin_v8f16:
+; LINUX: fmin [[R:v[0-9]+]].8h, v{{[0-9]+}}.8h, v{{[0-9]+}}.8h
+; LINUX-NEXT: fmin v{{[0-9]+}}.8h, [[R]].8h, v{{[0-9]+}}.8h
+; APPLE: fmin.8h [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.8h v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <8 x half> @fmin_fmin_v8f16(<8 x half> %a, <8 x half> %b, <8 x half> %c, <8 x half> %x, <8 x half> %y) {
+ %v0 = call <8 x half> @llvm.minimum.v8f16(<8 x half> %a, <8 x half> %b)
+ %d = fadd <8 x half> %x, %y
+ %v1 = call <8 x half> @llvm.minimum.v8f16(<8 x half> %v0, <8 x half> %c)
+ %r = fadd <8 x half> %v1, %d
+ ret <8 x half> %r
+}
+
+; CHECK-LABEL: fmax_fmax_v2f32:
+; LINUX: fmax [[R:v[0-9]+]].2s, v{{[0-9]+}}.2s, v{{[0-9]+}}.2s
+; LINUX-NEXT: fmax v{{[0-9]+}}.2s, [[R]].2s, v{{[0-9]+}}.2s
+; APPLE: fmax.2s [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.2s v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <2 x float> @fmax_fmax_v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c, <2 x float> %x, <2 x float> %y) {
+ %v0 = call <2 x float> @llvm.maximum.v2f32(<2 x float> %a, <2 x float> %b)
+ %d = fadd <2 x float> %x, %y
+ %v1 = call <2 x float> @llvm.maximum.v2f32(<2 x float> %v0, <2 x float> %c)
+ %r = fadd <2 x float> %v1, %d
+ ret <2 x float> %r
+}
+
+; CHECK-LABEL: fmax_fmin_v2f32:
+; LINUX: fmax [[R:v[0-9]+]].2s, v{{[0-9]+}}.2s, v{{[0-9]+}}.2s
+; LINUX-NEXT: fmin v{{[0-9]+}}.2s, [[R]].2s, v{{[0-9]+}}.2s
+; APPLE: fmax.2s [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.2s v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <2 x float> @fmax_fmin_v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c, <2 x float> %x, <2 x float> %y) {
+ %v0 = call <2 x float> @llvm.maximum.v2f32(<2 x float> %a, <2 x float> %b)
+ %d = fadd <2 x float> %x, %y
+ %v1 = call <2 x float> @llvm.minimum.v2f32(<2 x float> %v0, <2 x float> %c)
+ %r = fadd <2 x float> %v1, %d
+ ret <2 x float> %r
+}
+
+; CHECK-LABEL: fmin_fmax_v2f32:
+; LINUX: fmin [[R:v[0-9]+]].2s, v{{[0-9]+}}.2s, v{{[0-9]+}}.2s
+; LINUX-NEXT: fmax v{{[0-9]+}}.2s, [[R]].2s, v{{[0-9]+}}.2s
+; APPLE: fmin.2s [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.2s v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <2 x float> @fmin_fmax_v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c, <2 x float> %x, <2 x float> %y) {
+ %v0 = call <2 x float> @llvm.minimum.v2f32(<2 x float> %a, <2 x float> %b)
+ %d = fadd <2 x float> %x, %y
+ %v1 = call <2 x float> @llvm.maximum.v2f32(<2 x float> %v0, <2 x float> %c)
+ %r = fadd <2 x float> %v1, %d
+ ret <2 x float> %r
+}
+
+; CHECK-LABEL: fmin_fmin_v2f32:
+; LINUX: fmin [[R:v[0-9]+]].2s, v{{[0-9]+}}.2s, v{{[0-9]+}}.2s
+; LINUX-NEXT: fmin v{{[0-9]+}}.2s, [[R]].2s, v{{[0-9]+}}.2s
+; APPLE: fmin.2s [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.2s v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <2 x float> @fmin_fmin_v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c, <2 x float> %x, <2 x float> %y) {
+ %v0 = call <2 x float> @llvm.minimum.v2f32(<2 x float> %a, <2 x float> %b)
+ %d = fadd <2 x float> %x, %y
+ %v1 = call <2 x float> @llvm.minimum.v2f32(<2 x float> %v0, <2 x float> %c)
+ %r = fadd <2 x float> %v1, %d
+ ret <2 x float> %r
+}
+
+; CHECK-LABEL: fmax_fmax_v4f32:
+; LINUX: fmax [[R:v[0-9]+]].4s, v{{[0-9]+}}.4s, v{{[0-9]+}}.4s
+; LINUX-NEXT: fmax v{{[0-9]+}}.4s, [[R]].4s, v{{[0-9]+}}.4s
+; APPLE: fmax.4s [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.4s v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <4 x float> @fmax_fmax_v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %x, <4 x float> %y) {
+ %v0 = call <4 x float> @llvm.maximum.v4f32(<4 x float> %a, <4 x float> %b)
+ %d = fadd <4 x float> %x, %y
+ %v1 = call <4 x float> @llvm.maximum.v4f32(<4 x float> %v0, <4 x float> %c)
+ %r = fadd <4 x float> %v1, %d
+ ret <4 x float> %r
+}
+
+; CHECK-LABEL: fmax_fmin_v4f32:
+; LINUX: fmax [[R:v[0-9]+]].4s, v{{[0-9]+}}.4s, v{{[0-9]+}}.4s
+; LINUX-NEXT: fmin v{{[0-9]+}}.4s, [[R]].4s, v{{[0-9]+}}.4s
+; APPLE: fmax.4s [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.4s v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <4 x float> @fmax_fmin_v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %x, <4 x float> %y) {
+ %v0 = call <4 x float> @llvm.maximum.v4f32(<4 x float> %a, <4 x float> %b)
+ %d = fadd <4 x float> %x, %y
+ %v1 = call <4 x float> @llvm.minimum.v4f32(<4 x float> %v0, <4 x float> %c)
+ %r = fadd <4 x float> %v1, %d
+ ret <4 x float> %r
+}
+
+; CHECK-LABEL: fmin_fmax_v4f32:
+; LINUX: fmin [[R:v[0-9]+]].4s, v{{[0-9]+}}.4s, v{{[0-9]+}}.4s
+; LINUX-NEXT: fmax v{{[0-9]+}}.4s, [[R]].4s, v{{[0-9]+}}.4s
+; APPLE: fmin.4s [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.4s v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <4 x float> @fmin_fmax_v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %x, <4 x float> %y) {
+ %v0 = call <4 x float> @llvm.minimum.v4f32(<4 x float> %a, <4 x float> %b)
+ %d = fadd <4 x float> %x, %y
+ %v1 = call <4 x float> @llvm.maximum.v4f32(<4 x float> %v0, <4 x float> %c)
+ %r = fadd <4 x float> %v1, %d
+ ret <4 x float> %r
+}
+
+; CHECK-LABEL: fmin_fmin_v4f32:
+; LINUX: fmin [[R:v[0-9]+]].4s, v{{[0-9]+}}.4s, v{{[0-9]+}}.4s
+; LINUX-NEXT: fmin v{{[0-9]+}}.4s, [[R]].4s, v{{[0-9]+}}.4s
+; APPLE: fmin.4s [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.4s v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <4 x float> @fmin_fmin_v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %x, <4 x float> %y) {
+ %v0 = call <4 x float> @llvm.minimum.v4f32(<4 x float> %a, <4 x float> %b)
+ %d = fadd <4 x float> %x, %y
+ %v1 = call <4 x float> @llvm.minimum.v4f32(<4 x float> %v0, <4 x float> %c)
+ %r = fadd <4 x float> %v1, %d
+ ret <4 x float> %r
+}
+
+; CHECK-LABEL: fmax_fmax_v2f64:
+; LINUX: fmax [[R:v[0-9]+]].2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d
+; LINUX-NEXT: fmax v{{[0-9]+}}.2d, [[R]].2d, v{{[0-9]+}}.2d
+; APPLE: fmax.2d [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.2d v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <2 x double> @fmax_fmax_v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c, <2 x double> %x, <2 x double> %y) {
+ %v0 = call <2 x double> @llvm.maximum.v2f64(<2 x double> %a, <2 x double> %b)
+ %d = fadd <2 x double> %x, %y
+ %v1 = call <2 x double> @llvm.maximum.v2f64(<2 x double> %v0, <2 x double> %c)
+ %r = fadd <2 x double> %v1, %d
+ ret <2 x double> %r
+}
+
+; CHECK-LABEL: fmax_fmin_v2f64:
+; LINUX: fmax [[R:v[0-9]+]].2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d
+; LINUX-NEXT: fmin v{{[0-9]+}}.2d, [[R]].2d, v{{[0-9]+}}.2d
+; APPLE: fmax.2d [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.2d v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <2 x double> @fmax_fmin_v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c, <2 x double> %x, <2 x double> %y) {
+ %v0 = call <2 x double> @llvm.maximum.v2f64(<2 x double> %a, <2 x double> %b)
+ %d = fadd <2 x double> %x, %y
+ %v1 = call <2 x double> @llvm.minimum.v2f64(<2 x double> %v0, <2 x double> %c)
+ %r = fadd <2 x double> %v1, %d
+ ret <2 x double> %r
+}
+
+; CHECK-LABEL: fmin_fmax_v2f64:
+; LINUX: fmin [[R:v[0-9]+]].2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d
+; LINUX-NEXT: fmax v{{[0-9]+}}.2d, [[R]].2d, v{{[0-9]+}}.2d
+; APPLE: fmin.2d [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmax.2d v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <2 x double> @fmin_fmax_v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c, <2 x double> %x, <2 x double> %y) {
+ %v0 = call <2 x double> @llvm.minimum.v2f64(<2 x double> %a, <2 x double> %b)
+ %d = fadd <2 x double> %x, %y
+ %v1 = call <2 x double> @llvm.maximum.v2f64(<2 x double> %v0, <2 x double> %c)
+ %r = fadd <2 x double> %v1, %d
+ ret <2 x double> %r
+}
+
+; CHECK-LABEL: fmin_fmin_v2f64:
+; LINUX: fmin [[R:v[0-9]+]].2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d
+; LINUX-NEXT: fmin v{{[0-9]+}}.2d, [[R]].2d, v{{[0-9]+}}.2d
+; APPLE: fmin.2d [[R:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}}
+; APPLE-NEXT: fmin.2d v{{[0-9]+}}, [[R]], v{{[0-9]+}}
+define <2 x double> @fmin_fmin_v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c, <2 x double> %x, <2 x double> %y) {
+ %v0 = call <2 x double> @llvm.minimum.v2f64(<2 x double> %a, <2 x double> %b)
+ %d = fadd <2 x double> %x, %y
+ %v1 = call <2 x double> @llvm.minimum.v2f64(<2 x double> %v0, <2 x double> %c)
+ %r = fadd <2 x double> %v1, %d
+ ret <2 x double> %r
+}
diff --git a/llvm/test/TableGen/aarch64-apple-tuning-features.td b/llvm/test/TableGen/aarch64-apple-tuning-features.td
index fb0bd1e1c204f..ff97d4640ccfb 100644
--- a/llvm/test/TableGen/aarch64-apple-tuning-features.td
+++ b/llvm/test/TableGen/aarch64-apple-tuning-features.td
@@ -278,6 +278,7 @@
// CHECK-NEXT: FeatureFuseCryptoEOR,
// CHECK-NEXT: FeatureFuseCmpCSel,
// CHECK-NEXT: FeatureFuseFCmpFCSel,
+// CHECK-NEXT: FeatureFuseFMinFMax,
// CHECK-NEXT: FeatureFuseLiterals,
// CHECK-NEXT: FeatureMaxInterleaveFactor4,
// CHECK-NEXT: FeatureNoZCZeroingFPR64,
More information about the llvm-commits
mailing list