mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:29:58 +00:00
[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:
parent
3d93ea76e7
commit
887733c790
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user