diff options
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 51 | 
1 files changed, 44 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp index 40c1ba88354f1..55d3761c036f1 100644 --- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp +++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp @@ -152,13 +152,50 @@ static bool matchSelectWithOptionalNotCond(Value *V, Value *&Cond, Value *&A,      std::swap(A, B);    } -  // Set flavor if we find a match, or set it to unknown otherwise; in -  // either case, return true to indicate that this is a select we can -  // process. -  if (auto *CmpI = dyn_cast<ICmpInst>(Cond)) -    Flavor = matchDecomposedSelectPattern(CmpI, A, B, A, B).Flavor; -  else -    Flavor = SPF_UNKNOWN; +  // Match canonical forms of abs/nabs/min/max. We are not using ValueTracking's +  // more powerful matchSelectPattern() because it may rely on instruction flags +  // such as "nsw". That would be incompatible with the current hashing +  // mechanism that may remove flags to increase the likelihood of CSE. + +  // These are the canonical forms of abs(X) and nabs(X) created by instcombine: +  // %N = sub i32 0, %X +  // %C = icmp slt i32 %X, 0 +  // %ABS = select i1 %C, i32 %N, i32 %X +  // +  // %N = sub i32 0, %X +  // %C = icmp slt i32 %X, 0 +  // %NABS = select i1 %C, i32 %X, i32 %N +  Flavor = SPF_UNKNOWN; +  CmpInst::Predicate Pred; +  if (match(Cond, m_ICmp(Pred, m_Specific(B), m_ZeroInt())) && +      Pred == ICmpInst::ICMP_SLT && match(A, m_Neg(m_Specific(B)))) { +    // ABS: B < 0 ? -B : B +    Flavor = SPF_ABS; +    return true; +  } +  if (match(Cond, m_ICmp(Pred, m_Specific(A), m_ZeroInt())) && +      Pred == ICmpInst::ICMP_SLT && match(B, m_Neg(m_Specific(A)))) { +    // NABS: A < 0 ? A : -A +    Flavor = SPF_NABS; +    return true; +  } + +  if (!match(Cond, m_ICmp(Pred, m_Specific(A), m_Specific(B)))) { +    // Check for commuted variants of min/max by swapping predicate. +    // If we do not match the standard or commuted patterns, this is not a +    // recognized form of min/max, but it is still a select, so return true. +    if (!match(Cond, m_ICmp(Pred, m_Specific(B), m_Specific(A)))) +      return true; +    Pred = ICmpInst::getSwappedPredicate(Pred); +  } + +  switch (Pred) { +  case CmpInst::ICMP_UGT: Flavor = SPF_UMAX; break; +  case CmpInst::ICMP_ULT: Flavor = SPF_UMIN; break; +  case CmpInst::ICMP_SGT: Flavor = SPF_SMAX; break; +  case CmpInst::ICMP_SLT: Flavor = SPF_SMIN; break; +  default: break; +  }    return true;  }  | 
