diff options
Diffstat (limited to 'include/llvm/IR/PatternMatch.h')
-rw-r--r-- | include/llvm/IR/PatternMatch.h | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 41154e6441a9..f4d7d8c44416 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -1272,6 +1272,46 @@ inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMax(const Opnd0 &Op0, return m_Intrinsic<Intrinsic::maxnum>(Op0, Op1); } +template <typename Opnd_t> struct Signum_match { + Opnd_t Val; + Signum_match(const Opnd_t &V) : Val(V) {} + + template <typename OpTy> bool match(OpTy *V) { + unsigned TypeSize = V->getType()->getScalarSizeInBits(); + if (TypeSize == 0) + return false; + + unsigned ShiftWidth = TypeSize - 1; + Value *OpL = nullptr, *OpR = nullptr; + + // This is the representation of signum we match: + // + // signum(x) == (x >> 63) | (-x >>u 63) + // + // An i1 value is its own signum, so it's correct to match + // + // signum(x) == (x >> 0) | (-x >>u 0) + // + // for i1 values. + + auto LHS = m_AShr(m_Value(OpL), m_SpecificInt(ShiftWidth)); + auto RHS = m_LShr(m_Neg(m_Value(OpR)), m_SpecificInt(ShiftWidth)); + auto Signum = m_Or(LHS, RHS); + + return Signum.match(V) && OpL == OpR && Val.match(OpL); + } +}; + +/// \brief Matches a signum pattern. +/// +/// signum(x) = +/// x > 0 -> 1 +/// x == 0 -> 0 +/// x < 0 -> -1 +template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) { + return Signum_match<Val_t>(V); +} + } // end namespace PatternMatch } // end namespace llvm |