Skip to content

Conversation

@JaydeepChauhan14
Copy link
Contributor

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Nov 13, 2025

@llvm/pr-subscribers-backend-x86

Author: None (JaydeepChauhan14)

Changes

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

5 Files Affected:

  • (modified) llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp (+23)
  • (modified) llvm/lib/Target/X86/GISel/X86LegalizerInfo.h (+3)
  • (modified) llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp (+1)
  • (added) llvm/test/CodeGen/X86/GlobalISel/isel-fneg.mir (+116)
  • (modified) llvm/test/CodeGen/X86/isel-fneg.ll (+27-3)
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index e792b1bce3c5c..dee75a39acc59 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -126,6 +126,13 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
                                G_FSINCOS, G_FCEIL,   G_FFLOOR})
       .libcall();
 
+  getActionDefinitionsBuilder(G_FNEG)
+      .legalFor(UseX87 && !HasSSE1, {s32})
+      .legalFor(UseX87 && !HasSSE2, {s64})
+      .legalFor(UseX87, {s80})
+      .customFor(UseX87 && !Is64Bit, {s32})
+      .lowerFor({s32, s64});
+
   getActionDefinitionsBuilder(G_FSQRT)
       .legalFor(HasSSE1 || UseX87, {s32})
       .legalFor(HasSSE2 || UseX87, {s64})
@@ -993,6 +1000,22 @@ bool X86LegalizerInfo::legalizeSETROUNDING(MachineInstr &MI,
   return true;
 }
 
+bool X86LegalizerInfo::legalizeFNEG(MachineInstr &MI, MachineRegisterInfo &MRI,
+                                    LegalizerHelper &Helper) const {
+  bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();
+  bool Is64Bit = Subtarget.is64Bit();
+  if (UseX87 && !Is64Bit && MI.getMF()->getFunction().getReturnType()->isFloatTy()) {
+    auto DstReg = MI.getOperand(0).getReg();
+    auto SrcReg = MI.getOperand(1).getReg();
+    auto ExtReg = MRI.createVirtualRegister(&X86::RFP80RegClass);
+    Helper.MIRBuilder.buildFPExt(ExtReg, SrcReg);
+    Helper.MIRBuilder.buildCopy(DstReg, ExtReg);
+    MI.eraseFromParent();
+    return true;
+  }
+  return false;
+}
+
 bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
                                          MachineInstr &MI) const {
   return true;
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
index 09c727c8e8685..2bd35b6d5c58b 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
@@ -60,6 +60,9 @@ class X86LegalizerInfo : public LegalizerInfo {
 
   bool legalizeSETROUNDING(MachineInstr &MI, MachineRegisterInfo &MRI,
                            LegalizerHelper &Helper) const;
+
+  bool legalizeFNEG(MachineInstr &MI, MachineRegisterInfo &MRI,
+                           LegalizerHelper &Helper) const;
 };
 } // namespace llvm
 #endif
