forked from OSchip/llvm-project
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:
parent
1d5d245453
commit
aa92dc1e61
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue