diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-03-19 15:14:30 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-03-19 15:14:30 +0000 |
commit | 0ce308677793d1904d85ce341e169f7ac01e8c46 (patch) | |
tree | f0d889ad281d8600bca395fb7eadb3480788a77b /llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | |
parent | e5340a8ce962141534fc9b042e189b2ce84e6e01 (diff) | |
download | llvm-0ce308677793d1904d85ce341e169f7ac01e8c46.zip llvm-0ce308677793d1904d85ce341e169f7ac01e8c46.tar.gz llvm-0ce308677793d1904d85ce341e169f7ac01e8c46.tar.bz2 |
[InstCombine] canonicalize fcmp+select to fabs
This is complicated by -0.0 and nan. This is based on the DAG patterns
as shown in D44091. I'm hoping that we can just remove those DAG folds
and always rely on IR canonicalization to handle the matching to fabs.
We would still need to delete the broken code from DAGCombiner to fix
PR36600:
https://bugs.llvm.org/show_bug.cgi?id=36600
Differential Revision: https://reviews.llvm.org/D44550
llvm-svn: 327858
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 1f89ca6..ff682ac 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1569,7 +1569,37 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { // NOTE: if we wanted to, this is where to detect MIN/MAX } - // NOTE: if we wanted to, this is where to detect ABS + + // Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need + // fast-math-flags (nsz) or fsub with +0.0 (not fneg) for this to work. We + // also require nnan because we do not want to unintentionally change the + // sign of a NaN value. + Value *X = FCI->getOperand(0); + FCmpInst::Predicate Pred = FCI->getPredicate(); + if (match(FCI->getOperand(1), m_AnyZeroFP()) && FCI->hasNoNaNs()) { + // (X <= +/-0.0) ? (0.0 - X) : X --> fabs(X) + // (X > +/-0.0) ? X : (0.0 - X) --> fabs(X) + if ((X == FalseVal && match(TrueVal, m_FSub(m_Zero(), m_Specific(X))) && + Pred == FCmpInst::FCMP_OLE) || + (X == TrueVal && match(FalseVal, m_FSub(m_Zero(), m_Specific(X))) && + Pred == FCmpInst::FCMP_OGT)) { + Value *Fabs = Builder.CreateIntrinsic(Intrinsic::fabs, { X }, FCI); + return replaceInstUsesWith(SI, Fabs); + } + // With nsz: + // (X < +/-0.0) ? -X : X --> fabs(X) + // (X <= +/-0.0) ? -X : X --> fabs(X) + // (X > +/-0.0) ? X : -X --> fabs(X) + // (X >= +/-0.0) ? X : -X --> fabs(X) + if (FCI->hasNoSignedZeros() && + ((X == FalseVal && match(TrueVal, m_FNeg(m_Specific(X))) && + (Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE)) || + (X == TrueVal && match(FalseVal, m_FNeg(m_Specific(X))) && + (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_OGE)))) { + Value *Fabs = Builder.CreateIntrinsic(Intrinsic::fabs, { X }, FCI); + return replaceInstUsesWith(SI, Fabs); + } + } } // See if we are selecting two values based on a comparison of the two values. |