diff --git a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
index b23d791501729..4cb7b5cc6775c 100644
--- a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
@@ -292,6 +292,7 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
   switch (Opc) {
   case TargetOpcode::G_FSQRT:
   case TargetOpcode::G_FPEXT:
+  case TargetOpcode::G_FNEG:
   case TargetOpcode::G_FPTRUNC:
   case TargetOpcode::G_FCONSTANT:
     // Instruction having only floating-point operands (all scalars in
diff --git a/llvm/test/CodeGen/X86/GlobalISel/isel-fneg.mir b/llvm/test/CodeGen/X86/GlobalISel/isel-fneg.mir
new file mode 100644
index 0000000000000..7aa5478dcdd95
--- /dev/null
+++ b/llvm/test/CodeGen/X86/GlobalISel/isel-fneg.mir
@@ -0,0 +1,116 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=i686-linux-gnu -run-pass=regbankselect,instruction-select %s -o -  | FileCheck %s --check-prefixes GISEL-I686
+
+---
+name:            fneg_f64
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 0, size: 8, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: fneg_f64
+    ; GISEL-I686: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF
+    ; GISEL-I686-NEXT: [[CHS_Fp64_:%[0-9]+]]:rfp64 = CHS_Fp64 [[DEF]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp64_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %1:_(p0) = G_FRAME_INDEX %fixed-stack.0
+    %0:_(s64) = IMPLICIT_DEF
+    %2:_(s64) = G_FNEG %0
+    $fp0 = COPY %2(s64)
+    RET 0, implicit $fp0
+...
+---
+name:            fneg_f32
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 0, size: 4, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: fneg_f32
+    ; GISEL-I686: [[LD_Fp32m:%[0-9]+]]:rfp32 = nofpexcept LD_Fp32m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (invariant load (s32) from %fixed-stack.0, align 16)
+    ; GISEL-I686-NEXT: [[CHS_Fp32_:%[0-9]+]]:rfp32 = CHS_Fp32 [[LD_Fp32m]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp32_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %1:_(p0) = G_FRAME_INDEX %fixed-stack.0
+    %0:_(s32) = G_LOAD %1(p0) :: (invariant load (s32) from %fixed-stack.0, align 16)
+    %2:_(s32) = G_FNEG %0
+    $fp0 = COPY %2(s32)
+    RET 0, implicit $fp0
+...
+---
+name:            fneg_f64_mem
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 1, type: default, offset: 0, size: 4, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: fneg_f64_mem
+    ; GISEL-I686: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF
+    ; GISEL-I686-NEXT: [[CHS_Fp64_:%[0-9]+]]:rfp64 = CHS_Fp64 [[DEF]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp64_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %1:_(p0) = G_FRAME_INDEX %fixed-stack.1
+    %0:_(s64) = IMPLICIT_DEF
+    %2:_(s64) = G_FNEG %0
+    $fp0 = COPY %2(s64)
+    RET 0, implicit $fp0
+...
+---
+name:            fneg_f32_mem
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 1, type: default, offset: 0, size: 4, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: fneg_f32_mem
+    ; GISEL-I686: [[LD_Fp32m:%[0-9]+]]:rfp32 = nofpexcept LD_Fp32m %fixed-stack.1, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (invariant load (p0) from %fixed-stack.1)
+    ; GISEL-I686-NEXT: [[CHS_Fp32_:%[0-9]+]]:rfp32 = CHS_Fp32 [[LD_Fp32m]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp32_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %2:_(p0) = G_FRAME_INDEX %fixed-stack.1
+    %0:_(p0) = G_LOAD %2(p0) :: (invariant load (p0) from %fixed-stack.1, align 16)
+    %3:_(p0) = G_FRAME_INDEX %fixed-stack.0
+    %1:_(s32) = G_LOAD %3(p0) :: (invariant load (p0) from %fixed-stack.0)
+    %4:_(s32) = G_FNEG %1
+    $fp0 = COPY %4(s32)
+    RET 0, implicit $fp0
+...
+---
+name:            test_fp80
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 0, size: 10, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: test_fp80
+    ; GISEL-I686: [[LD_Fp80m:%[0-9]+]]:rfp80 = nofpexcept LD_Fp80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (invariant load (s80) from %fixed-stack.0, align 16)
+    ; GISEL-I686-NEXT: [[CHS_Fp80_:%[0-9]+]]:rfp80 = CHS_Fp80 [[LD_Fp80m]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp80_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %1:_(p0) = G_FRAME_INDEX %fixed-stack.0
+    %0:_(s80) = G_LOAD %1(p0) :: (invariant load (s80) from %fixed-stack.0, align 16)
+    %2:_(s80) = G_FNEG %0
+    $fp0 = COPY %2(s80)
+    RET 0, implicit $fp0
+...
diff --git a/llvm/test/CodeGen/X86/isel-fneg.ll b/llvm/test/CodeGen/X86/isel-fneg.ll
index 77b3f263213a9..e77c46c9d10d8 100644
--- a/llvm/test/CodeGen/X86/isel-fneg.ll
+++ b/llvm/test/CodeGen/X86/isel-fneg.ll
@@ -1,13 +1,13 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc < %s -mtriple=i686-linux-gnu -fast-isel                            | FileCheck %s --check-prefixes=X86,FASTISEL-X86
 ; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=0 -fast-isel=0           | FileCheck %s --check-prefixes=X86,SDAG-X86
-; DISABLED: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2   | FileCheck %s --check-prefixes=X86,GISEL-X86
+; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2   | FileCheck %s --check-prefixes=X86,GISEL-X86
 ; RUN: llc < %s -mtriple=i686-linux-gnu -fast-isel -mattr=+sse                            | FileCheck %s --check-prefixes=X86,SSE-X86,FASTISEL-SSE-X86
 ; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=0 -fast-isel=0 -mattr=+sse           | FileCheck %s --check-prefixes=X86,SSE-X86,SDAG-SSE-X86
-; DISABLED: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2 -mattr=+sse   | FileCheck %s --check-prefixes=X86,SSE-X86,GISEL-SSE-X86
+; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2 -mattr=+sse   | FileCheck %s --check-prefixes=X86,SSE-X86,GISEL-SSE-X86
 ; RUN: llc < %s -mtriple=x86_64-linux-gnu -fast-isel -mattr=+sse                          | FileCheck %s --check-prefixes=X64,SSE-X64,FASTISEL-SSE-X64
 ; RUN: llc < %s -mtriple=x86_64-linux-gnu -global-isel=0 -fast-isel=0 -mattr=+sse         | FileCheck %s --check-prefixes=X64,SSE-X64,SDAG-SSE-X64
-; RUN: llc < %s -mtriple=x86_64-linux-gnu -global-isel=1 -global-isel-abort=2 -mattr=+sse | FileCheck %s --check-prefixes=X64,SSE-X64,GISEL-SSE-X64
+; RUN: llc < %s -mtriple=x86_64-linux-gnu -global-isel=1 -global-isel-abort=1 -mattr=+sse | FileCheck %s --check-prefixes=X64,SSE-X64,GISEL-SSE-X64
 
 define double @fneg_f64(double %x) nounwind {
 ; X86-LABEL: fneg_f64:
@@ -53,6 +53,12 @@ define float @fneg_f32(float %x) nounwind {
 ; SDAG-X86-NEXT:    fchs
 ; SDAG-X86-NEXT:    retl
 ;
+; GISEL-X86-LABEL: fneg_f32:
+; GISEL-X86:       # %bb.0:
+; GISEL-X86-NEXT:    flds {{[0-9]+}}(%esp)
+; GISEL-X86-NEXT:    fchs
+; GISEL-X86-NEXT:    retl
+;
 ; SSE-X86-LABEL: fneg_f32:
 ; SSE-X86:       # %bb.0:
 ; SSE-X86-NEXT:    pushl %eax
@@ -143,6 +149,15 @@ define void @fneg_f32_mem(ptr %x, ptr %y) nounwind {
 ; SDAG-X86-NEXT:    movl %edx, (%eax)
 ; SDAG-X86-NEXT:    retl
 ;
+; GISEL-X86-LABEL: fneg_f32_mem:
+; GISEL-X86:       # %bb.0:
+; GISEL-X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; GISEL-X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; GISEL-X86-NEXT:    flds (%eax)
+; GISEL-X86-NEXT:    fchs
+; GISEL-X86-NEXT:    fstps (%ecx)
+; GISEL-X86-NEXT:    retl
+;
 ; FASTISEL-SSE-X86-LABEL: fneg_f32_mem:
 ; FASTISEL-SSE-X86:       # %bb.0:
 ; FASTISEL-SSE-X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
@@ -161,6 +176,15 @@ define void @fneg_f32_mem(ptr %x, ptr %y) nounwind {
 ; SDAG-SSE-X86-NEXT:    movl %edx, (%eax)
 ; SDAG-SSE-X86-NEXT:    retl
 ;
+; GISEL-SSE-X86-LABEL: fneg_f32_mem:
+; GISEL-SSE-X86:       # %bb.0:
+; GISEL-SSE-X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; GISEL-SSE-X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; GISEL-SSE-X86-NEXT:    movl $-2147483648, %edx # imm = 0x80000000
+; GISEL-SSE-X86-NEXT:    xorl (%ecx), %edx
+; GISEL-SSE-X86-NEXT:    movl %edx, (%eax)
+; GISEL-SSE-X86-NEXT:    retl
+;
 ; FASTISEL-SSE-X64-LABEL: fneg_f32_mem:
 ; FASTISEL-SSE-X64:       # %bb.0:
 ; FASTISEL-SSE-X64-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero

@llvmbot
Copy link
Member

llvmbot commented Nov 13, 2025

@llvm/pr-subscribers-llvm-globalisel

Author: None (JaydeepChauhan14)

Changes

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

5 Files Affected:

  • (modified) llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp (+23)
  • (modified) llvm/lib/Target/X86/GISel/X86LegalizerInfo.h (+3)
  • (modified) llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp (+1)
  • (added) llvm/test/CodeGen/X86/GlobalISel/isel-fneg.mir (+116)
  • (modified) llvm/test/CodeGen/X86/isel-fneg.ll (+27-3)
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index e792b1bce3c5c..dee75a39acc59 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -126,6 +126,13 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
                                G_FSINCOS, G_FCEIL,   G_FFLOOR})
       .libcall();
 
+  getActionDefinitionsBuilder(G_FNEG)
+      .legalFor(UseX87 && !HasSSE1, {s32})
+      .legalFor(UseX87 && !HasSSE2, {s64})
+      .legalFor(UseX87, {s80})
+      .customFor(UseX87 && !Is64Bit, {s32})
+      .lowerFor({s32, s64});
+
   getActionDefinitionsBuilder(G_FSQRT)
       .legalFor(HasSSE1 || UseX87, {s32})
       .legalFor(HasSSE2 || UseX87, {s64})
@@ -993,6 +1000,22 @@ bool X86LegalizerInfo::legalizeSETROUNDING(MachineInstr &MI,
   return true;
 }
 
+bool X86LegalizerInfo::legalizeFNEG(MachineInstr &MI, MachineRegisterInfo &MRI,
+                                    LegalizerHelper &Helper) const {
+  bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();
+  bool Is64Bit = Subtarget.is64Bit();
+  if (UseX87 && !Is64Bit && MI.getMF()->getFunction().getReturnType()->isFloatTy()) {
+    auto DstReg = MI.getOperand(0).getReg();
+    auto SrcReg = MI.getOperand(1).getReg();
+    auto ExtReg = MRI.createVirtualRegister(&X86::RFP80RegClass);
+    Helper.MIRBuilder.buildFPExt(ExtReg, SrcReg);
+    Helper.MIRBuilder.buildCopy(DstReg, ExtReg);
+    MI.eraseFromParent();
+    return true;
+  }
+  return false;
+}
+
 bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
                                          MachineInstr &MI) const {
   return true;
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
index 09c727c8e8685..2bd35b6d5c58b 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
@@ -60,6 +60,9 @@ class X86LegalizerInfo : public LegalizerInfo {
 
   bool legalizeSETROUNDING(MachineInstr &MI, MachineRegisterInfo &MRI,
                            LegalizerHelper &Helper) const;
+
+  bool legalizeFNEG(MachineInstr &MI, MachineRegisterInfo &MRI,
+                           LegalizerHelper &Helper) const;
 };
 } // namespace llvm
 #endif
diff --git a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
index b23d791501729..4cb7b5cc6775c 100644
--- a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
@@ -292,6 +292,7 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
   switch (Opc) {
   case TargetOpcode::G_FSQRT:
   case TargetOpcode::G_FPEXT:
+  case TargetOpcode::G_FNEG:
   case TargetOpcode::G_FPTRUNC:
   case TargetOpcode::G_FCONSTANT:
     // Instruction having only floating-point operands (all scalars in
diff --git a/llvm/test/CodeGen/X86/GlobalISel/isel-fneg.mir b/llvm/test/CodeGen/X86/GlobalISel/isel-fneg.mir
new file mode 100644
index 0000000000000..7aa5478dcdd95
--- /dev/null
+++ b/llvm/test/CodeGen/X86/GlobalISel/isel-fneg.mir
@@ -0,0 +1,116 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=i686-linux-gnu -run-pass=regbankselect,instruction-select %s -o -  | FileCheck %s --check-prefixes GISEL-I686
+
+---
+name:            fneg_f64
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 0, size: 8, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: fneg_f64
+    ; GISEL-I686: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF
+    ; GISEL-I686-NEXT: [[CHS_Fp64_:%[0-9]+]]:rfp64 = CHS_Fp64 [[DEF]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp64_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %1:_(p0) = G_FRAME_INDEX %fixed-stack.0
+    %0:_(s64) = IMPLICIT_DEF
+    %2:_(s64) = G_FNEG %0
+    $fp0 = COPY %2(s64)
+    RET 0, implicit $fp0
+...
+---
+name:            fneg_f32
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 0, size: 4, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: fneg_f32
+    ; GISEL-I686: [[LD_Fp32m:%[0-9]+]]:rfp32 = nofpexcept LD_Fp32m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (invariant load (s32) from %fixed-stack.0, align 16)
+    ; GISEL-I686-NEXT: [[CHS_Fp32_:%[0-9]+]]:rfp32 = CHS_Fp32 [[LD_Fp32m]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp32_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %1:_(p0) = G_FRAME_INDEX %fixed-stack.0
+    %0:_(s32) = G_LOAD %1(p0) :: (invariant load (s32) from %fixed-stack.0, align 16)
+    %2:_(s32) = G_FNEG %0
+    $fp0 = COPY %2(s32)
+    RET 0, implicit $fp0
+...
+---
+name:            fneg_f64_mem
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 1, type: default, offset: 0, size: 4, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: fneg_f64_mem
+    ; GISEL-I686: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF
+    ; GISEL-I686-NEXT: [[CHS_Fp64_:%[0-9]+]]:rfp64 = CHS_Fp64 [[DEF]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp64_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %1:_(p0) = G_FRAME_INDEX %fixed-stack.1
+    %0:_(s64) = IMPLICIT_DEF
+    %2:_(s64) = G_FNEG %0
+    $fp0 = COPY %2(s64)
+    RET 0, implicit $fp0
+...
+---
+name:            fneg_f32_mem
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 1, type: default, offset: 0, size: 4, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: fneg_f32_mem
+    ; GISEL-I686: [[LD_Fp32m:%[0-9]+]]:rfp32 = nofpexcept LD_Fp32m %fixed-stack.1, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (invariant load (p0) from %fixed-stack.1)
+    ; GISEL-I686-NEXT: [[CHS_Fp32_:%[0-9]+]]:rfp32 = CHS_Fp32 [[LD_Fp32m]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp32_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %2:_(p0) = G_FRAME_INDEX %fixed-stack.1
+    %0:_(p0) = G_LOAD %2(p0) :: (invariant load (p0) from %fixed-stack.1, align 16)
+    %3:_(p0) = G_FRAME_INDEX %fixed-stack.0
+    %1:_(s32) = G_LOAD %3(p0) :: (invariant load (p0) from %fixed-stack.0)
+    %4:_(s32) = G_FNEG %1
+    $fp0 = COPY %4(s32)
+    RET 0, implicit $fp0
+...
+---
+name:            test_fp80
+alignment:       16
+legalized:       true
+fixedStack:
+  - { id: 0, type: default, offset: 0, size: 10, alignment: 16, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  bb.1:
+    ; GISEL-I686-LABEL: name: test_fp80
+    ; GISEL-I686: [[LD_Fp80m:%[0-9]+]]:rfp80 = nofpexcept LD_Fp80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (invariant load (s80) from %fixed-stack.0, align 16)
+    ; GISEL-I686-NEXT: [[CHS_Fp80_:%[0-9]+]]:rfp80 = CHS_Fp80 [[LD_Fp80m]], implicit-def dead $fpsw
+    ; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp80_]]
+    ; GISEL-I686-NEXT: RET 0, implicit $fp0
+    %1:_(p0) = G_FRAME_INDEX %fixed-stack.0
+    %0:_(s80) = G_LOAD %1(p0) :: (invariant load (s80) from %fixed-stack.0, align 16)
+    %2:_(s80) = G_FNEG %0
+    $fp0 = COPY %2(s80)
+    RET 0, implicit $fp0
+...
diff --git a/llvm/test/CodeGen/X86/isel-fneg.ll b/llvm/test/CodeGen/X86/isel-fneg.ll
index 77b3f263213a9..e77c46c9d10d8 100644
--- a/llvm/test/CodeGen/X86/isel-fneg.ll
+++ b/llvm/test/CodeGen/X86/isel-fneg.ll
@@ -1,13 +1,13 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc < %s -mtriple=i686-linux-gnu -fast-isel                            | FileCheck %s --check-prefixes=X86,FASTISEL-X86
 ; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=0 -fast-isel=0           | FileCheck %s --check-prefixes=X86,SDAG-X86
-; DISABLED: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2   | FileCheck %s --check-prefixes=X86,GISEL-X86
+; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2   | FileCheck %s --check-prefixes=X86,GISEL-X86
 ; RUN: llc < %s -mtriple=i686-linux-gnu -fast-isel -mattr=+sse                            | FileCheck %s --check-prefixes=X86,SSE-X86,FASTISEL-SSE-X86
 ; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=0 -fast-isel=0 -mattr=+sse           | FileCheck %s --check-prefixes=X86,SSE-X86,SDAG-SSE-X86
-; DISABLED: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2 -mattr=+sse   | FileCheck %s --check-prefixes=X86,SSE-X86,GISEL-SSE-X86
+; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2 -mattr=+sse   | FileCheck %s --check-prefixes=X86,SSE-X86,GISEL-SSE-X86
 ; RUN: llc < %s -mtriple=x86_64-linux-gnu -fast-isel -mattr=+sse                          | FileCheck %s --check-prefixes=X64,SSE-X64,FASTISEL-SSE-X64
 ; RUN: llc < %s -mtriple=x86_64-linux-gnu -global-isel=0 -fast-isel=0 -mattr=+sse         | FileCheck %s --check-prefixes=X64,SSE-X64,SDAG-SSE-X64
-; RUN: llc < %s -mtriple=x86_64-linux-gnu -global-isel=1 -global-isel-abort=2 -mattr=+sse | FileCheck %s --check-prefixes=X64,SSE-X64,GISEL-SSE-X64
+; RUN: llc < %s -mtriple=x86_64-linux-gnu -global-isel=1 -global-isel-abort=1 -mattr=+sse | FileCheck %s --check-prefixes=X64,SSE-X64,GISEL-SSE-X64
 
 define double @fneg_f64(double %x) nounwind {
 ; X86-LABEL: fneg_f64:
@@ -53,6 +53,12 @@ define float @fneg_f32(float %x) nounwind {
 ; SDAG-X86-NEXT:    fchs
 ; SDAG-X86-NEXT:    retl
 ;
+; GISEL-X86-LABEL: fneg_f32:
+; GISEL-X86:       # %bb.0:
+; GISEL-X86-NEXT:    flds {{[0-9]+}}(%esp)
+; GISEL-X86-NEXT:    fchs
+; GISEL-X86-NEXT:    retl
+;
 ; SSE-X86-LABEL: fneg_f32:
 ; SSE-X86:       # %bb.0:
 ; SSE-X86-NEXT:    pushl %eax
@@ -143,6 +149,15 @@ define void @fneg_f32_mem(ptr %x, ptr %y) nounwind {
 ; SDAG-X86-NEXT:    movl %edx, (%eax)
 ; SDAG-X86-NEXT:    retl
 ;
+; GISEL-X86-LABEL: fneg_f32_mem:
+; GISEL-X86:       # %bb.0:
+; GISEL-X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; GISEL-X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; GISEL-X86-NEXT:    flds (%eax)
+; GISEL-X86-NEXT:    fchs
+; GISEL-X86-NEXT:    fstps (%ecx)
+; GISEL-X86-NEXT:    retl
+;
 ; FASTISEL-SSE-X86-LABEL: fneg_f32_mem:
 ; FASTISEL-SSE-X86:       # %bb.0:
 ; FASTISEL-SSE-X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
@@ -161,6 +176,15 @@ define void @fneg_f32_mem(ptr %x, ptr %y) nounwind {
 ; SDAG-SSE-X86-NEXT:    movl %edx, (%eax)
 ; SDAG-SSE-X86-NEXT:    retl
 ;
+; GISEL-SSE-X86-LABEL: fneg_f32_mem:
+; GISEL-SSE-X86:       # %bb.0:
+; GISEL-SSE-X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; GISEL-SSE-X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; GISEL-SSE-X86-NEXT:    movl $-2147483648, %edx # imm = 0x80000000
+; GISEL-SSE-X86-NEXT:    xorl (%ecx), %edx
+; GISEL-SSE-X86-NEXT:    movl %edx, (%eax)
+; GISEL-SSE-X86-NEXT:    retl
+;
 ; FASTISEL-SSE-X64-LABEL: fneg_f32_mem:
 ; FASTISEL-SSE-X64:       # %bb.0:
 ; FASTISEL-SSE-X64-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero

@github-actions
Copy link

github-actions bot commented Nov 13, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

LegalizerHelper &Helper) const {
bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();
bool Is64Bit = Subtarget.is64Bit();
if (UseX87 && !Is64Bit && MI.getMF()->getFunction().getReturnType()->isFloatTy()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be doing anything with the context function

auto SrcReg = MI.getOperand(1).getReg();
auto ExtReg = MRI.createVirtualRegister(&X86::RFP80RegClass);
Helper.MIRBuilder.buildFPExt(ExtReg, SrcReg);
Helper.MIRBuilder.buildCopy(DstReg, ExtReg);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no fneg here

Copy link
Contributor Author

@JaydeepChauhan14 JaydeepChauhan14 Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To fix #162269 (comment) issue added these changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't follow. This is just broken

if (UseX87 && !Is64Bit && MI.getMF()->getFunction().getReturnType()->isFloatTy()) {
auto DstReg = MI.getOperand(0).getReg();
auto SrcReg = MI.getOperand(1).getReg();
auto ExtReg = MRI.createVirtualRegister(&X86::RFP80RegClass);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no auto

@JaydeepChauhan14 JaydeepChauhan14 marked this pull request as draft November 13, 2025 17:49
@JaydeepChauhan14 JaydeepChauhan14 marked this pull request as ready for review November 13, 2025 18:32
Comment on lines +1022 to +1028
Register ExtReg = MRI.createGenericVirtualRegister(S80);
Helper.MIRBuilder.buildFPExt(ExtReg, SrcReg);

Register NegReg = MRI.createGenericVirtualRegister(S80);
Helper.MIRBuilder.buildFNeg(NegReg, ExtReg);

Helper.MIRBuilder.buildFPTrunc(DstReg, NegReg);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is reimplementing ordinary promotion, this doesn't need to be custom tt

@JaydeepChauhan14 JaydeepChauhan14 marked this pull request as draft November 18, 2025 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants