[llvm] 60f2c6a - [PatternMatch] allow intrinsic form of min/max with existing matchers

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 6 07:52:55 PDT 2020


Author: Sanjay Patel
Date: 2020-08-06T10:50:24-04:00
New Revision: 60f2c6a94cdff51fb8906030bbb73ba1c90da1c4

URL: https://github.com/llvm/llvm-project/commit/60f2c6a94cdff51fb8906030bbb73ba1c90da1c4
DIFF: https://github.com/llvm/llvm-project/commit/60f2c6a94cdff51fb8906030bbb73ba1c90da1c4.diff

LOG: [PatternMatch] allow intrinsic form of min/max with existing matchers

I skimmed the existing users of these matchers and don't see any problems
(eg, the caller assumes the matched value was a select instruction without checking).

So I think we can generalize the matching to allow the new intrinsics or the cmp+select idioms.

I did not find any unit tests for the matchers, so added some basics there. The instsimplify
tests are adapted from existing tests for the cmp+select pattern and cover the folds in
simplifyICmpWithMinMax().

Differential Revision: https://reviews.llvm.org/D85230

Added: 
    

Modified: 
    llvm/include/llvm/IR/PatternMatch.h
    llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll
    llvm/unittests/IR/PatternMatch.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 0850835aa014..f706d351420b 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -1590,6 +1590,17 @@ struct MaxMin_match {
   MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
 
   template <typename OpTy> bool match(OpTy *V) {
+    if (auto *II = dyn_cast<IntrinsicInst>(V)) {
+      Intrinsic::ID IID = II->getIntrinsicID();
+      if ((IID == Intrinsic::smax && Pred_t::match(ICmpInst::ICMP_SGT)) ||
+          (IID == Intrinsic::smin && Pred_t::match(ICmpInst::ICMP_SLT)) ||
+          (IID == Intrinsic::umax && Pred_t::match(ICmpInst::ICMP_UGT)) ||
+          (IID == Intrinsic::umin && Pred_t::match(ICmpInst::ICMP_ULT))) {
+        Value *LHS = II->getOperand(0), *RHS = II->getOperand(1);
+        return (L.match(LHS) && R.match(RHS)) ||
+               (Commutable && L.match(RHS) && R.match(LHS));
+      }
+    }
     // Look for "(x pred y) ? x : y" or "(x pred y) ? y : x".
     auto *SI = dyn_cast<SelectInst>(V);
     if (!SI)

diff  --git a/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll b/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll
index 1053bfa431ed..9fad690d79ac 100644
--- a/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll
+++ b/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll
@@ -812,9 +812,7 @@ define <2 x i8> @smax_smax_constants_partial_undef(<2 x i8> %x) {
 
 define i1 @smax_slt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_slt(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[M]], [[X]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %r = icmp slt i8 %m, %x
@@ -823,9 +821,7 @@ define i1 @smax_slt(i8 %x, i8 %y) {
 
 define i1 @smax_sge(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_sge(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp sge i8 [[M]], [[X]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %m = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %r = icmp sge i8 %m, %x
@@ -834,9 +830,7 @@ define i1 @smax_sge(i8 %x, i8 %y) {
 
 define i1 @umax_ult(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_ult(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[M]], [[X]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %r = icmp ult i8 %m, %x
@@ -845,9 +839,7 @@ define i1 @umax_ult(i8 %x, i8 %y) {
 
 define i1 @umax_uge(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_uge(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[M]], [[X]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %m = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %r = icmp uge i8 %m, %x
@@ -856,9 +848,7 @@ define i1 @umax_uge(i8 %x, i8 %y) {
 
 define i1 @smax_sgt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_sgt(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[X]], [[M]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %r = icmp sgt i8 %x, %m
@@ -867,9 +857,7 @@ define i1 @smax_sgt(i8 %x, i8 %y) {
 
 define i1 @smax_sle(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_sle(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp sle i8 [[X]], [[M]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %m = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %r = icmp sle i8 %x, %m
@@ -878,9 +866,7 @@ define i1 @smax_sle(i8 %x, i8 %y) {
 
 define i1 @umax_ugt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_ugt(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[X]], [[M]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %r = icmp ugt i8 %x, %m
@@ -889,9 +875,7 @@ define i1 @umax_ugt(i8 %x, i8 %y) {
 
 define i1 @umax_ule(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_ule(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[X]], [[M]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %m = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %r = icmp ule i8 %x, %m
@@ -900,9 +884,7 @@ define i1 @umax_ule(i8 %x, i8 %y) {
 
 define i1 @smin_sgt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_sgt(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[M]], [[X]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %r = icmp sgt i8 %m, %x
@@ -911,9 +893,7 @@ define i1 @smin_sgt(i8 %x, i8 %y) {
 
 define i1 @smin_sle(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_sle(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp sle i8 [[M]], [[X]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %r = icmp sle i8 %m, %x
@@ -922,9 +902,7 @@ define i1 @smin_sle(i8 %x, i8 %y) {
 
 define i1 @umin_ugt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_ugt(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[M]], [[X]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %r = icmp ugt i8 %m, %x
@@ -933,9 +911,7 @@ define i1 @umin_ugt(i8 %x, i8 %y) {
 
 define i1 @umin_ule(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_ule(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[M]], [[X]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %r = icmp ule i8 %m, %x
@@ -944,9 +920,7 @@ define i1 @umin_ule(i8 %x, i8 %y) {
 
 define i1 @smin_slt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_slt(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[X]], [[M]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %r = icmp slt i8 %x, %m
@@ -955,9 +929,7 @@ define i1 @smin_slt(i8 %x, i8 %y) {
 
 define i1 @smin_sge(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_sge(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp sge i8 [[X]], [[M]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %r = icmp sge i8 %x, %m
@@ -966,9 +938,7 @@ define i1 @smin_sge(i8 %x, i8 %y) {
 
 define i1 @umin_ult(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_ult(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[X]], [[M]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %r = icmp ult i8 %x, %m
@@ -977,9 +947,7 @@ define i1 @umin_ult(i8 %x, i8 %y) {
 
 define i1 @umin_uge(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_uge(
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[X]], [[M]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 true
 ;
   %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %r = icmp uge i8 %x, %m
@@ -988,10 +956,7 @@ define i1 @umin_uge(i8 %x, i8 %y) {
 
 define i1 @smaxmin_sge(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @smaxmin_sge(
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[Z:%.*]], i8 [[X]])
-; CHECK-NEXT:    [[C:%.*]] = icmp sge i8 [[MAX]], [[MIN]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 true
 ;
   %max = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %min = call i8 @llvm.smin.i8(i8 %z, i8 %x)
@@ -1001,10 +966,7 @@ define i1 @smaxmin_sge(i8 %x, i8 %y, i8 %z) {
 
 define i1 @smaxmin_sgt(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @smaxmin_sgt(
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[Z:%.*]], i8 [[X]])
-; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[MIN]], [[MAX]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 false
 ;
   %max = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %min = call i8 @llvm.smin.i8(i8 %z, i8 %x)
@@ -1014,10 +976,7 @@ define i1 @smaxmin_sgt(i8 %x, i8 %y, i8 %z) {
 
 define i1 @smaxmin_sle(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @smaxmin_sle(
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[Z:%.*]], i8 [[X]])
-; CHECK-NEXT:    [[C:%.*]] = icmp sle i8 [[MIN]], [[MAX]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 true
 ;
   %max = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %min = call i8 @llvm.smin.i8(i8 %z, i8 %x)
@@ -1027,10 +986,7 @@ define i1 @smaxmin_sle(i8 %x, i8 %y, i8 %z) {
 
 define i1 @smaxmin_slt(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @smaxmin_slt(
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[Z:%.*]], i8 [[X]])
-; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[MAX]], [[MIN]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 false
 ;
   %max = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %min = call i8 @llvm.smin.i8(i8 %z, i8 %x)
@@ -1040,10 +996,7 @@ define i1 @smaxmin_slt(i8 %x, i8 %y, i8 %z) {
 
 define i1 @umaxmin_uge(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @umaxmin_uge(
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X]])
-; CHECK-NEXT:    [[C:%.*]] = icmp uge i8 [[MAX]], [[MIN]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 true
 ;
   %max = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %min = call i8 @llvm.umin.i8(i8 %z, i8 %x)
@@ -1053,10 +1006,7 @@ define i1 @umaxmin_uge(i8 %x, i8 %y, i8 %z) {
 
 define i1 @umaxmin_ugt(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @umaxmin_ugt(
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X]])
-; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 [[MIN]], [[MAX]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 false
 ;
   %max = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %min = call i8 @llvm.umin.i8(i8 %z, i8 %x)
@@ -1066,10 +1016,7 @@ define i1 @umaxmin_ugt(i8 %x, i8 %y, i8 %z) {
 
 define i1 @umaxmin_ule(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @umaxmin_ule(
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X]])
-; CHECK-NEXT:    [[C:%.*]] = icmp ule i8 [[MIN]], [[MAX]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 true
 ;
   %max = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %min = call i8 @llvm.umin.i8(i8 %z, i8 %x)
@@ -1079,10 +1026,7 @@ define i1 @umaxmin_ule(i8 %x, i8 %y, i8 %z) {
 
 define i1 @umaxmin_ult(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @umaxmin_ult(
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X]])
-; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[MAX]], [[MIN]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 false
 ;
   %max = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %min = call i8 @llvm.umin.i8(i8 %z, i8 %x)
@@ -1090,6 +1034,8 @@ define i1 @umaxmin_ult(i8 %x, i8 %y, i8 %z) {
   ret i1 %c
 }
 
+; Negative test - should reduce via instcombine, but not here.
+
 define i1 @smax_eq(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_eq(
 ; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1101,6 +1047,8 @@ define i1 @smax_eq(i8 %x, i8 %y) {
   ret i1 %r
 }
 
+; Negative test - should reduce via instcombine, but not here.
+
 define i1 @smax_eq_commute(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_eq_commute(
 ; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1112,6 +1060,8 @@ define i1 @smax_eq_commute(i8 %x, i8 %y) {
   ret i1 %r
 }
 
+; Negative test - should reduce via instcombine, but not here.
+
 define i1 @umax_eq(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_eq(
 ; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1123,6 +1073,8 @@ define i1 @umax_eq(i8 %x, i8 %y) {
   ret i1 %r
 }
 
+; Negative test - should reduce via instcombine, but not here.
+
 define i1 @umax_eq_commute(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_eq_commute(
 ; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])

diff  --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp
index 34dc2767021a..8e6e48d05d37 100644
--- a/llvm/unittests/IR/PatternMatch.cpp
+++ b/llvm/unittests/IR/PatternMatch.cpp
@@ -1246,6 +1246,44 @@ TEST_F(PatternMatchTest, WithOverflowInst) {
   EXPECT_EQ(Add, WOI);
 }
 
+TEST_F(PatternMatchTest, MinMaxIntrinsics) {
+  Type *Ty = IRB.getInt32Ty();
+  Value *L = ConstantInt::get(Ty, 1);
+  Value *R = ConstantInt::get(Ty, 2);
+  Value *MatchL, *MatchR;
+
+  // Check for intrinsic ID match and capture of operands.
+  EXPECT_TRUE(m_SMax(m_Value(MatchL), m_Value(MatchR))
+                  .match(IRB.CreateBinaryIntrinsic(Intrinsic::smax, L, R)));
+  EXPECT_EQ(L, MatchL);
+  EXPECT_EQ(R, MatchR);
+
+  EXPECT_TRUE(m_SMin(m_Value(MatchL), m_Value(MatchR))
+                  .match(IRB.CreateBinaryIntrinsic(Intrinsic::smin, L, R)));
+  EXPECT_EQ(L, MatchL);
+  EXPECT_EQ(R, MatchR);
+
+  EXPECT_TRUE(m_UMax(m_Value(MatchL), m_Value(MatchR))
+                  .match(IRB.CreateBinaryIntrinsic(Intrinsic::umax, L, R)));
+  EXPECT_EQ(L, MatchL);
+  EXPECT_EQ(R, MatchR);
+
+  EXPECT_TRUE(m_UMin(m_Value(MatchL), m_Value(MatchR))
+                  .match(IRB.CreateBinaryIntrinsic(Intrinsic::umin, L, R)));
+  EXPECT_EQ(L, MatchL);
+  EXPECT_EQ(R, MatchR);
+
+  // Check for intrinsic ID mismatch.
+  EXPECT_FALSE(m_SMax(m_Value(MatchL), m_Value(MatchR))
+                  .match(IRB.CreateBinaryIntrinsic(Intrinsic::smin, L, R)));
+  EXPECT_FALSE(m_SMin(m_Value(MatchL), m_Value(MatchR))
+                  .match(IRB.CreateBinaryIntrinsic(Intrinsic::umax, L, R)));
+  EXPECT_FALSE(m_UMax(m_Value(MatchL), m_Value(MatchR))
+                  .match(IRB.CreateBinaryIntrinsic(Intrinsic::umin, L, R)));
+  EXPECT_FALSE(m_UMin(m_Value(MatchL), m_Value(MatchR))
+                  .match(IRB.CreateBinaryIntrinsic(Intrinsic::smax, L, R)));
+}
+
 TEST_F(PatternMatchTest, IntrinsicMatcher) {
   Value *Name = IRB.CreateAlloca(IRB.getInt8Ty());
   Value *Hash = IRB.getInt64(0);


        


More information about the llvm-commits mailing list