Skip to content

Commit 5cf1b01

Browse files
committed
[LegalizeDAG][TargetLowering] Move vXi64/i64->vXf32/f32 uint_to_fp legalizing code from TargetLowering::expandUINT_TO_FP back to LegalizeDAG.
This was moved in October 2018, but we don't appear to be using this for vectors on any in tree target. Moving it back simplifies D72794 so we can share the code for i32->f32.
1 parent 58265ad commit 5cf1b01

File tree

2 files changed

+89
-104
lines changed

2 files changed

+89
-104
lines changed

llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,11 +2417,60 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(SDNode *Node,
24172417
}
24182418
return Result;
24192419
}
2420-
assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
24212420
// Code below here assumes !isSigned without checking again.
2421+
assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
2422+
2423+
// TODO: Generalize this for use with other types.
2424+
if (SrcVT == MVT::i64 && DestVT == MVT::f32) {
2425+
LLVM_DEBUG(dbgs() << "Converting unsigned i64 to f32\n");
2426+
// For unsigned conversions, convert them to signed conversions using the
2427+
// algorithm from the x86_64 __floatundidf in compiler_rt.
2428+
2429+
// TODO: This really should be implemented using a branch rather than a
2430+
// select. We happen to get lucky and machinesink does the right
2431+
// thing most of the time. This would be a good candidate for a
2432+
// pseudo-op, or, even better, for whole-function isel.
2433+
EVT SetCCVT = getSetCCResultType(SrcVT);
2434+
2435+
SDValue SignBitTest = DAG.getSetCC(
2436+
dl, SetCCVT, Op0, DAG.getConstant(0, dl, SrcVT), ISD::SETLT);
2437+
2438+
EVT ShiftVT = TLI.getShiftAmountTy(SrcVT, DAG.getDataLayout());
2439+
SDValue ShiftConst = DAG.getConstant(1, dl, ShiftVT);
2440+
SDValue Shr = DAG.getNode(ISD::SRL, dl, SrcVT, Op0, ShiftConst);
2441+
SDValue AndConst = DAG.getConstant(1, dl, SrcVT);
2442+
SDValue And = DAG.getNode(ISD::AND, dl, SrcVT, Op0, AndConst);
2443+
SDValue Or = DAG.getNode(ISD::OR, dl, SrcVT, And, Shr);
2444+
2445+
SDValue Slow, Fast;
2446+
if (Node->isStrictFPOpcode()) {
2447+
// In strict mode, we must avoid spurious exceptions, and therefore
2448+
// must make sure to only emit a single STRICT_SINT_TO_FP.
2449+
SDValue InCvt = DAG.getSelect(dl, SrcVT, SignBitTest, Or, Op0);
2450+
Fast = DAG.getNode(ISD::STRICT_SINT_TO_FP, dl, { DestVT, MVT::Other },
2451+
{ Node->getOperand(0), InCvt });
2452+
Slow = DAG.getNode(ISD::STRICT_FADD, dl, { DestVT, MVT::Other },
2453+
{ Fast.getValue(1), Fast, Fast });
2454+
Chain = Slow.getValue(1);
2455+
// The STRICT_SINT_TO_FP inherits the exception mode from the
2456+
// incoming STRICT_UINT_TO_FP node; the STRICT_FADD node can
2457+
// never raise any exception.
2458+
SDNodeFlags Flags;
2459+
Flags.setNoFPExcept(Node->getFlags().hasNoFPExcept());
2460+
Fast->setFlags(Flags);
2461+
Flags.setNoFPExcept(true);
2462+
Slow->setFlags(Flags);
2463+
} else {
2464+
SDValue SignCvt = DAG.getNode(ISD::SINT_TO_FP, dl, DestVT, Or);
2465+
Slow = DAG.getNode(ISD::FADD, dl, DestVT, SignCvt, SignCvt);
2466+
Fast = DAG.getNode(ISD::SINT_TO_FP, dl, DestVT, Op0);
2467+
}
2468+
2469+
return DAG.getSelect(dl, DestVT, SignBitTest, Slow, Fast);
2470+
}
2471+
24222472
// FIXME: This can produce slightly incorrect results. See details in
24232473
// FIXME: https://reviews.llvm.org/D69275
2424-
24252474
SDValue Tmp1;
24262475
if (Node->isStrictFPOpcode()) {
24272476
Tmp1 = DAG.getNode(ISD::STRICT_SINT_TO_FP, dl, { DestVT, MVT::Other },

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 38 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -6198,114 +6198,50 @@ bool TargetLowering::expandUINT_TO_FP(SDNode *Node, SDValue &Result,
61986198
EVT SrcVT = Src.getValueType();
61996199
EVT DstVT = Node->getValueType(0);
62006200

6201-
if (SrcVT.getScalarType() != MVT::i64)
6201+
if (SrcVT.getScalarType() != MVT::i64 || DstVT.getScalarType() != MVT::f64)
6202+
return false;
6203+
6204+
// Only expand vector types if we have the appropriate vector bit operations.
6205+
if (SrcVT.isVector() && (!isOperationLegalOrCustom(ISD::SRL, SrcVT) ||
6206+
!isOperationLegalOrCustom(ISD::FADD, DstVT) ||
6207+
!isOperationLegalOrCustom(ISD::FSUB, DstVT) ||
6208+
!isOperationLegalOrCustomOrPromote(ISD::OR, SrcVT) ||
6209+
!isOperationLegalOrCustomOrPromote(ISD::AND, SrcVT)))
62026210
return false;
62036211

62046212
SDLoc dl(SDValue(Node, 0));
62056213
EVT ShiftVT = getShiftAmountTy(SrcVT, DAG.getDataLayout());
62066214

6207-
if (DstVT.getScalarType() == MVT::f32) {
6208-
// Only expand vector types if we have the appropriate vector bit
6209-
// operations.
6210-
if (SrcVT.isVector() &&
6211-
(!isOperationLegalOrCustom(ISD::SRL, SrcVT) ||
6212-
!isOperationLegalOrCustom(ISD::FADD, DstVT) ||
6213-
!isOperationLegalOrCustom(ISD::SINT_TO_FP, SrcVT) ||
6214-
!isOperationLegalOrCustomOrPromote(ISD::OR, SrcVT) ||
6215-
!isOperationLegalOrCustomOrPromote(ISD::AND, SrcVT)))
6216-
return false;
6217-
6218-
// For unsigned conversions, convert them to signed conversions using the
6219-
// algorithm from the x86_64 __floatundisf in compiler_rt.
6220-
6221-
// TODO: This really should be implemented using a branch rather than a
6222-
// select. We happen to get lucky and machinesink does the right
6223-
// thing most of the time. This would be a good candidate for a
6224-
// pseudo-op, or, even better, for whole-function isel.
6225-
EVT SetCCVT =
6226-
getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), SrcVT);
6227-
6228-
SDValue SignBitTest = DAG.getSetCC(
6229-
dl, SetCCVT, Src, DAG.getConstant(0, dl, SrcVT), ISD::SETLT);
6230-
6231-
SDValue ShiftConst = DAG.getConstant(1, dl, ShiftVT);
6232-
SDValue Shr = DAG.getNode(ISD::SRL, dl, SrcVT, Src, ShiftConst);
6233-
SDValue AndConst = DAG.getConstant(1, dl, SrcVT);
6234-
SDValue And = DAG.getNode(ISD::AND, dl, SrcVT, Src, AndConst);
6235-
SDValue Or = DAG.getNode(ISD::OR, dl, SrcVT, And, Shr);
6236-
6237-
SDValue Slow, Fast;
6238-
if (Node->isStrictFPOpcode()) {
6239-
// In strict mode, we must avoid spurious exceptions, and therefore
6240-
// must make sure to only emit a single STRICT_SINT_TO_FP.
6241-
SDValue InCvt = DAG.getSelect(dl, SrcVT, SignBitTest, Or, Src);
6242-
Fast = DAG.getNode(ISD::STRICT_SINT_TO_FP, dl, { DstVT, MVT::Other },
6243-
{ Node->getOperand(0), InCvt });
6244-
Slow = DAG.getNode(ISD::STRICT_FADD, dl, { DstVT, MVT::Other },
6245-
{ Fast.getValue(1), Fast, Fast });
6246-
Chain = Slow.getValue(1);
6247-
// The STRICT_SINT_TO_FP inherits the exception mode from the
6248-
// incoming STRICT_UINT_TO_FP node; the STRICT_FADD node can
6249-
// never raise any exception.
6250-
SDNodeFlags Flags;
6251-
Flags.setNoFPExcept(Node->getFlags().hasNoFPExcept());
6252-
Fast->setFlags(Flags);
6253-
Flags.setNoFPExcept(true);
6254-
Slow->setFlags(Flags);
6255-
} else {
6256-
SDValue SignCvt = DAG.getNode(ISD::SINT_TO_FP, dl, DstVT, Or);
6257-
Slow = DAG.getNode(ISD::FADD, dl, DstVT, SignCvt, SignCvt);
6258-
Fast = DAG.getNode(ISD::SINT_TO_FP, dl, DstVT, Src);
6259-
}
6260-
6261-
Result = DAG.getSelect(dl, DstVT, SignBitTest, Slow, Fast);
6262-
return true;
6263-
}
6264-
6265-
if (DstVT.getScalarType() == MVT::f64) {
6266-
// Only expand vector types if we have the appropriate vector bit
6267-
// operations.
6268-
if (SrcVT.isVector() &&
6269-
(!isOperationLegalOrCustom(ISD::SRL, SrcVT) ||
6270-
!isOperationLegalOrCustom(ISD::FADD, DstVT) ||
6271-
!isOperationLegalOrCustom(ISD::FSUB, DstVT) ||
6272-
!isOperationLegalOrCustomOrPromote(ISD::OR, SrcVT) ||
6273-
!isOperationLegalOrCustomOrPromote(ISD::AND, SrcVT)))
6274-
return false;
6275-
6276-
// Implementation of unsigned i64 to f64 following the algorithm in
6277-
// __floatundidf in compiler_rt. This implementation has the advantage
6278-
// of performing rounding correctly, both in the default rounding mode
6279-
// and in all alternate rounding modes.
6280-
SDValue TwoP52 = DAG.getConstant(UINT64_C(0x4330000000000000), dl, SrcVT);
6281-
SDValue TwoP84PlusTwoP52 = DAG.getConstantFP(
6282-
BitsToDouble(UINT64_C(0x4530000000100000)), dl, DstVT);
6283-
SDValue TwoP84 = DAG.getConstant(UINT64_C(0x4530000000000000), dl, SrcVT);
6284-
SDValue LoMask = DAG.getConstant(UINT64_C(0x00000000FFFFFFFF), dl, SrcVT);
6285-
SDValue HiShift = DAG.getConstant(32, dl, ShiftVT);
6286-
6287-
SDValue Lo = DAG.getNode(ISD::AND, dl, SrcVT, Src, LoMask);
6288-
SDValue Hi = DAG.getNode(ISD::SRL, dl, SrcVT, Src, HiShift);
6289-
SDValue LoOr = DAG.getNode(ISD::OR, dl, SrcVT, Lo, TwoP52);
6290-
SDValue HiOr = DAG.getNode(ISD::OR, dl, SrcVT, Hi, TwoP84);
6291-
SDValue LoFlt = DAG.getBitcast(DstVT, LoOr);
6292-
SDValue HiFlt = DAG.getBitcast(DstVT, HiOr);
6293-
if (Node->isStrictFPOpcode()) {
6294-
SDValue HiSub =
6295-
DAG.getNode(ISD::STRICT_FSUB, dl, {DstVT, MVT::Other},
6296-
{Node->getOperand(0), HiFlt, TwoP84PlusTwoP52});
6297-
Result = DAG.getNode(ISD::STRICT_FADD, dl, {DstVT, MVT::Other},
6298-
{HiSub.getValue(1), LoFlt, HiSub});
6299-
Chain = Result.getValue(1);
6300-
} else {
6301-
SDValue HiSub =
6302-
DAG.getNode(ISD::FSUB, dl, DstVT, HiFlt, TwoP84PlusTwoP52);
6303-
Result = DAG.getNode(ISD::FADD, dl, DstVT, LoFlt, HiSub);
6304-
}
6305-
return true;
6215+
// Implementation of unsigned i64 to f64 following the algorithm in
6216+
// __floatundidf in compiler_rt. This implementation has the advantage
6217+
// of performing rounding correctly, both in the default rounding mode
6218+
// and in all alternate rounding modes.
6219+
SDValue TwoP52 = DAG.getConstant(UINT64_C(0x4330000000000000), dl, SrcVT);
6220+
SDValue TwoP84PlusTwoP52 = DAG.getConstantFP(
6221+
BitsToDouble(UINT64_C(0x4530000000100000)), dl, DstVT);
6222+
SDValue TwoP84 = DAG.getConstant(UINT64_C(0x4530000000000000), dl, SrcVT);
6223+
SDValue LoMask = DAG.getConstant(UINT64_C(0x00000000FFFFFFFF), dl, SrcVT);
6224+
SDValue HiShift = DAG.getConstant(32, dl, ShiftVT);
6225+
6226+
SDValue Lo = DAG.getNode(ISD::AND, dl, SrcVT, Src, LoMask);
6227+
SDValue Hi = DAG.getNode(ISD::SRL, dl, SrcVT, Src, HiShift);
6228+
SDValue LoOr = DAG.getNode(ISD::OR, dl, SrcVT, Lo, TwoP52);
6229+
SDValue HiOr = DAG.getNode(ISD::OR, dl, SrcVT, Hi, TwoP84);
6230+
SDValue LoFlt = DAG.getBitcast(DstVT, LoOr);
6231+
SDValue HiFlt = DAG.getBitcast(DstVT, HiOr);
6232+
if (Node->isStrictFPOpcode()) {
6233+
SDValue HiSub =
6234+
DAG.getNode(ISD::STRICT_FSUB, dl, {DstVT, MVT::Other},
6235+
{Node->getOperand(0), HiFlt, TwoP84PlusTwoP52});
6236+
Result = DAG.getNode(ISD::STRICT_FADD, dl, {DstVT, MVT::Other},
6237+
{HiSub.getValue(1), LoFlt, HiSub});
6238+
Chain = Result.getValue(1);
6239+
} else {
6240+
SDValue HiSub =
6241+
DAG.getNode(ISD::FSUB, dl, DstVT, HiFlt, TwoP84PlusTwoP52);
6242+
Result = DAG.getNode(ISD::FADD, dl, DstVT, LoFlt, HiSub);
63066243
}
6307-
6308-
return false;
6244+
return true;
63096245
}
63106246

63116247
SDValue TargetLowering::expandFMINNUM_FMAXNUM(SDNode *Node,

0 commit comments

Comments
 (0)