Skip to content

Commit

Permalink
[CodeGen] Add lrint/llrint builtins
Browse files Browse the repository at this point in the history
This patch add the ISD::LRINT and ISD::LLRINT along with new
intrinsics.  The changes are straightforward as for other
floating-point rounding functions, with just some adjustments
required to handle the return value being an interger.

The idea is to optimize lrint/llrint generation for AArch64
in a subsequent patch.  Current semantic is just route it to libm
symbol.

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D62017

llvm-svn: 361875
  • Loading branch information
zatrazz committed May 28, 2019
1 parent dfc34f0 commit 6d7bf5e
Show file tree
Hide file tree
Showing 25 changed files with 847 additions and 3 deletions.
74 changes: 74 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12449,6 +12449,80 @@ Semantics:
This function returns the same values as the libm ``llround``
functions would, but without setting errno.

'``llvm.lrint.*``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Syntax:
"""""""

This is an overloaded intrinsic. You can use ``llvm.lrint`` on any
floating-point type. Not all targets support all types however.

::

declare i32 @llvm.lrint.i32.f32(float %Val)
declare i32 @llvm.lrint.i32.f64(double %Val)
declare i32 @llvm.lrint.i32.f80(float %Val)
declare i32 @llvm.lrint.i32.f128(double %Val)
declare i32 @llvm.lrint.i32.ppcf128(double %Val)

declare i64 @llvm.lrint.i64.f32(float %Val)
declare i64 @llvm.lrint.i64.f64(double %Val)
declare i64 @llvm.lrint.i64.f80(float %Val)
declare i64 @llvm.lrint.i64.f128(double %Val)
declare i64 @llvm.lrint.i64.ppcf128(double %Val)

Overview:
"""""""""

The '``llvm.lrint.*``' intrinsics returns the operand rounded to the
nearest integer.

Arguments:
""""""""""

The argument is a floating-point number and return is an integer type.

Semantics:
""""""""""

This function returns the same values as the libm ``lrint``
functions would, but without setting errno.

'``llvm.llrint.*``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Syntax:
"""""""

This is an overloaded intrinsic. You can use ``llvm.llrint`` on any
floating-point type. Not all targets support all types however.

::

declare i64 @llvm.llrint.i64.f32(float %Val)
declare i64 @llvm.llrint.i64.f64(double %Val)
declare i64 @llvm.llrint.i64.f80(float %Val)
declare i64 @llvm.llrint.i64.f128(double %Val)
declare i64 @llvm.llrint.i64.ppcf128(double %Val)

Overview:
"""""""""

The '``llvm.llrint.*``' intrinsics returns the operand rounded to the
nearest integer.

Arguments:
""""""""""

The argument is a floating-point number and return is an integer type.

Semantics:
""""""""""

This function returns the same values as the libm ``llrint``
functions would, but without setting errno.

Bit Manipulation Intrinsics
---------------------------

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/ISDOpcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ namespace ISD {
FNEG, FABS, FSQRT, FCBRT, FSIN, FCOS, FPOWI, FPOW,
FLOG, FLOG2, FLOG10, FEXP, FEXP2,
FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR,
LROUND, LLROUND,
LROUND, LLROUND, LRINT, LLRINT,

/// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
/// values.
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,8 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in {

def int_lround : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>;
def int_llround : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>;
def int_lrint : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>;
def int_llrint : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>;
}

def int_minnum : Intrinsic<[llvm_anyfloat_ty],
Expand Down
10 changes: 10 additions & 0 deletions llvm/include/llvm/IR/RuntimeLibcalls.def
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ HANDLE_LIBCALL(LLROUND_F64, "llround")
HANDLE_LIBCALL(LLROUND_F80, "llroundl")
HANDLE_LIBCALL(LLROUND_F128, "llroundl")
HANDLE_LIBCALL(LLROUND_PPCF128, "llroundl")
HANDLE_LIBCALL(LRINT_F32, "lrintf")
HANDLE_LIBCALL(LRINT_F64, "lrint")
HANDLE_LIBCALL(LRINT_F80, "lrintl")
HANDLE_LIBCALL(LRINT_F128, "lrintl")
HANDLE_LIBCALL(LRINT_PPCF128, "lrintl")
HANDLE_LIBCALL(LLRINT_F32, "llrintf")
HANDLE_LIBCALL(LLRINT_F64, "llrint")
HANDLE_LIBCALL(LLRINT_F80, "llrintl")
HANDLE_LIBCALL(LLRINT_F128, "llrintl")
HANDLE_LIBCALL(LLRINT_PPCF128, "llrintl")

// Conversion
HANDLE_LIBCALL(FPEXT_F32_PPCF128, "__gcc_stoq")
Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,8 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
case ISD::EXTRACT_VECTOR_ELT:
case ISD::LROUND:
case ISD::LLROUND:
case ISD::LRINT:
case ISD::LLRINT:
Action = TLI.getOperationAction(Node->getOpcode(),
Node->getOperand(0).getValueType());
break;
Expand Down Expand Up @@ -2919,6 +2921,18 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
RTLIB::LLROUND_F128,
RTLIB::LLROUND_PPCF128));
break;
case ISD::LRINT:
Results.push_back(ExpandArgFPLibCall(Node, RTLIB::LRINT_F32,
RTLIB::LRINT_F64, RTLIB::LRINT_F80,
RTLIB::LRINT_F128,
RTLIB::LRINT_PPCF128));
break;
case ISD::LLRINT:
Results.push_back(ExpandArgFPLibCall(Node, RTLIB::LLRINT_F32,
RTLIB::LLRINT_F64, RTLIB::LLRINT_F80,
RTLIB::LLRINT_F128,
RTLIB::LLRINT_PPCF128));
break;
case ISD::VAARG:
Results.push_back(DAG.expandVAArg(Node));
Results.push_back(Results[0].getValue(1));
Expand Down
56 changes: 56 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,8 @@ bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) {
case ISD::FP_TO_UINT: Res = SoftenFloatOp_FP_TO_XINT(N); break;
case ISD::LROUND: Res = SoftenFloatOp_LROUND(N); break;
case ISD::LLROUND: Res = SoftenFloatOp_LLROUND(N); break;
case ISD::LRINT: Res = SoftenFloatOp_LRINT(N); break;
case ISD::LLRINT: Res = SoftenFloatOp_LLRINT(N); break;
case ISD::SELECT: Res = SoftenFloatOp_SELECT(N); break;
case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break;
case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break;
Expand Down Expand Up @@ -1068,6 +1070,34 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_LLROUND(SDNode *N) {
NVT, Op, false, SDLoc(N)).first;
}

SDValue DAGTypeLegalizer::SoftenFloatOp_LRINT(SDNode *N) {
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));

SDValue Op = GetSoftenedFloat(N->getOperand(0));
EVT RetVT = N->getOperand(0).getValueType().getSimpleVT().SimpleTy;
return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
RTLIB::LRINT_F32,
RTLIB::LRINT_F64,
RTLIB::LRINT_F80,
RTLIB::LRINT_F128,
RTLIB::LRINT_PPCF128),
NVT, Op, false, SDLoc(N)).first;
}

SDValue DAGTypeLegalizer::SoftenFloatOp_LLRINT(SDNode *N) {
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));

SDValue Op = GetSoftenedFloat(N->getOperand(0));
EVT RetVT = N->getOperand(0).getValueType().getSimpleVT().SimpleTy;
return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
RTLIB::LLRINT_F32,
RTLIB::LLRINT_F64,
RTLIB::LLRINT_F80,
RTLIB::LLRINT_F128,
RTLIB::LLRINT_PPCF128),
NVT, Op, false, SDLoc(N)).first;
}

