@@ -59,6 +59,20 @@ using namespace llvm;
5959
6060namespace {
6161
62+ // / Keeps track of state when getting the sign of a floating-point value as an
63+ // / integer.
64+ struct FloatSignAsInt {
65+ EVT FloatVT;
66+ SDValue Chain;
67+ SDValue FloatPtr;
68+ SDValue IntPtr;
69+ MachinePointerInfo IntPointerInfo;
70+ MachinePointerInfo FloatPointerInfo;
71+ SDValue IntValue;
72+ APInt SignMask;
73+ uint8_t SignBit;
74+ };
75+
6276// ===----------------------------------------------------------------------===//
6377// / This takes an arbitrary SelectionDAG as input and
6478// / hacks on it until the target machine can handle it. This involves
@@ -152,6 +166,10 @@ class SelectionDAGLegalize {
152166 SDValue ExpandSCALAR_TO_VECTOR (SDNode *Node);
153167 void ExpandDYNAMIC_STACKALLOC (SDNode *Node,
154168 SmallVectorImpl<SDValue> &Results);
169+ void getSignAsIntValue (FloatSignAsInt &State, const SDLoc &DL,
170+ SDValue Value) const ;
171+ SDValue modifySignAsInt (const FloatSignAsInt &State, const SDLoc &DL,
172+ SDValue NewIntValue) const ;
155173 SDValue ExpandFCOPYSIGN (SDNode *Node) const ;
156174 SDValue ExpandFABS (SDNode *Node) const ;
157175 SDValue ExpandFNEG (SDNode *Node) const ;
@@ -1602,14 +1620,82 @@ SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) {
16021620 return DAG.getLoad (VT, dl, StoreChain, FIPtr, PtrInfo);
16031621}
16041622
1623+ // / Bitcast a floating-point value to an integer value. Only bitcast the part
1624+ // / containing the sign bit if the target has no integer value capable of
1625+ // / holding all bits of the floating-point value.
1626+ void SelectionDAGLegalize::getSignAsIntValue (FloatSignAsInt &State,
1627+ const SDLoc &DL,
1628+ SDValue Value) const {
1629+ EVT FloatVT = Value.getValueType ();
1630+ unsigned NumBits = FloatVT.getScalarSizeInBits ();
1631+ State.FloatVT = FloatVT;
1632+ EVT IVT = EVT::getIntegerVT (*DAG.getContext (), NumBits);
1633+ // Convert to an integer of the same size.
1634+ if (TLI.isTypeLegal (IVT)) {
1635+ State.IntValue = DAG.getNode (ISD::BITCAST, DL, IVT, Value);
1636+ State.SignMask = APInt::getSignMask (NumBits);
1637+ State.SignBit = NumBits - 1 ;
1638+ return ;
1639+ }
1640+
1641+ auto &DataLayout = DAG.getDataLayout ();
1642+ // Store the float to memory, then load the sign part out as an integer.
1643+ MVT LoadTy = TLI.getRegisterType (MVT::i8 );
1644+ // First create a temporary that is aligned for both the load and store.
1645+ SDValue StackPtr = DAG.CreateStackTemporary (FloatVT, LoadTy);
1646+ int FI = cast<FrameIndexSDNode>(StackPtr.getNode ())->getIndex ();
1647+ // Then store the float to it.
1648+ State.FloatPtr = StackPtr;
1649+ MachineFunction &MF = DAG.getMachineFunction ();
1650+ State.FloatPointerInfo = MachinePointerInfo::getFixedStack (MF, FI);
1651+ State.Chain = DAG.getStore (DAG.getEntryNode (), DL, Value, State.FloatPtr ,
1652+ State.FloatPointerInfo );
1653+
1654+ SDValue IntPtr;
1655+ if (DataLayout.isBigEndian ()) {
1656+ assert (FloatVT.isByteSized () && " Unsupported floating point type!" );
1657+ // Load out a legal integer with the same sign bit as the float.
1658+ IntPtr = StackPtr;
1659+ State.IntPointerInfo = State.FloatPointerInfo ;
1660+ } else {
1661+ // Advance the pointer so that the loaded byte will contain the sign bit.
1662+ unsigned ByteOffset = (NumBits / 8 ) - 1 ;
1663+ IntPtr =
1664+ DAG.getMemBasePlusOffset (StackPtr, TypeSize::getFixed (ByteOffset), DL);
1665+ State.IntPointerInfo = MachinePointerInfo::getFixedStack (MF, FI,
1666+ ByteOffset);
1667+ }
1668+
1669+ State.IntPtr = IntPtr;
1670+ State.IntValue = DAG.getExtLoad (ISD::EXTLOAD, DL, LoadTy, State.Chain , IntPtr,
1671+ State.IntPointerInfo , MVT::i8 );
1672+ State.SignMask = APInt::getOneBitSet (LoadTy.getScalarSizeInBits (), 7 );
1673+ State.SignBit = 7 ;
1674+ }
1675+
1676+ // / Replace the integer value produced by getSignAsIntValue() with a new value
1677+ // / and cast the result back to a floating-point type.
1678+ SDValue SelectionDAGLegalize::modifySignAsInt (const FloatSignAsInt &State,
1679+ const SDLoc &DL,
1680+ SDValue NewIntValue) const {
1681+ if (!State.Chain )
1682+ return DAG.getNode (ISD::BITCAST, DL, State.FloatVT , NewIntValue);
1683+
1684+ // Override the part containing the sign bit in the value stored on the stack.
1685+ SDValue Chain = DAG.getTruncStore (State.Chain , DL, NewIntValue, State.IntPtr ,
1686+ State.IntPointerInfo , MVT::i8 );
1687+ return DAG.getLoad (State.FloatVT , DL, Chain, State.FloatPtr ,
1688+ State.FloatPointerInfo );
1689+ }
1690+
16051691SDValue SelectionDAGLegalize::ExpandFCOPYSIGN (SDNode *Node) const {
16061692 SDLoc DL (Node);
16071693 SDValue Mag = Node->getOperand (0 );
16081694 SDValue Sign = Node->getOperand (1 );
16091695
16101696 // Get sign bit into an integer value.
16111697 FloatSignAsInt SignAsInt;
1612- DAG. getSignAsIntValue (SignAsInt, DL, Sign);
1698+ getSignAsIntValue (SignAsInt, DL, Sign);
16131699
16141700 EVT IntVT = SignAsInt.IntValue .getValueType ();
16151701 SDValue SignMask = DAG.getConstant (SignAsInt.SignMask , DL, IntVT);
@@ -1630,7 +1716,7 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode *Node) const {
16301716
16311717 // Transform Mag value to integer, and clear the sign bit.
16321718 FloatSignAsInt MagAsInt;
1633- DAG. getSignAsIntValue (MagAsInt, DL, Mag);
1719+ getSignAsIntValue (MagAsInt, DL, Mag);
16341720 EVT MagVT = MagAsInt.IntValue .getValueType ();
16351721 SDValue ClearSignMask = DAG.getConstant (~MagAsInt.SignMask , DL, MagVT);
16361722 SDValue ClearedSign = DAG.getNode (ISD::AND, DL, MagVT, MagAsInt.IntValue ,
@@ -1660,14 +1746,14 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode *Node) const {
16601746 SDValue CopiedSign = DAG.getNode (ISD::OR, DL, MagVT, ClearedSign, SignBit,
16611747 SDNodeFlags::Disjoint);
16621748
1663- return DAG. modifySignAsInt (MagAsInt, DL, CopiedSign);
1749+ return modifySignAsInt (MagAsInt, DL, CopiedSign);
16641750}
16651751
16661752SDValue SelectionDAGLegalize::ExpandFNEG (SDNode *Node) const {
16671753 // Get the sign bit as an integer.
16681754 SDLoc DL (Node);
16691755 FloatSignAsInt SignAsInt;
1670- DAG. getSignAsIntValue (SignAsInt, DL, Node->getOperand (0 ));
1756+ getSignAsIntValue (SignAsInt, DL, Node->getOperand (0 ));
16711757 EVT IntVT = SignAsInt.IntValue .getValueType ();
16721758
16731759 // Flip the sign.
@@ -1676,7 +1762,7 @@ SDValue SelectionDAGLegalize::ExpandFNEG(SDNode *Node) const {
16761762 DAG.getNode (ISD::XOR, DL, IntVT, SignAsInt.IntValue , SignMask);
16771763
16781764 // Convert back to float.
1679- return DAG. modifySignAsInt (SignAsInt, DL, SignFlip);
1765+ return modifySignAsInt (SignAsInt, DL, SignFlip);
16801766}
16811767
16821768SDValue SelectionDAGLegalize::ExpandFABS (SDNode *Node) const {
@@ -1692,12 +1778,12 @@ SDValue SelectionDAGLegalize::ExpandFABS(SDNode *Node) const {
16921778
16931779 // Transform value to integer, clear the sign bit and transform back.
16941780 FloatSignAsInt ValueAsInt;
1695- DAG. getSignAsIntValue (ValueAsInt, DL, Value);
1781+ getSignAsIntValue (ValueAsInt, DL, Value);
16961782 EVT IntVT = ValueAsInt.IntValue .getValueType ();
16971783 SDValue ClearSignMask = DAG.getConstant (~ValueAsInt.SignMask , DL, IntVT);
16981784 SDValue ClearedSign = DAG.getNode (ISD::AND, DL, IntVT, ValueAsInt.IntValue ,
16991785 ClearSignMask);
1700- return DAG. modifySignAsInt (ValueAsInt, DL, ClearedSign);
1786+ return modifySignAsInt (ValueAsInt, DL, ClearedSign);
17011787}
17021788
17031789void SelectionDAGLegalize::ExpandDYNAMIC_STACKALLOC (SDNode* Node,
0 commit comments