[FastISel][X86] If selectFNeg fails, fall back to SelectionDAG not treating it as an fsub.

Summary:
If fneg lowering for fsub -0.0, x fails we currently fall back to treating it as an fsub. This has different behavior for nans than the xor with sign bit trick we normally try to do. On X86, the xor trick for double fails fast-isel in 32-bit mode with sse2 due to 64 bit integer types not being available. With -O2 we would always use an xorpd for this case. If we use subsd, this creates an observable behavior difference between -O0 and -O2. So fall back to SelectionDAG if we can't fast-isel it, that way SelectionDAG will use the xorpd.

I believe this patch is restoring the behavior prior to r345295 from last October. This was missed then because our fast isel case in 32-bit mode aborted fast-isel earlier for another reason. But I've added new tests to cover that.

Reviewers: andrew.w.kaylor, cameron.mcinally, spatel, efriedma

Reviewed By: cameron.mcinally

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D61622

llvm-svn: 360111
This commit is contained in:
Craig Topper 2019-05-07 04:25:24 +00:00
parent 3d93ea76e7
commit 887733c790
3 changed files with 12 additions and 11 deletions

View File

@ -527,7 +527,7 @@ protected:
/// Select and emit code for a binary operator instruction, which has
/// an opcode which directly corresponds to the given ISD opcode.
bool selectBinaryOp(const User *I, unsigned ISDOpcode);
bool selectFNeg(const User *I);
bool selectFNeg(const User *I, const Value *In);
bool selectGetElementPtr(const User *I);
bool selectStackmap(const CallInst *I);
bool selectPatchpoint(const CallInst *I);

View File

@ -1712,14 +1712,11 @@ void FastISel::finishCondBranch(const BasicBlock *BranchBB,
}
/// Emit an FNeg operation.
bool FastISel::selectFNeg(const User *I) {
Value *X;
if (!match(I, m_FNeg(m_Value(X))))
return false;
unsigned OpReg = getRegForValue(X);
bool FastISel::selectFNeg(const User *I, const Value *In) {
unsigned OpReg = getRegForValue(In);
if (!OpReg)
return false;
bool OpRegIsKill = hasTrivialKill(X);
bool OpRegIsKill = hasTrivialKill(In);
// If the target has ISD::FNEG, use it.
EVT VT = TLI.getValueType(DL, I->getType());
@ -1806,9 +1803,13 @@ bool FastISel::selectOperator(const User *I, unsigned Opcode) {
return selectBinaryOp(I, ISD::FADD);
case Instruction::Sub:
return selectBinaryOp(I, ISD::SUB);
case Instruction::FSub:
case Instruction::FSub: {
// FNeg is currently represented in LLVM IR as a special case of FSub.
return selectFNeg(I) || selectBinaryOp(I, ISD::FSUB);
Value *X;
if (match(I, m_FNeg(m_Value(X))))
return selectFNeg(I, X);
return selectBinaryOp(I, ISD::FSUB);
}
case Instruction::Mul:
return selectBinaryOp(I, ISD::MUL);
case Instruction::FMul:

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -fast-isel -fast-isel-abort=3 -mtriple=x86_64-apple-darwin10 | FileCheck %s
; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=i686-- -mattr=+sse2 | FileCheck --check-prefix=SSE2 %s
; RUN: llc < %s -fast-isel -mtriple=i686-- -mattr=+sse2 | FileCheck --check-prefix=SSE2 %s
define double @doo(double %x) nounwind {
; CHECK-LABEL: doo:
@ -65,7 +65,7 @@ define void @goo(double* %x, double* %y) nounwind {
; SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax
; SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx
; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
; SSE2-NEXT: subsd (%ecx), %xmm0
; SSE2-NEXT: xorps {{\.LCPI.*}}, %xmm0
; SSE2-NEXT: movsd %xmm0, (%eax)
; SSE2-NEXT: retl
%a = load double, double* %x