//===----------------------------------------------------------------------===//
// Float Result Expansion
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1602,6 +1632,8 @@ bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) {
case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_UINT(N); break;
case ISD::LROUND: Res = ExpandFloatOp_LROUND(N); break;
case ISD::LLROUND: Res = ExpandFloatOp_LLROUND(N); break;
case ISD::LRINT: Res = ExpandFloatOp_LRINT(N); break;
case ISD::LLRINT: Res = ExpandFloatOp_LLRINT(N); break;
case ISD::SELECT_CC: Res = ExpandFloatOp_SELECT_CC(N); break;
case ISD::SETCC: Res = ExpandFloatOp_SETCC(N); break;
case ISD::STORE: Res = ExpandFloatOp_STORE(cast<StoreSDNode>(N),
Expand Down Expand Up @@ -1796,6 +1828,30 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_LLROUND(SDNode *N) {
RVT, N->getOperand(0), false, SDLoc(N)).first;
}

SDValue DAGTypeLegalizer::ExpandFloatOp_LRINT(SDNode *N) {
EVT RVT = N->getValueType(0);
EVT RetVT = N->getOperand(0).getValueType().getSimpleVT().SimpleTy;
return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
RTLIB::LRINT_F32,
RTLIB::LRINT_F64,
RTLIB::LRINT_F80,
RTLIB::LRINT_F128,
RTLIB::LRINT_PPCF128),
RVT, N->getOperand(0), false, SDLoc(N)).first;
}

SDValue DAGTypeLegalizer::ExpandFloatOp_LLRINT(SDNode *N) {
EVT RVT = N->getValueType(0);
EVT RetVT = N->getOperand(0).getValueType().getSimpleVT().SimpleTy;
return TLI.makeLibCall(DAG, GetFPLibCall(RetVT,
RTLIB::LLRINT_F32,
RTLIB::LLRINT_F64,
RTLIB::LLRINT_F80,
RTLIB::LLRINT_F128,
RTLIB::LLRINT_PPCF128),
RVT, N->getOperand(0), false, SDLoc(N)).first;
}

//===----------------------------------------------------------------------===//
// Float Operand Promotion
//===----------------------------------------------------------------------===//
Expand Down
27 changes: 27 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1624,6 +1624,7 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
case ISD::FP_TO_SINT: ExpandIntRes_FP_TO_SINT(N, Lo, Hi); break;
case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break;
case ISD::LLROUND: ExpandIntRes_LLROUND(N, Lo, Hi); break;
case ISD::LLRINT: ExpandIntRes_LLRINT(N, Lo, Hi); break;
case ISD::LOAD: ExpandIntRes_LOAD(cast<LoadSDNode>(N), Lo, Hi); break;
case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break;
case ISD::READCYCLECOUNTER: ExpandIntRes_READCYCLECOUNTER(N, Lo, Hi); break;
Expand Down Expand Up @@ -2517,6 +2518,32 @@ void DAGTypeLegalizer::ExpandIntRes_LLROUND(SDNode *N, SDValue &Lo,
Lo, Hi);
}

void DAGTypeLegalizer::ExpandIntRes_LLRINT(SDNode *N, SDValue &Lo,
SDValue &Hi) {
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
EVT VT = N->getOperand(0).getValueType().getSimpleVT().SimpleTy;
if (VT == MVT::f32)
LC = RTLIB::LLRINT_F32;
else if (VT == MVT::f64)
LC = RTLIB::LLRINT_F64;
else if (VT == MVT::f80)
LC = RTLIB::LLRINT_F80;
else if (VT == MVT::f128)
LC = RTLIB::LLRINT_F128;
else if (VT == MVT::ppcf128)
LC = RTLIB::LLRINT_PPCF128;
assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected llrint input type!");

SDValue Op = N->getOperand(0);
if (getTypeAction(Op.getValueType()) == TargetLowering::TypePromoteFloat)
Op = GetPromotedFloat(Op);

SDLoc dl(N);
EVT RetVT = N->getValueType(0);
SplitInteger(TLI.makeLibCall(DAG, LC, RetVT, Op, true/*irrelevant*/, dl).first,
Lo, Hi);
}

