diff --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp index 3090ad313b90d..9b0dd0562cde3 100644 --- a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp +++ b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp @@ -95,6 +95,8 @@ class X86InstructionSelector : public InstructionSelector { MachineFunction &MF) const; bool selectFCmp(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; + bool selectFAbs(MachineInstr &I, MachineRegisterInfo &MRI, + MachineFunction &MF) const; bool selectUAddSub(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; bool selectDebugInstr(MachineInstr &I, MachineRegisterInfo &MRI) const; @@ -391,6 +393,8 @@ bool X86InstructionSelector::select(MachineInstr &I) { switch (I.getOpcode()) { default: return false; + case TargetOpcode::G_FABS: + return selectFAbs(I, MRI, MF); case TargetOpcode::G_STORE: case TargetOpcode::G_LOAD: return selectLoadStoreOp(I, MRI, MF); @@ -1050,6 +1054,35 @@ bool X86InstructionSelector::selectCmp(MachineInstr &I, I.eraseFromParent(); return true; } +bool X86InstructionSelector::selectFAbs(MachineInstr &I, + MachineRegisterInfo &MRI, + MachineFunction &MF) const { + assert((I.getOpcode() == TargetOpcode::G_FABS) && "unexpected instruction"); + Register SrcReg = I.getOperand(1).getReg(); + Register DstReg = I.getOperand(0).getReg(); + LLT Ty = MRI.getType(SrcReg); + unsigned OpAbs; + const TargetRegisterClass *DstRC; + switch (Ty.getSizeInBits()) { + default: + return false; + case 32: + OpAbs = X86::ABS_Fp32; + DstRC = &X86::FR32RegClass; + break; + case 64: + OpAbs = X86::ABS_Fp64; + DstRC = &X86::FR64RegClass; + break; + } + MRI.setRegClass(DstReg, DstRC); + MachineInstr &FAbsInst = + *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpAbs), DstReg) + .addReg(SrcReg); + constrainSelectedInstRegOperands(FAbsInst, TII, TRI, RBI); + I.eraseFromParent(); + return true; +} bool X86InstructionSelector::selectFCmp(MachineInstr &I, MachineRegisterInfo &MRI, diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp index 7a3650f0c5898..0250ec66c0b99 100644 --- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp @@ -418,6 +418,10 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, .legalFor(HasAVX512, {v16s32, v8s64}) .legalFor(UseX87, {s80}); + getActionDefinitionsBuilder(G_FABS) + .legalFor(UseX87 && !HasSSE2 && !HasSSE1, {s64, s80}) + .lower(); + // fp comparison getActionDefinitionsBuilder(G_FCMP) .legalFor(HasSSE1 || UseX87, {s8, s32}) diff --git a/llvm/test/CodeGen/X86/isel-fabs-x87.ll b/llvm/test/CodeGen/X86/isel-fabs-x87.ll index 8b846499946cc..a0534e6a1a82e 100644 --- a/llvm/test/CodeGen/X86/isel-fabs-x87.ll +++ b/llvm/test/CodeGen/X86/isel-fabs-x87.ll @@ -1,8 +1,48 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 ; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse2,-sse | FileCheck %s --check-prefixes=X64 -; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse2,-sse -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefixes=X64 -; RUN: llc < %s -mtriple=i686-- -mattr=+x87,-sse2,-sse | FileCheck %s --check-prefixes=X86 -; RUN: llc < %s -mtriple=i686-- -mattr=+x87,-sse2,-sse -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefixes=X86 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse2,-sse -fast-isel | FileCheck %s --check-prefixes=X64 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse2,-sse -global-isel -global-isel-abort=1 | FileCheck %s --check-prefixes=X64 +; RUN: llc < %s -mtriple=i686-- -mattr=+x87,-sse2,-sse | FileCheck %s --check-prefixes=X86,SDAG-ISEL +; RUN: llc < %s -mtriple=i686-- -mattr=+x87,-sse2,-sse -fast-isel | FileCheck %s --check-prefixes=X86,Fast-ISEL +; RUN: llc < %s -mtriple=i686-- -mattr=+x87,-sse2,-sse -global-isel -global-isel-abort=0 | FileCheck %s --check-prefixes=X86,GISEL-ISEL + +define void @test_float_abs(ptr %argptr) { +; SDAG-ISEL-LABEL: test_float_abs: +; SDAG-ISEL: # %bb.0: +; SDAG-ISEL-NEXT: movl {{[0-9]+}}(%esp), %eax +; SDAG-ISEL-NEXT: andb $127, 3(%eax) +; SDAG-ISEL-NEXT: retl +; +; Fast-ISEL-LABEL: test_float_abs: +; Fast-ISEL: # %bb.0: +; Fast-ISEL-NEXT: movl {{[0-9]+}}(%esp), %eax +; Fast-ISEL-NEXT: andb $127, 3(%eax) +; Fast-ISEL-NEXT: retl +; +; GISEL-ISEL-LABEL: test_float_abs: +; GISEL-ISEL: # %bb.0: +; GISEL-ISEL-NEXT: movl {{[0-9]+}}(%esp), %eax +; GISEL-ISEL-NEXT: andl $2147483647, (%eax) # imm = 0x7FFFFFFF +; GISEL-ISEL-NEXT: retl + %arg = load float, float* %argptr + %abs = tail call float @llvm.fabs.f32(float %arg) + store float %abs, ptr %argptr + ret void + } + +define void @test_double_abs(ptr %argptr) { +; X86-LABEL: test_double_abs: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: fldl (%eax) +; X86-NEXT: fabs +; X86-NEXT: fstpl (%eax) +; X86-NEXT: retl + %arg = load double, double* %argptr + %abs = tail call double @llvm.fabs.f64(double %arg) + store double %abs, double* %argptr + ret void +} define x86_fp80 @test_x86_fp80_abs(x86_fp80 %arg) { ; X64-LABEL: test_x86_fp80_abs: diff --git a/llvm/test/CodeGen/X86/isel-fabs.ll b/llvm/test/CodeGen/X86/isel-fabs.ll index 10bd5799280ad..c2d29248e49ba 100644 --- a/llvm/test/CodeGen/X86/isel-fabs.ll +++ b/llvm/test/CodeGen/X86/isel-fabs.ll @@ -1,37 +1,61 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 -; RUN: llc < %s -mtriple=x86_64-- -mattr=-x87 | FileCheck %s --check-prefixes=X64 -; RUN: llc < %s -mtriple=x86_64-- -mattr=-x87 -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefixes=X64 -; RUN: llc < %s -mtriple=i686-- -mattr=-x87 | FileCheck %s --check-prefixes=X86 -; RUN: llc < %s -mtriple=i686-- -mattr=-x87 -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefixes=FASTISEL-X86 +; RUN: llc < %s -mtriple=x86_64-- -mattr=-x87,+sse,+sse2 | FileCheck %s --check-prefixes=X64 +; RUN: llc < %s -mtriple=x86_64-- -mattr=-x87,+sse,+sse2 -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefixes=X64 +; RUN: llc < %s -mtriple=x86_64-- -mattr=-x87,+sse,+sse2 -global-isel -global-isel-abort=1 | FileCheck %s --check-prefixes=GISEL-X64 +; RUN: llc < %s -mtriple=i686-- -mattr=-x87,+sse,+sse2 | FileCheck %s --check-prefixes=X86 +; RUN: llc < %s -mtriple=i686-- -mattr=-x87,+sse,+sse2 -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefixes=FASTISEL-X86 +; RUN: llc < %s -mtriple=i686-- -mattr=-x87,+sse,+sse2 -global-isel -global-isel-abort=1 | FileCheck %s --check-prefixes=GISEL-X86 - -define float @test_float_abs(float %arg) { +define float @test_float_abs(float %arg) nounwind { ; X64-LABEL: test_float_abs: ; X64: # %bb.0: ; X64-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; X64-NEXT: retq ; +; GISEL-X64-LABEL: test_float_abs: +; GISEL-X64: # %bb.0: +; GISEL-X64-NEXT: movd %xmm0, %eax +; GISEL-X64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF +; GISEL-X64-NEXT: movd %eax, %xmm0 +; GISEL-X64-NEXT: retq +; ; X86-LABEL: test_float_abs: ; X86: # %bb.0: -; X86-NEXT: movl $2147483647, %eax # imm = 0x7FFFFFFF -; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero +; X86-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 +; X86-NEXT: movd %xmm0, %eax ; X86-NEXT: retl ; ; FASTISEL-X86-LABEL: test_float_abs: ; FASTISEL-X86: # %bb.0: -; FASTISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; FASTISEL-X86-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF +; FASTISEL-X86-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero +; FASTISEL-X86-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 +; FASTISEL-X86-NEXT: movd %xmm0, %eax ; FASTISEL-X86-NEXT: retl +; +; GISEL-X86-LABEL: test_float_abs: +; GISEL-X86: # %bb.0: +; GISEL-X86-NEXT: movl $2147483647, %eax # imm = 0x7FFFFFFF +; GISEL-X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: retl %abs = tail call float @llvm.fabs.f32(float %arg) ret float %abs } -define double @test_double_abs(double %arg) { +define double @test_double_abs(double %arg) nounwind { ; X64-LABEL: test_double_abs: ; X64: # %bb.0: ; X64-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; X64-NEXT: retq ; +; GISEL-X64-LABEL: test_double_abs: +; GISEL-X64: # %bb.0: +; GISEL-X64-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF +; GISEL-X64-NEXT: movq %xmm0, %rcx +; GISEL-X64-NEXT: andq %rax, %rcx +; GISEL-X64-NEXT: movq %rcx, %xmm0 +; GISEL-X64-NEXT: retq +; ; X86-LABEL: test_double_abs: ; X86: # %bb.0: ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax @@ -41,10 +65,26 @@ define double @test_double_abs(double %arg) { ; ; FASTISEL-X86-LABEL: test_double_abs: ; FASTISEL-X86: # %bb.0: +; FASTISEL-X86-NEXT: pushl %ebp +; FASTISEL-X86-NEXT: movl %esp, %ebp +; FASTISEL-X86-NEXT: andl $-8, %esp +; FASTISEL-X86-NEXT: subl $8, %esp +; FASTISEL-X86-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero +; FASTISEL-X86-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 +; FASTISEL-X86-NEXT: movlps %xmm0, (%esp) +; FASTISEL-X86-NEXT: movl (%esp), %eax ; FASTISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; FASTISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; FASTISEL-X86-NEXT: andl $2147483647, %edx # imm = 0x7FFFFFFF +; FASTISEL-X86-NEXT: movl %ebp, %esp +; FASTISEL-X86-NEXT: popl %ebp ; FASTISEL-X86-NEXT: retl +; +; GISEL-X86-LABEL: test_double_abs: +; GISEL-X86: # %bb.0: +; GISEL-X86-NEXT: movl $-1, %eax +; GISEL-X86-NEXT: movl $2147483647, %edx # imm = 0x7FFFFFFF +; GISEL-X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: andl {{[0-9]+}}(%esp), %edx +; GISEL-X86-NEXT: retl %abs = tail call double @llvm.fabs.f64(double %arg) ret double %abs }