Skip to content

Commit ae79135

Browse files
committed
[IR] Add llvm.modf intrinsic
This adds the `llvm.modf` intrinsic, legalization, and lowering. The `llvm.modf` intrinsic takes a floating-point value and returns both the integral and fractional parts (as a struct). ``` declare { float, float } @llvm.modf.f32(float %Val) declare { double, double } @llvm.modf.f64(double %Val) declare { x86_fp80, x86_fp80 } @llvm.modf.f80(x86_fp80 %Val) declare { fp128, fp128 } @llvm.modf.f128(fp128 %Val) declare { ppc_fp128, ppc_fp128 } @llvm.modf.ppcf128(ppc_fp128 %Val) declare { <4 x float>, <4 x float> } @llvm.modf.v4f32(<4 x float> %Val) ``` This corresponds to the libm `modf` function but returns multiple values in a struct (rather than take output pointers), which makes it easier to vectorize.
1 parent 4ecd9bd commit ae79135

16 files changed

+420
-20
lines changed

llvm/docs/LangRef.rst

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16004,6 +16004,49 @@ of the argument.
1600416004
When specified with the fast-math-flag 'afn', the result may be approximated
1600516005
using a less accurate calculation.
1600616006

16007+
'``llvm.modf.*``' Intrinsic
16008+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
16009+
16010+
Syntax:
16011+
"""""""
16012+
16013+
This is an overloaded intrinsic. You can use ``llvm.modf`` on any floating-point
16014+
or vector of floating-point type. However, not all targets support all types.
16015+
16016+
::
16017+
16018+
declare { float, float } @llvm.modf.f32(float %Val)
16019+
declare { double, double } @llvm.modf.f64(double %Val)
16020+
declare { x86_fp80, x86_fp80 } @llvm.modf.f80(x86_fp80 %Val)
16021+
declare { fp128, fp128 } @llvm.modf.f128(fp128 %Val)
16022+
declare { ppc_fp128, ppc_fp128 } @llvm.modf.ppcf128(ppc_fp128 %Val)
16023+
declare { <4 x float>, <4 x float> } @llvm.modf.v4f32(<4 x float> %Val)
16024+
16025+
Overview:
16026+
"""""""""
16027+
16028+
The '``llvm.modf.*``' intrinsics return the operand's integral and fractional
16029+
parts.
16030+
16031+
Arguments:
16032+
""""""""""
16033+
16034+
The argument is a :ref:`floating-point <t_floating>` value or
16035+
:ref:`vector <t_vector>` of floating-point values. Returns two values matching
16036+
the argument type in a struct.
16037+
16038+
Semantics:
16039+
""""""""""
16040+
16041+
Return the same values as a corresponding libm '``modf``' function without
16042+
trapping or setting ``errno``.
16043+
16044+
The first result is the fractional part of the operand and the second result is
16045+
the integral part of the operand. Both results have the same sign as the operand.
16046+
16047+
When specified with the fast-math-flag 'afn', the result may be approximated
16048+
using a less accurate calculation.
16049+
1600716050
'``llvm.pow.*``' Intrinsic
1600816051
^^^^^^^^^^^^^^^^^^^^^^^^^^
1600916052

llvm/include/llvm/CodeGen/BasicTTIImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2078,6 +2078,9 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
20782078
case Intrinsic::sincos:
20792079
ISD = ISD::FSINCOS;
20802080
break;
2081+
case Intrinsic::modf:
2082+
ISD = ISD::FMODF;
2083+
break;
20812084
case Intrinsic::tan:
20822085
ISD = ISD::FTAN;
20832086
break;

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,10 @@ enum NodeType {
10581058
/// FSINCOS - Compute both fsin and fcos as a single operation.
10591059
FSINCOS,
10601060

1061+
/// FMODF - Decomposes the given arg in integral and fractional parts, each
1062+
/// having the same type and sign as the arg.
1063+
FMODF,
1064+
10611065
/// Gets the current floating-point environment. The first operand is a token
10621066
/// chain. The results are FP environment, represented by an integer value,
10631067
/// and a token chain.

llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ Libcall getFREXP(EVT RetVT);
6666
/// UNKNOWN_LIBCALL if there is none.
6767
Libcall getFSINCOS(EVT RetVT);
6868

69+
/// getMODF - Return the MODF_* value for the given types, or
70+
/// UNKNOWN_LIBCALL if there is none.
71+
Libcall getMODF(EVT RetVT);
72+
6973
/// Return the SYNC_FETCH_AND_* value for the given opcode and type, or
7074
/// UNKNOWN_LIBCALL if there is none.
7175
Libcall getSYNC(unsigned Opc, MVT VT);

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,8 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
10631063
def int_roundeven : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10641064
def int_sincos : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>],
10651065
[llvm_anyfloat_ty]>;
1066+
def int_modf : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>],
1067+
[llvm_anyfloat_ty]>;
10661068

10671069
// Truncate a floating point number with a specific rounding mode
10681070
def int_fptrunc_round : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],

llvm/include/llvm/IR/RuntimeLibcalls.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,11 @@ HANDLE_LIBCALL(FREXP_F64, "frexp")
354354
HANDLE_LIBCALL(FREXP_F80, "frexpl")
355355
HANDLE_LIBCALL(FREXP_F128, "frexpl")
356356
HANDLE_LIBCALL(FREXP_PPCF128, "frexpl")
357+
HANDLE_LIBCALL(MODF_F32, "modff")
358+
HANDLE_LIBCALL(MODF_F64, "modf")
359+
HANDLE_LIBCALL(MODF_F80, "modfl")
360+
HANDLE_LIBCALL(MODF_F128, "modfl")
361+
HANDLE_LIBCALL(MODF_PPCF128, "modfl")
357362

358363
// Floating point environment
359364
HANDLE_LIBCALL(FEGETENV, "fegetenv")

llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4609,12 +4609,15 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
46094609
ExpandFPLibCall(Node, RTLIB::LDEXP_F32, RTLIB::LDEXP_F64, RTLIB::LDEXP_F80,
46104610
RTLIB::LDEXP_F128, RTLIB::LDEXP_PPCF128, Results);
46114611
break;
4612+
case ISD::FMODF:
46124613
case ISD::FFREXP: {
4613-
RTLIB::Libcall LC = RTLIB::getFREXP(Node->getValueType(0));
4614+
EVT VT = Node->getValueType(0);
4615+
RTLIB::Libcall LC = Node->getOpcode() == ISD::FMODF ? RTLIB::getMODF(VT)
4616+
: RTLIB::getFREXP(VT);
46144617
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results,
46154618
/*CallRetResNo=*/0);
46164619
if (!Expanded)
4617-
llvm_unreachable("Expected scalar FFREXP to expand to libcall!");
4620+
llvm_unreachable("Expected scalar FFREXP/FMODF to expand to libcall!");
46184621
break;
46194622
}
46204623
case ISD::FPOWI:
@@ -5509,9 +5512,10 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
55095512
Results.push_back(Tmp2.getValue(1));
55105513
break;
55115514
}
5515+
case ISD::FMODF:
55125516
case ISD::FSINCOS: {
55135517
Tmp1 = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(0));
5514-
Tmp2 = DAG.getNode(ISD::FSINCOS, dl, DAG.getVTList(NVT, NVT), Tmp1,
5518+
Tmp2 = DAG.getNode(Node->getOpcode(), dl, DAG.getVTList(NVT, NVT), Tmp1,
55155519
Node->getFlags());
55165520
Tmp3 = DAG.getIntPtrConstant(0, dl, /*isTarget=*/true);
55175521
for (unsigned ResNum = 0; ResNum < Node->getNumValues(); ResNum++)

llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2766,10 +2766,10 @@ void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
27662766
case ISD::FLDEXP: R = PromoteFloatRes_ExpOp(N); break;
27672767
case ISD::FFREXP: R = PromoteFloatRes_FFREXP(N); break;
27682768

2769+
case ISD::FMODF:
27692770
case ISD::FSINCOS:
27702771
R = PromoteFloatRes_UnaryWithTwoFPResults(N);
27712772
break;
2772-
27732773
case ISD::FP_ROUND: R = PromoteFloatRes_FP_ROUND(N); break;
27742774
case ISD::STRICT_FP_ROUND:
27752775
R = PromoteFloatRes_STRICT_FP_ROUND(N);
@@ -3228,6 +3228,7 @@ void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
32283228

32293229
case ISD::FFREXP: R = SoftPromoteHalfRes_FFREXP(N); break;
32303230

3231+
case ISD::FMODF:
32313232
case ISD::FSINCOS:
32323233
R = SoftPromoteHalfRes_UnaryWithTwoFPResults(N);
32333234
break;

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
454454
case ISD::UMULO:
455455
case ISD::FCANONICALIZE:
456456
case ISD::FFREXP:
457+
case ISD::FMODF:
457458
case ISD::FSINCOS:
458459
case ISD::SADDSAT:
459460
case ISD::UADDSAT:
@@ -1205,6 +1206,14 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
12051206
return;
12061207
break;
12071208
}
1209+
case ISD::FMODF: {
1210+
RTLIB::Libcall LC =
1211+
RTLIB::getMODF(Node->getValueType(0).getVectorElementType());
1212+
if (DAG.expandMultipleResultFPLibCall(LC, Node, Results,
1213+
/*CallRetResNo=*/0))
1214+
return;
1215+
break;
1216+
}
12081217
case ISD::VECTOR_COMPRESS:
12091218
Results.push_back(TLI.expandVECTOR_COMPRESS(Node, DAG));
12101219
return;

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
129129
case ISD::ADDRSPACECAST:
130130
R = ScalarizeVecRes_ADDRSPACECAST(N);
131131
break;
132+
case ISD::FMODF:
132133
case ISD::FFREXP:
133134
case ISD::FSINCOS:
134135
R = ScalarizeVecRes_UnaryOpWithTwoResults(N, ResNo);
@@ -1257,6 +1258,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
12571258
case ISD::ADDRSPACECAST:
12581259
SplitVecRes_ADDRSPACECAST(N, Lo, Hi);
12591260
break;
1261+
case ISD::FMODF:
12601262
case ISD::FFREXP:
12611263
case ISD::FSINCOS:
12621264
SplitVecRes_UnaryOpWithTwoResults(N, ResNo, Lo, Hi);
@@ -4779,6 +4781,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
47794781
case ISD::VP_FSHR:
47804782
Res = WidenVecRes_Ternary(N);
47814783
break;
4784+
case ISD::FMODF:
47824785
case ISD::FFREXP:
47834786
case ISD::FSINCOS: {
47844787
if (!unrollExpandedOp())

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6994,6 +6994,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
69946994
getValue(I.getArgOperand(0)),
69956995
getValue(I.getArgOperand(1)), Flags));
69966996
return;
6997+
case Intrinsic::modf:
69976998
case Intrinsic::sincos:
69986999
case Intrinsic::frexp: {
69997000
unsigned Opcode;
@@ -7003,6 +7004,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
70037004
case Intrinsic::sincos:
70047005
Opcode = ISD::FSINCOS;
70057006
break;
7007+
case Intrinsic::modf:
7008+
Opcode = ISD::FMODF;
7009+
break;
70067010
case Intrinsic::frexp:
70077011
Opcode = ISD::FFREXP;
70087012
break;

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
219219
case ISD::FCOS: return "fcos";
220220
case ISD::STRICT_FCOS: return "strict_fcos";
221221
case ISD::FSINCOS: return "fsincos";
222+
case ISD::FMODF: return "fmodf";
222223
case ISD::FTAN: return "ftan";
223224
case ISD::STRICT_FTAN: return "strict_ftan";
224225
case ISD::FASIN: return "fasin";

llvm/lib/CodeGen/TargetLoweringBase.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ RTLIB::Libcall RTLIB::getFSINCOS(EVT RetVT) {
407407
SINCOS_PPCF128);
408408
}
409409

410+
RTLIB::Libcall RTLIB::getMODF(EVT RetVT) {
411+
return getFPLibCall(RetVT, MODF_F32, MODF_F64, MODF_F80, MODF_F128,
412+
MODF_PPCF128);
413+
}
414+
410415
RTLIB::Libcall RTLIB::getOutlineAtomicHelper(const Libcall (&LC)[5][4],
411416
AtomicOrdering Order,
412417
uint64_t MemSize) {
@@ -775,9 +780,9 @@ void TargetLoweringBase::initActions() {
775780
setOperationAction({ISD::BITREVERSE, ISD::PARITY}, VT, Expand);
776781

777782
// These library functions default to expand.
778-
setOperationAction(
779-
{ISD::FROUND, ISD::FPOWI, ISD::FLDEXP, ISD::FFREXP, ISD::FSINCOS}, VT,
780-
Expand);
783+
setOperationAction({ISD::FROUND, ISD::FPOWI, ISD::FLDEXP, ISD::FFREXP,
784+
ISD::FSINCOS, ISD::FMODF},
785+
VT, Expand);
781786

782787
// These operations default to expand for vector types.
783788
if (VT.isVector())

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -732,19 +732,19 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
732732
setOperationAction(ISD::FCOPYSIGN, MVT::bf16, Promote);
733733
}
734734

735-
for (auto Op : {ISD::FREM, ISD::FPOW, ISD::FPOWI,
736-
ISD::FCOS, ISD::FSIN, ISD::FSINCOS,
737-
ISD::FACOS, ISD::FASIN, ISD::FATAN,
738-
ISD::FATAN2, ISD::FCOSH, ISD::FSINH,
739-
ISD::FTANH, ISD::FTAN, ISD::FEXP,
740-
ISD::FEXP2, ISD::FEXP10, ISD::FLOG,
741-
ISD::FLOG2, ISD::FLOG10, ISD::STRICT_FREM,
742-
ISD::STRICT_FPOW, ISD::STRICT_FPOWI, ISD::STRICT_FCOS,
743-
ISD::STRICT_FSIN, ISD::STRICT_FACOS, ISD::STRICT_FASIN,
744-
ISD::STRICT_FATAN, ISD::STRICT_FATAN2, ISD::STRICT_FCOSH,
745-
ISD::STRICT_FSINH, ISD::STRICT_FTANH, ISD::STRICT_FEXP,
746-
ISD::STRICT_FEXP2, ISD::STRICT_FLOG, ISD::STRICT_FLOG2,
747-
ISD::STRICT_FLOG10, ISD::STRICT_FTAN}) {
735+
for (auto Op : {ISD::FREM, ISD::FPOW, ISD::FPOWI,
736+
ISD::FCOS, ISD::FSIN, ISD::FSINCOS,
737+
ISD::FMODF, ISD::FACOS, ISD::FASIN,
738+
ISD::FATAN, ISD::FATAN2, ISD::FCOSH,
739+
ISD::FSINH, ISD::FTANH, ISD::FTAN,
740+
ISD::FEXP, ISD::FEXP2, ISD::FEXP10,
741+
ISD::FLOG, ISD::FLOG2, ISD::FLOG10,
742+
ISD::STRICT_FREM, ISD::STRICT_FPOW, ISD::STRICT_FPOWI,
743+
ISD::STRICT_FCOS, ISD::STRICT_FSIN, ISD::STRICT_FACOS,
744+
ISD::STRICT_FASIN, ISD::STRICT_FATAN, ISD::STRICT_FATAN2,
745+
ISD::STRICT_FCOSH, ISD::STRICT_FSINH, ISD::STRICT_FTANH,
746+
ISD::STRICT_FEXP, ISD::STRICT_FEXP2, ISD::STRICT_FLOG,
747+
ISD::STRICT_FLOG2, ISD::STRICT_FLOG10, ISD::STRICT_FTAN}) {
748748
setOperationAction(Op, MVT::f16, Promote);
749749
setOperationAction(Op, MVT::v4f16, Expand);
750750
setOperationAction(Op, MVT::v8f16, Expand);

0 commit comments

Comments
 (0)