[llvm] [X86][TTI]Model the sqrt folded into the reciprocal estimate as free (PR #229482)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 6 09:59:17 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Alexey Bataev (alexey-bataev)

<details>
<summary>Changes</summary>

The scalar sqrt, divided into with the reciprocal allowed, is folded with
the division into the rsqrt* estimate sequence. Report no cost for it when
the type has the estimate and the function does not disable it, so the
vectorizers do not pack it and break the folding.

Assisted-by: Cursor


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


7 Files Affected:

- (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+1) 
- (modified) llvm/lib/CodeGen/TargetLoweringBase.cpp (+10-2) 
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+18-14) 
- (modified) llvm/lib/Target/X86/X86ISelLowering.h (+4) 
- (modified) llvm/lib/Target/X86/X86TargetTransformInfo.cpp (+22) 
- (added) llvm/test/Analysis/CostModel/X86/sqrt-rsqrt-estimate.ll (+95) 
- (added) llvm/test/Transforms/SLPVectorizer/X86/once-used-rsqrt-seeds.ll (+119) 


``````````diff
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index a17cfa5c254a6..1950167a89299 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -615,6 +615,7 @@ class LLVM_ABI TargetLoweringBase {
   /// based on the function's attributes. If the operation is not overridden by
   /// the function's attributes, "Unspecified" is returned and target defaults
   /// are expected to be used for instruction selection.
+  int getRecipEstimateSqrtEnabled(EVT VT, const Function &F) const;
   int getRecipEstimateSqrtEnabled(EVT VT, MachineFunction &MF) const;
 
   /// Return a ReciprocalEstimate enum value for a division of the given type
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 1c7bca06b225a..ff7b8439b549c 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -2303,11 +2303,14 @@ unsigned TargetLoweringBase::getMaxPermittedBytesForAlignment(
 
 /// Get the reciprocal estimate attribute string for a function that will
 /// override the target defaults.
-static StringRef getRecipEstimateForFunc(MachineFunction &MF) {
-  const Function &F = MF.getFunction();
+static StringRef getRecipEstimateForFunc(const Function &F) {
   return F.getFnAttribute("reciprocal-estimates").getValueAsString();
 }
 
+static StringRef getRecipEstimateForFunc(MachineFunction &MF) {
+  return getRecipEstimateForFunc(MF.getFunction());
+}
+
 /// Construct a string for the given reciprocal operation of the given type.
 /// This string should match the corresponding option to the front-end's
 /// "-mrecip" flag assuming those strings have been passed through in an
@@ -2463,6 +2466,11 @@ static int getOpRefinementSteps(bool IsSqrt, EVT VT, StringRef Override) {
   return TargetLoweringBase::ReciprocalEstimate::Unspecified;
 }
 
+int TargetLoweringBase::getRecipEstimateSqrtEnabled(EVT VT,
+                                                    const Function &F) const {
+  return getOpEnabled(true, VT, getRecipEstimateForFunc(F));
+}
+
 int TargetLoweringBase::getRecipEstimateSqrtEnabled(EVT VT,
                                                     MachineFunction &MF) const {
   return getOpEnabled(true, VT, getRecipEstimateForFunc(MF));
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 4137f971a0280..5657d3448ddbd 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -24195,6 +24195,23 @@ bool X86TargetLowering::isFsqrtCheap(SDValue Op, SelectionDAG &DAG) const {
   return Subtarget.hasFastScalarFSQRT();
 }
 
+bool X86TargetLowering::hasSqrtEstimate(EVT VT, bool Reciprocal) const {
+  // SSE1 has rsqrtss and rsqrtps. AVX adds a 256-bit variant for rsqrtps.
+  // It is likely not profitable to do this for f64 because a double-precision
+  // rsqrt estimate with refinement on x86 prior to FMA requires at least 16
+  // instructions: convert to single, rsqrtss, convert back to double, refine
+  // (3 steps = at least 13 insts). If an 'rsqrtsd' variant was added to the ISA
+  // along with FMA, this could be a throughput win.
+  // TODO: SQRT requires SSE2 to prevent the introduction of an illegal v4i32
+  // after legalize types.
+  return isTypeLegal(VT) &&
+         ((VT == MVT::f32 && Subtarget.hasSSE1()) ||
+          (VT == MVT::v4f32 && Subtarget.hasSSE1() && Reciprocal) ||
+          (VT == MVT::v4f32 && Subtarget.hasSSE2() && !Reciprocal) ||
+          (VT == MVT::v8f32 && Subtarget.hasAVX()) ||
+          (VT == MVT::v16f32 && Subtarget.useAVX512Regs()));
+}
+
 /// The minimum architected relative accuracy is 2^-12. We need one
 /// Newton-Raphson step to have a good float result (24 bits of precision).
 SDValue X86TargetLowering::getSqrtEstimate(SDValue Op,
@@ -24205,20 +24222,7 @@ SDValue X86TargetLowering::getSqrtEstimate(SDValue Op,
   SDLoc DL(Op);
   EVT VT = Op.getValueType();
 
-  // SSE1 has rsqrtss and rsqrtps. AVX adds a 256-bit variant for rsqrtps.
-  // It is likely not profitable to do this for f64 because a double-precision
-  // rsqrt estimate with refinement on x86 prior to FMA requires at least 16
-  // instructions: convert to single, rsqrtss, convert back to double, refine
-  // (3 steps = at least 13 insts). If an 'rsqrtsd' variant was added to the ISA
-  // along with FMA, this could be a throughput win.
-  // TODO: SQRT requires SSE2 to prevent the introduction of an illegal v4i32
-  // after legalize types.
-  if (isTypeLegal(VT) &&
-      ((VT == MVT::f32 && Subtarget.hasSSE1()) ||
-       (VT == MVT::v4f32 && Subtarget.hasSSE1() && Reciprocal) ||
-       (VT == MVT::v4f32 && Subtarget.hasSSE2() && !Reciprocal) ||
-       (VT == MVT::v8f32 && Subtarget.hasAVX()) ||
-       (VT == MVT::v16f32 && Subtarget.useAVX512Regs()))) {
+  if (hasSqrtEstimate(VT, Reciprocal)) {
     if (RefinementSteps == ReciprocalEstimate::Unspecified)
       RefinementSteps = 1;
 
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index ba04080573c42..b972949b5727e 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -743,6 +743,10 @@ namespace llvm {
       return TargetLoweringBase::getTypeToTransformTo(Context, VT);
     }
 
+    /// Return true if \p VT has the rsqrt* based estimate of the square root,
+    /// or of its reciprocal if \p Reciprocal is set.
+    bool hasSqrtEstimate(EVT VT, bool Reciprocal) const;
+
   protected:
     std::pair<const TargetRegisterClass *, uint8_t>
     findRepresentativeClass(const TargetRegisterInfo *TRI,
diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
index 393e5bfe45ffb..a28d17bcc27ad 100644
--- a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
+++ b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
@@ -4141,6 +4141,23 @@ InstructionCost X86TTIImpl::getCmpSelInstrCost(
 
 unsigned X86TTIImpl::getAtomicMemIntrinsicMaxElementSize() const { return 16; }
 
+/// Returns true if the square root is divided into with the reciprocal
+/// allowed and the target replaces the pair with the rsqrt* based estimate.
+static bool isFoldedIntoRsqrtEstimate(const IntrinsicCostAttributes &ICA,
+                                      const X86TargetLowering &TLI,
+                                      const DataLayout &DL) {
+  using namespace PatternMatch;
+  const IntrinsicInst *II = ICA.getInst();
+  if (!II || !II->hasOneUse() ||
+      !match(II->user_back(), m_FDiv(m_Value(), m_Specific(II))) ||
+      !cast<FPMathOperator>(II->user_back())->hasAllowReciprocal())
+    return false;
+  EVT VT = TLI.getValueType(DL, ICA.getReturnType());
+  return TLI.hasSqrtEstimate(VT, /*Reciprocal=*/true) &&
+         TLI.getRecipEstimateSqrtEnabled(VT, *II->getFunction()) !=
+             TargetLoweringBase::ReciprocalEstimate::Disabled;
+}
+
 InstructionCost
 X86TTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
                                   TTI::TargetCostKind CostKind) const {
@@ -5128,6 +5145,11 @@ X86TTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
     ISD = ISD::MULHU;
     break;
   case Intrinsic::sqrt:
+    // The estimate sequence is costed with the division it is folded into.
+    if ((CostKind == TTI::TCK_RecipThroughput ||
+         CostKind == TTI::TCK_Latency) &&
+        isFoldedIntoRsqrtEstimate(ICA, *TLI, DL))
+      return TTI::TCC_Free;
     ISD = ISD::FSQRT;
     break;
   case Intrinsic::sadd_with_overflow:
diff --git a/llvm/test/Analysis/CostModel/X86/sqrt-rsqrt-estimate.ll b/llvm/test/Analysis/CostModel/X86/sqrt-rsqrt-estimate.ll
new file mode 100644
index 0000000000000..1bc561f54e743
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/X86/sqrt-rsqrt-estimate.ll
@@ -0,0 +1,95 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes="print<cost-model>" 2>&1 -disable-output -cost-kind=all -mtriple=x86_64-- -mattr=+avx2 | FileCheck %s
+
+; The square root, divided into with the reciprocal allowed, is folded with the
+; division into the estimate, the division carries the cost of the pair.
+
+define float @folded(float %x, float %y) {
+; CHECK-LABEL: 'folded'
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:0 SizeLat:1 for: %s = call float @llvm.sqrt.f32(float %x)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:13 SizeLat:1 for: %d = fdiv arcp float %y, %s
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret float %d
+;
+  %s = call float @llvm.sqrt.f32(float %x)
+  %d = fdiv arcp float %y, %s
+  ret float %d
+}
+
+define float @no_arcp(float %x, float %y) {
+; CHECK-LABEL: 'no_arcp'
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:15 SizeLat:1 for: %s = call float @llvm.sqrt.f32(float %x)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:13 SizeLat:1 for: %d = fdiv float %y, %s
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret float %d
+;
+  %s = call float @llvm.sqrt.f32(float %x)
+  %d = fdiv float %y, %s
+  ret float %d
+}
+
+define float @multi_use(float %x, float %y) {
+; CHECK-LABEL: 'multi_use'
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:15 SizeLat:1 for: %s = call float @llvm.sqrt.f32(float %x)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:13 SizeLat:1 for: %d = fdiv arcp float %y, %s
+; CHECK-NEXT:  Cost Model: Found costs of RThru:1 CodeSize:1 Lat:4 SizeLat:1 for: %r = fadd float %d, %s
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret float %r
+;
+  %s = call float @llvm.sqrt.f32(float %x)
+  %d = fdiv arcp float %y, %s
+  %r = fadd float %d, %s
+  ret float %r
+}
+
+define float @numerator(float %x, float %y) {
+; CHECK-LABEL: 'numerator'
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:15 SizeLat:1 for: %s = call float @llvm.sqrt.f32(float %x)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:13 SizeLat:1 for: %d = fdiv arcp float %s, %y
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret float %d
+;
+  %s = call float @llvm.sqrt.f32(float %x)
+  %d = fdiv arcp float %s, %y
+  ret float %d
+}
+
+define double @f64(double %x, double %y) {
+; CHECK-LABEL: 'f64'
+; CHECK-NEXT:  Cost Model: Found costs of RThru:14 CodeSize:1 Lat:21 SizeLat:1 for: %s = call double @llvm.sqrt.f64(double %x)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:14 CodeSize:1 Lat:20 SizeLat:1 for: %d = fdiv arcp double %y, %s
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret double %d
+;
+  %s = call double @llvm.sqrt.f64(double %x)
+  %d = fdiv arcp double %y, %s
+  ret double %d
+}
+
+define <2 x float> @v2f32(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: 'v2f32'
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:15 SizeLat:1 for: %s = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:13 SizeLat:1 for: %d = fdiv arcp <2 x float> %y, %s
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret <2 x float> %d
+;
+  %s = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x)
+  %d = fdiv arcp <2 x float> %y, %s
+  ret <2 x float> %d
+}
+
+define <8 x float> @v8f32(<8 x float> %x, <8 x float> %y) {
+; CHECK-LABEL: 'v8f32'
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:0 SizeLat:3 for: %s = call <8 x float> @llvm.sqrt.v8f32(<8 x float> %x)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:14 CodeSize:1 Lat:21 SizeLat:3 for: %d = fdiv arcp <8 x float> %y, %s
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret <8 x float> %d
+;
+  %s = call <8 x float> @llvm.sqrt.v8f32(<8 x float> %x)
+  %d = fdiv arcp <8 x float> %y, %s
+  ret <8 x float> %d
+}
+
+define float @disabled(float %x, float %y) "reciprocal-estimates"="!sqrtf" {
+; CHECK-LABEL: 'disabled'
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:15 SizeLat:1 for: %s = call float @llvm.sqrt.f32(float %x)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:7 CodeSize:1 Lat:13 SizeLat:1 for: %d = fdiv arcp float %y, %s
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret float %d
+;
+  %s = call float @llvm.sqrt.f32(float %x)
+  %d = fdiv arcp float %y, %s
+  ret float %d
+}
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/once-used-rsqrt-seeds.ll b/llvm/test/Transforms/SLPVectorizer/X86/once-used-rsqrt-seeds.ll
new file mode 100644
index 0000000000000..efd3e00c24c1e
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/once-used-rsqrt-seeds.ll
@@ -0,0 +1,119 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=slp-vectorizer -S < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=znver4 | FileCheck %s
+
+; The single-use square roots, folded with the divisions into the reciprocal
+; square root estimate, are not profitable as the standalone seeds, the vector
+; node breaks the folding.
+
+declare float @llvm.sqrt.f32(float)
+
+define void @rsqrt(ptr %x, ptr %f, i64 %j) {
+; CHECK-LABEL: define void @rsqrt(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[F:%.*]], i64 [[J:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:    [[I1:%.*]] = add nsw i64 [[J]], 1
+; CHECK-NEXT:    [[I2:%.*]] = add nsw i64 [[J]], 2
+; CHECK-NEXT:    [[PX0:%.*]] = getelementptr inbounds float, ptr [[X]], i64 [[J]]
+; CHECK-NEXT:    [[PX1:%.*]] = getelementptr inbounds float, ptr [[X]], i64 [[I1]]
+; CHECK-NEXT:    [[PX2:%.*]] = getelementptr inbounds float, ptr [[X]], i64 [[I2]]
+; CHECK-NEXT:    [[X0:%.*]] = load float, ptr [[PX0]], align 4
+; CHECK-NEXT:    [[X1:%.*]] = load float, ptr [[PX1]], align 4
+; CHECK-NEXT:    [[X2:%.*]] = load float, ptr [[PX2]], align 4
+; CHECK-NEXT:    [[S1:%.*]] = call fast float @llvm.sqrt.f32(float [[X1]])
+; CHECK-NEXT:    [[S2:%.*]] = call fast float @llvm.sqrt.f32(float [[X2]])
+; CHECK-NEXT:    [[R2:%.*]] = fdiv fast float 1.000000e+00, [[S2]]
+; CHECK-NEXT:    [[PF0:%.*]] = getelementptr inbounds float, ptr [[F]], i64 [[J]]
+; CHECK-NEXT:    [[PF2:%.*]] = getelementptr inbounds float, ptr [[F]], i64 [[I2]]
+; CHECK-NEXT:    [[F2:%.*]] = load float, ptr [[PF2]], align 4
+; CHECK-NEXT:    [[NF2:%.*]] = fadd fast float [[F2]], [[R2]]
+; CHECK-NEXT:    [[R1:%.*]] = fdiv fast float 1.000000e+00, [[S1]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X0]], f0x3DFBE770
+; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x float>, ptr [[PF0]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x float> poison, float [[MUL]], i64 0
+; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x float> [[TMP2]], float [[R1]], i64 1
+; CHECK-NEXT:    [[TMP4:%.*]] = fadd fast <2 x float> [[TMP1]], [[TMP3]]
+; CHECK-NEXT:    store <2 x float> [[TMP4]], ptr [[PF0]], align 4
+; CHECK-NEXT:    store float [[NF2]], ptr [[PF2]], align 4
+; CHECK-NEXT:    ret void
+;
+  %i1 = add nsw i64 %j, 1
+  %i2 = add nsw i64 %j, 2
+  %px0 = getelementptr inbounds float, ptr %x, i64 %j
+  %px1 = getelementptr inbounds float, ptr %x, i64 %i1
+  %px2 = getelementptr inbounds float, ptr %x, i64 %i2
+  %x0 = load float, ptr %px0, align 4
+  %x1 = load float, ptr %px1, align 4
+  %x2 = load float, ptr %px2, align 4
+  %s1 = call fast float @llvm.sqrt.f32(float %x1)
+  %s2 = call fast float @llvm.sqrt.f32(float %x2)
+  %r1 = fdiv fast float 1.0, %s1
+  %r2 = fdiv fast float 1.0, %s2
+  %mul = fmul fast float %x0, 0x3FBF7CEE00000000
+  %pf0 = getelementptr inbounds float, ptr %f, i64 %j
+  %pf1 = getelementptr inbounds float, ptr %f, i64 %i1
+  %pf2 = getelementptr inbounds float, ptr %f, i64 %i2
+  %f0 = load float, ptr %pf0, align 4
+  %f1 = load float, ptr %pf1, align 4
+  %f2 = load float, ptr %pf2, align 4
+  %nf0 = fadd fast float %f0, %mul
+  %nf1 = fadd fast float %f1, %r1
+  %nf2 = fadd fast float %f2, %r2
+  store float %nf0, ptr %pf0, align 4
+  store float %nf1, ptr %pf1, align 4
+  store float %nf2, ptr %pf2, align 4
+  ret void
+}
+
+define void @no_arcp(ptr %x, ptr %f, i64 %j) {
+; CHECK-LABEL: define void @no_arcp(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[F:%.*]], i64 [[J:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[I1:%.*]] = add nsw i64 [[J]], 1
+; CHECK-NEXT:    [[I2:%.*]] = add nsw i64 [[J]], 2
+; CHECK-NEXT:    [[PX0:%.*]] = getelementptr inbounds float, ptr [[X]], i64 [[J]]
+; CHECK-NEXT:    [[PX1:%.*]] = getelementptr inbounds float, ptr [[X]], i64 [[I1]]
+; CHECK-NEXT:    [[X0:%.*]] = load float, ptr [[PX0]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x float>, ptr [[PX1]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = call fast <2 x float> @llvm.sqrt.v2f32(<2 x float> [[TMP1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <2 x float> [[TMP2]], i64 1
+; CHECK-NEXT:    [[R2:%.*]] = fdiv nnan float 1.000000e+00, [[TMP3]]
+; CHECK-NEXT:    [[PF0:%.*]] = getelementptr inbounds float, ptr [[F]], i64 [[J]]
+; CHECK-NEXT:    [[PF2:%.*]] = getelementptr inbounds float, ptr [[F]], i64 [[I2]]
+; CHECK-NEXT:    [[F2:%.*]] = load float, ptr [[PF2]], align 4
+; CHECK-NEXT:    [[NF2:%.*]] = fadd fast float [[F2]], [[R2]]
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x float> [[TMP2]], i64 0
+; CHECK-NEXT:    [[R1:%.*]] = fdiv nnan float 1.000000e+00, [[TMP4]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X0]], f0x3DFBE770
+; CHECK-NEXT:    [[TMP5:%.*]] = load <2 x float>, ptr [[PF0]], align 4
+; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <2 x float> poison, float [[MUL]], i64 0
+; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[R1]], i64 1
+; CHECK-NEXT:    [[TMP8:%.*]] = fadd fast <2 x float> [[TMP5]], [[TMP7]]
+; CHECK-NEXT:    store <2 x float> [[TMP8]], ptr [[PF0]], align 4
+; CHECK-NEXT:    store float [[NF2]], ptr [[PF2]], align 4
+; CHECK-NEXT:    ret void
+;
+  %i1 = add nsw i64 %j, 1
+  %i2 = add nsw i64 %j, 2
+  %px0 = getelementptr inbounds float, ptr %x, i64 %j
+  %px1 = getelementptr inbounds float, ptr %x, i64 %i1
+  %px2 = getelementptr inbounds float, ptr %x, i64 %i2
+  %x0 = load float, ptr %px0, align 4
+  %x1 = load float, ptr %px1, align 4
+  %x2 = load float, ptr %px2, align 4
+  %s1 = call fast float @llvm.sqrt.f32(float %x1)
+  %s2 = call fast float @llvm.sqrt.f32(float %x2)
+  %r1 = fdiv nnan float 1.0, %s1
+  %r2 = fdiv nnan float 1.0, %s2
+  %mul = fmul fast float %x0, 0x3FBF7CEE00000000
+  %pf0 = getelementptr inbounds float, ptr %f, i64 %j
+  %pf1 = getelementptr inbounds float, ptr %f, i64 %i1
+  %pf2 = getelementptr inbounds float, ptr %f, i64 %i2
+  %f0 = load float, ptr %pf0, align 4
+  %f1 = load float, ptr %pf1, align 4
+  %f2 = load float, ptr %pf2, align 4
+  %nf0 = fadd fast float %f0, %mul
+  %nf1 = fadd fast float %f1, %r1
+  %nf2 = fadd fast float %f2, %r2
+  store float %nf0, ptr %pf0, align 4
+  store float %nf1, ptr %pf1, align 4
+  store float %nf2, ptr %pf2, align 4
+  ret void
+}

``````````

</details>


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


More information about the llvm-commits mailing list