[llvm] [PatternMatch] Add m_SpecificType(Type*) matcher (PR #208427)

Benjamin Jurk via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 16 03:46:34 PDT 2026


https://github.com/bnjmnjrk updated https://github.com/llvm/llvm-project/pull/208427

>From a128e6bcffbc4d51df94f275ccf278a490ef4256 Mon Sep 17 00:00:00 2001
From: Benjamin Jurk <beni.jurk.20 at gmail.com>
Date: Thu, 9 Jul 2026 13:10:39 +0200
Subject: [PATCH 1/4] [PatternMatch] Add m_SpecificType(Type*) matcher

---
 llvm/include/llvm/IR/PatternMatch.h           | 25 +++++
 .../InstCombine/InstCombineCasts.cpp          | 95 +++++++++----------
 llvm/unittests/IR/PatternMatch.cpp            | 23 +++++
 3 files changed, 95 insertions(+), 48 deletions(-)

diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 0fb3fa83004df..98bfe26a614a4 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -824,6 +824,31 @@ inline cstfp_pred_ty<is_non_zero_not_denormal_fp> m_NonZeroNotDenormalFP() {
 
 ///////////////////////////////////////////////////////////////////////////////
 
+template <typename Pattern> struct SpecificType_match {
+  Type *RefTy;
+  Pattern P;
+
+  SpecificType_match(Type *RefTy, const Pattern &P) : RefTy(RefTy), P(P) {}
+
+  template <typename ITy> bool match(ITy *V) const {
+    return V->getType() == RefTy && P.match(V);
+  }
+};
+
+// Explicit deduction guide.
+template <typename Pattern>
+SpecificType_match(const Type *, const Pattern &)
+    -> SpecificType_match<Pattern>;
+
+/// Match a value of a specific type.
+template <typename Pattern>
+inline auto m_SpecificType(Type *RefTy, const Pattern &P) {
+  return SpecificType_match<Pattern>(RefTy, P);
+}
+inline auto m_SpecificType(Type *RefTy) {
+  return m_SpecificType(RefTy, m_Value());
+}
+
 /// Match a value, capturing it if we match.
 inline match_bind<Value> m_Value(Value *&V) { return V; }
 inline match_bind<const Value> m_Value(const Value *&V) { return V; }
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index f630d1efbd7e7..074474306e714 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -478,8 +478,8 @@ bool TypeEvaluationHelper::canAlwaysEvaluateInType(Value *V, Type *Ty) {
     return match(V, m_ImmConstant());
 
   Value *X;
-  if ((match(V, m_ZExtOrSExt(m_Value(X))) || match(V, m_Trunc(m_Value(X)))) &&
-      X->getType() == Ty)
+  if (match(V, m_ZExtOrSExt(m_Value(X, m_SpecificType(Ty)))) ||
+      match(V, m_Trunc(m_Value(X, m_SpecificType(Ty)))))
     return true;
 
   return false;
@@ -947,12 +947,12 @@ Instruction *InstCombinerImpl::narrowBinOp(TruncInst &Trunc) {
       return BinaryOperator::Create(BinOp->getOpcode(), TruncX, NarrowC);
     }
     Value *X;
-    if (match(BinOp0, m_ZExtOrSExt(m_Value(X))) && X->getType() == DestTy) {
+    if (match(BinOp0, m_ZExtOrSExt(m_Value(X, m_SpecificType(DestTy))))) {
       // trunc (binop (ext X), Y) --> binop X, (trunc Y)
       Value *NarrowOp1 = Builder.CreateTrunc(BinOp1, DestTy);
       return BinaryOperator::Create(BinOp->getOpcode(), X, NarrowOp1);
     }
-    if (match(BinOp1, m_ZExtOrSExt(m_Value(X))) && X->getType() == DestTy) {
+    if (match(BinOp1, m_ZExtOrSExt(m_Value(X, m_SpecificType(DestTy))))) {
       // trunc (binop Y, (ext X)) --> binop (trunc Y), X
       Value *NarrowOp0 = Builder.CreateTrunc(BinOp0, DestTy);
       return BinaryOperator::Create(BinOp->getOpcode(), NarrowOp0, X);
@@ -1157,20 +1157,21 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) {
   // trunc(u/smin(zext(a) + zext(b), MAX)) --> uadd.sat(a, b)
   if (match(Src,
             m_OneUse(m_CombineOr(
-                m_UMin(m_OneUse(m_Add(m_ZExt(m_Value(A)), m_ZExt(m_Value(B)))),
+                m_UMin(m_OneUse(m_Add(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
+                                      m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
                        m_SpecificInt(APInt::getMaxValue(DestWidth))),
-                m_SMin(m_OneUse(m_Add(m_ZExt(m_Value(A)), m_ZExt(m_Value(B)))),
-                       m_SpecificInt(APInt::getMaxValue(DestWidth)))))) &&
-      A->getType() == DestTy && B->getType() == DestTy) {
+                m_SMin(m_OneUse(m_Add(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
+                                      m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
+                       m_SpecificInt(APInt::getMaxValue(DestWidth))))))) {
     return replaceInstUsesWith(
         Trunc, Builder.CreateBinaryIntrinsic(Intrinsic::uadd_sat, A, B));
   }
 
   // trunc(smax(zext(a) - zext(b), 0)) --> usub.sat(a, b)
   if (match(Src, m_OneUse(m_SMax(
-                     m_OneUse(m_Sub(m_ZExt(m_Value(A)), m_ZExt(m_Value(B)))),
-                     m_Zero()))) &&
-      A->getType() == DestTy && B->getType() == DestTy) {
+                     m_OneUse(m_Sub(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
+                                    m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
+                     m_Zero())))) {
     return replaceInstUsesWith(
         Trunc, Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, A, B));
   }
@@ -1680,15 +1681,14 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
   // zext((trunc(X) & C) ^ C) -> ((X & zext(C)) ^ zext(C)).
   Value *And;
   if (match(Src, m_OneUse(m_Xor(m_Value(And), m_Constant(C)))) &&
-      match(And, m_OneUse(m_And(m_Trunc(m_Value(X)), m_Specific(C)))) &&
-      X->getType() == DestTy) {
+      match(And, m_OneUse(m_And(m_Trunc(m_Value(X, m_SpecificType(DestTy))),
+                                m_Specific(C))))) {
     Value *ZC = Builder.CreateZExt(C, DestTy);
     return BinaryOperator::CreateXor(Builder.CreateAnd(X, ZC), ZC);
   }
 
   // zext(sub(0, trunc(X))) -> and(sub(0, X), mask)
-  if (match(Src, m_Sub(m_Zero(), m_Trunc(m_Value(X)))) &&
-      X->getType() == DestTy) {
+  if (match(Src, m_Sub(m_Zero(), m_Trunc(m_Value(X, m_SpecificType(DestTy)))))) {
     APInt Mask = APInt::getLowBitsSet(DestTy->getScalarSizeInBits(),
                                       SrcTy->getScalarSizeInBits());
     Value *Neg = Builder.CreateSub(ConstantInt::get(DestTy, 0), X);
@@ -1700,16 +1700,15 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
   // intermediate values have extra uses. This could be generalized further for
   // a non-constant mask operand.
   // zext (and (trunc X), C) --> and X, (zext C)
-  if (match(Src, m_And(m_Trunc(m_Value(X)), m_Constant(C))) &&
-      X->getType() == DestTy) {
+  if (match(Src, m_And(m_Trunc(m_Value(X, m_SpecificType(DestTy))),
+                       m_Constant(C)))) {
     Value *ZextC = Builder.CreateZExt(C, DestTy);
     return BinaryOperator::CreateAnd(X, ZextC);
   }
 
   Value *Y;
-  if (match(Src,
-            m_OneUse(m_c_BitwiseLogic(m_NUWTrunc(m_Value(X)), m_Value(Y)))) &&
-      X->getType() == DestTy) {
+  if (match(Src, m_OneUse(m_c_BitwiseLogic(
+                     m_NUWTrunc(m_Value(X, m_SpecificType(DestTy))), m_Value(Y))))) {
     Value *ZextY = Builder.CreateZExt(Y, DestTy);
     return BinaryOperator::Create(cast<BinaryOperator>(Src)->getOpcode(), X,
                                   ZextY);
@@ -1991,9 +1990,10 @@ Instruction *InstCombinerImpl::visitSExt(SExtInst &Sext) {
   Value *A = nullptr;
   // TODO: Eventually this could be subsumed by EvaluateInDifferentType.
   Constant *BA = nullptr, *CA = nullptr;
-  if (match(Src, m_AShr(m_Shl(m_Trunc(m_Value(A)), m_Constant(BA)),
+  if (match(Src, m_AShr(m_Shl(m_Trunc(m_Value(A, m_SpecificType(DestTy))),
+                               m_Constant(BA)),
                         m_ImmConstant(CA))) &&
-      BA->isElementWiseEqual(CA) && A->getType() == DestTy) {
+      BA->isElementWiseEqual(CA)) {
     Constant *WideCurrShAmt =
         ConstantFoldCastOperand(Instruction::SExt, CA, DestTy, DL);
     assert(WideCurrShAmt && "Constant folding of ImmConstant cannot fail");
@@ -2047,9 +2047,8 @@ Instruction *InstCombinerImpl::visitSExt(SExtInst &Sext) {
                                       {CI->getLHS(), CI->getRHS()}));
 
   Value *Y;
-  if (match(Src,
-            m_OneUse(m_c_BitwiseLogic(m_NSWTrunc(m_Value(X)), m_Value(Y)))) &&
-      X->getType() == DestTy) {
+  if (match(Src, m_OneUse(m_c_BitwiseLogic(
+                     m_NSWTrunc(m_Value(X, m_SpecificType(DestTy))), m_Value(Y))))) {
     Value *SextY = Builder.CreateSExt(Y, DestTy);
     return BinaryOperator::Create(cast<BinaryOperator>(Src)->getOpcode(), X,
                                   SextY);
@@ -2352,16 +2351,16 @@ Instruction *InstCombinerImpl::visitFPTrunc(FPTruncInst &FPT) {
     // If we are truncating a select that has an extended operand, we can
     // narrow the other operand and do the select as a narrow op.
     Value *Cond, *X, *Y;
-    if (match(Op, m_Select(m_Value(Cond), m_FPExt(m_Value(X)), m_Value(Y))) &&
-        X->getType() == Ty) {
+    if (match(Op, m_Select(m_Value(Cond), m_FPExt(m_Value(X, m_SpecificType(Ty))),
+                           m_Value(Y)))) {
       // fptrunc (select Cond, (fpext X), Y --> select Cond, X, (fptrunc Y)
       Value *NarrowY = Builder.CreateFPTruncFMF(Y, Ty, FMF);
       Value *Sel =
           Builder.CreateSelectFMF(Cond, X, NarrowY, FMF, "narrow.sel", Op);
       return replaceInstUsesWith(FPT, Sel);
     }
-    if (match(Op, m_Select(m_Value(Cond), m_Value(Y), m_FPExt(m_Value(X)))) &&
-        X->getType() == Ty) {
+    if (match(Op, m_Select(m_Value(Cond), m_Value(Y),
+                           m_FPExt(m_Value(X, m_SpecificType(Ty)))))) {
       // fptrunc (select Cond, Y, (fpext X) --> select Cond, (fptrunc Y), X
       Value *NarrowY = Builder.CreateFPTruncFMF(Y, Ty, FMF);
       Value *Sel =
@@ -2719,18 +2718,16 @@ Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) {
   //    -> (and (ptrtoint P), M)
   // This is generally beneficial as `and` is better supported than `ptrmask`.
   Value *Ptr, *Mask;
-  if (match(SrcOp, m_OneUse(m_Intrinsic<Intrinsic::ptrmask>(m_Value(Ptr),
-                                                            m_Value(Mask)))) &&
-      Mask->getType() == Ty)
+  if (match(SrcOp, m_OneUse(m_Intrinsic<Intrinsic::ptrmask>(
+                       m_Value(Ptr), m_Value(Mask, m_SpecificType(Ty))))))
     return BinaryOperator::CreateAnd(Builder.CreatePtrToInt(Ptr, Ty), Mask);
 
   if (Value *V = foldPtrToIntOrAddrOfGEP(Ty, SrcOp))
     return replaceInstUsesWith(CI, V);
 
   Value *Vec, *Scalar, *Index;
-  if (match(SrcOp, m_OneUse(m_InsertElt(m_IntToPtr(m_Value(Vec)),
-                                        m_Value(Scalar), m_Value(Index)))) &&
-      Vec->getType() == Ty) {
+  if (match(SrcOp, m_OneUse(m_InsertElt(m_IntToPtr(m_Value(Vec, m_SpecificType(Ty))),
+                                        m_Value(Scalar), m_Value(Index))))) {
     assert(Vec->getType()->getScalarSizeInBits() == PtrSize && "Wrong type");
     // Convert the scalar to int followed by insert to eliminate one cast:
     // p2i (ins (i2p Vec), Scalar, Index --> ins Vec, (p2i Scalar), Index
@@ -2749,9 +2746,8 @@ Instruction *InstCombinerImpl::visitPtrToAddr(PtrToAddrInst &CI) {
   //    -> (and (ptrtoaddr P), M)
   // This is generally beneficial as `and` is better supported than `ptrmask`.
   Value *Ptr, *Mask;
-  if (match(SrcOp, m_OneUse(m_Intrinsic<Intrinsic::ptrmask>(m_Value(Ptr),
-                                                            m_Value(Mask)))) &&
-      Mask->getType() == Ty)
+  if (match(SrcOp, m_OneUse(m_Intrinsic<Intrinsic::ptrmask>(
+                       m_Value(Ptr), m_Value(Mask, m_SpecificType(Ty))))))
     return BinaryOperator::CreateAnd(Builder.CreatePtrToAddr(Ptr), Mask);
 
   if (Value *V = foldPtrToIntOrAddrOfGEP(Ty, SrcOp))
@@ -3084,15 +3080,17 @@ static Instruction *foldBitCastBitwiseLogic(BitCastInst &BitCast,
     return nullptr;
 
   Value *X;
-  if (match(BO->getOperand(0), m_OneUse(m_BitCast(m_Value(X)))) &&
-      X->getType() == DestTy && !isa<Constant>(X)) {
+  if (match(BO->getOperand(0),
+            m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy))))) &&
+      !isa<Constant>(X)) {
     // bitcast(logic(bitcast(X), Y)) --> logic'(X, bitcast(Y))
     Value *CastedOp1 = Builder.CreateBitCast(BO->getOperand(1), DestTy);
     return BinaryOperator::Create(BO->getOpcode(), X, CastedOp1);
   }
 
-  if (match(BO->getOperand(1), m_OneUse(m_BitCast(m_Value(X)))) &&
-      X->getType() == DestTy && !isa<Constant>(X)) {
+  if (match(BO->getOperand(1),
+            m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy))))) &&
+      !isa<Constant>(X)) {
     // bitcast(logic(Y, bitcast(X))) --> logic'(bitcast(Y), X)
     Value *CastedOp0 = Builder.CreateBitCast(BO->getOperand(0), DestTy);
     return BinaryOperator::Create(BO->getOpcode(), CastedOp0, X);
@@ -3154,14 +3152,14 @@ static Instruction *foldBitCastSelect(BitCastInst &BitCast,
     return nullptr;
 
   Value *X;
-  if (match(TVal, m_OneUse(m_BitCast(m_Value(X)))) && X->getType() == DestTy &&
+  if (match(TVal, m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy))))) &&
       !isa<Constant>(X)) {
     // bitcast(select(Cond, bitcast(X), Y)) --> select'(Cond, X, bitcast(Y))
     Value *CastedVal = Builder.CreateBitCast(FVal, DestTy);
     return SelectInst::Create(Cond, X, CastedVal, "", nullptr, Sel);
   }
 
-  if (match(FVal, m_OneUse(m_BitCast(m_Value(X)))) && X->getType() == DestTy &&
+  if (match(FVal, m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy))))) &&
       !isa<Constant>(X)) {
     // bitcast(select(Cond, Y, bitcast(X))) --> select'(Cond, bitcast(Y), X)
     Value *CastedVal = Builder.CreateBitCast(TVal, DestTy);
@@ -3433,10 +3431,11 @@ Instruction *InstCombinerImpl::visitBitCast(BitCastInst &CI) {
     unsigned BitWidth = DestTy->getScalarSizeInBits();
     Value *X, *Y;
     uint64_t IndexC;
-    if (match(Src, m_OneUse(m_InsertElt(m_OneUse(m_BitCast(m_Value(X))),
-                                        m_Value(Y), m_ConstantInt(IndexC)))) &&
-        DestTy->isIntegerTy() && X->getType() == DestTy &&
-        Y->getType()->isIntegerTy() && isDesirableIntType(BitWidth)) {
+    if (match(Src, m_OneUse(m_InsertElt(
+                       m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy)))),
+                       m_Value(Y), m_ConstantInt(IndexC)))) &&
+        DestTy->isIntegerTy() && Y->getType()->isIntegerTy() &&
+        isDesirableIntType(BitWidth)) {
       // Adjust for big endian - the LSBs are at the high index.
       if (DL.isBigEndian())
         IndexC = SrcVTy->getNumElements() - 1 - IndexC;
diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp
index 3f81739ef3c7b..e126aa8c7d9b9 100644
--- a/llvm/unittests/IR/PatternMatch.cpp
+++ b/llvm/unittests/IR/PatternMatch.cpp
@@ -2758,6 +2758,29 @@ TEST_F(PatternMatchTest, ShiftOrSelf) {
   EXPECT_EQ(ShAmtC, 0U);
 }
 
+TEST_F(PatternMatchTest, SpecificType) {
+  Type *I32 = IRB.getInt32Ty();
+  Type *I64 = IRB.getInt64Ty();
+  Value *X = IRB.CreateAdd(IRB.getInt32(1), IRB.getInt32(2));
+  Value *Y = IRB.CreateZExt(X, I64);
+
+  EXPECT_TRUE(match(X, m_SpecificType(I32)));
+  EXPECT_FALSE(match(X, m_SpecificType(I64)));
+
+  Value *Bound = nullptr;
+  EXPECT_TRUE(match(X, m_Value(Bound, m_SpecificType(I32))));
+  EXPECT_EQ(X, Bound);
+  Bound = nullptr;
+  EXPECT_FALSE(match(X, m_Value(Bound, m_SpecificType(I64))));
+
+  Bound = nullptr;
+  EXPECT_TRUE(match(Y, m_ZExt(m_Value(Bound, m_SpecificType(I32)))));
+  EXPECT_EQ(X, Bound);
+
+  EXPECT_TRUE(match(X, m_SpecificType(I32, m_Add(m_Value(), m_Value()))));
+  EXPECT_FALSE(match(X, m_SpecificType(I64, m_Add(m_Value(), m_Value()))));
+}
+
 TEST_F(PatternMatchTest, CommutativeDeferredIntrinsicMatch) {
   Value *X = ConstantFP::get(IRB.getDoubleTy(), 1.0);
   Value *Y = ConstantFP::get(IRB.getDoubleTy(), 2.0);

>From 0c89268d6715aa59b096fd8a12b44bfcca801e91 Mon Sep 17 00:00:00 2001
From: Benjamin Jurk <beni.jurk.20 at gmail.com>
Date: Fri, 10 Jul 2026 10:12:56 +0200
Subject: [PATCH 2/4] revision 1

---
 llvm/include/llvm/IR/PatternMatch.h           | 50 +++++++++----------
 .../InstCombine/InstCombineCasts.cpp          | 48 ++++++++++--------
 2 files changed, 53 insertions(+), 45 deletions(-)

diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 98bfe26a614a4..6b820bcba6097 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -824,31 +824,6 @@ inline cstfp_pred_ty<is_non_zero_not_denormal_fp> m_NonZeroNotDenormalFP() {
 
 ///////////////////////////////////////////////////////////////////////////////
 
-template <typename Pattern> struct SpecificType_match {
-  Type *RefTy;
-  Pattern P;
-
-  SpecificType_match(Type *RefTy, const Pattern &P) : RefTy(RefTy), P(P) {}
-
-  template <typename ITy> bool match(ITy *V) const {
-    return V->getType() == RefTy && P.match(V);
-  }
-};
-
-// Explicit deduction guide.
-template <typename Pattern>
-SpecificType_match(const Type *, const Pattern &)
-    -> SpecificType_match<Pattern>;
-
-/// Match a value of a specific type.
-template <typename Pattern>
-inline auto m_SpecificType(Type *RefTy, const Pattern &P) {
-  return SpecificType_match<Pattern>(RefTy, P);
-}
-inline auto m_SpecificType(Type *RefTy) {
-  return m_SpecificType(RefTy, m_Value());
-}
-
 /// Match a value, capturing it if we match.
 inline match_bind<Value> m_Value(Value *&V) { return V; }
 inline match_bind<const Value> m_Value(const Value *&V) { return V; }
@@ -1107,6 +1082,31 @@ inline specific_bbval m_SpecificBB(BasicBlock *BB) {
   return specific_bbval(BB);
 }
 
+template <typename Pattern> struct SpecificType_match {
+  Type *RefTy;
+  Pattern P;
+
+  SpecificType_match(Type *RefTy, const Pattern &P) : RefTy(RefTy), P(P) {}
+
+  template <typename ITy> bool match(ITy *V) const {
+    return V->getType() == RefTy && P.match(V);
+  }
+};
+
+// Explicit deduction guide.
+template <typename Pattern>
+SpecificType_match(const Type *, const Pattern &)
+    -> SpecificType_match<Pattern>;
+
+/// Match a value of a specific type.
+template <typename Pattern>
+inline auto m_SpecificType(Type *RefTy, const Pattern &P) {
+  return SpecificType_match<Pattern>(RefTy, P);
+}
+inline auto m_SpecificType(Type *RefTy) {
+  return m_SpecificType(RefTy, m_Value());
+}
+
 /// A commutative-friendly version of m_Specific().
 inline match_deferred<BasicBlock> m_Deferred(BasicBlock *const &BB) {
   return BB;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 074474306e714..0ab3618e654e4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -1157,21 +1157,24 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) {
   // trunc(u/smin(zext(a) + zext(b), MAX)) --> uadd.sat(a, b)
   if (match(Src,
             m_OneUse(m_CombineOr(
-                m_UMin(m_OneUse(m_Add(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
-                                      m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
-                       m_SpecificInt(APInt::getMaxValue(DestWidth))),
-                m_SMin(m_OneUse(m_Add(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
-                                      m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
-                       m_SpecificInt(APInt::getMaxValue(DestWidth))))))) {
+                m_UMin(
+                    m_OneUse(m_Add(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
+                                   m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
+                    m_SpecificInt(APInt::getMaxValue(DestWidth))),
+                m_SMin(
+                    m_OneUse(m_Add(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
+                                   m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
+                    m_SpecificInt(APInt::getMaxValue(DestWidth))))))) {
     return replaceInstUsesWith(
         Trunc, Builder.CreateBinaryIntrinsic(Intrinsic::uadd_sat, A, B));
   }
 
   // trunc(smax(zext(a) - zext(b), 0)) --> usub.sat(a, b)
-  if (match(Src, m_OneUse(m_SMax(
-                     m_OneUse(m_Sub(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
-                                    m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
-                     m_Zero())))) {
+  if (match(Src,
+            m_OneUse(m_SMax(
+                m_OneUse(m_Sub(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
+                               m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
+                m_Zero())))) {
     return replaceInstUsesWith(
         Trunc, Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, A, B));
   }
@@ -1688,7 +1691,8 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
   }
 
   // zext(sub(0, trunc(X))) -> and(sub(0, X), mask)
-  if (match(Src, m_Sub(m_Zero(), m_Trunc(m_Value(X, m_SpecificType(DestTy)))))) {
+  if (match(Src,
+            m_Sub(m_Zero(), m_Trunc(m_Value(X, m_SpecificType(DestTy)))))) {
     APInt Mask = APInt::getLowBitsSet(DestTy->getScalarSizeInBits(),
                                       SrcTy->getScalarSizeInBits());
     Value *Neg = Builder.CreateSub(ConstantInt::get(DestTy, 0), X);
@@ -1707,8 +1711,9 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
   }
 
   Value *Y;
-  if (match(Src, m_OneUse(m_c_BitwiseLogic(
-                     m_NUWTrunc(m_Value(X, m_SpecificType(DestTy))), m_Value(Y))))) {
+  if (match(Src,
+            m_OneUse(m_c_BitwiseLogic(
+                m_NUWTrunc(m_Value(X, m_SpecificType(DestTy))), m_Value(Y))))) {
     Value *ZextY = Builder.CreateZExt(Y, DestTy);
     return BinaryOperator::Create(cast<BinaryOperator>(Src)->getOpcode(), X,
                                   ZextY);
@@ -1991,7 +1996,7 @@ Instruction *InstCombinerImpl::visitSExt(SExtInst &Sext) {
   // TODO: Eventually this could be subsumed by EvaluateInDifferentType.
   Constant *BA = nullptr, *CA = nullptr;
   if (match(Src, m_AShr(m_Shl(m_Trunc(m_Value(A, m_SpecificType(DestTy))),
-                               m_Constant(BA)),
+                              m_Constant(BA)),
                         m_ImmConstant(CA))) &&
       BA->isElementWiseEqual(CA)) {
     Constant *WideCurrShAmt =
@@ -2047,8 +2052,9 @@ Instruction *InstCombinerImpl::visitSExt(SExtInst &Sext) {
                                       {CI->getLHS(), CI->getRHS()}));
 
   Value *Y;
-  if (match(Src, m_OneUse(m_c_BitwiseLogic(
-                     m_NSWTrunc(m_Value(X, m_SpecificType(DestTy))), m_Value(Y))))) {
+  if (match(Src,
+            m_OneUse(m_c_BitwiseLogic(
+                m_NSWTrunc(m_Value(X, m_SpecificType(DestTy))), m_Value(Y))))) {
     Value *SextY = Builder.CreateSExt(Y, DestTy);
     return BinaryOperator::Create(cast<BinaryOperator>(Src)->getOpcode(), X,
                                   SextY);
@@ -2351,8 +2357,9 @@ Instruction *InstCombinerImpl::visitFPTrunc(FPTruncInst &FPT) {
     // If we are truncating a select that has an extended operand, we can
     // narrow the other operand and do the select as a narrow op.
     Value *Cond, *X, *Y;
-    if (match(Op, m_Select(m_Value(Cond), m_FPExt(m_Value(X, m_SpecificType(Ty))),
-                           m_Value(Y)))) {
+    if (match(Op,
+              m_Select(m_Value(Cond), m_FPExt(m_Value(X, m_SpecificType(Ty))),
+                       m_Value(Y)))) {
       // fptrunc (select Cond, (fpext X), Y --> select Cond, X, (fptrunc Y)
       Value *NarrowY = Builder.CreateFPTruncFMF(Y, Ty, FMF);
       Value *Sel =
@@ -2726,8 +2733,9 @@ Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) {
     return replaceInstUsesWith(CI, V);
 
   Value *Vec, *Scalar, *Index;
-  if (match(SrcOp, m_OneUse(m_InsertElt(m_IntToPtr(m_Value(Vec, m_SpecificType(Ty))),
-                                        m_Value(Scalar), m_Value(Index))))) {
+  if (match(SrcOp,
+            m_OneUse(m_InsertElt(m_IntToPtr(m_Value(Vec, m_SpecificType(Ty))),
+                                 m_Value(Scalar), m_Value(Index))))) {
     assert(Vec->getType()->getScalarSizeInBits() == PtrSize && "Wrong type");
     // Convert the scalar to int followed by insert to eliminate one cast:
     // p2i (ins (i2p Vec), Scalar, Index --> ins Vec, (p2i Scalar), Index

>From 756607503a85d4acea4ebd2c51462222467e2358 Mon Sep 17 00:00:00 2001
From: Benjamin Jurk <beni.jurk.20 at gmail.com>
Date: Fri, 10 Jul 2026 16:20:44 +0200
Subject: [PATCH 3/4] revision 2

---
 llvm/include/llvm/IR/PatternMatch.h | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 6b820bcba6097..957e0dab0a912 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -1082,6 +1082,15 @@ inline specific_bbval m_SpecificBB(BasicBlock *BB) {
   return specific_bbval(BB);
 }
 
+/// A commutative-friendly version of m_Specific().
+inline match_deferred<BasicBlock> m_Deferred(BasicBlock *const &BB) {
+  return BB;
+}
+inline match_deferred<const BasicBlock>
+m_Deferred(const BasicBlock *const &BB) {
+  return BB;
+}
+
 template <typename Pattern> struct SpecificType_match {
   Type *RefTy;
   Pattern P;
@@ -1107,15 +1116,6 @@ inline auto m_SpecificType(Type *RefTy) {
   return m_SpecificType(RefTy, m_Value());
 }
 
-/// A commutative-friendly version of m_Specific().
-inline match_deferred<BasicBlock> m_Deferred(BasicBlock *const &BB) {
-  return BB;
-}
-inline match_deferred<const BasicBlock>
-m_Deferred(const BasicBlock *const &BB) {
-  return BB;
-}
-
 //===----------------------------------------------------------------------===//
 // Matcher for any binary operator.
 //

>From 3dcce6a6ffabf1b5f9f8ea394639020e4f198ef8 Mon Sep 17 00:00:00 2001
From: Benjamin Jurk <beni.jurk.20 at gmail.com>
Date: Thu, 16 Jul 2026 12:46:43 +0200
Subject: [PATCH 4/4] revision 3

---
 llvm/include/llvm/IR/PatternMatch.h           |  8 +++
 .../InstCombine/InstCombineCasts.cpp          | 52 +++++++++----------
 llvm/unittests/IR/PatternMatch.cpp            |  6 +--
 3 files changed, 37 insertions(+), 29 deletions(-)

diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 957e0dab0a912..0b0e9fa98f04c 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -1116,6 +1116,14 @@ inline auto m_SpecificType(Type *RefTy) {
   return m_SpecificType(RefTy, m_Value());
 }
 
+/// Match a value of a specific type, capturing it if we match.
+inline auto m_SpecificType(Type *RefTy, Value *&V) {
+  return m_SpecificType(RefTy, m_Value(V));
+}
+inline auto m_SpecificType(Type *RefTy, const Value *&V) {
+  return m_SpecificType(RefTy, m_Value(V));
+}
+
 //===----------------------------------------------------------------------===//
 // Matcher for any binary operator.
 //
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 0ab3618e654e4..9c0a0e19f27e9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -478,8 +478,8 @@ bool TypeEvaluationHelper::canAlwaysEvaluateInType(Value *V, Type *Ty) {
     return match(V, m_ImmConstant());
 
   Value *X;
-  if (match(V, m_ZExtOrSExt(m_Value(X, m_SpecificType(Ty)))) ||
-      match(V, m_Trunc(m_Value(X, m_SpecificType(Ty)))))
+  if (match(V, m_ZExtOrSExt(m_SpecificType(Ty, X))) ||
+      match(V, m_Trunc(m_SpecificType(Ty, X))))
     return true;
 
   return false;
@@ -947,12 +947,12 @@ Instruction *InstCombinerImpl::narrowBinOp(TruncInst &Trunc) {
       return BinaryOperator::Create(BinOp->getOpcode(), TruncX, NarrowC);
     }
     Value *X;
-    if (match(BinOp0, m_ZExtOrSExt(m_Value(X, m_SpecificType(DestTy))))) {
+    if (match(BinOp0, m_ZExtOrSExt(m_SpecificType(DestTy, X)))) {
       // trunc (binop (ext X), Y) --> binop X, (trunc Y)
       Value *NarrowOp1 = Builder.CreateTrunc(BinOp1, DestTy);
       return BinaryOperator::Create(BinOp->getOpcode(), X, NarrowOp1);
     }
-    if (match(BinOp1, m_ZExtOrSExt(m_Value(X, m_SpecificType(DestTy))))) {
+    if (match(BinOp1, m_ZExtOrSExt(m_SpecificType(DestTy, X)))) {
       // trunc (binop Y, (ext X)) --> binop (trunc Y), X
       Value *NarrowOp0 = Builder.CreateTrunc(BinOp0, DestTy);
       return BinaryOperator::Create(BinOp->getOpcode(), NarrowOp0, X);
@@ -1158,12 +1158,12 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) {
   if (match(Src,
             m_OneUse(m_CombineOr(
                 m_UMin(
-                    m_OneUse(m_Add(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
-                                   m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
+                    m_OneUse(m_Add(m_ZExt(m_SpecificType(DestTy, A)),
+                                   m_ZExt(m_SpecificType(DestTy, B)))),
                     m_SpecificInt(APInt::getMaxValue(DestWidth))),
                 m_SMin(
-                    m_OneUse(m_Add(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
-                                   m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
+                    m_OneUse(m_Add(m_ZExt(m_SpecificType(DestTy, A)),
+                                   m_ZExt(m_SpecificType(DestTy, B)))),
                     m_SpecificInt(APInt::getMaxValue(DestWidth))))))) {
     return replaceInstUsesWith(
         Trunc, Builder.CreateBinaryIntrinsic(Intrinsic::uadd_sat, A, B));
@@ -1172,8 +1172,8 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) {
   // trunc(smax(zext(a) - zext(b), 0)) --> usub.sat(a, b)
   if (match(Src,
             m_OneUse(m_SMax(
-                m_OneUse(m_Sub(m_ZExt(m_Value(A, m_SpecificType(DestTy))),
-                               m_ZExt(m_Value(B, m_SpecificType(DestTy))))),
+                m_OneUse(m_Sub(m_ZExt(m_SpecificType(DestTy, A)),
+                               m_ZExt(m_SpecificType(DestTy, B)))),
                 m_Zero())))) {
     return replaceInstUsesWith(
         Trunc, Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, A, B));
@@ -1684,7 +1684,7 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
   // zext((trunc(X) & C) ^ C) -> ((X & zext(C)) ^ zext(C)).
   Value *And;
   if (match(Src, m_OneUse(m_Xor(m_Value(And), m_Constant(C)))) &&
-      match(And, m_OneUse(m_And(m_Trunc(m_Value(X, m_SpecificType(DestTy))),
+      match(And, m_OneUse(m_And(m_Trunc(m_SpecificType(DestTy, X)),
                                 m_Specific(C))))) {
     Value *ZC = Builder.CreateZExt(C, DestTy);
     return BinaryOperator::CreateXor(Builder.CreateAnd(X, ZC), ZC);
@@ -1692,7 +1692,7 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
 
   // zext(sub(0, trunc(X))) -> and(sub(0, X), mask)
   if (match(Src,
-            m_Sub(m_Zero(), m_Trunc(m_Value(X, m_SpecificType(DestTy)))))) {
+            m_Sub(m_Zero(), m_Trunc(m_SpecificType(DestTy, X))))) {
     APInt Mask = APInt::getLowBitsSet(DestTy->getScalarSizeInBits(),
                                       SrcTy->getScalarSizeInBits());
     Value *Neg = Builder.CreateSub(ConstantInt::get(DestTy, 0), X);
@@ -1704,7 +1704,7 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
   // intermediate values have extra uses. This could be generalized further for
   // a non-constant mask operand.
   // zext (and (trunc X), C) --> and X, (zext C)
-  if (match(Src, m_And(m_Trunc(m_Value(X, m_SpecificType(DestTy))),
+  if (match(Src, m_And(m_Trunc(m_SpecificType(DestTy, X)),
                        m_Constant(C)))) {
     Value *ZextC = Builder.CreateZExt(C, DestTy);
     return BinaryOperator::CreateAnd(X, ZextC);
@@ -1713,7 +1713,7 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
   Value *Y;
   if (match(Src,
             m_OneUse(m_c_BitwiseLogic(
-                m_NUWTrunc(m_Value(X, m_SpecificType(DestTy))), m_Value(Y))))) {
+                m_NUWTrunc(m_SpecificType(DestTy, X)), m_Value(Y))))) {
     Value *ZextY = Builder.CreateZExt(Y, DestTy);
     return BinaryOperator::Create(cast<BinaryOperator>(Src)->getOpcode(), X,
                                   ZextY);
@@ -1995,7 +1995,7 @@ Instruction *InstCombinerImpl::visitSExt(SExtInst &Sext) {
   Value *A = nullptr;
   // TODO: Eventually this could be subsumed by EvaluateInDifferentType.
   Constant *BA = nullptr, *CA = nullptr;
-  if (match(Src, m_AShr(m_Shl(m_Trunc(m_Value(A, m_SpecificType(DestTy))),
+  if (match(Src, m_AShr(m_Shl(m_Trunc(m_SpecificType(DestTy, A)),
                               m_Constant(BA)),
                         m_ImmConstant(CA))) &&
       BA->isElementWiseEqual(CA)) {
@@ -2054,7 +2054,7 @@ Instruction *InstCombinerImpl::visitSExt(SExtInst &Sext) {
   Value *Y;
   if (match(Src,
             m_OneUse(m_c_BitwiseLogic(
-                m_NSWTrunc(m_Value(X, m_SpecificType(DestTy))), m_Value(Y))))) {
+                m_NSWTrunc(m_SpecificType(DestTy, X)), m_Value(Y))))) {
     Value *SextY = Builder.CreateSExt(Y, DestTy);
     return BinaryOperator::Create(cast<BinaryOperator>(Src)->getOpcode(), X,
                                   SextY);
@@ -2358,7 +2358,7 @@ Instruction *InstCombinerImpl::visitFPTrunc(FPTruncInst &FPT) {
     // narrow the other operand and do the select as a narrow op.
     Value *Cond, *X, *Y;
     if (match(Op,
-              m_Select(m_Value(Cond), m_FPExt(m_Value(X, m_SpecificType(Ty))),
+              m_Select(m_Value(Cond), m_FPExt(m_SpecificType(Ty, X)),
                        m_Value(Y)))) {
       // fptrunc (select Cond, (fpext X), Y --> select Cond, X, (fptrunc Y)
       Value *NarrowY = Builder.CreateFPTruncFMF(Y, Ty, FMF);
@@ -2367,7 +2367,7 @@ Instruction *InstCombinerImpl::visitFPTrunc(FPTruncInst &FPT) {
       return replaceInstUsesWith(FPT, Sel);
     }
     if (match(Op, m_Select(m_Value(Cond), m_Value(Y),
-                           m_FPExt(m_Value(X, m_SpecificType(Ty)))))) {
+                           m_FPExt(m_SpecificType(Ty, X))))) {
       // fptrunc (select Cond, Y, (fpext X) --> select Cond, (fptrunc Y), X
       Value *NarrowY = Builder.CreateFPTruncFMF(Y, Ty, FMF);
       Value *Sel =
@@ -2726,7 +2726,7 @@ Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) {
   // This is generally beneficial as `and` is better supported than `ptrmask`.
   Value *Ptr, *Mask;
   if (match(SrcOp, m_OneUse(m_Intrinsic<Intrinsic::ptrmask>(
-                       m_Value(Ptr), m_Value(Mask, m_SpecificType(Ty))))))
+                       m_Value(Ptr), m_SpecificType(Ty, Mask)))))
     return BinaryOperator::CreateAnd(Builder.CreatePtrToInt(Ptr, Ty), Mask);
 
   if (Value *V = foldPtrToIntOrAddrOfGEP(Ty, SrcOp))
@@ -2734,7 +2734,7 @@ Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) {
 
   Value *Vec, *Scalar, *Index;
   if (match(SrcOp,
-            m_OneUse(m_InsertElt(m_IntToPtr(m_Value(Vec, m_SpecificType(Ty))),
+            m_OneUse(m_InsertElt(m_IntToPtr(m_SpecificType(Ty, Vec)),
                                  m_Value(Scalar), m_Value(Index))))) {
     assert(Vec->getType()->getScalarSizeInBits() == PtrSize && "Wrong type");
     // Convert the scalar to int followed by insert to eliminate one cast:
@@ -2755,7 +2755,7 @@ Instruction *InstCombinerImpl::visitPtrToAddr(PtrToAddrInst &CI) {
   // This is generally beneficial as `and` is better supported than `ptrmask`.
   Value *Ptr, *Mask;
   if (match(SrcOp, m_OneUse(m_Intrinsic<Intrinsic::ptrmask>(
-                       m_Value(Ptr), m_Value(Mask, m_SpecificType(Ty))))))
+                       m_Value(Ptr), m_SpecificType(Ty, Mask)))))
     return BinaryOperator::CreateAnd(Builder.CreatePtrToAddr(Ptr), Mask);
 
   if (Value *V = foldPtrToIntOrAddrOfGEP(Ty, SrcOp))
@@ -3089,7 +3089,7 @@ static Instruction *foldBitCastBitwiseLogic(BitCastInst &BitCast,
 
   Value *X;
   if (match(BO->getOperand(0),
-            m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy))))) &&
+            m_OneUse(m_BitCast(m_SpecificType(DestTy, X)))) &&
       !isa<Constant>(X)) {
     // bitcast(logic(bitcast(X), Y)) --> logic'(X, bitcast(Y))
     Value *CastedOp1 = Builder.CreateBitCast(BO->getOperand(1), DestTy);
@@ -3097,7 +3097,7 @@ static Instruction *foldBitCastBitwiseLogic(BitCastInst &BitCast,
   }
 
   if (match(BO->getOperand(1),
-            m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy))))) &&
+            m_OneUse(m_BitCast(m_SpecificType(DestTy, X)))) &&
       !isa<Constant>(X)) {
     // bitcast(logic(Y, bitcast(X))) --> logic'(bitcast(Y), X)
     Value *CastedOp0 = Builder.CreateBitCast(BO->getOperand(0), DestTy);
@@ -3160,14 +3160,14 @@ static Instruction *foldBitCastSelect(BitCastInst &BitCast,
     return nullptr;
 
   Value *X;
-  if (match(TVal, m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy))))) &&
+  if (match(TVal, m_OneUse(m_BitCast(m_SpecificType(DestTy, X)))) &&
       !isa<Constant>(X)) {
     // bitcast(select(Cond, bitcast(X), Y)) --> select'(Cond, X, bitcast(Y))
     Value *CastedVal = Builder.CreateBitCast(FVal, DestTy);
     return SelectInst::Create(Cond, X, CastedVal, "", nullptr, Sel);
   }
 
-  if (match(FVal, m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy))))) &&
+  if (match(FVal, m_OneUse(m_BitCast(m_SpecificType(DestTy, X)))) &&
       !isa<Constant>(X)) {
     // bitcast(select(Cond, Y, bitcast(X))) --> select'(Cond, bitcast(Y), X)
     Value *CastedVal = Builder.CreateBitCast(TVal, DestTy);
@@ -3440,7 +3440,7 @@ Instruction *InstCombinerImpl::visitBitCast(BitCastInst &CI) {
     Value *X, *Y;
     uint64_t IndexC;
     if (match(Src, m_OneUse(m_InsertElt(
-                       m_OneUse(m_BitCast(m_Value(X, m_SpecificType(DestTy)))),
+                       m_OneUse(m_BitCast(m_SpecificType(DestTy, X))),
                        m_Value(Y), m_ConstantInt(IndexC)))) &&
         DestTy->isIntegerTy() && Y->getType()->isIntegerTy() &&
         isDesirableIntType(BitWidth)) {
diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp
index e126aa8c7d9b9..64ccd1fdc47dd 100644
--- a/llvm/unittests/IR/PatternMatch.cpp
+++ b/llvm/unittests/IR/PatternMatch.cpp
@@ -2768,13 +2768,13 @@ TEST_F(PatternMatchTest, SpecificType) {
   EXPECT_FALSE(match(X, m_SpecificType(I64)));
 
   Value *Bound = nullptr;
-  EXPECT_TRUE(match(X, m_Value(Bound, m_SpecificType(I32))));
+  EXPECT_TRUE(match(X, m_SpecificType(I32, Bound)));
   EXPECT_EQ(X, Bound);
   Bound = nullptr;
-  EXPECT_FALSE(match(X, m_Value(Bound, m_SpecificType(I64))));
+  EXPECT_FALSE(match(X, m_SpecificType(I64, Bound)));
 
   Bound = nullptr;
-  EXPECT_TRUE(match(Y, m_ZExt(m_Value(Bound, m_SpecificType(I32)))));
+  EXPECT_TRUE(match(Y, m_ZExt(m_SpecificType(I32, Bound))));
   EXPECT_EQ(X, Bound);
 
   EXPECT_TRUE(match(X, m_SpecificType(I32, m_Add(m_Value(), m_Value()))));



More information about the llvm-commits mailing list