Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand Down Expand Up @@ -623,6 +630,8 @@ bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
return legalizeGETROUNDING(MI, MRI, Helper);
case TargetOpcode::G_SET_ROUNDING:
return legalizeSETROUNDING(MI, MRI, Helper);
case TargetOpcode::G_FNEG:
return legalizeFNEG(MI, MRI, Helper);
}
llvm_unreachable("expected switch to return");
}
Expand Down Expand Up @@ -993,6 +1002,35 @@ 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))
return false;

Register DstReg = MI.getOperand(0).getReg();
Register SrcReg = MI.getOperand(1).getReg();

LLT S32 = LLT::scalar(32);
LLT S80 = LLT::scalar(80);

if (MRI.getType(SrcReg) != S32 || MRI.getType(DstReg) != S32)
return false;

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);
Comment on lines +1022 to +1028
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


MI.eraseFromParent();
return true;
}

bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
MachineInstr &MI) const {
return true;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
116 changes: 116 additions & 0 deletions llvm/test/CodeGen/X86/GlobalISel/isel-fneg.mir
Original file line number Diff line number Diff line change
@@ -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
...
30 changes: 27 additions & 3 deletions llvm/test/CodeGen/X86/isel-fneg.ll
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading