diff options
author | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2015-01-07 17:33:03 +0000 |
---|---|---|
committer | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2015-01-07 17:33:03 +0000 |
commit | d412c608fcaee75a08160bcf4646257af9f82466 (patch) | |
tree | 357e7670b736c8f1fecd2a96ce4f794ad221bb5d /lib/Target/X86/X86ISelLowering.cpp | |
parent | 1763c0ad7f5cfb773213c39261f5664683219c3e (diff) | |
download | llvm-d412c608fcaee75a08160bcf4646257af9f82466.tar.gz |
[X86] Teach FCOPYSIGN lowering to recognize constant magnitudes.
For code like:
float foo(float x) { return copysign(1.0, x); }
We used to generate:
andps <-0.000000e+00,0,0,0>, %xmm0
movss <1.000000e+00>, %xmm1
andps <nan>, %xmm1
orps %xmm0, %xmm1
Basically doing an abs(1.0f) in the two middle instructions.
We now generate:
andps <-0.000000e+00,0,0,0>, %xmm0
orps <1.000000e+00,0,0,0>, %xmm0
Builds on cleanups r223415, r223542.
rdar://19049548
Differential Revision: http://reviews.llvm.org/D6555
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225357 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 98935890d36..57fedb8f387 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -14530,14 +14530,27 @@ static SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) { SDValue SignBit = DAG.getNode(X86ISD::FAND, dl, SrcVT, Op1, Mask1); // Next, clear the sign bit from the first operand (magnitude). - CV[0] = ConstantFP::get( - *Context, APFloat(Sem, APInt::getLowBitsSet(SizeInBits, SizeInBits - 1))); + // If it's a constant, we can clear it here. + if (ConstantFPSDNode *Op0CN = dyn_cast<ConstantFPSDNode>(Op0)) { + APFloat APF = Op0CN->getValueAPF(); + // If the magnitude is a positive zero, the sign bit alone is enough. + if (APF.isPosZero()) + return SignBit; + APF.clearSign(); + CV[0] = ConstantFP::get(*Context, APF); + } else { + CV[0] = ConstantFP::get( + *Context, + APFloat(Sem, APInt::getLowBitsSet(SizeInBits, SizeInBits - 1))); + } C = ConstantVector::get(CV); CPIdx = DAG.getConstantPool(C, TLI.getPointerTy(), 16); - SDValue Mask2 = DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, - MachinePointerInfo::getConstantPool(), - false, false, false, 16); - SDValue Val = DAG.getNode(X86ISD::FAND, dl, VT, Op0, Mask2); + SDValue Val = DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, + MachinePointerInfo::getConstantPool(), + false, false, false, 16); + // If the magnitude operand wasn't a constant, we need to AND out the sign. + if (!isa<ConstantFPSDNode>(Op0)) + Val = DAG.getNode(X86ISD::FAND, dl, VT, Op0, Val); // OR the magnitude value with the sign bit. return DAG.getNode(X86ISD::FOR, dl, VT, Val, SignBit); |