summaryrefslogtreecommitdiffstats
path: root/include/llvm/Support/PatternMatch.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Support/PatternMatch.h')
-rw-r--r--include/llvm/Support/PatternMatch.h93
1 files changed, 93 insertions, 0 deletions
diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h
index 172480e..f0fb516 100644
--- a/include/llvm/Support/PatternMatch.h
+++ b/include/llvm/Support/PatternMatch.h
@@ -694,6 +694,99 @@ inline brc_match<Cond_t> m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) {
return brc_match<Cond_t>(C, T, F);
}
+
+//===----------------------------------------------------------------------===//
+// Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y).
+//
+
+template<typename LHS_t, typename RHS_t, typename Pred_t>
+struct MaxMin_match {
+ LHS_t L;
+ RHS_t R;
+
+ MaxMin_match(const LHS_t &LHS, const RHS_t &RHS)
+ : L(LHS), R(RHS) {}
+
+ template<typename OpTy>
+ bool match(OpTy *V) {
+ // Look for "(x pred y) ? x : y" or "(x pred y) ? y : x".
+ SelectInst *SI = dyn_cast<SelectInst>(V);
+ if (!SI)
+ return false;
+ ICmpInst *Cmp = dyn_cast<ICmpInst>(SI->getCondition());
+ if (!Cmp)
+ return false;
+ // At this point we have a select conditioned on a comparison. Check that
+ // it is the values returned by the select that are being compared.
+ Value *TrueVal = SI->getTrueValue();
+ Value *FalseVal = SI->getFalseValue();
+ Value *LHS = Cmp->getOperand(0);
+ Value *RHS = Cmp->getOperand(1);
+ if ((TrueVal != LHS || FalseVal != RHS) &&
+ (TrueVal != RHS || FalseVal != LHS))
+ return false;
+ ICmpInst::Predicate Pred = LHS == TrueVal ?
+ Cmp->getPredicate() : Cmp->getSwappedPredicate();
+ // Does "(x pred y) ? x : y" represent the desired max/min operation?
+ if (!Pred_t::match(Pred))
+ return false;
+ // It does! Bind the operands.
+ return L.match(LHS) && R.match(RHS);
+ }
+};
+
+/// smax_pred_ty - Helper class for identifying signed max predicates.
+struct smax_pred_ty {
+ static bool match(ICmpInst::Predicate Pred) {
+ return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE;
+ }
+};
+
+/// smin_pred_ty - Helper class for identifying signed min predicates.
+struct smin_pred_ty {
+ static bool match(ICmpInst::Predicate Pred) {
+ return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE;
+ }
+};
+
+/// umax_pred_ty - Helper class for identifying unsigned max predicates.
+struct umax_pred_ty {
+ static bool match(ICmpInst::Predicate Pred) {
+ return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE;
+ }
+};
+
+/// umin_pred_ty - Helper class for identifying unsigned min predicates.
+struct umin_pred_ty {
+ static bool match(ICmpInst::Predicate Pred) {
+ return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE;
+ }
+};
+
+template<typename LHS, typename RHS>
+inline MaxMin_match<LHS, RHS, smax_pred_ty>
+m_SMax(const LHS &L, const RHS &R) {
+ return MaxMin_match<LHS, RHS, smax_pred_ty>(L, R);
+}
+
+template<typename LHS, typename RHS>
+inline MaxMin_match<LHS, RHS, smin_pred_ty>
+m_SMin(const LHS &L, const RHS &R) {
+ return MaxMin_match<LHS, RHS, smin_pred_ty>(L, R);
+}
+
+template<typename LHS, typename RHS>
+inline MaxMin_match<LHS, RHS, umax_pred_ty>
+m_UMax(const LHS &L, const RHS &R) {
+ return MaxMin_match<LHS, RHS, umax_pred_ty>(L, R);
+}
+
+template<typename LHS, typename RHS>
+inline MaxMin_match<LHS, RHS, umin_pred_ty>
+m_UMin(const LHS &L, const RHS &R) {
+ return MaxMin_match<LHS, RHS, umin_pred_ty>(L, R);
+}
+
} // end namespace PatternMatch
} // end namespace llvm
OpenPOWER on IntegriCloud