This is an archive of the discontinued LLVM Phabricator instance.

[SelectionDAG] Expand nnan FMINNUM/FMAXNUM to select sequence
ClosedPublic

Authored by uweigand on Dec 3 2019, 8:11 AM.

Details

Summary

As discussed in D70852, currently LLVM may introduce calls to fmin/fmax into programs that originally did not have any dependency against libm, potentially causing failures at link time.

This patch attempts to solve this issue by adding code to TargetLowering::expandFMINNUM_FMAXNUM to expand FMINNUM/FMAXNUM to a compare+select sequence instead of the libcall. This is done only if the node is marked as "nnan". In this case, the expansion to compare+select is always correct. This also catches all cases where the FMINNUM/FMAXNUM was synthesized by LLVM; this is also only done in the nnan case.

Diff Detail

Event Timeline

uweigand created this revision.Dec 3 2019, 8:11 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 3 2019, 8:11 AM
spatel added inline comments.Dec 3 2019, 9:08 AM
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
6234

I think this is an acceptable check of the FMF, but the reasoning is subtle. If we synthesized the intrinsic in IR, it required 'nsz' for the fcmp/select because the original code using fcmp can produce a different result for -0.0.

And that is because the intrinsics have this clause:
"If the operands compare equal, returns a value that compares equal to both operands. This means that fmin(+/-0.0, +/-0.0) could return either -0.0 or 0.0"

So once we have the intrinsic, the 'nsz' behavior becomes implicit.

And since we're not checking for 'nsz' explicitly in this expansion, that means that we may be transforming code that originally had the libcall in source to inline code (the intrinsic was not created by InstCombine without 'nsz').

But that's probably a good optimization for a target that is expanding these nodes anyway?

To not lose an optimization opportunity, I think we need to add 'nsz' to the setFlags() call under here. Or avoid this complexity and check for 'nsz' in the first place.

6237–6239

Variables named 'Tmp' make me nervous. :)
I'd prefer to not reassign local names:

SDValue Op0 = Node->getOperand(0);
SDValue Op1 = Node->getOperand(1);
SDValue SelCC = DAG.getSelectCC(dl, Op0, Op1, Op0, Op1, Pred);
uweigand updated this revision to Diff 231960.Dec 3 2019, 12:24 PM
uweigand marked 4 inline comments as done.Dec 3 2019, 12:27 PM
uweigand added inline comments.
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
6234

I deliberately did not check nsz because I understood this to be implied anyway by the semantics of the FMINNUM/FMAXNUM nodes:

/// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.

I've now added code to explicitly set nsz on the select node.

6237–6239

Sorry about that, too much copy-and-paste from LegalizeDAG :-)

spatel accepted this revision.Dec 3 2019, 1:22 PM

LGTM

This revision is now accepted and ready to land.Dec 3 2019, 1:22 PM
This revision was automatically updated to reflect the committed changes.
uweigand marked 2 inline comments as done.