void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N,
SDValue &Lo, SDValue &Hi) {
if (ISD::isNormalLoad(N)) {
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
void ExpandIntRes_FP_TO_SINT (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandIntRes_FP_TO_UINT (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandIntRes_LLROUND (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandIntRes_LLRINT (SDNode *N, SDValue &Lo, SDValue &Hi);

void ExpandIntRes_Logical (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandIntRes_ADDSUB (SDNode *N, SDValue &Lo, SDValue &Hi);
Expand Down Expand Up @@ -556,6 +557,8 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue SoftenFloatOp_FP_TO_XINT(SDNode *N);
SDValue SoftenFloatOp_LROUND(SDNode *N);
SDValue SoftenFloatOp_LLROUND(SDNode *N);
SDValue SoftenFloatOp_LRINT(SDNode *N);
SDValue SoftenFloatOp_LLRINT(SDNode *N);
SDValue SoftenFloatOp_SELECT(SDNode *N);
SDValue SoftenFloatOp_SELECT_CC(SDNode *N);
SDValue SoftenFloatOp_SETCC(SDNode *N);
Expand Down Expand Up @@ -617,6 +620,8 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue ExpandFloatOp_FP_TO_UINT(SDNode *N);
SDValue ExpandFloatOp_LROUND(SDNode *N);
SDValue ExpandFloatOp_LLROUND(SDNode *N);
SDValue ExpandFloatOp_LRINT(SDNode *N);
SDValue ExpandFloatOp_LLRINT(SDNode *N);
SDValue ExpandFloatOp_SELECT_CC(SDNode *N);
SDValue ExpandFloatOp_SETCC(SDNode *N);
SDValue ExpandFloatOp_STORE(SDNode *N, unsigned OpNo);
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6029,12 +6029,16 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
return;
}
case Intrinsic::lround:
case Intrinsic::llround: {
case Intrinsic::llround:
case Intrinsic::lrint:
case Intrinsic::llrint: {
unsigned Opcode;
switch (Intrinsic) {
default: llvm_unreachable("Impossible intrinsic"); // Can't reach here.
case Intrinsic::lround: Opcode = ISD::LROUND; break;
case Intrinsic::llround: Opcode = ISD::LLROUND; break;
case Intrinsic::lrint: Opcode = ISD::LRINT; break;
case Intrinsic::llrint: Opcode = ISD::LLRINT; break;
}

EVT RetVT = TLI.getValueType(DAG.getDataLayout(), I.getType());
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::FP_TO_FP16: return "fp_to_fp16";
case ISD::LROUND: return "lround";
case ISD::LLROUND: return "llround";
case ISD::LRINT: return "lrint";
case ISD::LLRINT: return "llrint";

// Control flow instructions
case ISD::BR: return "br";
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/TargetLoweringBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,8 @@ void TargetLoweringBase::initActions() {
setOperationAction(ISD::FROUND, VT, Expand);
setOperationAction(ISD::LROUND, VT, Expand);
setOperationAction(ISD::LLROUND, VT, Expand);
setOperationAction(ISD::LRINT, VT, Expand);
setOperationAction(ISD::LLRINT, VT, Expand);
}

// Default ISD::TRAP to expand (which turns it into abort).
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4622,7 +4622,9 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
break;
}
case Intrinsic::lround:
case Intrinsic::llround: {
case Intrinsic::llround:
case Intrinsic::lrint:
case Intrinsic::llrint: {
Type *ValTy = Call.getArgOperand(0)->getType();
Type *ResultTy = Call.getType();
Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,8 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::FMA, MVT::f80, Expand);
setOperationAction(ISD::LROUND, MVT::f80, Expand);
setOperationAction(ISD::LLROUND, MVT::f80, Expand);
setOperationAction(ISD::LRINT, MVT::f80, Expand);
setOperationAction(ISD::LLRINT, MVT::f80, Expand);
}

// Always use a library call for pow.
Expand Down
Loading

0 comments on commit 6d7bf5e

Please sign in to comment.