diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-02-21 13:51:43 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-02-21 13:51:43 +0000 |
commit | 3f4bde29a30d8c43db5cbe8f5541ebc5d1fdc6af (patch) | |
tree | 87140683fc3fee4e14b3c37e2aa7a4031d473f49 /lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | |
parent | a322a4af1fe8b989fe5d1bbc15de8736a26c03ca (diff) |
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeDAG.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 5d572c4c2b02..f7836345f720 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1637,6 +1637,7 @@ struct FloatSignAsInt { MachinePointerInfo FloatPointerInfo; SDValue IntValue; APInt SignMask; + uint8_t SignBit; }; } @@ -1653,6 +1654,7 @@ void SelectionDAGLegalize::getSignAsIntValue(FloatSignAsInt &State, if (TLI.isTypeLegal(IVT)) { State.IntValue = DAG.getNode(ISD::BITCAST, DL, IVT, Value); State.SignMask = APInt::getSignBit(NumBits); + State.SignBit = NumBits - 1; return; } @@ -1689,6 +1691,7 @@ void SelectionDAGLegalize::getSignAsIntValue(FloatSignAsInt &State, IntPtr, State.IntPointerInfo, MVT::i8, false, false, false, 0); State.SignMask = APInt::getOneBitSet(LoadTy.getSizeInBits(), 7); + State.SignBit = 7; } /// Replace the integer value produced by getSignAsIntValue() with a new value @@ -1731,15 +1734,38 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode *Node) const { return DAG.getSelect(DL, FloatVT, Cond, NegValue, AbsValue); } - // Transform values to integer, copy the sign bit and transform back. + // Transform Mag value to integer, and clear the sign bit. FloatSignAsInt MagAsInt; getSignAsIntValue(MagAsInt, DL, Mag); - assert(SignAsInt.SignMask == MagAsInt.SignMask); - SDValue ClearSignMask = DAG.getConstant(~SignAsInt.SignMask, DL, IntVT); - SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, MagAsInt.IntValue, + EVT MagVT = MagAsInt.IntValue.getValueType(); + SDValue ClearSignMask = DAG.getConstant(~MagAsInt.SignMask, DL, MagVT); + SDValue ClearedSign = DAG.getNode(ISD::AND, DL, MagVT, MagAsInt.IntValue, ClearSignMask); - SDValue CopiedSign = DAG.getNode(ISD::OR, DL, IntVT, ClearedSign, SignBit); + // Get the signbit at the right position for MagAsInt. + int ShiftAmount = SignAsInt.SignBit - MagAsInt.SignBit; + if (SignBit.getValueSizeInBits() > ClearedSign.getValueSizeInBits()) { + if (ShiftAmount > 0) { + SDValue ShiftCnst = DAG.getConstant(ShiftAmount, DL, IntVT); + SignBit = DAG.getNode(ISD::SRL, DL, IntVT, SignBit, ShiftCnst); + } else if (ShiftAmount < 0) { + SDValue ShiftCnst = DAG.getConstant(-ShiftAmount, DL, IntVT); + SignBit = DAG.getNode(ISD::SHL, DL, IntVT, SignBit, ShiftCnst); + } + SignBit = DAG.getNode(ISD::TRUNCATE, DL, MagVT, SignBit); + } else if (SignBit.getValueSizeInBits() < ClearedSign.getValueSizeInBits()) { + SignBit = DAG.getNode(ISD::ZERO_EXTEND, DL, MagVT, SignBit); + if (ShiftAmount > 0) { + SDValue ShiftCnst = DAG.getConstant(ShiftAmount, DL, MagVT); + SignBit = DAG.getNode(ISD::SRL, DL, MagVT, SignBit, ShiftCnst); + } else if (ShiftAmount < 0) { + SDValue ShiftCnst = DAG.getConstant(-ShiftAmount, DL, MagVT); + SignBit = DAG.getNode(ISD::SHL, DL, MagVT, SignBit, ShiftCnst); + } + } + + // Store the part with the modified sign and convert back to float. + SDValue CopiedSign = DAG.getNode(ISD::OR, DL, MagVT, ClearedSign, SignBit); return modifySignAsInt(MagAsInt, DL, CopiedSign); } |