[llvm] [AArch64] Parameterize repeated FP divisor combine threshold by subtarget (PR #216930)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 19:52:25 PDT 2026


https://github.com/yamash-fj updated https://github.com/llvm/llvm-project/pull/216930

>From 6b79491518852a4a85e4064634cff43fc83ef388 Mon Sep 17 00:00:00 2001
From: yamash-fj <yamashita.ta-16 at fujitsu.com>
Date: Tue, 18 Aug 2026 15:50:56 +0900
Subject: [PATCH 1/2] [AArch64]  Parameterize repeated FP divisor combine
 threshold by subtarget

This change makes the threshold for combining repeated FP divisors configurable by AArch64 subtarget, instead of using fixed value.

The existing fixed value is 3, but some subtargets may benefit with lower threshold, such as A64FX. This patch also includes setting this parameter of A64FX 2.
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |   5 +-
 llvm/lib/Target/AArch64/AArch64Subtarget.cpp  |   1 +
 llvm/lib/Target/AArch64/AArch64Subtarget.h    |   3 +
 llvm/test/CodeGen/AArch64/fdiv-combine.ll     | 123 +++++++++++++-----
 4 files changed, 97 insertions(+), 35 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index dc02cbc05fbce..c78d09479a73a 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -32679,8 +32679,9 @@ SDValue AArch64TargetLowering::emitStackGuardMixFP(SelectionDAG &DAG,
 
 unsigned AArch64TargetLowering::combineRepeatedFPDivisors() const {
   // Combine multiple FDIVs with the same divisor into multiple FMULs by the
-  // reciprocal if there are three or more FDIVs.
-  return 3;
+  // reciprocal if there are enough FDivs. The threshold is set as 
+  // MinFDivForCombining.
+  return Subtarget->getMinFDivForCombining();
 }
 
 TargetLoweringBase::LegalizeTypeAction
diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
index 4fef12ab37ad8..6e13913eea930 100644
--- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
+++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
@@ -205,6 +205,7 @@ void AArch64Subtarget::initializeProperties(bool HasMinSize) {
     MinPrefetchStride = 1024;
     MaxPrefetchIterationsAhead = 4;
     VScaleForTuning = 4;
+    MinFDivForCombining = 2;
     break;
   case MONAKA:
     VScaleForTuning = 2;
diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h
index 98cc97ae0a695..3244f6b2919b3 100644
--- a/llvm/lib/Target/AArch64/AArch64Subtarget.h
+++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h
@@ -72,6 +72,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
   unsigned MinimumJumpTableEntries = 4;
   unsigned MaxJumpTableSize = 0;
   unsigned FixedLoadLatency = 0;
+  unsigned MinFDivForCombining = 3;
 
   // ReserveXRegister[i] - X#i is not available as a general purpose register.
   BitVector ReserveXRegister;
@@ -313,6 +314,8 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
 
   unsigned getFixedLoadLatency() const { return FixedLoadLatency; }
 
+  unsigned getMinFDivForCombining() const { return MinFDivForCombining; }
+
   /// CPU has TBI (top byte of addresses is ignored during HW address
   /// translation) and OS enables it.
   bool supportsAddressTopByteIgnored() const;
diff --git a/llvm/test/CodeGen/AArch64/fdiv-combine.ll b/llvm/test/CodeGen/AArch64/fdiv-combine.ll
index 9eacb61eecd06..e5dc5275696cb 100644
--- a/llvm/test/CodeGen/AArch64/fdiv-combine.ll
+++ b/llvm/test/CodeGen/AArch64/fdiv-combine.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
-; RUN: llc -mtriple=aarch64-unknown-unknown < %s -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s --check-prefixes=CHECK,CHECK-THREE,CHECK-SDGI,CHECK-SD
+; RUN: llc -mtriple=aarch64-unknown-unknown < %s -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-THREE,CHECK-SDGI,CHECK-GI
+; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=neoverse-v2 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-THREE,CHECK-MCPU
+; RUN: llc -mtriple=aarch64-unknown-unknown -mcpu=a64fx < %s | FileCheck %s --check-prefixes=CHECK,CHECK-MCPU,CHECK-TWO
 
 ; CHECK-GI:       warning: Instruction selection used fallback path for splat_fdiv_nxv4f32
 ; CHECK-GI-NEXT:  warning: Instruction selection used fallback path for splat_three_fdiv_nxv4f32
@@ -75,15 +77,23 @@ define void @three_fdiv_2xdouble(<2 x double> %D, <2 x double> %a, <2 x double>
   ret void
 }
 
-; Following test cases check we never combine two FDIVs if neither of them
-; calculates a reciprocal.
+; Following test cases check we combine two FDIVs 
+; if MinFDivForCombining setting by the subtarget is 2.
 define void @two_fdiv_float(float %D, float %a, float %b) {
-; CHECK-LABEL: two_fdiv_float:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    fdiv s3, s1, s0
-; CHECK-NEXT:    fdiv s1, s2, s0
-; CHECK-NEXT:    fmov s0, s3
-; CHECK-NEXT:    b foo_2f
+; CHECK-THREE-LABEL: two_fdiv_float:
+; CHECK-THREE:       // %bb.0:
+; CHECK-THREE-NEXT:    fdiv s3, s1, s0
+; CHECK-THREE-NEXT:    fdiv s1, s2, s0
+; CHECK-THREE-NEXT:    fmov s0, s3
+; CHECK-THREE-NEXT:    b foo_2f
+;
+; CHECK-TWO-LABEL: two_fdiv_float:
+; CHECK-TWO:       // %bb.0:
+; CHECK-TWO-NEXT:    fmov s3, #1.00000000
+; CHECK-TWO-NEXT:    fdiv s3, s3, s0
+; CHECK-TWO-NEXT:    fmul s0, s1, s3
+; CHECK-TWO-NEXT:    fmul s1, s2, s3
+; CHECK-TWO-NEXT:    b foo_2f
   %div = fdiv arcp float %a, %D
   %div1 = fdiv arcp float %b, %D
   tail call void @foo_2f(float %div, float %div1)
@@ -91,12 +101,20 @@ define void @two_fdiv_float(float %D, float %a, float %b) {
 }
 
 define void @two_fdiv_double(double %D, double %a, double %b) {
-; CHECK-LABEL: two_fdiv_double:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    fdiv d3, d1, d0
-; CHECK-NEXT:    fdiv d1, d2, d0
-; CHECK-NEXT:    fmov d0, d3
-; CHECK-NEXT:    b foo_2d
+; CHECK-THREE-LABEL: two_fdiv_double:
+; CHECK-THREE:       // %bb.0:
+; CHECK-THREE-NEXT:    fdiv d3, d1, d0
+; CHECK-THREE-NEXT:    fdiv d1, d2, d0
+; CHECK-THREE-NEXT:    fmov d0, d3
+; CHECK-THREE-NEXT:    b foo_2d
+;
+; CHECK-TWO-LABEL: two_fdiv_double:
+; CHECK-TWO:       // %bb.0:
+; CHECK-TWO-NEXT:    fmov d3, #1.00000000
+; CHECK-TWO-NEXT:    fdiv d3, d3, d0
+; CHECK-TWO-NEXT:    fmul d0, d1, d3
+; CHECK-TWO-NEXT:    fmul d1, d2, d3
+; CHECK-TWO-NEXT:    b foo_2d
   %div = fdiv arcp double %a, %D
   %div1 = fdiv arcp double %b, %D
   tail call void @foo_2d(double %div, double %div1)
@@ -125,6 +143,17 @@ define void @four_fdiv_multi_float(float %D, float %a, float %b, float %c) #0 {
 ; CHECK-GI-NEXT:    fmul s2, s3, s5
 ; CHECK-GI-NEXT:    fmov s3, s4
 ; CHECK-GI-NEXT:    b foo_4f
+;
+; CHECK-MCPU-LABEL: four_fdiv_multi_float:
+; CHECK-MCPU:       // %bb.0:
+; CHECK-MCPU-NEXT:    fmov s4, #1.00000000
+; CHECK-MCPU-NEXT:    fdiv s5, s4, s0
+; CHECK-MCPU-NEXT:    fmul s4, s1, s5
+; CHECK-MCPU-NEXT:    fmul s1, s2, s5
+; CHECK-MCPU-NEXT:    fmul s2, s3, s5
+; CHECK-MCPU-NEXT:    fmul s3, s0, s5
+; CHECK-MCPU-NEXT:    fmov s0, s4
+; CHECK-MCPU-NEXT:    b foo_4f
   %div = fdiv arcp float %a, %D
   %div1 = fdiv arcp float %b, %D
   %div2 = fdiv arcp float %c, %D
@@ -134,16 +163,27 @@ define void @four_fdiv_multi_float(float %D, float %a, float %b, float %c) #0 {
 }
 
 define void @splat_three_fdiv_4xfloat(float %D, <4 x float> %a, <4 x float> %b, <4 x float> %c) {
-; CHECK-LABEL: splat_three_fdiv_4xfloat:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    // kill: def $s0 killed $s0 def $q0
-; CHECK-NEXT:    fmov v4.4s, #1.00000000
-; CHECK-NEXT:    dup v0.4s, v0.s[0]
-; CHECK-NEXT:    fdiv v4.4s, v4.4s, v0.4s
-; CHECK-NEXT:    fmul v0.4s, v1.4s, v4.4s
-; CHECK-NEXT:    fmul v1.4s, v2.4s, v4.4s
-; CHECK-NEXT:    fmul v2.4s, v3.4s, v4.4s
-; CHECK-NEXT:    b foo_3_4xf
+; CHECK-SDGI-LABEL: splat_three_fdiv_4xfloat:
+; CHECK-SDGI:       // %bb.0:
+; CHECK-SDGI-NEXT:    // kill: def $s0 killed $s0 def $q0
+; CHECK-SDGI-NEXT:    fmov v4.4s, #1.00000000
+; CHECK-SDGI-NEXT:    dup v0.4s, v0.s[0]
+; CHECK-SDGI-NEXT:    fdiv v4.4s, v4.4s, v0.4s
+; CHECK-SDGI-NEXT:    fmul v0.4s, v1.4s, v4.4s
+; CHECK-SDGI-NEXT:    fmul v1.4s, v2.4s, v4.4s
+; CHECK-SDGI-NEXT:    fmul v2.4s, v3.4s, v4.4s
+; CHECK-SDGI-NEXT:    b foo_3_4xf
+;
+; CHECK-MCPU-LABEL: splat_three_fdiv_4xfloat:
+; CHECK-MCPU:       // %bb.0:
+; CHECK-MCPU-NEXT:    // kill: def $s0 killed $s0 def $q0
+; CHECK-MCPU-NEXT:    dup v0.4s, v0.s[0]
+; CHECK-MCPU-NEXT:    fmov v4.4s, #1.00000000
+; CHECK-MCPU-NEXT:    fdiv v4.4s, v4.4s, v0.4s
+; CHECK-MCPU-NEXT:    fmul v0.4s, v1.4s, v4.4s
+; CHECK-MCPU-NEXT:    fmul v1.4s, v2.4s, v4.4s
+; CHECK-MCPU-NEXT:    fmul v2.4s, v3.4s, v4.4s
+; CHECK-MCPU-NEXT:    b foo_3_4xf
   %D.ins = insertelement <4 x float> poison, float %D, i64 0
   %splat = shufflevector <4 x float> %D.ins, <4 x float> poison, <4 x i32> zeroinitializer
   %div = fdiv arcp <4 x float> %a, %splat
@@ -169,6 +209,15 @@ define <4 x float> @splat_fdiv_v4f32(float %D, <4 x float> %a) #0 {
 ; CHECK-GI-NEXT:    dup v0.4s, v0.s[0]
 ; CHECK-GI-NEXT:    fdiv v0.4s, v1.4s, v0.4s
 ; CHECK-GI-NEXT:    ret
+;
+; CHECK-MCPU-LABEL: splat_fdiv_v4f32:
+; CHECK-MCPU:       // %bb.0: // %entry
+; CHECK-MCPU-NEXT:    // kill: def $s0 killed $s0 def $q0
+; CHECK-MCPU-NEXT:    dup v0.4s, v0.s[0]
+; CHECK-MCPU-NEXT:    fmov v2.4s, #1.00000000
+; CHECK-MCPU-NEXT:    fdiv v0.4s, v2.4s, v0.4s
+; CHECK-MCPU-NEXT:    fmul v0.4s, v1.4s, v0.4s
+; CHECK-MCPU-NEXT:    ret
 entry:
   %D.ins = insertelement <4 x float> poison, float %D, i64 0
   %splat = shufflevector <4 x float> %D.ins, <4 x float> poison, <4 x i32> zeroinitializer
@@ -212,13 +261,21 @@ entry:
 }
 
 define <vscale x 2 x double> @splat_fdiv_nxv2f64(double %D, <vscale x 2 x double> %a) #0 {
-; CHECK-LABEL: splat_fdiv_nxv2f64:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    // kill: def $d0 killed $d0 def $z0
-; CHECK-NEXT:    ptrue p0.d
-; CHECK-NEXT:    mov z0.d, d0
-; CHECK-NEXT:    fdivr z0.d, p0/m, z0.d, z1.d
-; CHECK-NEXT:    ret
+; CHECK-SDGI-LABEL: splat_fdiv_nxv2f64:
+; CHECK-SDGI:       // %bb.0: // %entry
+; CHECK-SDGI-NEXT:    // kill: def $d0 killed $d0 def $z0
+; CHECK-SDGI-NEXT:    ptrue p0.d
+; CHECK-SDGI-NEXT:    mov z0.d, d0
+; CHECK-SDGI-NEXT:    fdivr z0.d, p0/m, z0.d, z1.d
+; CHECK-SDGI-NEXT:    ret
+;
+; CHECK-MCPU-LABEL: splat_fdiv_nxv2f64:
+; CHECK-MCPU:       // %bb.0: // %entry
+; CHECK-MCPU-NEXT:    // kill: def $d0 killed $d0 def $z0
+; CHECK-MCPU-NEXT:    mov z0.d, d0
+; CHECK-MCPU-NEXT:    ptrue p0.d
+; CHECK-MCPU-NEXT:    fdivr z0.d, p0/m, z0.d, z1.d
+; CHECK-MCPU-NEXT:    ret
 entry:
   %D.ins = insertelement <vscale x 2 x double> poison, double %D, i64 0
   %splat = shufflevector <vscale x 2 x double> %D.ins, <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer

>From d9f413884780c4151a48778cf479435705d9c1c5 Mon Sep 17 00:00:00 2001
From: yamash-fj <yamashita.ta-16 at fujitsu.com>
Date: Tue, 18 Aug 2026 16:53:29 +0900
Subject: [PATCH 2/2] clang-format

---
 llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index c78d09479a73a..96c5e8e826bee 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -32679,7 +32679,7 @@ SDValue AArch64TargetLowering::emitStackGuardMixFP(SelectionDAG &DAG,
 
 unsigned AArch64TargetLowering::combineRepeatedFPDivisors() const {
   // Combine multiple FDIVs with the same divisor into multiple FMULs by the
-  // reciprocal if there are enough FDivs. The threshold is set as 
+  // reciprocal if there are enough FDIVs. The threshold is set as
   // MinFDivForCombining.
   return Subtarget->getMinFDivForCombining();
 }



More information about the llvm-commits mailing list