[llvm] [X86] combineStore - fold scalar float store(fabs/fneg(load())) -> store(and/xor(load(),c)) (PR #118680)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 4 10:20:26 PST 2024


https://github.com/RKSimon created https://github.com/llvm/llvm-project/pull/118680

As noted on #117557 - its not worth performing scalar float fabs/fneg on the fpu if we're not doing any other fp ops.

This is currently limited to store + load pairs - I could try to extend this further if necessary, but we need to be careful that we don't end up in an infinite loop with the DAGCombiner foldBitcastedFPLogic combine.

Fixes #117557

>From 4b15f05c67643da4e593bfa6e475a9e4f39fa2ff Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Wed, 4 Dec 2024 18:16:11 +0000
Subject: [PATCH] [X86] combineStore - fold scalar float
 store(fabs/fneg(load())) -> store(and/xor(load(),c))

As noted on #117557 - its not worth performing scalar float fabs/fneg on the fpu if we're not doing any other fp ops.
---
 llvm/lib/Target/X86/X86ISelLowering.cpp  | 23 +++++++++++++++++++
 llvm/test/CodeGen/X86/combine-fabs.ll    | 23 ++++++++-----------
 llvm/test/CodeGen/X86/combine-fneg.ll    | 29 ++++++++----------------
 llvm/test/CodeGen/X86/fsxor-alignment.ll | 15 ++++++------
 4 files changed, 49 insertions(+), 41 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 7b46b109de3b09..a23a4b67df5424 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -52661,6 +52661,29 @@ static SDValue combineStore(SDNode *N, SelectionDAG &DAG,
                         St->getMemOperand()->getFlags());
   }
 
+  // Convert scalar fabs/fneg load-store to integer equivalents.
+  if ((VT == MVT::f32 || VT == MVT::f64) &&
+      (StoredVal.getOpcode() == ISD::FABS ||
+       StoredVal.getOpcode() == ISD::FNEG) &&
+      ISD::isNormalLoad(StoredVal.getOperand(0).getNode()) &&
+      StoredVal.hasOneUse() && StoredVal.getOperand(0).hasOneUse()) {
+    MVT IntVT = VT.getSimpleVT().changeTypeToInteger();
+    if (TLI.isTypeLegal(IntVT)) {
+      APInt SignMask = APInt::getSignMask(VT.getScalarSizeInBits());
+      unsigned SignOp = ISD::XOR;
+      if (StoredVal.getOpcode() == ISD::FABS) {
+        SignMask = ~SignMask;
+        SignOp = ISD::AND;
+      }
+      SDValue LogicOp = DAG.getNode(
+          SignOp, dl, IntVT, DAG.getBitcast(IntVT, StoredVal.getOperand(0)),
+          DAG.getConstant(SignMask, dl, IntVT));
+      return DAG.getStore(St->getChain(), dl, LogicOp, St->getBasePtr(),
+                          St->getPointerInfo(), St->getOriginalAlign(),
+                          St->getMemOperand()->getFlags());
+    }
+  }
+
   // If we are saving a 32-byte vector and 32-byte stores are slow, such as on
   // Sandy Bridge, perform two 16-byte stores.
   unsigned Fast;
diff --git a/llvm/test/CodeGen/X86/combine-fabs.ll b/llvm/test/CodeGen/X86/combine-fabs.ll
index d337c7693ff7d6..b9aad9075261b1 100644
--- a/llvm/test/CodeGen/X86/combine-fabs.ll
+++ b/llvm/test/CodeGen/X86/combine-fabs.ll
@@ -135,20 +135,16 @@ define <4 x float> @combine_vec_fabs_fcopysign(<4 x float> %a, <4 x float> %b) {
   ret <4 x float> %2
 }
 
