Skip to content

Commit 0afcaf4

Browse files
[X86][GlobalISel] Added support for FNEG
1 parent 09122fe commit 0afcaf4

File tree

5 files changed

+170
-3
lines changed

5 files changed

+170
-3
lines changed

llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
126126
G_FSINCOS, G_FCEIL, G_FFLOOR})
127127
.libcall();
128128

129+
getActionDefinitionsBuilder(G_FNEG)
130+
.legalFor(UseX87 && !HasSSE1, {s32})
131+
.legalFor(UseX87 && !HasSSE2, {s64})
132+
.legalFor(UseX87, {s80})
133+
.customFor(UseX87 && !Is64Bit, {s32})
134+
.lowerFor({s32, s64});
135+
129136
getActionDefinitionsBuilder(G_FSQRT)
130137
.legalFor(HasSSE1 || UseX87, {s32})
131138
.legalFor(HasSSE2 || UseX87, {s64})
@@ -993,6 +1000,22 @@ bool X86LegalizerInfo::legalizeSETROUNDING(MachineInstr &MI,
9931000
return true;
9941001
}
9951002

1003+
bool X86LegalizerInfo::legalizeFNEG(MachineInstr &MI, MachineRegisterInfo &MRI,
1004+
LegalizerHelper &Helper) const {
1005+
bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();
1006+
bool Is64Bit = Subtarget.is64Bit();
1007+
if (UseX87 && !Is64Bit && MI.getMF()->getFunction().getReturnType()->isFloatTy()) {
1008+
auto DstReg = MI.getOperand(0).getReg();
1009+
auto SrcReg = MI.getOperand(1).getReg();
1010+
auto ExtReg = MRI.createVirtualRegister(&X86::RFP80RegClass);
1011+
Helper.MIRBuilder.buildFPExt(ExtReg, SrcReg);
1012+
Helper.MIRBuilder.buildCopy(DstReg, ExtReg);
1013+
MI.eraseFromParent();
1014+
return true;
1015+
}
1016+
return false;
1017+
}
1018+
9961019
bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
9971020
MachineInstr &MI) const {
9981021
return true;

llvm/lib/Target/X86/GISel/X86LegalizerInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ class X86LegalizerInfo : public LegalizerInfo {
6060

6161
bool legalizeSETROUNDING(MachineInstr &MI, MachineRegisterInfo &MRI,
6262
LegalizerHelper &Helper) const;
63+
64+
bool legalizeFNEG(MachineInstr &MI, MachineRegisterInfo &MRI,
65+
LegalizerHelper &Helper) const;
6366
};
6467
} // namespace llvm
6568
#endif

llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
292292
switch (Opc) {
293293
case TargetOpcode::G_FSQRT:
294294
case TargetOpcode::G_FPEXT:
295+
case TargetOpcode::G_FNEG:
295296
case TargetOpcode::G_FPTRUNC:
296297
case TargetOpcode::G_FCONSTANT:
297298
// Instruction having only floating-point operands (all scalars in
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
2+
# RUN: llc -mtriple=i686-linux-gnu -run-pass=regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes GISEL-I686
3+
4+
---
5+
name: fneg_f64
6+
alignment: 16
7+
legalized: true
8+
fixedStack:
9+
- { id: 0, type: default, offset: 0, size: 8, alignment: 16, stack-id: default,
10+
isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
11+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
12+
body: |
13+
bb.1:
14+
; GISEL-I686-LABEL: name: fneg_f64
15+
; GISEL-I686: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF
16+
; GISEL-I686-NEXT: [[CHS_Fp64_:%[0-9]+]]:rfp64 = CHS_Fp64 [[DEF]], implicit-def dead $fpsw
17+
; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp64_]]
18+
; GISEL-I686-NEXT: RET 0, implicit $fp0
19+
%1:_(p0) = G_FRAME_INDEX %fixed-stack.0
20+
%0:_(s64) = IMPLICIT_DEF
21+
%2:_(s64) = G_FNEG %0
22+
$fp0 = COPY %2(s64)
23+
RET 0, implicit $fp0
24+
...
25+
---
26+
name: fneg_f32
27+
alignment: 16
28+
legalized: true
29+
fixedStack:
30+
- { id: 0, type: default, offset: 0, size: 4, alignment: 16, stack-id: default,
31+
isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
32+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
33+
body: |
34+
bb.1:
35+
; GISEL-I686-LABEL: name: fneg_f32
36+
; 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)
37+
; GISEL-I686-NEXT: [[CHS_Fp32_:%[0-9]+]]:rfp32 = CHS_Fp32 [[LD_Fp32m]], implicit-def dead $fpsw
38+
; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp32_]]
39+
; GISEL-I686-NEXT: RET 0, implicit $fp0
40+
%1:_(p0) = G_FRAME_INDEX %fixed-stack.0
41+
%0:_(s32) = G_LOAD %1(p0) :: (invariant load (s32) from %fixed-stack.0, align 16)
42+
%2:_(s32) = G_FNEG %0
43+
$fp0 = COPY %2(s32)
44+
RET 0, implicit $fp0
45+
...
46+
---
47+
name: fneg_f64_mem
48+
alignment: 16
49+
legalized: true
50+
fixedStack:
51+
- { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
52+
isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
53+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
54+
- { id: 1, type: default, offset: 0, size: 4, alignment: 16, stack-id: default,
55+
isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
56+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
57+
body: |
58+
bb.1:
59+
; GISEL-I686-LABEL: name: fneg_f64_mem
60+
; GISEL-I686: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF
61+
; GISEL-I686-NEXT: [[CHS_Fp64_:%[0-9]+]]:rfp64 = CHS_Fp64 [[DEF]], implicit-def dead $fpsw
62+
; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp64_]]
63+
; GISEL-I686-NEXT: RET 0, implicit $fp0
64+
%1:_(p0) = G_FRAME_INDEX %fixed-stack.1
65+
%0:_(s64) = IMPLICIT_DEF
66+
%2:_(s64) = G_FNEG %0
67+
$fp0 = COPY %2(s64)
68+
RET 0, implicit $fp0
69+
...
70+
---
71+
name: fneg_f32_mem
72+
alignment: 16
73+
legalized: true
74+
fixedStack:
75+
- { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
76+
isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
77+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
78+
- { id: 1, type: default, offset: 0, size: 4, alignment: 16, stack-id: default,
79+
isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
80+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
81+
body: |
82+
bb.1:
83+
; GISEL-I686-LABEL: name: fneg_f32_mem
84+
; 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)
85+
; GISEL-I686-NEXT: [[CHS_Fp32_:%[0-9]+]]:rfp32 = CHS_Fp32 [[LD_Fp32m]], implicit-def dead $fpsw
86+
; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp32_]]
87+
; GISEL-I686-NEXT: RET 0, implicit $fp0
88+
%2:_(p0) = G_FRAME_INDEX %fixed-stack.1
89+
%0:_(p0) = G_LOAD %2(p0) :: (invariant load (p0) from %fixed-stack.1, align 16)
90+
%3:_(p0) = G_FRAME_INDEX %fixed-stack.0
91+
%1:_(s32) = G_LOAD %3(p0) :: (invariant load (p0) from %fixed-stack.0)
92+
%4:_(s32) = G_FNEG %1
93+
$fp0 = COPY %4(s32)
94+
RET 0, implicit $fp0
95+
...
96+
---
97+
name: test_fp80
98+
alignment: 16
99+
legalized: true
100+
fixedStack:
101+
- { id: 0, type: default, offset: 0, size: 10, alignment: 16, stack-id: default,
102+
isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
103+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
104+
body: |
105+
bb.1:
106+
; GISEL-I686-LABEL: name: test_fp80
107+
; 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)
108+
; GISEL-I686-NEXT: [[CHS_Fp80_:%[0-9]+]]:rfp80 = CHS_Fp80 [[LD_Fp80m]], implicit-def dead $fpsw
109+
; GISEL-I686-NEXT: $fp0 = COPY [[CHS_Fp80_]]
110+
; GISEL-I686-NEXT: RET 0, implicit $fp0
111+
%1:_(p0) = G_FRAME_INDEX %fixed-stack.0
112+
%0:_(s80) = G_LOAD %1(p0) :: (invariant load (s80) from %fixed-stack.0, align 16)
113+
%2:_(s80) = G_FNEG %0
114+
$fp0 = COPY %2(s80)
115+
RET 0, implicit $fp0
116+
...

