@@ -39,6 +39,10 @@ using namespace llvm;
39
39
40
40
#define DEBUG_TYPE " legalizedag"
41
41
42
+ namespace {
43
+
44
+ struct FloatSignAsInt ;
45
+
42
46
// ===----------------------------------------------------------------------===//
43
47
// / This takes an arbitrary SelectionDAG as input and
44
48
// / hacks on it until the target machine can handle it. This involves
@@ -51,7 +55,6 @@ using namespace llvm;
51
55
// / 'setcc' instruction efficiently, but does support 'brcc' instruction, this
52
56
// / will attempt merge setcc and brc instructions into brcc's.
53
57
// /
54
- namespace {
55
58
class SelectionDAGLegalize {
56
59
const TargetMachine &TM;
57
60
const TargetLowering &TLI;
@@ -130,7 +133,11 @@ class SelectionDAGLegalize {
130
133
SDValue ExpandSCALAR_TO_VECTOR (SDNode *Node);
131
134
void ExpandDYNAMIC_STACKALLOC (SDNode *Node,
132
135
SmallVectorImpl<SDValue> &Results);
133
- SDValue ExpandFCOPYSIGN (SDNode *Node);
136
+ void getSignAsIntValue (FloatSignAsInt &State, SDLoc DL, SDValue Value) const ;
137
+ SDValue modifySignAsInt (const FloatSignAsInt &State, SDLoc DL,
138
+ SDValue NewIntValue) const ;
139
+ SDValue ExpandFCOPYSIGN (SDNode *Node) const ;
140
+ SDValue ExpandFABS (SDNode *Node) const ;
134
141
SDValue ExpandLegalINT_TO_FP (bool isSigned, SDValue LegalOp, EVT DestVT,
135
142
SDLoc dl);
136
143
SDValue PromoteLegalINT_TO_FP (SDValue LegalOp, EVT DestVT, bool isSigned,
@@ -1568,69 +1575,147 @@ SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) {
1568
1575
false , false , false , 0 );
1569
1576
}
1570
1577
1571
- SDValue SelectionDAGLegalize::ExpandFCOPYSIGN (SDNode* Node) {
1572
- SDLoc dl (Node);
1573
- SDValue Tmp1 = Node->getOperand (0 );
1574
- SDValue Tmp2 = Node->getOperand (1 );
1575
-
1576
- // Get the sign bit of the RHS. First obtain a value that has the same
1577
- // sign as the sign bit, i.e. negative if and only if the sign bit is 1.
1578
- SDValue SignBit;
1579
- EVT FloatVT = Tmp2.getValueType ();
1580
- EVT IVT = EVT::getIntegerVT (*DAG.getContext (), FloatVT.getSizeInBits ());
1578
+ namespace {
1579
+ // / Keeps track of state when getting the sign of a floatingpoint value as an
1580
+ // / integer.
1581
+ struct FloatSignAsInt {
1582
+ EVT FloatVT;
1583
+ SDValue Chain;
1584
+ SDValue FloatPtr;
1585
+ SDValue IntPtr;
1586
+ MachinePointerInfo IntPointerInfo;
1587
+ MachinePointerInfo FloatPointerInfo;
1588
+ SDValue IntValue;
1589
+ APInt SignMask;
1590
+ };
1591
+ }
1592
+
1593
+ // / Bitcast a floatingpoint value to an integer value. Only bitcast the part
1594
+ // / containing the sign bit if the target has no integer value capable of
1595
+ // / holding all bits of the floatingpoint value.
1596
+ void SelectionDAGLegalize::getSignAsIntValue (FloatSignAsInt &State,
1597
+ SDLoc DL, SDValue Value) const {
1598
+ EVT FloatVT = Value.getValueType ();
1599
+ unsigned NumBits = FloatVT.getSizeInBits ();
1600
+ State.FloatVT = FloatVT;
1601
+ EVT IVT = EVT::getIntegerVT (*DAG.getContext (), NumBits);
1602
+ // Convert to an integer of the same size.
1581
1603
if (TLI.isTypeLegal (IVT)) {
1582
- // Convert to an integer with the same sign bit.
1583
- SignBit = DAG.getNode (ISD::BITCAST, dl, IVT, Tmp2);
1584
- } else {
1585
- auto &DL = DAG.getDataLayout ();
1586
- // Store the float to memory, then load the sign part out as an integer.
1587
- MVT LoadTy = TLI.getPointerTy (DL);
1588
- // First create a temporary that is aligned for both the load and store.
1589
- SDValue StackPtr = DAG.CreateStackTemporary (FloatVT, LoadTy);
1590
- // Then store the float to it.
1591
- SDValue Ch =
1592
- DAG.getStore (DAG.getEntryNode (), dl, Tmp2, StackPtr, MachinePointerInfo (),
1593
- false , false , 0 );
1594
- if (DL.isBigEndian ()) {
1595
- assert (FloatVT.isByteSized () && " Unsupported floating point type!" );
1596
- // Load out a legal integer with the same sign bit as the float.
1597
- SignBit = DAG.getLoad (LoadTy, dl, Ch, StackPtr, MachinePointerInfo (),
1598
- false , false , false , 0 );
1599
- } else { // Little endian
1600
- SDValue LoadPtr = StackPtr;
1601
- // The float may be wider than the integer we are going to load. Advance
1602
- // the pointer so that the loaded integer will contain the sign bit.
1603
- unsigned Strides = (FloatVT.getSizeInBits ()-1 )/LoadTy.getSizeInBits ();
1604
- unsigned ByteOffset = (Strides * LoadTy.getSizeInBits ()) / 8 ;
1605
- LoadPtr = DAG.getNode (ISD::ADD, dl, LoadPtr.getValueType (), LoadPtr,
1606
- DAG.getConstant (ByteOffset , dl,
1607
- LoadPtr.getValueType ()));
1608
- // Load a legal integer containing the sign bit.
1609
- SignBit = DAG.getLoad (LoadTy, dl, Ch, LoadPtr, MachinePointerInfo (),
1610
- false , false , false , 0 );
1611
- // Move the sign bit to the top bit of the loaded integer.
1612
- unsigned BitShift = LoadTy.getSizeInBits () -
1613
- (FloatVT.getSizeInBits () - 8 * ByteOffset );
1614
- assert (BitShift < LoadTy.getSizeInBits () && " Pointer advanced wrong?" );
1615
- if (BitShift )
1616
- SignBit = DAG.getNode (
1617
- ISD::SHL, dl, LoadTy, SignBit,
1618
- DAG.getConstant (BitShift , dl,
1619
- TLI.getShiftAmountTy (SignBit.getValueType (), DL)));
1620
- }
1604
+ State.IntValue = DAG.getNode (ISD::BITCAST, DL, IVT, Value);
1605
+ State.SignMask = APInt::getSignBit (NumBits);
1606
+ return ;
1607
+ }
1608
+
1609
+ auto &DataLayout = DAG.getDataLayout ();
1610
+ // Store the float to memory, then load the sign part out as an integer.
1611
+ MVT LoadTy = TLI.getPointerTy (DataLayout);
1612
+ // First create a temporary that is aligned for both the load and store.
1613
+ SDValue StackPtr = DAG.CreateStackTemporary (FloatVT, LoadTy);
1614
+ int FI = cast<FrameIndexSDNode>(StackPtr.getNode ())->getIndex ();
1615
+ // Then store the float to it.
1616
+ State.FloatPtr = StackPtr;
1617
+ State.FloatPointerInfo = MachinePointerInfo::getFixedStack (FI);
1618
+ State.Chain = DAG.getStore (DAG.getEntryNode (), DL, Value, State.FloatPtr ,
1619
+ State.FloatPointerInfo , false , false , 0 );
1620
+
1621
+ if (DataLayout.isBigEndian ()) {
1622
+ assert (FloatVT.isByteSized () && " Unsupported floating point type!" );
1623
+ // Load out a legal integer with the same sign bit as the float.
1624
+ State.IntPtr = StackPtr;
1625
+ State.IntPointerInfo = State.FloatPointerInfo ;
1626
+ State.IntValue = DAG.getLoad (LoadTy, DL, State.Chain , StackPtr,
1627
+ State.IntPointerInfo , false , false , false , 0 );
1628
+ State.SignMask = APInt::getSignBit (LoadTy.getSizeInBits ());
1629
+ } else { // Little endian
1630
+ // The float may be wider than the integer we are going to load. Advance
1631
+ // the pointer so that the loaded integer will contain the sign bit.
1632
+ unsigned Strides = (FloatVT.getSizeInBits ()-1 )/LoadTy.getSizeInBits ();
1633
+ unsigned ByteOffset = (Strides * LoadTy.getSizeInBits ()) / 8 ;
1634
+ SDValue LoadPtr
1635
+ = DAG.getNode (ISD::ADD, DL, StackPtr.getValueType (), StackPtr,
1636
+ DAG.getConstant (ByteOffset , DL, StackPtr.getValueType ()));
1637
+ // Load a legal integer containing the sign bit.
1638
+ State.IntPtr = LoadPtr;
1639
+ State.IntPointerInfo = MachinePointerInfo::getFixedStack (FI, ByteOffset );
1640
+ State.IntValue = DAG.getLoad (LoadTy, DL, State.Chain , LoadPtr,
1641
+ State.IntPointerInfo , false , false , false , 0 );
1642
+ unsigned NumBits = LoadTy.getSizeInBits ();
1643
+ unsigned SignBit = (FloatVT.getSizeInBits ()-1 ) - 8 *ByteOffset ;
1644
+ State.SignMask = APInt::getOneBitSet (NumBits, SignBit);
1621
1645
}
1622
- // Now get the sign bit proper, by seeing whether the value is negative.
1623
- SignBit = DAG.getSetCC (dl, getSetCCResultType (SignBit.getValueType ()),
1624
- SignBit,
1625
- DAG.getConstant (0 , dl, SignBit.getValueType ()),
1626
- ISD::SETLT);
1627
- // Get the absolute value of the result.
1628
- SDValue AbsVal = DAG.getNode (ISD::FABS, dl, Tmp1.getValueType (), Tmp1);
1629
- // Select between the nabs and abs value based on the sign bit of
1630
- // the input.
1631
- return DAG.getSelect (dl, AbsVal.getValueType (), SignBit,
1632
- DAG.getNode (ISD::FNEG, dl, AbsVal.getValueType (), AbsVal),
1633
- AbsVal);
1646
+ }
1647
+
1648
+ // / Replace the integer value produced by getSignAsIntValue() with a new value
1649
+ // / and cast the result back to a floatingpoint type.
1650
+ SDValue SelectionDAGLegalize::modifySignAsInt (const FloatSignAsInt &State,
1651
+ SDLoc DL, SDValue NewIntValue) const {
1652
+ if (!State.Chain ) {
1653
+ return DAG.getNode (ISD::BITCAST, DL, State.FloatVT , NewIntValue);
1654
+ }
1655
+
1656
+ // Override the part containing the sign bit in the value stored on the stack.
1657
+ SDValue Chain = DAG.getStore (State.Chain , DL, NewIntValue, State.IntPtr ,
1658
+ State.IntPointerInfo , false , false , 0 );
1659
+ return DAG.getLoad (State.FloatVT , DL, Chain, State.FloatPtr ,
1660
+ State.FloatPointerInfo , false , false , false , 0 );
1661
+ }
1662
+
1663
+ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN (SDNode *Node) const {
1664
+ SDLoc DL (Node);
1665
+ SDValue Mag = Node->getOperand (0 );
1666
+ SDValue Sign = Node->getOperand (1 );
1667
+
1668
+ // Get sign bit into an integer value.
1669
+ FloatSignAsInt SignAsInt;
1670
+ getSignAsIntValue (SignAsInt, DL, Sign);
1671
+
1672
+ EVT IntVT = SignAsInt.IntValue .getValueType ();
1673
+ SDValue SignMask = DAG.getConstant (SignAsInt.SignMask , DL, IntVT);
1674
+ SDValue SignBit = DAG.getNode (ISD::AND, DL, IntVT, SignAsInt.IntValue ,
1675
+ SignMask);
1676
+
1677
+ // Transform FCOPYSIGN(x, y) => sign(x) ? -FABS(x) : FABS(X) if FABS is legal.
1678
+ EVT FloatVT = Mag.getValueType ();
1679
+ if (TLI.isOperationLegalOrCustom (ISD::FABS, FloatVT) &&
1680
+ TLI.isOperationLegalOrCustom (ISD::FNEG, FloatVT)) {
1681
+ SDValue AbsValue = DAG.getNode (ISD::FABS, DL, FloatVT, Mag);
1682
+ SDValue NegValue = DAG.getNode (ISD::FNEG, DL, FloatVT, AbsValue);
1683
+ SDValue Cond = DAG.getSetCC (DL, getSetCCResultType (IntVT), SignBit,
1684
+ DAG.getConstant (0 , DL, IntVT), ISD::SETNE);
1685
+ return DAG.getSelect (DL, FloatVT, Cond, NegValue, AbsValue);
1686
+ }
1687
+
1688
+ // Transform values to integer, copy the sign bit and transform back.
1689
+ FloatSignAsInt MagAsInt;
1690
+ getSignAsIntValue (MagAsInt, DL, Mag);
1691
+ assert (SignAsInt.SignMask == MagAsInt.SignMask );
1692
+ SDValue ClearSignMask = DAG.getConstant (~SignAsInt.SignMask , DL, IntVT);
1693
+ SDValue ClearedSign = DAG.getNode (ISD::AND, DL, IntVT, MagAsInt.IntValue ,
1694
+ ClearSignMask);
1695
+ SDValue CopiedSign = DAG.getNode (ISD::OR, DL, IntVT, ClearedSign, SignBit);
1696
+
1697
+ return modifySignAsInt (MagAsInt, DL, CopiedSign);
1698
+ }
1699
+
1700
+ SDValue SelectionDAGLegalize::ExpandFABS (SDNode *Node) const {
1701
+ SDLoc DL (Node);
1702
+ SDValue Value = Node->getOperand (0 );
1703
+
1704
+ // Transform FABS(x) => FCOPYSIGN(x, 0.0) if FCOPYSIGN is legal.
1705
+ EVT FloatVT = Value.getValueType ();
1706
+ if (TLI.isOperationLegalOrCustom (ISD::FCOPYSIGN, FloatVT)) {
1707
+ SDValue Zero = DAG.getConstantFP (0.0 , DL, FloatVT);
1708
+ return DAG.getNode (ISD::FCOPYSIGN, DL, FloatVT, Value, Zero);
1709
+ }
1710
+
1711
+ // Transform value to integer, clear the sign bit and transform back.
1712
+ FloatSignAsInt ValueAsInt;
1713
+ getSignAsIntValue (ValueAsInt, DL, Value);
1714
+ EVT IntVT = ValueAsInt.IntValue .getValueType ();
1715
+ SDValue ClearSignMask = DAG.getConstant (~ValueAsInt.SignMask , DL, IntVT);
1716
+ SDValue ClearedSign = DAG.getNode (ISD::AND, DL, IntVT, ValueAsInt.IntValue ,
1717
+ ClearSignMask);
1718
+ return modifySignAsInt (ValueAsInt, DL, ClearedSign);
1634
1719
}
1635
1720
1636
1721
void SelectionDAGLegalize::ExpandDYNAMIC_STACKALLOC (SDNode* Node,
@@ -3312,18 +3397,9 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
3312
3397
Node->getOperand (0 ));
3313
3398
Results.push_back (Tmp1);
3314
3399
break ;
3315
- case ISD::FABS: {
3316
- // Expand Y = FABS(X) -> Y = (X >u 0.0) ? X : fneg(X).
3317
- EVT VT = Node->getValueType (0 );
3318
- Tmp1 = Node->getOperand (0 );
3319
- Tmp2 = DAG.getConstantFP (0.0 , dl, VT);
3320
- Tmp2 = DAG.getSetCC (dl, getSetCCResultType (Tmp1.getValueType ()),
3321
- Tmp1, Tmp2, ISD::SETUGT);
3322
- Tmp3 = DAG.getNode (ISD::FNEG, dl, VT, Tmp1);
3323
- Tmp1 = DAG.getSelect (dl, VT, Tmp2, Tmp1, Tmp3);
3324
- Results.push_back (Tmp1);
3400
+ case ISD::FABS:
3401
+ Results.push_back (ExpandFABS (Node));
3325
3402
break ;
3326
- }
3327
3403
case ISD::SMIN:
3328
3404
case ISD::SMAX:
3329
3405
case ISD::UMIN:
0 commit comments