Skip to content

Commit 0fc98a6

Browse files
MacDueKornevNikita
authored andcommitted
[IR] Add llvm.modf intrinsic (#121948)
This adds the `llvm.modf` intrinsic, legalization, and lowering (mostly reusing the lowering for sincos and frexp). 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 6b73a71 commit 0fc98a6

16 files changed

+521
-20
lines changed

llvm/docs/LangRef.rst

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16122,6 +16122,63 @@ of the argument.
1612216122
When specified with the fast-math-flag 'afn', the result may be approximated
1612316123
using a less accurate calculation.
1612416124

16125+
'``llvm.modf.*``' Intrinsic
16126+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
16127+
16128+
Syntax:
16129+
"""""""
16130+
16131+
This is an overloaded intrinsic. You can use ``llvm.modf`` on any floating-point
16132+
or vector of floating-point type. However, not all targets support all types.
16133+
16134+
::
16135+
16136+
declare { float, float } @llvm.modf.f32(float %Val)
16137+
declare { double, double } @llvm.modf.f64(double %Val)
16138+
declare { x86_fp80, x86_fp80 } @llvm.modf.f80(x86_fp80 %Val)
16139+
declare { fp128, fp128 } @llvm.modf.f128(fp128 %Val)
16140+
declare { ppc_fp128, ppc_fp128 } @llvm.modf.ppcf128(ppc_fp128 %Val)
16141+
declare { <4 x float>, <4 x float> } @llvm.modf.v4f32(<4 x float> %Val)
16142+
16143+
Overview:
16144+
"""""""""
16145+
16146+
The '``llvm.modf.*``' intrinsics return the operand's integral and fractional
16147+
parts.
16148+
16149+
Arguments:
16150+
""""""""""
16151+
16152+
The argument is a :ref:`floating-point <t_floating>` value or
16153+
:ref:`vector <t_vector>` of floating-point values. Returns two values matching
16154+
the argument type in a struct.
16155+
16156+
Semantics:
16157+
""""""""""
16158+
16159+
Return the same values as a corresponding libm '``modf``' function without
16160+
trapping or setting ``errno``.
16161+
16162+
The first result is the fractional part of the operand and the second result is
16163+
the integral part of the operand. Both results have the same sign as the operand.
16164+
16165+
Not including exceptional inputs (listed below), `llvm.modf.*` is semantically
16166+
equivalent to:
16167+
16168+
%fp = frem <fptype> %x, 1.0 ; Fractional part
16169+
%ip = fsub <fptype> %x, %fp ; Integral part
16170+
16171+
(assuming no floating-point precision errors)
16172+
16173+
If the argument is a zero, returns a zero with the same sign for both the
16174+
fractional and integral parts.
16175+
16176+
If the argument is an infinity, returns a fractional part of zero with the same
16177+
sign, and infinity with the same sign as the integral part.
16178+
16179+
When specified with the fast-math-flag 'afn', the result may be approximated
16180+
using a less accurate calculation.
16181+
1612516182
'``llvm.pow.*``' Intrinsic
1612616183
^^^^^^^^^^^^^^^^^^^^^^^^^^
1612716184

llvm/include/llvm/CodeGen/BasicTTIImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,6 +2077,9 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
20772077
case Intrinsic::sincos:
20782078
ISD = ISD::FSINCOS;
20792079
break;
2080+
case Intrinsic::modf:
2081+
ISD = ISD::FMODF;
2082+
break;
20802083
case Intrinsic::tan:
20812084
ISD = ISD::FTAN;
20822085
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 operand into integral and fractional parts, each
1062+
/// having the same type and sign as the operand.
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
@@ -4610,12 +4610,15 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
46104610
ExpandFPLibCall(Node, RTLIB::LDEXP_F32, RTLIB::LDEXP_F64, RTLIB::LDEXP_F80,
46114611
RTLIB::LDEXP_F128, RTLIB::LDEXP_PPCF128, Results);
46124612
break;
4613+
case ISD::FMODF:
46134614
case ISD::FFREXP: {
4614-
RTLIB::Libcall LC = RTLIB::getFREXP(Node->getValueType(0));
4615+
EVT VT = Node->getValueType(0);
4616+
RTLIB::Libcall LC = Node->getOpcode() == ISD::FMODF ? RTLIB::getMODF(VT)
4617+
: RTLIB::getFREXP(VT);
46154618
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results,
46164619
/*CallRetResNo=*/0);
46174620
if (!Expanded)
4618-
llvm_unreachable("Expected scalar FFREXP to expand to libcall!");
4621+
llvm_unreachable("Expected scalar FFREXP/FMODF to expand to libcall!");
46194622
break;
46204623
}
46214624
case ISD::FPOWI:
@@ -5504,9 +5507,10 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
55045507
Results.push_back(Tmp2.getValue(1));
55055508
break;
55065509
}
5510+
case ISD::FMODF:
55075511
case ISD::FSINCOS: {
55085512
Tmp1 = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(0));
5509-
Tmp2 = DAG.getNode(ISD::FSINCOS, dl, DAG.getVTList(NVT, NVT), Tmp1,
5513+
Tmp2 = DAG.getNode(Node->getOpcode(), dl, DAG.getVTList(NVT, NVT), Tmp1,
55105514
Node->getFlags());
55115515
Tmp3 = DAG.getIntPtrConstant(0, dl, /*isTarget=*/true);
55125516
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:
@@ -1223,6 +1224,14 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
12231224
return;
12241225
break;
12251226
}
1227+
case ISD::FMODF: {
1228+
RTLIB::Libcall LC =
1229+
RTLIB::getMODF(Node->getValueType(0).getVectorElementType());
1230+
if (DAG.expandMultipleResultFPLibCall(LC, Node, Results,
1231+
/*CallRetResNo=*/0))
1232+
return;
1233+
break;
1234+
}
12261235
case ISD::VECTOR_COMPRESS:
12271236
Results.push_back(TLI.expandVECTOR_COMPRESS(Node, DAG));
12281237
return;

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
133133
case ISD::ADDRSPACECAST:
134134
R = ScalarizeVecRes_ADDRSPACECAST(N);
135135
break;
136+
case ISD::FMODF:
136137
case ISD::FFREXP:
137138
case ISD::FSINCOS:
138139
R = ScalarizeVecRes_UnaryOpWithTwoResults(N, ResNo);
@@ -1261,6 +1262,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
12611262
case ISD::ADDRSPACECAST:
12621263
SplitVecRes_ADDRSPACECAST(N, Lo, Hi);
12631264
break;
1265+
case ISD::FMODF:
12641266
case ISD::FFREXP:
12651267
case ISD::FSINCOS:
12661268
SplitVecRes_UnaryOpWithTwoResults(N, ResNo, Lo, Hi);
@@ -4783,6 +4785,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
47834785
case ISD::VP_FSHR:
47844786
Res = WidenVecRes_Ternary(N);
47854787
break;
4788+
case ISD::FMODF:
47864789
case ISD::FFREXP:
47874790
case ISD::FSINCOS: {
47884791
if (!unrollExpandedOp())

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6977,6 +6977,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
69776977
getValue(I.getArgOperand(0)),
69786978
getValue(I.getArgOperand(1)), Flags));
69796979
return;
6980+
case Intrinsic::modf:
69806981
case Intrinsic::sincos:
69816982
case Intrinsic::frexp: {
69826983
unsigned Opcode;
@@ -6986,6 +6987,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
69866987
case Intrinsic::sincos:
69876988
Opcode = ISD::FSINCOS;
69886989
break;
6990+
case Intrinsic::modf:
6991+
Opcode = ISD::FMODF;
6992+
break;
69896993
case Intrinsic::frexp:
69906994
Opcode = ISD::FFREXP;
69916995
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)