llvm/test/CodeGen/X86/isel-fneg.ll

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
22
; RUN: llc < %s -mtriple=i686-linux-gnu -fast-isel | FileCheck %s --check-prefixes=X86,FASTISEL-X86
33
; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=0 -fast-isel=0 | FileCheck %s --check-prefixes=X86,SDAG-X86
4-
; DISABLED: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes=X86,GISEL-X86
4+
; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes=X86,GISEL-X86
55
; RUN: llc < %s -mtriple=i686-linux-gnu -fast-isel -mattr=+sse | FileCheck %s --check-prefixes=X86,SSE-X86,FASTISEL-SSE-X86
66
; 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
7-
; 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
7+
; 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
88
; RUN: llc < %s -mtriple=x86_64-linux-gnu -fast-isel -mattr=+sse | FileCheck %s --check-prefixes=X64,SSE-X64,FASTISEL-SSE-X64
99
; 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
10-
; 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
10+
; 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
1111

1212
define double @fneg_f64(double %x) nounwind {
1313
; X86-LABEL: fneg_f64:
@@ -53,6 +53,12 @@ define float @fneg_f32(float %x) nounwind {
5353
; SDAG-X86-NEXT: fchs
5454
; SDAG-X86-NEXT: retl
5555
;
56+
; GISEL-X86-LABEL: fneg_f32:
57+
; GISEL-X86: # %bb.0:
58+
; GISEL-X86-NEXT: flds {{[0-9]+}}(%esp)
59+
; GISEL-X86-NEXT: fchs
60+
; GISEL-X86-NEXT: retl
61+
;
5662
; SSE-X86-LABEL: fneg_f32:
5763
; SSE-X86: # %bb.0:
5864
; SSE-X86-NEXT: pushl %eax
@@ -143,6 +149,15 @@ define void @fneg_f32_mem(ptr %x, ptr %y) nounwind {
143149
; SDAG-X86-NEXT: movl %edx, (%eax)
144150
; SDAG-X86-NEXT: retl
145151
;
152+
; GISEL-X86-LABEL: fneg_f32_mem:
153+
; GISEL-X86: # %bb.0:
154+
; GISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %eax
155+
; GISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
156+
; GISEL-X86-NEXT: flds (%eax)
157+
; GISEL-X86-NEXT: fchs
158+
; GISEL-X86-NEXT: fstps (%ecx)
159+
; GISEL-X86-NEXT: retl
160+
;
146161
; FASTISEL-SSE-X86-LABEL: fneg_f32_mem:
147162
; FASTISEL-SSE-X86: # %bb.0:
148163
; FASTISEL-SSE-X86-NEXT: movl {{[0-9]+}}(%esp), %eax
@@ -161,6 +176,15 @@ define void @fneg_f32_mem(ptr %x, ptr %y) nounwind {
161176
; SDAG-SSE-X86-NEXT: movl %edx, (%eax)
162177
; SDAG-SSE-X86-NEXT: retl
163178
;
179+
; GISEL-SSE-X86-LABEL: fneg_f32_mem:
180+
; GISEL-SSE-X86: # %bb.0:
181+
; GISEL-SSE-X86-NEXT: movl {{[0-9]+}}(%esp), %eax
182+
; GISEL-SSE-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
183+
; GISEL-SSE-X86-NEXT: movl $-2147483648, %edx # imm = 0x80000000
184+
; GISEL-SSE-X86-NEXT: xorl (%ecx), %edx
185+
; GISEL-SSE-X86-NEXT: movl %edx, (%eax)
186+
; GISEL-SSE-X86-NEXT: retl
187+
;
164188
; FASTISEL-SSE-X64-LABEL: fneg_f32_mem:
165189
; FASTISEL-SSE-X64: # %bb.0:
166190
; FASTISEL-SSE-X64-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero

0 commit comments

Comments
 (0)