Skip to content

Commit

Permalink
[SelectionDAG] lower math intrinsics to finite version of libcalls wh…
Browse files Browse the repository at this point in the history
…en possible (PR35672)

Ingredients in this patch:
1. Add HANDLE_LIBCALL defs for finite mathlib functions that correspond to LLVM intrinsics.
2. Plumbing to send TargetLibraryInfo down to SelectionDAGLegalize.
3. Relaxed math and library checking in SelectionDAGLegalize::ConvertNodeToLibcall() to choose finite libcalls.

There was a bug about determining the availability of the finite calls that should be fixed with:
rL322010

Not in this patch:
This doesn't resolve the question/bug of clang creating the intrinsic IR in the first place.
There's likely follow-up work needed to support the long double variants better.
There's room for improvement to reduce the code duplication.
Create finite calls that don't originate from a corresponding intrinsic or DAG node?

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

llvm-svn: 322087
  • Loading branch information
rotateright committed Jan 9, 2018
1 parent 2b3bd30 commit 37e28e4
Show file tree
Hide file tree
Showing 6 changed files with 485 additions and 34 deletions.
30 changes: 30 additions & 0 deletions llvm/include/llvm/CodeGen/RuntimeLibcalls.def
Expand Up @@ -130,26 +130,51 @@ HANDLE_LIBCALL(LOG_F64, "log")
HANDLE_LIBCALL(LOG_F80, "logl")
HANDLE_LIBCALL(LOG_F128, "logl")
HANDLE_LIBCALL(LOG_PPCF128, "logl")
HANDLE_LIBCALL(LOG_FINITE_F32, "__logf_finite")
HANDLE_LIBCALL(LOG_FINITE_F64, "__log_finite")
HANDLE_LIBCALL(LOG_FINITE_F80, "__logl_finite")
HANDLE_LIBCALL(LOG_FINITE_F128, "__logl_finite")
HANDLE_LIBCALL(LOG_FINITE_PPCF128, "__logl_finite")
HANDLE_LIBCALL(LOG2_F32, "log2f")
HANDLE_LIBCALL(LOG2_F64, "log2")
HANDLE_LIBCALL(LOG2_F80, "log2l")
HANDLE_LIBCALL(LOG2_F128, "log2l")
HANDLE_LIBCALL(LOG2_PPCF128, "log2l")
HANDLE_LIBCALL(LOG2_FINITE_F32, "__log2f_finite")
HANDLE_LIBCALL(LOG2_FINITE_F64, "__log2_finite")
HANDLE_LIBCALL(LOG2_FINITE_F80, "__log2l_finite")
HANDLE_LIBCALL(LOG2_FINITE_F128, "__log2l_finite")
HANDLE_LIBCALL(LOG2_FINITE_PPCF128, "__log2l_finite")
HANDLE_LIBCALL(LOG10_F32, "log10f")
HANDLE_LIBCALL(LOG10_F64, "log10")
HANDLE_LIBCALL(LOG10_F80, "log10l")
HANDLE_LIBCALL(LOG10_F128, "log10l")
HANDLE_LIBCALL(LOG10_PPCF128, "log10l")
HANDLE_LIBCALL(LOG10_FINITE_F32, "__log10f_finite")
HANDLE_LIBCALL(LOG10_FINITE_F64, "__log10_finite")
HANDLE_LIBCALL(LOG10_FINITE_F80, "__log10l_finite")
HANDLE_LIBCALL(LOG10_FINITE_F128, "__log10l_finite")
HANDLE_LIBCALL(LOG10_FINITE_PPCF128, "__log10l_finite")
HANDLE_LIBCALL(EXP_F32, "expf")
HANDLE_LIBCALL(EXP_F64, "exp")
HANDLE_LIBCALL(EXP_F80, "expl")
HANDLE_LIBCALL(EXP_F128, "expl")
HANDLE_LIBCALL(EXP_PPCF128, "expl")
HANDLE_LIBCALL(EXP_FINITE_F32, "__expf_finite")
HANDLE_LIBCALL(EXP_FINITE_F64, "__exp_finite")
HANDLE_LIBCALL(EXP_FINITE_F80, "__expl_finite")
HANDLE_LIBCALL(EXP_FINITE_F128, "__expl_finite")
HANDLE_LIBCALL(EXP_FINITE_PPCF128, "__expl_finite")
HANDLE_LIBCALL(EXP2_F32, "exp2f")
HANDLE_LIBCALL(EXP2_F64, "exp2")
HANDLE_LIBCALL(EXP2_F80, "exp2l")
HANDLE_LIBCALL(EXP2_F128, "exp2l")
HANDLE_LIBCALL(EXP2_PPCF128, "exp2l")
HANDLE_LIBCALL(EXP2_FINITE_F32, "__exp2f_finite")
HANDLE_LIBCALL(EXP2_FINITE_F64, "__exp2_finite")
HANDLE_LIBCALL(EXP2_FINITE_F80, "__exp2l_finite")
HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2l_finite")
HANDLE_LIBCALL(EXP2_FINITE_PPCF128, "__exp2l_finite")
HANDLE_LIBCALL(SIN_F32, "sinf")
HANDLE_LIBCALL(SIN_F64, "sin")
HANDLE_LIBCALL(SIN_F80, "sinl")
Expand All @@ -172,6 +197,11 @@ HANDLE_LIBCALL(POW_F64, "pow")
HANDLE_LIBCALL(POW_F80, "powl")
HANDLE_LIBCALL(POW_F128, "powl")
HANDLE_LIBCALL(POW_PPCF128, "powl")
HANDLE_LIBCALL(POW_FINITE_F32, "__powf_finite")
HANDLE_LIBCALL(POW_FINITE_F64, "__pow_finite")
HANDLE_LIBCALL(POW_FINITE_F80, "__powl_finite")
HANDLE_LIBCALL(POW_FINITE_F128, "__powl_finite")
HANDLE_LIBCALL(POW_FINITE_PPCF128, "__powl_finite")
HANDLE_LIBCALL(CEIL_F32, "ceilf")
HANDLE_LIBCALL(CEIL_F64, "ceil")
HANDLE_LIBCALL(CEIL_F80, "ceill")
Expand Down
5 changes: 4 additions & 1 deletion llvm/include/llvm/CodeGen/SelectionDAG.h
Expand Up @@ -73,6 +73,7 @@ class OptimizationRemarkEmitter;
class SDDbgValue;
class SelectionDAG;
class SelectionDAGTargetInfo;
class TargetLibraryInfo;
class TargetLowering;
class TargetMachine;
class TargetSubtargetInfo;
Expand Down Expand Up @@ -210,6 +211,7 @@ class SelectionDAG {
const TargetMachine &TM;
const SelectionDAGTargetInfo *TSI = nullptr;
const TargetLowering *TLI = nullptr;
const TargetLibraryInfo *LibInfo = nullptr;
MachineFunction *MF;
Pass *SDAGISelPass = nullptr;
LLVMContext *Context;
Expand Down Expand Up @@ -376,7 +378,7 @@ class SelectionDAG {

/// Prepare this SelectionDAG to process code in the given MachineFunction.
void init(MachineFunction &NewMF, OptimizationRemarkEmitter &NewORE,
Pass *PassPtr);
Pass *PassPtr, const TargetLibraryInfo *LibraryInfo);

/// Clear state and free memory necessary to make this
/// SelectionDAG ready to process a new block.
Expand All @@ -389,6 +391,7 @@ class SelectionDAG {
const TargetMachine &getTarget() const { return TM; }
const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); }
const TargetLowering &getTargetLoweringInfo() const { return *TLI; }
const TargetLibraryInfo &getLibInfo() const { return *LibInfo; }
const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; }
LLVMContext *getContext() const {return Context; }
OptimizationRemarkEmitter &getORE() const { return *ORE; }
Expand Down
80 changes: 62 additions & 18 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Expand Up @@ -3932,6 +3932,8 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
DEBUG(dbgs() << "Trying to convert node to libcall\n");
SmallVector<SDValue, 8> Results;
SDLoc dl(Node);
// FIXME: Check flags on the node to see if we can use a finite call.
bool CanUseFiniteLibCall = TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath;
unsigned Opc = Node->getOpcode();
switch (Opc) {
case ISD::ATOMIC_FENCE: {
Expand Down Expand Up @@ -4026,33 +4028,68 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
break;
case ISD::FLOG:
case ISD::STRICT_FLOG:
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_F32, RTLIB::LOG_F64,
RTLIB::LOG_F80, RTLIB::LOG_F128,
RTLIB::LOG_PPCF128));
if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_log_finite))
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_FINITE_F32,
RTLIB::LOG_FINITE_F64,
RTLIB::LOG_FINITE_F80,
RTLIB::LOG_FINITE_F128,
RTLIB::LOG_FINITE_PPCF128));
else
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_F32, RTLIB::LOG_F64,
RTLIB::LOG_F80, RTLIB::LOG_F128,
RTLIB::LOG_PPCF128));
break;
case ISD::FLOG2:
case ISD::STRICT_FLOG2:
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64,
RTLIB::LOG2_F80, RTLIB::LOG2_F128,
RTLIB::LOG2_PPCF128));
if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_log2_finite))
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_FINITE_F32,
RTLIB::LOG2_FINITE_F64,
RTLIB::LOG2_FINITE_F80,
RTLIB::LOG2_FINITE_F128,
RTLIB::LOG2_FINITE_PPCF128));
else
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64,
RTLIB::LOG2_F80, RTLIB::LOG2_F128,
RTLIB::LOG2_PPCF128));
break;
case ISD::FLOG10:
case ISD::STRICT_FLOG10:
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64,
RTLIB::LOG10_F80, RTLIB::LOG10_F128,
RTLIB::LOG10_PPCF128));
if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_log10_finite))
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_FINITE_F32,
RTLIB::LOG10_FINITE_F64,
RTLIB::LOG10_FINITE_F80,
RTLIB::LOG10_FINITE_F128,
RTLIB::LOG10_FINITE_PPCF128));
else
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64,
RTLIB::LOG10_F80, RTLIB::LOG10_F128,
RTLIB::LOG10_PPCF128));
break;
case ISD::FEXP:
case ISD::STRICT_FEXP:
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_F32, RTLIB::EXP_F64,
RTLIB::EXP_F80, RTLIB::EXP_F128,
RTLIB::EXP_PPCF128));
if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_exp_finite))
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_FINITE_F32,
RTLIB::EXP_FINITE_F64,
RTLIB::EXP_FINITE_F80,
RTLIB::EXP_FINITE_F128,
RTLIB::EXP_FINITE_PPCF128));
else
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_F32, RTLIB::EXP_F64,
RTLIB::EXP_F80, RTLIB::EXP_F128,
RTLIB::EXP_PPCF128));
break;
case ISD::FEXP2:
case ISD::STRICT_FEXP2:
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64,
RTLIB::EXP2_F80, RTLIB::EXP2_F128,
RTLIB::EXP2_PPCF128));
if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_exp2_finite))
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_FINITE_F32,
RTLIB::EXP2_FINITE_F64,
RTLIB::EXP2_FINITE_F80,
RTLIB::EXP2_FINITE_F128,
RTLIB::EXP2_FINITE_PPCF128));
else
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64,
RTLIB::EXP2_F80, RTLIB::EXP2_F128,
RTLIB::EXP2_PPCF128));
break;
case ISD::FTRUNC:
Results.push_back(ExpandFPLibCall(Node, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64,
Expand Down Expand Up @@ -4098,9 +4135,16 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
break;
case ISD::FPOW:
case ISD::STRICT_FPOW:
Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_F32, RTLIB::POW_F64,
RTLIB::POW_F80, RTLIB::POW_F128,
RTLIB::POW_PPCF128));
if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_pow_finite))
Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_FINITE_F32,
RTLIB::POW_FINITE_F64,
RTLIB::POW_FINITE_F80,
RTLIB::POW_FINITE_F128,
RTLIB::POW_FINITE_PPCF128));
else
Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_F32, RTLIB::POW_F64,
RTLIB::POW_F80, RTLIB::POW_F128,
RTLIB::POW_PPCF128));
break;
case ISD::FDIV:
Results.push_back(ExpandFPLibCall(Node, RTLIB::DIV_F32, RTLIB::DIV_F64,
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Expand Up @@ -903,12 +903,13 @@ SelectionDAG::SelectionDAG(const TargetMachine &tm, CodeGenOpt::Level OL)

void SelectionDAG::init(MachineFunction &NewMF,
OptimizationRemarkEmitter &NewORE,
Pass *PassPtr) {
Pass *PassPtr, const TargetLibraryInfo *LibraryInfo) {
MF = &NewMF;
SDAGISelPass = PassPtr;
ORE = &NewORE;
TLI = getSubtarget().getTargetLowering();
TSI = getSubtarget().getSelectionDAGInfo();
LibInfo = LibraryInfo;
Context = &MF->getFunction().getContext();
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
Expand Up @@ -414,7 +414,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {

SplitCriticalSideEffectEdges(const_cast<Function &>(Fn), DT, LI);

CurDAG->init(*MF, *ORE, this);
CurDAG->init(*MF, *ORE, this, LibInfo);
FuncInfo->set(Fn, *MF, CurDAG);

// Now get the optional analyzes if we want to.
Expand Down

0 comments on commit 37e28e4

Please sign in to comment.