diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index b2cc94db4e5..6cd551976c4 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -300,6 +300,8 @@ protected: private: bool SelectBinaryOp(User *I, ISD::NodeType ISDOpcode); + bool SelectFNeg(User *I); + bool SelectGetElementPtr(User *I); bool SelectCall(User *I); diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 5b4c79a9fd9..f0c70861843 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -608,6 +608,26 @@ FastISel::FastEmitBranch(MachineBasicBlock *MSucc) { MBB->addSuccessor(MSucc); } +/// SelectFNeg - Emit an FNeg operation. +/// +bool +FastISel::SelectFNeg(User *I) { + unsigned OpReg = getRegForValue(BinaryOperator::getFNegArgument(I)); + if (OpReg == 0) return false; + + // Twiddle the sign bit with xor. + EVT VT = TLI.getValueType(I->getType()); + if (VT.getSizeInBits() > 64) return false; + unsigned ResultReg = FastEmit_ri_(VT.getSimpleVT(), ISD::XOR, OpReg, + UINT64_C(1) << (VT.getSizeInBits()-1), + VT.getSimpleVT()); + if (ResultReg == 0) + return false; + + UpdateValueMap(I, ResultReg); + return true; +} + bool FastISel::SelectOperator(User *I, unsigned Opcode) { switch (Opcode) { @@ -618,6 +638,9 @@ FastISel::SelectOperator(User *I, unsigned Opcode) { case Instruction::Sub: return SelectBinaryOp(I, ISD::SUB); case Instruction::FSub: + // FNeg is currently represented in LLVM IR as a special case of FSub. + if (BinaryOperator::isFNeg(I)) + return SelectFNeg(I); return SelectBinaryOp(I, ISD::FSUB); case Instruction::Mul: return SelectBinaryOp(I, ISD::MUL); diff --git a/test/CodeGen/X86/fast-isel-fneg.ll b/test/CodeGen/X86/fast-isel-fneg.ll new file mode 100644 index 00000000000..41b288ba1de --- /dev/null +++ b/test/CodeGen/X86/fast-isel-fneg.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as < %s | llc -fast-isel -march=x86-64 | FileCheck %s + +; CHECK: doo: +; CHECK: xorpd +define double @doo(double %x) nounwind { + %y = fsub double -0.0, %x + ret double %y +} + +; CHECK: foo: +; CHECK: xorps +define float @foo(float %x) nounwind { + %y = fsub float -0.0, %x + ret float %y +}