Skip to content

Commit b1d8576

Browse files
committed
This adds constrained intrinsics for the signed and unsigned conversions
of integers to floating point. This includes some of Craig Topper's changes for promotion support from D71130. Differential Revision: https://reviews.llvm.org/D69275
1 parent 1ed832e commit b1d8576

17 files changed

+2833
-91
lines changed

llvm/docs/LangRef.rst

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15667,6 +15667,78 @@ Semantics:
1566715667
The result produced is a signed integer converted from the floating
1566815668
point operand. The value is truncated, so it is rounded towards zero.
1566915669

15670+
'``llvm.experimental.constrained.uitofp``' Intrinsic
15671+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15672+
15673+
Syntax:
15674+
"""""""
15675+
15676+
::
15677+
15678+
declare <ty2>
15679+
@llvm.experimental.constrained.uitofp(<type> <value>,
15680+
metadata <rounding mode>,
15681+
metadata <exception behavior>)
15682+
15683+
Overview:
15684+
"""""""""
15685+
15686+
The '``llvm.experimental.constrained.uitofp``' intrinsic converts an
15687+
unsigned integer ``value`` to a floating-point of type ``ty2``.
15688+
15689+
Arguments:
15690+
""""""""""
15691+
15692+
The first argument to the '``llvm.experimental.constrained.uitofp``'
15693+
intrinsic must be an :ref:`integer <t_integer>` or :ref:`vector
15694+
<t_vector>` of integer values.
15695+
15696+
The second and third arguments specify the rounding mode and exception
15697+
behavior as described above.
15698+
15699+
Semantics:
15700+
""""""""""
15701+
15702+
An inexact floating-point exception will be raised if rounding is required.
15703+
Any result produced is a floating point value converted from the input
15704+
integer operand.
15705+
15706+
'``llvm.experimental.constrained.sitofp``' Intrinsic
15707+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15708+
15709+
Syntax:
15710+
"""""""
15711+
15712+
::
15713+
15714+
declare <ty2>
15715+
@llvm.experimental.constrained.sitofp(<type> <value>,
15716+
metadata <rounding mode>,
15717+
metadata <exception behavior>)
15718+
15719+
Overview:
15720+
"""""""""
15721+
15722+
The '``llvm.experimental.constrained.sitofp``' intrinsic converts a
15723+
signed integer ``value`` to a floating-point of type ``ty2``.
15724+
15725+
Arguments:
15726+
""""""""""
15727+
15728+
The first argument to the '``llvm.experimental.constrained.sitofp``'
15729+
intrinsic must be an :ref:`integer <t_integer>` or :ref:`vector
15730+
<t_vector>` of integer values.
15731+
15732+
The second and third arguments specify the rounding mode and exception
15733+
behavior as described above.
15734+
15735+
Semantics:
15736+
""""""""""
15737+
15738+
An inexact floating-point exception will be raised if rounding is required.
15739+
Any result produced is a floating point value converted from the input
15740+
integer operand.
15741+
1567015742
'``llvm.experimental.constrained.fptrunc``' Intrinsic
1567115743
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1567215744

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,13 @@ namespace ISD {
312312
STRICT_FP_TO_SINT,
313313
STRICT_FP_TO_UINT,
314314

315+
/// STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to
316+
/// a floating point value. These have the same semantics as sitofp and
317+
/// uitofp in IR.
318+
/// They are used to limit optimizations while the DAG is being optimized.
319+
STRICT_SINT_TO_FP,
320+
STRICT_UINT_TO_FP,
321+
315322
/// X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating
316323
/// point type down to the precision of the destination VT. TRUNC is a
317324
/// flag, which is always an integer that is zero or one. If TRUNC is 0,

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,11 @@ class SelectionDAG {
811811
/// float type VT, by either extending or rounding (by truncation).
812812
SDValue getFPExtendOrRound(SDValue Op, const SDLoc &DL, EVT VT);
813813

814+
/// Convert Op, which must be a STRICT operation of float type, to the
815+
/// float type VT, by either extending or rounding (by truncation).
816+
std::pair<SDValue, SDValue>
817+
getStrictFPExtendOrRound(SDValue Op, SDValue Chain, const SDLoc &DL, EVT VT);
818+
814819
/// Convert Op, which must be of integer type, to the
815820
/// integer type VT, by either any-extending or truncating it.
816821
SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT);

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4123,14 +4123,18 @@ class TargetLowering : public TargetLoweringBase {
41234123
/// Expand float to UINT conversion
41244124
/// \param N Node to expand
41254125
/// \param Result output after conversion
4126+
/// \param Chain output chain after conversion
41264127
/// \returns True, if the expansion was successful, false otherwise
4127-
bool expandFP_TO_UINT(SDNode *N, SDValue &Result, SDValue &Chain, SelectionDAG &DAG) const;
4128+
bool expandFP_TO_UINT(SDNode *N, SDValue &Result, SDValue &Chain,
4129+
SelectionDAG &DAG) const;
41284130

41294131
/// Expand UINT(i64) to double(f64) conversion
41304132
/// \param N Node to expand
41314133
/// \param Result output after conversion
4134+
/// \param Chain output chain after conversion
41324135
/// \returns True, if the expansion was successful, false otherwise
4133-
bool expandUINT_TO_FP(SDNode *N, SDValue &Result, SelectionDAG &DAG) const;
4136+
bool expandUINT_TO_FP(SDNode *N, SDValue &Result, SDValue &Chain,
4137+
SelectionDAG &DAG) const;
41344138

41354139
/// Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
41364140
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const;

llvm/include/llvm/IR/ConstrainedOps.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ INSTRUCTION(FMul, 2, 1, experimental_constrained_fmul, FMUL)
4141
INSTRUCTION(FDiv, 2, 1, experimental_constrained_fdiv, FDIV)
4242
INSTRUCTION(FRem, 2, 1, experimental_constrained_frem, FREM)
4343
INSTRUCTION(FPExt, 1, 0, experimental_constrained_fpext, FP_EXTEND)
44+
INSTRUCTION(SIToFP, 1, 1, experimental_constrained_sitofp, SINT_TO_FP)
45+
INSTRUCTION(UIToFP, 1, 1, experimental_constrained_uitofp, UINT_TO_FP)
4446
INSTRUCTION(FPToSI, 1, 0, experimental_constrained_fptosi, FP_TO_SINT)
4547
INSTRUCTION(FPToUI, 1, 0, experimental_constrained_fptoui, FP_TO_UINT)
4648
INSTRUCTION(FPTrunc, 1, 1, experimental_constrained_fptrunc, FP_ROUND)

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,16 @@ let IntrProperties = [IntrInaccessibleMemOnly, IntrWillReturn] in {
640640
[ llvm_anyfloat_ty,
641641
llvm_metadata_ty ]>;
642642

643+
def int_experimental_constrained_sitofp : Intrinsic<[ llvm_anyfloat_ty ],
644+
[ llvm_anyint_ty,
645+
llvm_metadata_ty,
646+
llvm_metadata_ty ]>;
647+
648+
def int_experimental_constrained_uitofp : Intrinsic<[ llvm_anyfloat_ty ],
649+
[ llvm_anyint_ty,
650+
llvm_metadata_ty,
651+
llvm_metadata_ty ]>;
652+
643653
def int_experimental_constrained_fptrunc : Intrinsic<[ llvm_anyfloat_ty ],
644654
[ llvm_anyfloat_ty,
645655
llvm_metadata_ty,

llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

Lines changed: 91 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,9 @@ class SelectionDAGLegalize {
173173
SDValue NewIntValue) const;
174174
SDValue ExpandFCOPYSIGN(SDNode *Node) const;
175175
SDValue ExpandFABS(SDNode *Node) const;
176-
SDValue ExpandLegalINT_TO_FP(bool isSigned, SDValue Op0, EVT DestVT,
177-
const SDLoc &dl);
178-
SDValue PromoteLegalINT_TO_FP(SDValue LegalOp, EVT DestVT, bool isSigned,
179-
const SDLoc &dl);
176+
SDValue ExpandLegalINT_TO_FP(SDNode *Node, SDValue &Chain);
177+
void PromoteLegalINT_TO_FP(SDNode *N, const SDLoc &dl,
178+
SmallVectorImpl<SDValue> &Results);
180179
void PromoteLegalFP_TO_INT(SDNode *N, const SDLoc &dl,
181180
SmallVectorImpl<SDValue> &Results);
182181

@@ -1010,6 +1009,8 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
10101009
Action = TLI.getOperationAction(Node->getOpcode(),
10111010
Node->getOperand(0).getValueType());
10121011
break;
1012+
case ISD::STRICT_SINT_TO_FP:
1013+
case ISD::STRICT_UINT_TO_FP:
10131014
case ISD::STRICT_LRINT:
10141015
case ISD::STRICT_LLRINT:
10151016
case ISD::STRICT_LROUND:
@@ -2338,9 +2339,14 @@ SelectionDAGLegalize::ExpandSinCosLibCall(SDNode *Node,
23382339
/// INT_TO_FP operation of the specified operand when the target requests that
23392340
/// we expand it. At this point, we know that the result and operand types are
23402341
/// legal for the target.
2341-
SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, SDValue Op0,
2342-
EVT DestVT,
2343-
const SDLoc &dl) {
2342+
SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(SDNode *Node,
2343+
SDValue &Chain) {
2344+
bool isSigned = (Node->getOpcode() == ISD::STRICT_SINT_TO_FP ||
2345+
Node->getOpcode() == ISD::SINT_TO_FP);
2346+
EVT DestVT = Node->getValueType(0);
2347+
SDLoc dl(Node);
2348+
unsigned OpNo = Node->isStrictFPOpcode() ? 1 : 0;
2349+
SDValue Op0 = Node->getOperand(OpNo);
23442350
EVT SrcVT = Op0.getValueType();
23452351

23462352
// TODO: Should any fast-math-flags be set for the created nodes?
@@ -2387,16 +2393,38 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, SDValue Op0,
23872393
BitsToDouble(0x4330000080000000ULL) :
23882394
BitsToDouble(0x4330000000000000ULL),
23892395
dl, MVT::f64);
2390-
// subtract the bias
2391-
SDValue Sub = DAG.getNode(ISD::FSUB, dl, MVT::f64, Load, Bias);
2392-
// final result
2393-
SDValue Result = DAG.getFPExtendOrRound(Sub, dl, DestVT);
2396+
// Subtract the bias and get the final result.
2397+
SDValue Sub;
2398+
SDValue Result;
2399+
if (Node->isStrictFPOpcode()) {
2400+
Sub = DAG.getNode(ISD::STRICT_FSUB, dl, {MVT::f64, MVT::Other},
2401+
{Node->getOperand(0), Load, Bias});
2402+
if (DestVT != Sub.getValueType()) {
2403+
std::pair<SDValue, SDValue> ResultPair;
2404+
ResultPair =
2405+
DAG.getStrictFPExtendOrRound(Sub, SDValue(Node, 1), dl, DestVT);
2406+
Result = ResultPair.first;
2407+
Chain = ResultPair.second;
2408+
}
2409+
else
2410+
Result = Sub;
2411+
} else {
2412+
Sub = DAG.getNode(ISD::FSUB, dl, MVT::f64, Load, Bias);
2413+
Result = DAG.getFPExtendOrRound(Sub, dl, DestVT);
2414+
}
23942415
return Result;
23952416
}
23962417
assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
23972418
// Code below here assumes !isSigned without checking again.
2419+
// FIXME: This can produce slightly incorrect results. See details in
2420+
// FIXME: https://reviews.llvm.org/D69275
23982421

2399-
SDValue Tmp1 = DAG.getNode(ISD::SINT_TO_FP, dl, DestVT, Op0);
2422+
SDValue Tmp1;
2423+
if (Node->isStrictFPOpcode()) {
2424+
Tmp1 = DAG.getNode(ISD::STRICT_SINT_TO_FP, dl, { DestVT, MVT::Other },
2425+
{ Node->getOperand(0), Op0 });
2426+
} else
2427+
Tmp1 = DAG.getNode(ISD::SINT_TO_FP, dl, DestVT, Op0);
24002428

24012429
SDValue SignSet = DAG.getSetCC(dl, getSetCCResultType(SrcVT), Op0,
24022430
DAG.getConstant(0, dl, SrcVT), ISD::SETLT);
@@ -2442,6 +2470,13 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, SDValue Op0,
24422470
FudgeInReg = Handle.getValue();
24432471
}
24442472

2473+
if (Node->isStrictFPOpcode()) {
2474+
SDValue Result = DAG.getNode(ISD::STRICT_FADD, dl, { DestVT, MVT::Other },
2475+
{ Tmp1.getValue(1), Tmp1, FudgeInReg });
2476+
Chain = Result.getValue(1);
2477+
return Result;
2478+
}
2479+
24452480
return DAG.getNode(ISD::FADD, dl, DestVT, Tmp1, FudgeInReg);
24462481
}
24472482

@@ -2450,9 +2485,16 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, SDValue Op0,
24502485
/// we promote it. At this point, we know that the result and operand types are
24512486
/// legal for the target, and that there is a legal UINT_TO_FP or SINT_TO_FP
24522487
/// operation that takes a larger input.
2453-
SDValue SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDValue LegalOp, EVT DestVT,
2454-
bool isSigned,
2455-
const SDLoc &dl) {
2488+
void SelectionDAGLegalize::PromoteLegalINT_TO_FP(
2489+
SDNode *N, const SDLoc &dl, SmallVectorImpl<SDValue> &Results) {
2490+
bool IsStrict = N->isStrictFPOpcode();
2491+
bool IsSigned = N->getOpcode() == ISD::SINT_TO_FP ||
2492+
N->getOpcode() == ISD::STRICT_SINT_TO_FP;
2493+
EVT DestVT = N->getValueType(0);
2494+
SDValue LegalOp = N->getOperand(IsStrict ? 1 : 0);
2495+
unsigned UIntOp = IsStrict ? ISD::STRICT_UINT_TO_FP : ISD::UINT_TO_FP;
2496+
unsigned SIntOp = IsStrict ? ISD::STRICT_SINT_TO_FP : ISD::SINT_TO_FP;
2497+
24562498
// First step, figure out the appropriate *INT_TO_FP operation to use.
24572499
EVT NewInTy = LegalOp.getValueType();
24582500

@@ -2464,15 +2506,16 @@ SDValue SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDValue LegalOp, EVT DestVT,
24642506
assert(NewInTy.isInteger() && "Ran out of possibilities!");
24652507

24662508
// If the target supports SINT_TO_FP of this type, use it.
2467-
if (TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, NewInTy)) {
2468-
OpToUse = ISD::SINT_TO_FP;
2509+
if (TLI.isOperationLegalOrCustom(SIntOp, NewInTy)) {
2510+
OpToUse = SIntOp;
24692511
break;
24702512
}
2471-
if (isSigned) continue;
2513+
if (IsSigned)
2514+
continue;
24722515

24732516
// If the target supports UINT_TO_FP of this type, use it.
2474-
if (TLI.isOperationLegalOrCustom(ISD::UINT_TO_FP, NewInTy)) {
2475-
OpToUse = ISD::UINT_TO_FP;
2517+
if (TLI.isOperationLegalOrCustom(UIntOp, NewInTy)) {
2518+
OpToUse = UIntOp;
24762519
break;
24772520
}
24782521

@@ -2481,9 +2524,20 @@ SDValue SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDValue LegalOp, EVT DestVT,
24812524

24822525
// Okay, we found the operation and type to use. Zero extend our input to the
24832526
// desired type then run the operation on it.
2484-
return DAG.getNode(OpToUse, dl, DestVT,
2485-
DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND,
2486-
dl, NewInTy, LegalOp));
2527+
if (IsStrict) {
2528+
SDValue Res =
2529+
DAG.getNode(OpToUse, dl, {DestVT, MVT::Other},
2530+
{N->getOperand(0),
2531+
DAG.getNode(IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND,
2532+
dl, NewInTy, LegalOp)});
2533+
Results.push_back(Res);
2534+
Results.push_back(Res.getValue(1));
2535+
}
2536+
2537+
Results.push_back(
2538+
DAG.getNode(OpToUse, dl, DestVT,
2539+
DAG.getNode(IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND,
2540+
dl, NewInTy, LegalOp)));
24872541
}
24882542

24892543
/// This function is responsible for legalizing a
@@ -2899,15 +2953,20 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
28992953
break;
29002954
}
29012955
case ISD::UINT_TO_FP:
2902-
if (TLI.expandUINT_TO_FP(Node, Tmp1, DAG)) {
2956+
case ISD::STRICT_UINT_TO_FP:
2957+
if (TLI.expandUINT_TO_FP(Node, Tmp1, Tmp2, DAG)) {
29032958
Results.push_back(Tmp1);
2959+
if (Node->isStrictFPOpcode())
2960+
Results.push_back(Tmp2);
29042961
break;
29052962
}
29062963
LLVM_FALLTHROUGH;
29072964
case ISD::SINT_TO_FP:
2908-
Tmp1 = ExpandLegalINT_TO_FP(Node->getOpcode() == ISD::SINT_TO_FP,
2909-
Node->getOperand(0), Node->getValueType(0), dl);
2965+
case ISD::STRICT_SINT_TO_FP:
2966+
Tmp1 = ExpandLegalINT_TO_FP(Node, Tmp2);
29102967
Results.push_back(Tmp1);
2968+
if (Node->isStrictFPOpcode())
2969+
Results.push_back(Tmp2);
29112970
break;
29122971
case ISD::FP_TO_SINT:
29132972
if (TLI.expandFP_TO_SINT(Node, Tmp1, DAG))
@@ -4194,6 +4253,9 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
41944253
Node->getOpcode() == ISD::INSERT_VECTOR_ELT) {
41954254
OVT = Node->getOperand(0).getSimpleValueType();
41964255
}
4256+
if (Node->getOpcode() == ISD::STRICT_UINT_TO_FP ||
4257+
Node->getOpcode() == ISD::STRICT_SINT_TO_FP)
4258+
OVT = Node->getOperand(1).getSimpleValueType();
41974259
if (Node->getOpcode() == ISD::BR_CC)
41984260
OVT = Node->getOperand(2).getSimpleValueType();
41994261
MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OVT);
@@ -4248,10 +4310,10 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
42484310
PromoteLegalFP_TO_INT(Node, dl, Results);
42494311
break;
42504312
case ISD::UINT_TO_FP:
4313+
case ISD::STRICT_UINT_TO_FP:
42514314
case ISD::SINT_TO_FP:
4252-
Tmp1 = PromoteLegalINT_TO_FP(Node->getOperand(0), Node->getValueType(0),
4253-
Node->getOpcode() == ISD::SINT_TO_FP, dl);
4254-
Results.push_back(Tmp1);
4315+
case ISD::STRICT_SINT_TO_FP:
4316+
PromoteLegalINT_TO_FP(Node, dl, Results);
42554317
break;
42564318
case ISD::VAARG: {
42574319
SDValue Chain = Node->getOperand(0); // Get the chain.

0 commit comments

Comments
 (0)