-; TODO: store(fabs(load())) - convert scalar to integer
+; store(fabs(load())) - convert scalar to integer
 define void @combine_fabs_int_rmw_f64(ptr %ptr) {
 ; SSE-LABEL: combine_fabs_int_rmw_f64:
 ; SSE:       # %bb.0:
-; SSE-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
-; SSE-NEXT:    andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; SSE-NEXT:    movlps %xmm0, (%rdi)
+; SSE-NEXT:    andb $127, 7(%rdi)
 ; SSE-NEXT:    retq
 ;
 ; AVX-LABEL: combine_fabs_int_rmw_f64:
 ; AVX:       # %bb.0:
-; AVX-NEXT:    vmovsd {{.*#+}} xmm0 = mem[0],zero
-; AVX-NEXT:    vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
-; AVX-NEXT:    vmovlps %xmm0, (%rdi)
+; AVX-NEXT:    andb $127, 7(%rdi)
 ; AVX-NEXT:    retq
   %1 = load double, ptr %ptr
   %2 = call double @llvm.fabs.f64(double %1)
@@ -159,17 +155,16 @@ define void @combine_fabs_int_rmw_f64(ptr %ptr) {
 define void @combine_fabs_int_f32(ptr %src, ptr %dst) {
 ; SSE-LABEL: combine_fabs_int_f32:
 ; SSE:       # %bb.0:
-; SSE-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; SSE-NEXT:    andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; SSE-NEXT:    movss %xmm0, (%rsi)
+; SSE-NEXT:    movl $2147483647, %eax # imm = 0x7FFFFFFF
+; SSE-NEXT:    andl (%rdi), %eax
+; SSE-NEXT:    movl %eax, (%rsi)
 ; SSE-NEXT:    retq
 ;
 ; AVX-LABEL: combine_fabs_int_f32:
 ; AVX:       # %bb.0:
-; AVX-NEXT:    vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; AVX-NEXT:    vbroadcastss {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN]
-; AVX-NEXT:    vandps %xmm1, %xmm0, %xmm0
-; AVX-NEXT:    vmovss %xmm0, (%rsi)
+; AVX-NEXT:    movl $2147483647, %eax # imm = 0x7FFFFFFF
+; AVX-NEXT:    andl (%rdi), %eax
+; AVX-NEXT:    movl %eax, (%rsi)
 ; AVX-NEXT:    retq
   %1 = load float, ptr %src
   %2 = call float @llvm.fabs.f32(float %1)
diff --git a/llvm/test/CodeGen/X86/combine-fneg.ll b/llvm/test/CodeGen/X86/combine-fneg.ll
index e8e3465c99383d..855b64229a9c33 100644
--- a/llvm/test/CodeGen/X86/combine-fneg.ll
+++ b/llvm/test/CodeGen/X86/combine-fneg.ll
@@ -205,21 +205,17 @@ define <4 x float> @fneg(<4 x float> %Q) nounwind {
   ret <4 x float> %tmp
 }
 
-; TODO: store(fneg(load())) - convert scalar to integer
+; store(fneg(load())) - convert scalar to integer
 define void @fneg_int_rmw_f32(ptr %ptr) {
 ; X86-SSE-LABEL: fneg_int_rmw_f32:
 ; X86-SSE:       # %bb.0:
 ; X86-SSE-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X86-SSE-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; X86-SSE-NEXT:    xorps {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0
-; X86-SSE-NEXT:    movss %xmm0, (%eax)
+; X86-SSE-NEXT:    xorb $-128, 3(%eax)
 ; X86-SSE-NEXT:    retl
 ;
 ; X64-SSE-LABEL: fneg_int_rmw_f32:
 ; X64-SSE:       # %bb.0:
-; X64-SSE-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; X64-SSE-NEXT:    xorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; X64-SSE-NEXT:    movss %xmm0, (%rdi)
+; X64-SSE-NEXT:    xorb $-128, 3(%rdi)
 ; X64-SSE-NEXT:    retq
   %1 = load float, ptr %ptr
   %2 = fneg float %1
@@ -246,19 +242,12 @@ define void @fneg_int_f64(ptr %src, ptr %dst) {
 ; X86-SSE2-NEXT:    movlps %xmm0, (%eax)
 ; X86-SSE2-NEXT:    retl
 ;
-; X64-SSE1-LABEL: fneg_int_f64:
-; X64-SSE1:       # %bb.0:
-; X64-SSE1-NEXT:    fldl (%rdi)
-; X64-SSE1-NEXT:    fchs
-; X64-SSE1-NEXT:    fstpl (%rsi)
-; X64-SSE1-NEXT:    retq
-;
-; X64-SSE2-LABEL: fneg_int_f64:
-; X64-SSE2:       # %bb.0:
-; X64-SSE2-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
-; X64-SSE2-NEXT:    xorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; X64-SSE2-NEXT:    movlps %xmm0, (%rsi)
-; X64-SSE2-NEXT:    retq
+; X64-SSE-LABEL: fneg_int_f64:
+; X64-SSE:       # %bb.0:
+; X64-SSE-NEXT:    movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000
+; X64-SSE-NEXT:    xorq (%rdi), %rax
+; X64-SSE-NEXT:    movq %rax, (%rsi)
+; X64-SSE-NEXT:    retq
   %1 = load double, ptr %src
   %2 = fneg double %1
   store double %2, ptr %dst
diff --git a/llvm/test/CodeGen/X86/fsxor-alignment.ll b/llvm/test/CodeGen/X86/fsxor-alignment.ll
index 1b9d6c91ad2b23..6fa4a310956dc6 100644
--- a/llvm/test/CodeGen/X86/fsxor-alignment.ll
+++ b/llvm/test/CodeGen/X86/fsxor-alignment.ll
@@ -8,15 +8,16 @@
 define void @foo(ptr %p, ptr %q, float %s, float %y) nounwind {
 ; CHECK-LABEL: foo:
 ; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushl %esi
 ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; CHECK-NEXT:    movaps {{.*#+}} xmm1 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
-; CHECK-NEXT:    xorps %xmm1, %xmm0
-; CHECK-NEXT:    movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; CHECK-NEXT:    xorps %xmm1, %xmm2
-; CHECK-NEXT:    movss %xmm0, (%ecx)
-; CHECK-NEXT:    movss %xmm2, (%eax)
+; CHECK-NEXT:    movl $-2147483648, %edx # imm = 0x80000000
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; CHECK-NEXT:    xorl %edx, %esi
+; CHECK-NEXT:    movl %esi, (%ecx)
+; CHECK-NEXT:    xorl {{[0-9]+}}(%esp), %edx
+; CHECK-NEXT:    movl %edx, (%eax)
+; CHECK-NEXT:    popl %esi
 ; CHECK-NEXT:    retl
   %ss = fsub float -0.0, %s
   %yy = fsub float -0.0, %y



More information about the llvm-commits mailing list