This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Complete folding of fneg-of-fabs
ClosedPublic

Authored by Chenbing.Zheng on Apr 14 2022, 7:40 PM.

Details

Summary

This patch add a function foldSelectToFabs, and do more combine for
fneg-of-fabs.

With 'nsz'

fold (X <  +/-0.0) ? X : -X or (X <= +/-0.0) ? X : -X to -fabs(x)
fold (X >  +/-0.0) ? X : -X or (X >= +/-0.0) ? X : -X to -fabs(x)

Diff Detail

Event Timeline

Chenbing.Zheng created this revision.Apr 14 2022, 7:40 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 14 2022, 7:40 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
Chenbing.Zheng requested review of this revision.Apr 14 2022, 7:40 PM

format correction

This doesn't solve the root problem. If we start with the existing code in the test that is changing, it will not become fneg(fabs) like we want?
https://alive2.llvm.org/ce/z/e_uhUQ

We should extend the code under InstCombinerImpl::visitSelectInst() to match "nabs" patterns. Search for: "// Canonicalize select with fcmp to fabs()."

Chenbing.Zheng retitled this revision from [InstCombine] Optimize folding of fneg-of-fabs to [InstCombine] Complete folding of fneg-of-fabs.
Chenbing.Zheng edited the summary of this revision. (Show Details)

address comments

spatel added inline comments.Apr 21 2022, 5:24 AM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2812

We don't check 'nnan', so this comment is wrong.

I see that it is copied from above, so that suggests a better solution than only fixing it on this line: can you reduce the code duplication by moving the existing fabs transforms to a helper function or lambda?

Maybe it is easier if we match the negated value in the select first (and give it the name 'X'), then match the compare?

Chenbing.Zheng edited the summary of this revision. (Show Details)

Thanks for spatel's suggestion , that's very useful.

Thanks for spatel's suggestion , that's very useful.

Yes, this looks nicer. See inline for some small improvements.

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2503

Swap should be a bool parameter, and the caller can use "for (bool Swap : {false, true} )".
Or we can move the FNeg part of the transform into this function and avoid the parameter completely?

2506

If we name this value 'X', then the code would match the comments, so that seems easier to read - see the next comments for a possible reduction.

2512–2513

We can move this statement to above the function declaration now. It describes the complete behavior of this function.

2532–2533

This logic seems more complicated than needed. If we always match the TrueVal as -X, then we can get the swapped predicate and reduce the code to something like this:

if (!match(TrueVal, m_FNeg(m_Specific(FalseVal))) || !SI.hasNoSignedZeros())
  return nullptr;

if (Swap)
  Pred = FCmpInst::getSwappedPredicate(Pred);

// With nsz:
// fold (X <  +/-0.0) ? -X : X or (X <= +/-0.0) ? -X : X to fabs(X)
// fold (X >  +/-0.0) ? -X : X or (X >= +/-0.0) ? X : -X to -fabs(x)
bool IsLTOrLE = Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE ||
                Pred == FCmpInst::FCMP_ULT || Pred == FCmpInst::FCMP_ULE;
bool IsGTOrGE = Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_OGE ||
                Pred == FCmpInst::FCMP_UGT || Pred == FCmpInst::FCMP_UGE;

if (IsLTOrLE)
  return Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FalseVal, &SI);
if (IsGTOrGE) {
  IsNeg = true;
  return Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FalseVal, &SI);
}

address comments

spatel accepted this revision.Apr 24 2022, 7:27 AM

LGTM

This revision is now accepted and ready to land.Apr 24 2022, 7:27 AM
This revision was landed with ongoing or failed builds.Apr 24 2022, 6:54 PM
This revision was automatically updated to reflect the committed changes.