LLVM currently represents floating-point negation as -0.0 - x. Fix

FastISel to recognize this pattern and emit a floating-point
negation using xor.

llvm-svn: 80963
This commit is contained in:
Dan Gohman 2009-09-03 22:53:57 +00:00
parent 1d5d245453
commit aa92dc1e61
3 changed files with 40 additions and 0 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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
}