aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-03-19 15:14:30 +0000
committerSanjay Patel <spatel@rotateright.com>2018-03-19 15:14:30 +0000
commit0ce308677793d1904d85ce341e169f7ac01e8c46 (patch)
treef0d889ad281d8600bca395fb7eadb3480788a77b /llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
parente5340a8ce962141534fc9b042e189b2ce84e6e01 (diff)
downloadllvm-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.cpp32
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.