[llvm] [IR][NFC] Introduce Constant::containsMatchingVectorElement and corresponding matcher m_ContainsMatchingVectorElement (PR #200502)

Sean Clarke via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 5 07:54:59 PDT 2026


https://github.com/xarkenz updated https://github.com/llvm/llvm-project/pull/200502

>From c2888381b1560022a040cc0cd5c9c92b8a0d20a2 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 29 May 2026 16:30:19 -0500
Subject: [PATCH 01/10] Add Constant::anyVectorElement and corresponding
 matcher m_AnyVectorElement

---
 llvm/include/llvm/Analysis/VectorUtils.h      |  5 --
 llvm/include/llvm/IR/Constant.h               | 19 +-----
 llvm/include/llvm/IR/PatternMatch.h           | 22 +++++--
 llvm/lib/Analysis/ConstantFolding.cpp         | 10 +--
 llvm/lib/Analysis/ValueTracking.cpp           | 14 ++---
 llvm/lib/Analysis/VectorUtils.cpp             | 25 --------
 llvm/lib/CodeGen/MachineFunction.cpp          |  4 +-
 llvm/lib/IR/ConstantFold.cpp                  |  2 +-
 llvm/lib/IR/Constants.cpp                     | 61 ++++---------------
 .../InstCombine/InstCombineCalls.cpp          |  2 +-
 .../InstCombine/InstCombineMulDivRem.cpp      | 12 +---
 .../InstCombine/InstCombineNegator.cpp        |  2 +-
 .../InstCombine/InstructionCombining.cpp      | 12 +---
 .../Instrumentation/MemorySanitizer.cpp       |  5 +-
 llvm/lib/Transforms/Scalar/Reassociate.cpp    |  4 +-
 llvm/unittests/IR/ConstantsTest.cpp           | 18 +++---
 16 files changed, 67 insertions(+), 150 deletions(-)

diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h
index 1c73269a54af5..a9c1283e354e5 100644
--- a/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/llvm/include/llvm/Analysis/VectorUtils.h
@@ -487,11 +487,6 @@ LLVM_ABI bool maskIsAllZeroOrUndef(Value *Mask);
 /// lanes can be assumed active.
 LLVM_ABI bool maskIsAllOneOrUndef(Value *Mask);
 
-/// Given a mask vector of i1, Return true if any of the elements of this
-/// predicate mask are known to be true or undef.  That is, return true if at
-/// least one lane can be assumed active.
-LLVM_ABI bool maskContainsAllOneOrUndef(Value *Mask);
-
 /// Given a mask vector of the form <Y x i1>, return an APInt (of bitwidth Y)
 /// for each lane which may be active.
 LLVM_ABI APInt possiblyDemandedEltsInMask(Value *Mask);
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 2ab1400264327..29af0c1004e8d 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -112,23 +112,8 @@ class Constant : public User {
   /// lane, the constants still match.
   LLVM_ABI bool isElementWiseEqual(Value *Y) const;
 
-  /// Return true if this is a vector constant that includes any undef or
-  /// poison elements. Since it is impossible to inspect a scalable vector
-  /// element- wise at compile time, this function returns true only if the
-  /// entire vector is undef or poison.
-  LLVM_ABI bool containsUndefOrPoisonElement() const;
-
-  /// Return true if this is a vector constant that includes any poison
-  /// elements.
-  LLVM_ABI bool containsPoisonElement() const;
-
-  /// Return true if this is a vector constant that includes any strictly undef
-  /// (not poison) elements.
-  LLVM_ABI bool containsUndefElement() const;
-
-  /// Return true if this is a fixed width vector constant that includes
-  /// any constant expressions.
-  LLVM_ABI bool containsConstantExpression() const;
+  /// Return true if this is a vector constant where at least one element satisfies the given predicate. For scalable vectors, the predicate is tested on the value as a whole.
+  LLVM_ABI bool anyVectorElement(function_ref<bool(Constant *)> PredFn) const;
 
   /// Return true if the value can vary between threads.
   LLVM_ABI bool isThreadDependent() const;
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index e6650e73ec0ac..c618948eee873 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -181,16 +181,27 @@ inline auto m_ConstantInt() { return m_Isa<ConstantInt>(); }
 /// Match an arbitrary ConstantFP and ignore it.
 inline auto m_ConstantFP() { return m_Isa<ConstantFP>(); }
 
-struct constantexpr_match {
+template <typename SPTy> struct anyvectorelement_match {
+  SPTy SubPattern;
+  anyvectorelement_match(const SPTy &SP) : SubPattern(SP) {}
+
   template <typename ITy> bool match(ITy *V) const {
     auto *C = dyn_cast<Constant>(V);
-    return C && (isa<ConstantExpr>(C) || C->containsConstantExpression());
+    return C && C->anyVectorElement([&](Constant *E) { return SubPattern.match(E); });
   }
 };
 
+/// Match a vector constant where at least one of its elements matches the subpattern. Any bindings in the subpattern will be bound to the first match.
+template <typename SPTy>
+inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
+  return SubPattern;
+}
+
 /// Match a constant expression or a constant that contains a constant
 /// expression.
-inline constantexpr_match m_ConstantExpr() { return constantexpr_match(); }
+inline auto m_ConstantExpr() {
+  return m_CombineOr(m_Isa<ConstantExpr>(), m_AnyVectorElement(m_Isa<ConstantExpr>()));
+}
 
 template <typename SubPattern_t> struct Splat_match {
   SubPattern_t SubPattern;
@@ -884,13 +895,12 @@ inline match_bind<const BasicBlock> m_BasicBlock(const BasicBlock *&V) {
 struct immconstant_ty {
   template <typename ITy> static bool isImmConstant(ITy *V) {
     if (auto *CV = dyn_cast<Constant>(V)) {
-      if (!isa<ConstantExpr>(CV) && !CV->containsConstantExpression())
+      if (!match(CV, m_ConstantExpr()))
         return true;
 
       if (CV->getType()->isVectorTy()) {
         if (auto *Splat = CV->getSplatValue(/*AllowPoison=*/true)) {
-          if (!isa<ConstantExpr>(Splat) &&
-              !Splat->containsConstantExpression()) {
+          if (!match(Splat, m_ConstantExpr())) {
             return true;
           }
         }
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 959b46f8eff46..ef43d829bb48c 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -51,6 +51,7 @@
 #include "llvm/IR/IntrinsicsX86.h"
 #include "llvm/IR/NVVMIntrinsicUtils.h"
 #include "llvm/IR/Operator.h"
+#include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Support/Casting.h"
@@ -64,6 +65,7 @@
 #include <cstdint>
 
 using namespace llvm;
+using namespace llvm::PatternMatch;
 
 static cl::opt<bool> DisableFPCallFolding(
     "disable-fp-call-folding",
@@ -118,7 +120,7 @@ static bool foldMixesPoisonBits(Constant *C, unsigned NumSrcElt,
   // If element counts don't divide evenly, bail out if a poison source element
   // might span multiple destination lanes.
   if (NumSrcElt % NumDstElt != 0)
-    return C->containsPoisonElement();
+    return match(C, m_AnyVectorElement(m_Poison()));
   unsigned Ratio = NumSrcElt / NumDstElt;
   for (unsigned i = 0; i != NumSrcElt; i += Ratio) {
     bool HasPoison = false;
@@ -149,7 +151,7 @@ static bool computePoisonDstLanes(Constant *C, unsigned NumSrcElt,
   // If element counts don't divide evenly, bail out if a poison source element
   // might span multiple destination lanes.
   if ((NumDstElt < NumSrcElt ? NumSrcElt % NumDstElt : NumDstElt % NumSrcElt))
-    return !C->containsPoisonElement();
+    return !match(C, m_AnyVectorElement(m_Poison()));
   if (NumDstElt < NumSrcElt) {
     unsigned Ratio = NumSrcElt / NumDstElt;
     for (unsigned i = 0; i != NumDstElt; ++i) {
@@ -195,7 +197,7 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
 
       // Bitcasting a byte containing any poison bit to an integer or fp type
       // yields poison.
-      if (SrcEltTy->isByteTy() && C->containsPoisonElement())
+      if (SrcEltTy->isByteTy() && match(C, m_AnyVectorElement(m_Poison())))
         return PoisonValue::get(DestTy);
 
       // If the vector is a vector of floating point or bytes, convert it to a
@@ -2313,7 +2315,7 @@ Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) {
   auto *OpVT = cast<VectorType>(Op->getType());
 
   // This is the same as the underlying binops - poison propagates.
-  if (Op->containsPoisonElement())
+  if (match(Op, m_AnyVectorElement(m_Poison())))
     return PoisonValue::get(OpVT->getElementType());
 
   // Shortcut non-accumulating reductions.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8ff5b750203cc..d6e9bd154e90d 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7813,11 +7813,11 @@ static bool isGuaranteedNotToBeUndefOrPoison(
           if (isa<ConstantInt>(SplatC) || isa<ConstantFP>(SplatC))
             return true;
       } else {
-        if (includesUndef(Kind) && C->containsUndefElement())
+        if (includesUndef(Kind) && match(C, m_AnyVectorElement(m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
           return false;
-        if (includesPoison(Kind) && C->containsPoisonElement())
+        if (includesPoison(Kind) && match(C, m_AnyVectorElement(m_Poison())))
           return false;
-        return !C->containsConstantExpression();
+        return !match(C, m_ConstantExpr());
       }
     }
   }
@@ -8849,7 +8849,7 @@ llvm::getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C) {
   // undefined elements, so replace those elements with the first safe constant
   // that we found.
   // TODO: in case of poison, it is safe; let's replace undefs only.
-  if (C->containsUndefOrPoisonElement()) {
+  if (match(C, m_AnyVectorElement(m_UndefValue()))) {
     assert(SafeReplacementConstant && "Replacement constant not set");
     C = Constant::replaceUndefsWith(C, SafeReplacementConstant);
   }
@@ -8876,11 +8876,9 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
     // purpose of identifying min/max. Disregard vector constants with undefined
     // elements because those can not be back-propagated for analysis.
     Value *OutputZeroVal = nullptr;
-    if (match(TrueVal, m_AnyZeroFP()) && !match(FalseVal, m_AnyZeroFP()) &&
-        !cast<Constant>(TrueVal)->containsUndefOrPoisonElement())
+    if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(m_UndefValue())))) && !match(FalseVal, m_AnyZeroFP()))
       OutputZeroVal = TrueVal;
-    else if (match(FalseVal, m_AnyZeroFP()) && !match(TrueVal, m_AnyZeroFP()) &&
-             !cast<Constant>(FalseVal)->containsUndefOrPoisonElement())
+    else if (match(FalseVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(m_UndefValue())))) && !match(TrueVal, m_AnyZeroFP()))
       OutputZeroVal = FalseVal;
 
     if (OutputZeroVal) {
diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp
index 402bef65c2f13..84cd368c470d6 100644
--- a/llvm/lib/Analysis/VectorUtils.cpp
+++ b/llvm/lib/Analysis/VectorUtils.cpp
@@ -1308,31 +1308,6 @@ bool llvm::maskIsAllOneOrUndef(Value *Mask) {
   return true;
 }
 
-bool llvm::maskContainsAllOneOrUndef(Value *Mask) {
-  assert(isa<VectorType>(Mask->getType()) &&
-         isa<IntegerType>(Mask->getType()->getScalarType()) &&
-         cast<IntegerType>(Mask->getType()->getScalarType())->getBitWidth() ==
-             1 &&
-         "Mask must be a vector of i1");
-
-  auto *ConstMask = dyn_cast<Constant>(Mask);
-  if (!ConstMask)
-    return false;
-  if (ConstMask->isAllOnesValue() || isa<UndefValue>(ConstMask))
-    return true;
-  if (isa<ScalableVectorType>(ConstMask->getType()))
-    return false;
-  for (unsigned
-           I = 0,
-           E = cast<FixedVectorType>(ConstMask->getType())->getNumElements();
-       I != E; ++I) {
-    if (auto *MaskElt = ConstMask->getAggregateElement(I))
-      if (MaskElt->isAllOnesValue() || isa<UndefValue>(MaskElt))
-        return true;
-  }
-  return false;
-}
-
 /// TODO: This is a lot like known bits, but for
 /// vectors.  Is there something we can common this with?
 APInt llvm::possiblyDemandedEltsInMask(Value *Mask) {
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index 49d8a19e5d126..ea01c3241e84d 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -54,6 +54,7 @@
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/ModuleSlotTracker.h"
+#include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/Value.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCSymbol.h"
@@ -79,6 +80,7 @@
 #include "LiveDebugValues/LiveDebugValues.h"
 
 using namespace llvm;
+using namespace llvm::PatternMatch;
 
 #define DEBUG_TYPE "codegen"
 
@@ -1561,7 +1563,7 @@ static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B,
   if (StoreSize != DL.getTypeStoreSize(B->getType()) || StoreSize > 128)
     return false;
 
-  bool ContainsUndefOrPoisonA = A->containsUndefOrPoisonElement();
+  bool ContainsUndefOrPoisonA = match(A, m_AnyVectorElement(m_UndefValue()));
 
   Type *IntTy = IntegerType::get(A->getContext(), StoreSize*8);
 
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index f8abd576f93c4..80e00cb7cc1af 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -359,7 +359,7 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
       return true;
 
     if (C->getType()->isVectorTy())
-      return !C->containsPoisonElement() && !C->containsConstantExpression();
+      return !match(C, m_CombineOr(m_AnyVectorElement(m_Poison()), m_ConstantExpr()));
 
     // TODO: Recursively analyze aggregates or other constants.
     return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index cadb48b1a649b..29d18d7afd4c4 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -183,13 +183,8 @@ bool Constant::isNotMinSignedValue() const {
     return !CFP->getValueAPF().bitcastToAPInt().isMinSignedValue();
 
   // Check that vectors don't contain INT_MIN
-  if (auto *VTy = dyn_cast<FixedVectorType>(getType())) {
-    for (unsigned I = 0, E = VTy->getNumElements(); I != E; ++I) {
-      Constant *Elt = getAggregateElement(I);
-      if (!Elt || !Elt->isNotMinSignedValue())
-        return false;
-    }
-    return true;
+  if (isa<FixedVectorType>(getType())) {
+    return !anyVectorElement([&](const auto *E) { return !E->isNotMinSignedValue(); });
   }
 
   // Check for splats that aren't INT_MIN
@@ -309,21 +304,19 @@ bool Constant::isElementWiseEqual(Value *Y) const {
   return CmpEq && (isa<PoisonValue>(CmpEq) || match(CmpEq, m_One()));
 }
 
-static bool
-containsUndefinedElement(const Constant *C,
-                         function_ref<bool(const Constant *)> HasFn) {
-  if (auto *VTy = dyn_cast<VectorType>(C->getType())) {
-    if (HasFn(C))
+bool Constant::anyVectorElement(function_ref<bool(Constant *)> PredFn) const {
+  if (!getType()->isVectorTy())
+    return false;
+  
+  if (Constant *SplatVal = getSplatValue())
+    if (PredFn(SplatVal))
       return true;
-    if (isa<ConstantAggregateZero>(C))
-      return false;
-    if (isa<ScalableVectorType>(C->getType()))
-      return false;
 
-    for (unsigned i = 0, e = cast<FixedVectorType>(VTy)->getNumElements();
-         i != e; ++i) {
-      if (Constant *Elem = C->getAggregateElement(i))
-        if (HasFn(Elem))
+  if (auto *FVTy = dyn_cast<FixedVectorType>(getType())) {
+    unsigned NumElts = FVTy->getNumElements();
+    for (unsigned I = 0; I != NumElts; ++I) {
+      if (Constant *Elem = getAggregateElement(I))
+        if (PredFn(Elem))
           return true;
     }
   }
@@ -331,34 +324,6 @@ containsUndefinedElement(const Constant *C,
   return false;
 }
 
-bool Constant::containsUndefOrPoisonElement() const {
-  return containsUndefinedElement(
-      this, [&](const auto *C) { return isa<UndefValue>(C); });
-}
-
-bool Constant::containsPoisonElement() const {
-  return containsUndefinedElement(
-      this, [&](const auto *C) { return isa<PoisonValue>(C); });
-}
-
-bool Constant::containsUndefElement() const {
-  return containsUndefinedElement(this, [&](const auto *C) {
-    return isa<UndefValue>(C) && !isa<PoisonValue>(C);
-  });
-}
-
-bool Constant::containsConstantExpression() const {
-  if (isa<ConstantInt>(this) || isa<ConstantFP>(this))
-    return false;
-
-  if (auto *VTy = dyn_cast<FixedVectorType>(getType())) {
-    for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
-      if (isa<ConstantExpr>(getAggregateElement(i)))
-        return true;
-  }
-  return false;
-}
-
 /// Constructor to create a '0' constant of arbitrary type.
 Constant *Constant::getNullValue(Type *Ty) {
   switch (Ty->getTypeID()) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index df693293b03dd..7f2f2c5ded995 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -396,7 +396,7 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
   if (auto *SplatPtr = getSplatValue(II.getArgOperand(1))) {
     // scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr
     if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) {
-      if (maskContainsAllOneOrUndef(ConstMask)) {
+      if (match(ConstMask, m_AnyVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
         Align Alignment = II.getParamAlign(1).valueOrOne();
         StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false,
                                      Alignment);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 17ac09c10f41c..5e241132ca3dd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1290,16 +1290,8 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
 
   // If any element of a constant divisor fixed width vector is zero or undef
   // the behavior is undefined and we can fold the whole op to poison.
-  auto *Op1C = dyn_cast<Constant>(Op1);
-  Type *Ty = I.getType();
-  auto *VTy = dyn_cast<FixedVectorType>(Ty);
-  if (Op1C && VTy) {
-    unsigned NumElts = VTy->getNumElements();
-    for (unsigned i = 0; i != NumElts; ++i) {
-      Constant *Elt = Op1C->getAggregateElement(i);
-      if (Elt && (Elt->isNullValue() || isa<UndefValue>(Elt)))
-        return replaceInstUsesWith(I, PoisonValue::get(Ty));
-    }
+  if (match(Op1, m_AnyVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
+    return replaceInstUsesWith(I, PoisonValue::get(I.getType()));
   }
 
   if (Instruction *Phi = foldBinopWithPhiOperands(I))
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
index b0a0bcfbde19e..45d15cfe27fdb 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
@@ -275,7 +275,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     // While this is normally not behind a use-check,
     // let's consider division to be special since it's costly.
     if (auto *Op1C = dyn_cast<Constant>(I->getOperand(1))) {
-      if (!Op1C->containsUndefOrPoisonElement() &&
+      if (!match(Op1C, m_AnyVectorElement(m_UndefValue())) &&
           Op1C->isNotMinSignedValue() && Op1C->isNotOneValue()) {
         Value *BO =
             Builder.CreateSDiv(I->getOperand(0), ConstantExpr::getNeg(Op1C),
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 348dd162501a0..e9e1f23f2a2f1 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5486,21 +5486,13 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
     auto *VTy = dyn_cast<FixedVectorType>(Ty);
     if (!VTy)
       return nullptr;
-    unsigned NumElts = VTy->getNumElements();
     Constant *BestValue = Constant::getNullValue(VTy->getScalarType());
-    for (unsigned i = 0; i != NumElts; ++i) {
-      Constant *EltC = C->getAggregateElement(i);
-      if (EltC && !match(EltC, m_Undef())) {
-        BestValue = EltC;
-        break;
-      }
-    }
+    match(C, m_AnyVectorElement(m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
     return Constant::replaceUndefsWith(C, BestValue);
   };
 
   Constant *C;
-  if (match(Op0, m_Constant(C)) && C->containsUndefOrPoisonElement() &&
-      !C->containsConstantExpression()) {
+  if (match(Op0, m_CombineAnd(m_Constant(C), m_AnyVectorElement(m_UndefValue()), m_Unless(m_ConstantExpr())))) {
     if (Constant *Repl = getFreezeVectorReplacement(C))
       return replaceInstUsesWith(I, Repl);
   }
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index c45ec68f3cd07..e133840db0e01 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -185,6 +185,7 @@
 #include "llvm/IR/IntrinsicsX86.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 #include "llvm/IR/ValueMap.h"
@@ -212,6 +213,7 @@
 #include <tuple>
 
 using namespace llvm;
+using namespace llvm::PatternMatch;
 
 #define DEBUG_TYPE "msan"
 
@@ -2173,8 +2175,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
 
     // Check for partially-undefined constant vectors
     // TODO: scalable vectors (this is hard because we do not have IRBuilder)
-    if (isa<FixedVectorType>(V->getType()) && isa<Constant>(V) &&
-        cast<Constant>(V)->containsUndefOrPoisonElement() && PropagateShadow &&
+    if (match(V, m_AnyVectorElement(m_UndefValue())) && PropagateShadow &&
         PoisonUndefVectors) {
       unsigned NumElems = cast<FixedVectorType>(V->getType())->getNumElements();
       SmallVector<Constant *, 32> ShadowVector(NumElems);
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index 1d90cd5fe87e7..06756f9c6783d 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -816,9 +816,7 @@ static Value *NegateValue(Value *V, Instruction *BI,
     Instruction *TheNeg = dyn_cast<Instruction>(U);
 
     // We can't safely propagate a vector zero constant with poison/undef lanes.
-    Constant *C;
-    if (match(TheNeg, m_BinOp(m_Constant(C), m_Value())) &&
-        C->containsUndefOrPoisonElement())
+    if (match(TheNeg, m_BinOp(m_AnyVectorElement(m_UndefValue()), m_Value())))
       continue;
 
     // Verify that the negate is in this function, V might be a constant expr.
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 6716ec581bd06..1e330a364df6b 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -16,10 +16,12 @@
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/PatternMatch.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
+using namespace llvm::PatternMatch;
 
 namespace {
 
@@ -595,26 +597,26 @@ TEST(ConstantsTest, containsUndefElemTest) {
 
   {
     Constant *V1 = ConstantVector::get({C1, C2});
-    EXPECT_FALSE(V1->containsUndefOrPoisonElement());
-    EXPECT_FALSE(V1->containsPoisonElement());
+    EXPECT_FALSE(match(V1, m_AnyVectorElement(m_UndefValue())));
+    EXPECT_FALSE(match(V1, m_AnyVectorElement(m_Poison())));
   }
 
   {
     Constant *V2 = ConstantVector::get({C1, CU});
-    EXPECT_TRUE(V2->containsUndefOrPoisonElement());
-    EXPECT_FALSE(V2->containsPoisonElement());
+    EXPECT_TRUE(match(V2, m_AnyVectorElement(m_UndefValue())));
+    EXPECT_FALSE(match(V2, m_AnyVectorElement(m_Poison())));
   }
 
   {
     Constant *V3 = ConstantVector::get({C1, CP});
-    EXPECT_TRUE(V3->containsUndefOrPoisonElement());
-    EXPECT_TRUE(V3->containsPoisonElement());
+    EXPECT_TRUE(match(V3, m_AnyVectorElement(m_UndefValue())));
+    EXPECT_TRUE(match(V3, m_AnyVectorElement(m_Poison())));
   }
 
   {
     Constant *V4 = ConstantVector::get({CU, CP});
-    EXPECT_TRUE(V4->containsUndefOrPoisonElement());
-    EXPECT_TRUE(V4->containsPoisonElement());
+    EXPECT_TRUE(match(V4, m_AnyVectorElement(m_UndefValue())));
+    EXPECT_TRUE(match(V4, m_AnyVectorElement(m_Poison())));
   }
 }
 

>From 21eec1ff6e218ed85135eac7963f27c07b813539 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 29 May 2026 16:32:48 -0500
Subject: [PATCH 02/10] Format with clang-format

---
 llvm/include/llvm/IR/Constant.h                     |  4 +++-
 llvm/include/llvm/IR/PatternMatch.h                 |  9 ++++++---
 llvm/lib/Analysis/ValueTracking.cpp                 | 13 ++++++++++---
 llvm/lib/IR/ConstantFold.cpp                        |  3 ++-
 llvm/lib/IR/Constants.cpp                           |  5 +++--
 .../lib/Transforms/InstCombine/InstCombineCalls.cpp |  3 ++-
 .../Transforms/InstCombine/InstructionCombining.cpp |  6 ++++--
 7 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 29af0c1004e8d..8da078ce12d83 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -112,7 +112,9 @@ class Constant : public User {
   /// lane, the constants still match.
   LLVM_ABI bool isElementWiseEqual(Value *Y) const;
 
-  /// Return true if this is a vector constant where at least one element satisfies the given predicate. For scalable vectors, the predicate is tested on the value as a whole.
+  /// Return true if this is a vector constant where at least one element
+  /// satisfies the given predicate. For scalable vectors, the predicate is
+  /// tested on the value as a whole.
   LLVM_ABI bool anyVectorElement(function_ref<bool(Constant *)> PredFn) const;
 
   /// Return true if the value can vary between threads.
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index c618948eee873..7fadd23a85566 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -187,11 +187,13 @@ template <typename SPTy> struct anyvectorelement_match {
 
   template <typename ITy> bool match(ITy *V) const {
     auto *C = dyn_cast<Constant>(V);
-    return C && C->anyVectorElement([&](Constant *E) { return SubPattern.match(E); });
+    return C && C->anyVectorElement(
+                    [&](Constant *E) { return SubPattern.match(E); });
   }
 };
 
-/// Match a vector constant where at least one of its elements matches the subpattern. Any bindings in the subpattern will be bound to the first match.
+/// Match a vector constant where at least one of its elements matches the
+/// subpattern. Any bindings in the subpattern will be bound to the first match.
 template <typename SPTy>
 inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
   return SubPattern;
@@ -200,7 +202,8 @@ inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
 /// Match a constant expression or a constant that contains a constant
 /// expression.
 inline auto m_ConstantExpr() {
-  return m_CombineOr(m_Isa<ConstantExpr>(), m_AnyVectorElement(m_Isa<ConstantExpr>()));
+  return m_CombineOr(m_Isa<ConstantExpr>(),
+                     m_AnyVectorElement(m_Isa<ConstantExpr>()));
 }
 
 template <typename SubPattern_t> struct Splat_match {
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index d6e9bd154e90d..7e38da703c188 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7813,7 +7813,9 @@ static bool isGuaranteedNotToBeUndefOrPoison(
           if (isa<ConstantInt>(SplatC) || isa<ConstantFP>(SplatC))
             return true;
       } else {
-        if (includesUndef(Kind) && match(C, m_AnyVectorElement(m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
+        if (includesUndef(Kind) &&
+            match(C, m_AnyVectorElement(
+                         m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
           return false;
         if (includesPoison(Kind) && match(C, m_AnyVectorElement(m_Poison())))
           return false;
@@ -8876,9 +8878,14 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
     // purpose of identifying min/max. Disregard vector constants with undefined
     // elements because those can not be back-propagated for analysis.
     Value *OutputZeroVal = nullptr;
-    if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(m_UndefValue())))) && !match(FalseVal, m_AnyZeroFP()))
+    if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(
+                                                       m_UndefValue())))) &&
+        !match(FalseVal, m_AnyZeroFP()))
       OutputZeroVal = TrueVal;
-    else if (match(FalseVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(m_UndefValue())))) && !match(TrueVal, m_AnyZeroFP()))
+    else if (match(FalseVal,
+                   m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(
+                                                   m_UndefValue())))) &&
+             !match(TrueVal, m_AnyZeroFP()))
       OutputZeroVal = FalseVal;
 
     if (OutputZeroVal) {
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 80e00cb7cc1af..c997cbaa68fa8 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -359,7 +359,8 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
       return true;
 
     if (C->getType()->isVectorTy())
-      return !match(C, m_CombineOr(m_AnyVectorElement(m_Poison()), m_ConstantExpr()));
+      return !match(
+          C, m_CombineOr(m_AnyVectorElement(m_Poison()), m_ConstantExpr()));
 
     // TODO: Recursively analyze aggregates or other constants.
     return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 29d18d7afd4c4..c0e7e298ea312 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -184,7 +184,8 @@ bool Constant::isNotMinSignedValue() const {
 
   // Check that vectors don't contain INT_MIN
   if (isa<FixedVectorType>(getType())) {
-    return !anyVectorElement([&](const auto *E) { return !E->isNotMinSignedValue(); });
+    return !anyVectorElement(
+        [&](const auto *E) { return !E->isNotMinSignedValue(); });
   }
 
   // Check for splats that aren't INT_MIN
@@ -307,7 +308,7 @@ bool Constant::isElementWiseEqual(Value *Y) const {
 bool Constant::anyVectorElement(function_ref<bool(Constant *)> PredFn) const {
   if (!getType()->isVectorTy())
     return false;
-  
+
   if (Constant *SplatVal = getSplatValue())
     if (PredFn(SplatVal))
       return true;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 7f2f2c5ded995..46ab11481f08a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -396,7 +396,8 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
   if (auto *SplatPtr = getSplatValue(II.getArgOperand(1))) {
     // scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr
     if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) {
-      if (match(ConstMask, m_AnyVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
+      if (match(ConstMask,
+                m_AnyVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
         Align Alignment = II.getParamAlign(1).valueOrOne();
         StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false,
                                      Alignment);
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index e9e1f23f2a2f1..3568d7225730c 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5487,12 +5487,14 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
     if (!VTy)
       return nullptr;
     Constant *BestValue = Constant::getNullValue(VTy->getScalarType());
-    match(C, m_AnyVectorElement(m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
+    match(C, m_AnyVectorElement(
+                 m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
     return Constant::replaceUndefsWith(C, BestValue);
   };
 
   Constant *C;
-  if (match(Op0, m_CombineAnd(m_Constant(C), m_AnyVectorElement(m_UndefValue()), m_Unless(m_ConstantExpr())))) {
+  if (match(Op0, m_CombineAnd(m_Constant(C), m_AnyVectorElement(m_UndefValue()),
+                              m_Unless(m_ConstantExpr())))) {
     if (Constant *Repl = getFreezeVectorReplacement(C))
       return replaceInstUsesWith(I, Repl);
   }

>From 2ca00a1a21fc1713925c7c304e4facab2fdd569a Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 29 May 2026 16:43:56 -0500
Subject: [PATCH 03/10] Fix misleading documentation for
 Constant::anyVectorElement

---
 llvm/include/llvm/IR/Constant.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 8da078ce12d83..e327bbc0a6983 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -114,7 +114,7 @@ class Constant : public User {
 
   /// Return true if this is a vector constant where at least one element
   /// satisfies the given predicate. For scalable vectors, the predicate is
-  /// tested on the value as a whole.
+  /// only tested on the splat value.
   LLVM_ABI bool anyVectorElement(function_ref<bool(Constant *)> PredFn) const;
 
   /// Return true if the value can vary between threads.

>From a490d9bd0cc53b6b29d1a7d2ca4eadc13661a262 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Mon, 1 Jun 2026 10:52:45 -0500
Subject: [PATCH 04/10] Renamed anyVectorElement/m_AnyVectorElement to
 containsVectorElement/m_ContainsVectorElement

---
 llvm/include/llvm/IR/Constant.h                  |  2 +-
 llvm/include/llvm/IR/PatternMatch.h              | 10 +++++-----
 llvm/lib/Analysis/ConstantFolding.cpp            |  8 ++++----
 llvm/lib/Analysis/ValueTracking.cpp              | 10 +++++-----
 llvm/lib/CodeGen/MachineFunction.cpp             |  2 +-
 llvm/lib/IR/ConstantFold.cpp                     |  2 +-
 llvm/lib/IR/Constants.cpp                        |  4 ++--
 .../Transforms/InstCombine/InstCombineCalls.cpp  |  2 +-
 .../InstCombine/InstCombineMulDivRem.cpp         |  2 +-
 .../InstCombine/InstCombineNegator.cpp           |  2 +-
 .../InstCombine/InstructionCombining.cpp         |  4 ++--
 .../Instrumentation/MemorySanitizer.cpp          |  2 +-
 llvm/lib/Transforms/Scalar/Reassociate.cpp       |  2 +-
 llvm/unittests/IR/ConstantsTest.cpp              | 16 ++++++++--------
 14 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index e327bbc0a6983..4394bd6032faf 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -115,7 +115,7 @@ class Constant : public User {
   /// Return true if this is a vector constant where at least one element
   /// satisfies the given predicate. For scalable vectors, the predicate is
   /// only tested on the splat value.
-  LLVM_ABI bool anyVectorElement(function_ref<bool(Constant *)> PredFn) const;
+  LLVM_ABI bool containsVectorElement(function_ref<bool(Constant *)> PredFn) const;
 
   /// Return true if the value can vary between threads.
   LLVM_ABI bool isThreadDependent() const;
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 7fadd23a85566..43ed066bfa0e4 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -181,13 +181,13 @@ inline auto m_ConstantInt() { return m_Isa<ConstantInt>(); }
 /// Match an arbitrary ConstantFP and ignore it.
 inline auto m_ConstantFP() { return m_Isa<ConstantFP>(); }
 
-template <typename SPTy> struct anyvectorelement_match {
+template <typename SPTy> struct containsvectorelement_match {
   SPTy SubPattern;
-  anyvectorelement_match(const SPTy &SP) : SubPattern(SP) {}
+  containsvectorelement_match(const SPTy &SP) : SubPattern(SP) {}
 
   template <typename ITy> bool match(ITy *V) const {
     auto *C = dyn_cast<Constant>(V);
-    return C && C->anyVectorElement(
+    return C && C->containsVectorElement(
                     [&](Constant *E) { return SubPattern.match(E); });
   }
 };
@@ -195,7 +195,7 @@ template <typename SPTy> struct anyvectorelement_match {
 /// Match a vector constant where at least one of its elements matches the
 /// subpattern. Any bindings in the subpattern will be bound to the first match.
 template <typename SPTy>
-inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
+inline containsvectorelement_match<SPTy> m_ContainsVectorElement(const SPTy &SubPattern) {
   return SubPattern;
 }
 
@@ -203,7 +203,7 @@ inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
 /// expression.
 inline auto m_ConstantExpr() {
   return m_CombineOr(m_Isa<ConstantExpr>(),
-                     m_AnyVectorElement(m_Isa<ConstantExpr>()));
+                     m_ContainsVectorElement(m_Isa<ConstantExpr>()));
 }
 
 template <typename SubPattern_t> struct Splat_match {
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index ef43d829bb48c..b806d932d240c 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -120,7 +120,7 @@ static bool foldMixesPoisonBits(Constant *C, unsigned NumSrcElt,
   // If element counts don't divide evenly, bail out if a poison source element
   // might span multiple destination lanes.
   if (NumSrcElt % NumDstElt != 0)
-    return match(C, m_AnyVectorElement(m_Poison()));
+    return match(C, m_ContainsVectorElement(m_Poison()));
   unsigned Ratio = NumSrcElt / NumDstElt;
   for (unsigned i = 0; i != NumSrcElt; i += Ratio) {
     bool HasPoison = false;
@@ -151,7 +151,7 @@ static bool computePoisonDstLanes(Constant *C, unsigned NumSrcElt,
   // If element counts don't divide evenly, bail out if a poison source element
   // might span multiple destination lanes.
   if ((NumDstElt < NumSrcElt ? NumSrcElt % NumDstElt : NumDstElt % NumSrcElt))
-    return !match(C, m_AnyVectorElement(m_Poison()));
+    return !match(C, m_ContainsVectorElement(m_Poison()));
   if (NumDstElt < NumSrcElt) {
     unsigned Ratio = NumSrcElt / NumDstElt;
     for (unsigned i = 0; i != NumDstElt; ++i) {
@@ -197,7 +197,7 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
 
       // Bitcasting a byte containing any poison bit to an integer or fp type
       // yields poison.
-      if (SrcEltTy->isByteTy() && match(C, m_AnyVectorElement(m_Poison())))
+      if (SrcEltTy->isByteTy() && match(C, m_ContainsVectorElement(m_Poison())))
         return PoisonValue::get(DestTy);
 
       // If the vector is a vector of floating point or bytes, convert it to a
@@ -2315,7 +2315,7 @@ Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) {
   auto *OpVT = cast<VectorType>(Op->getType());
 
   // This is the same as the underlying binops - poison propagates.
-  if (match(Op, m_AnyVectorElement(m_Poison())))
+  if (match(Op, m_ContainsVectorElement(m_Poison())))
     return PoisonValue::get(OpVT->getElementType());
 
   // Shortcut non-accumulating reductions.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 7e38da703c188..f2f2641d8b7f2 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7814,10 +7814,10 @@ static bool isGuaranteedNotToBeUndefOrPoison(
             return true;
       } else {
         if (includesUndef(Kind) &&
-            match(C, m_AnyVectorElement(
+            match(C, m_ContainsVectorElement(
                          m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
           return false;
-        if (includesPoison(Kind) && match(C, m_AnyVectorElement(m_Poison())))
+        if (includesPoison(Kind) && match(C, m_ContainsVectorElement(m_Poison())))
           return false;
         return !match(C, m_ConstantExpr());
       }
@@ -8851,7 +8851,7 @@ llvm::getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C) {
   // undefined elements, so replace those elements with the first safe constant
   // that we found.
   // TODO: in case of poison, it is safe; let's replace undefs only.
-  if (match(C, m_AnyVectorElement(m_UndefValue()))) {
+  if (match(C, m_ContainsVectorElement(m_UndefValue()))) {
     assert(SafeReplacementConstant && "Replacement constant not set");
     C = Constant::replaceUndefsWith(C, SafeReplacementConstant);
   }
@@ -8878,12 +8878,12 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
     // purpose of identifying min/max. Disregard vector constants with undefined
     // elements because those can not be back-propagated for analysis.
     Value *OutputZeroVal = nullptr;
-    if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(
+    if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
                                                        m_UndefValue())))) &&
         !match(FalseVal, m_AnyZeroFP()))
       OutputZeroVal = TrueVal;
     else if (match(FalseVal,
-                   m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(
+                   m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
                                                    m_UndefValue())))) &&
              !match(TrueVal, m_AnyZeroFP()))
       OutputZeroVal = FalseVal;
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index ea01c3241e84d..bb2616c565c1a 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -1563,7 +1563,7 @@ static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B,
   if (StoreSize != DL.getTypeStoreSize(B->getType()) || StoreSize > 128)
     return false;
 
-  bool ContainsUndefOrPoisonA = match(A, m_AnyVectorElement(m_UndefValue()));
+  bool ContainsUndefOrPoisonA = match(A, m_ContainsVectorElement(m_UndefValue()));
 
   Type *IntTy = IntegerType::get(A->getContext(), StoreSize*8);
 
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index c997cbaa68fa8..beb55b3c7147d 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -360,7 +360,7 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
 
     if (C->getType()->isVectorTy())
       return !match(
-          C, m_CombineOr(m_AnyVectorElement(m_Poison()), m_ConstantExpr()));
+          C, m_CombineOr(m_ContainsVectorElement(m_Poison()), m_ConstantExpr()));
 
     // TODO: Recursively analyze aggregates or other constants.
     return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index c0e7e298ea312..2ef42058c8e15 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -184,7 +184,7 @@ bool Constant::isNotMinSignedValue() const {
 
   // Check that vectors don't contain INT_MIN
   if (isa<FixedVectorType>(getType())) {
-    return !anyVectorElement(
+    return !containsVectorElement(
         [&](const auto *E) { return !E->isNotMinSignedValue(); });
   }
 
@@ -305,7 +305,7 @@ bool Constant::isElementWiseEqual(Value *Y) const {
   return CmpEq && (isa<PoisonValue>(CmpEq) || match(CmpEq, m_One()));
 }
 
-bool Constant::anyVectorElement(function_ref<bool(Constant *)> PredFn) const {
+bool Constant::containsVectorElement(function_ref<bool(Constant *)> PredFn) const {
   if (!getType()->isVectorTy())
     return false;
 
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 46ab11481f08a..fb849c296ad25 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -397,7 +397,7 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
     // scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr
     if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) {
       if (match(ConstMask,
-                m_AnyVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
+                m_ContainsVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
         Align Alignment = II.getParamAlign(1).valueOrOne();
         StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false,
                                      Alignment);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 5e241132ca3dd..564d342256f41 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1290,7 +1290,7 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
 
   // If any element of a constant divisor fixed width vector is zero or undef
   // the behavior is undefined and we can fold the whole op to poison.
-  if (match(Op1, m_AnyVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
+  if (match(Op1, m_ContainsVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
     return replaceInstUsesWith(I, PoisonValue::get(I.getType()));
   }
 
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
index 45d15cfe27fdb..7a9fc4a32a91b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
@@ -275,7 +275,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     // While this is normally not behind a use-check,
     // let's consider division to be special since it's costly.
     if (auto *Op1C = dyn_cast<Constant>(I->getOperand(1))) {
-      if (!match(Op1C, m_AnyVectorElement(m_UndefValue())) &&
+      if (!match(Op1C, m_ContainsVectorElement(m_UndefValue())) &&
           Op1C->isNotMinSignedValue() && Op1C->isNotOneValue()) {
         Value *BO =
             Builder.CreateSDiv(I->getOperand(0), ConstantExpr::getNeg(Op1C),
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 3568d7225730c..705d110e8b078 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5487,13 +5487,13 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
     if (!VTy)
       return nullptr;
     Constant *BestValue = Constant::getNullValue(VTy->getScalarType());
-    match(C, m_AnyVectorElement(
+    match(C, m_ContainsVectorElement(
                  m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
     return Constant::replaceUndefsWith(C, BestValue);
   };
 
   Constant *C;
-  if (match(Op0, m_CombineAnd(m_Constant(C), m_AnyVectorElement(m_UndefValue()),
+  if (match(Op0, m_CombineAnd(m_Constant(C), m_ContainsVectorElement(m_UndefValue()),
                               m_Unless(m_ConstantExpr())))) {
     if (Constant *Repl = getFreezeVectorReplacement(C))
       return replaceInstUsesWith(I, Repl);
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index e133840db0e01..103f5dd4e8246 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -2175,7 +2175,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
 
     // Check for partially-undefined constant vectors
     // TODO: scalable vectors (this is hard because we do not have IRBuilder)
-    if (match(V, m_AnyVectorElement(m_UndefValue())) && PropagateShadow &&
+    if (match(V, m_ContainsVectorElement(m_UndefValue())) && PropagateShadow &&
         PoisonUndefVectors) {
       unsigned NumElems = cast<FixedVectorType>(V->getType())->getNumElements();
       SmallVector<Constant *, 32> ShadowVector(NumElems);
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index 06756f9c6783d..e5b5413487b7e 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -816,7 +816,7 @@ static Value *NegateValue(Value *V, Instruction *BI,
     Instruction *TheNeg = dyn_cast<Instruction>(U);
 
     // We can't safely propagate a vector zero constant with poison/undef lanes.
-    if (match(TheNeg, m_BinOp(m_AnyVectorElement(m_UndefValue()), m_Value())))
+    if (match(TheNeg, m_BinOp(m_ContainsVectorElement(m_UndefValue()), m_Value())))
       continue;
 
     // Verify that the negate is in this function, V might be a constant expr.
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 1e330a364df6b..8b7caad3212ff 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -597,26 +597,26 @@ TEST(ConstantsTest, containsUndefElemTest) {
 
   {
     Constant *V1 = ConstantVector::get({C1, C2});
-    EXPECT_FALSE(match(V1, m_AnyVectorElement(m_UndefValue())));
-    EXPECT_FALSE(match(V1, m_AnyVectorElement(m_Poison())));
+    EXPECT_FALSE(match(V1, m_ContainsVectorElement(m_UndefValue())));
+    EXPECT_FALSE(match(V1, m_ContainsVectorElement(m_Poison())));
   }
 
   {
     Constant *V2 = ConstantVector::get({C1, CU});
-    EXPECT_TRUE(match(V2, m_AnyVectorElement(m_UndefValue())));
-    EXPECT_FALSE(match(V2, m_AnyVectorElement(m_Poison())));
+    EXPECT_TRUE(match(V2, m_ContainsVectorElement(m_UndefValue())));
+    EXPECT_FALSE(match(V2, m_ContainsVectorElement(m_Poison())));
   }
 
   {
     Constant *V3 = ConstantVector::get({C1, CP});
-    EXPECT_TRUE(match(V3, m_AnyVectorElement(m_UndefValue())));
-    EXPECT_TRUE(match(V3, m_AnyVectorElement(m_Poison())));
+    EXPECT_TRUE(match(V3, m_ContainsVectorElement(m_UndefValue())));
+    EXPECT_TRUE(match(V3, m_ContainsVectorElement(m_Poison())));
   }
 
   {
     Constant *V4 = ConstantVector::get({CU, CP});
-    EXPECT_TRUE(match(V4, m_AnyVectorElement(m_UndefValue())));
-    EXPECT_TRUE(match(V4, m_AnyVectorElement(m_Poison())));
+    EXPECT_TRUE(match(V4, m_ContainsVectorElement(m_UndefValue())));
+    EXPECT_TRUE(match(V4, m_ContainsVectorElement(m_Poison())));
   }
 }
 

>From 2460a9ea9b28df37508b31ac48042a409419e012 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Mon, 1 Jun 2026 10:57:21 -0500
Subject: [PATCH 05/10] Format with clang-format

---
 llvm/include/llvm/IR/Constant.h                          | 3 ++-
 llvm/include/llvm/IR/PatternMatch.h                      | 3 ++-
 llvm/lib/Analysis/ValueTracking.cpp                      | 8 +++++---
 llvm/lib/CodeGen/MachineFunction.cpp                     | 3 ++-
 llvm/lib/IR/ConstantFold.cpp                             | 4 ++--
 llvm/lib/IR/Constants.cpp                                | 3 ++-
 llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp     | 4 ++--
 llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 3 ++-
 llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 5 +++--
 llvm/lib/Transforms/Scalar/Reassociate.cpp               | 3 ++-
 10 files changed, 24 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 4394bd6032faf..3a179bad0a512 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -115,7 +115,8 @@ class Constant : public User {
   /// Return true if this is a vector constant where at least one element
   /// satisfies the given predicate. For scalable vectors, the predicate is
   /// only tested on the splat value.
-  LLVM_ABI bool containsVectorElement(function_ref<bool(Constant *)> PredFn) const;
+  LLVM_ABI bool
+  containsVectorElement(function_ref<bool(Constant *)> PredFn) const;
 
   /// Return true if the value can vary between threads.
   LLVM_ABI bool isThreadDependent() const;
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 43ed066bfa0e4..c5ef54966aae3 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -195,7 +195,8 @@ template <typename SPTy> struct containsvectorelement_match {
 /// Match a vector constant where at least one of its elements matches the
 /// subpattern. Any bindings in the subpattern will be bound to the first match.
 template <typename SPTy>
-inline containsvectorelement_match<SPTy> m_ContainsVectorElement(const SPTy &SubPattern) {
+inline containsvectorelement_match<SPTy>
+m_ContainsVectorElement(const SPTy &SubPattern) {
   return SubPattern;
 }
 
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f2f2641d8b7f2..6855a20109b85 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7817,7 +7817,8 @@ static bool isGuaranteedNotToBeUndefOrPoison(
             match(C, m_ContainsVectorElement(
                          m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
           return false;
-        if (includesPoison(Kind) && match(C, m_ContainsVectorElement(m_Poison())))
+        if (includesPoison(Kind) &&
+            match(C, m_ContainsVectorElement(m_Poison())))
           return false;
         return !match(C, m_ConstantExpr());
       }
@@ -8878,8 +8879,9 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
     // purpose of identifying min/max. Disregard vector constants with undefined
     // elements because those can not be back-propagated for analysis.
     Value *OutputZeroVal = nullptr;
-    if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
-                                                       m_UndefValue())))) &&
+    if (match(TrueVal,
+              m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
+                                              m_UndefValue())))) &&
         !match(FalseVal, m_AnyZeroFP()))
       OutputZeroVal = TrueVal;
     else if (match(FalseVal,
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index bb2616c565c1a..7d7a1ad274290 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -1563,7 +1563,8 @@ static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B,
   if (StoreSize != DL.getTypeStoreSize(B->getType()) || StoreSize > 128)
     return false;
 
-  bool ContainsUndefOrPoisonA = match(A, m_ContainsVectorElement(m_UndefValue()));
+  bool ContainsUndefOrPoisonA =
+      match(A, m_ContainsVectorElement(m_UndefValue()));
 
   Type *IntTy = IntegerType::get(A->getContext(), StoreSize*8);
 
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index beb55b3c7147d..9c3d9e21c3f2e 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -359,8 +359,8 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
       return true;
 
     if (C->getType()->isVectorTy())
-      return !match(
-          C, m_CombineOr(m_ContainsVectorElement(m_Poison()), m_ConstantExpr()));
+      return !match(C, m_CombineOr(m_ContainsVectorElement(m_Poison()),
+                                   m_ConstantExpr()));
 
     // TODO: Recursively analyze aggregates or other constants.
     return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 2ef42058c8e15..b947b78ed4929 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -305,7 +305,8 @@ bool Constant::isElementWiseEqual(Value *Y) const {
   return CmpEq && (isa<PoisonValue>(CmpEq) || match(CmpEq, m_One()));
 }
 
-bool Constant::containsVectorElement(function_ref<bool(Constant *)> PredFn) const {
+bool Constant::containsVectorElement(
+    function_ref<bool(Constant *)> PredFn) const {
   if (!getType()->isVectorTy())
     return false;
 
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index fb849c296ad25..eb2c4c52c4bea 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -396,8 +396,8 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
   if (auto *SplatPtr = getSplatValue(II.getArgOperand(1))) {
     // scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr
     if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) {
-      if (match(ConstMask,
-                m_ContainsVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
+      if (match(ConstMask, m_ContainsVectorElement(
+                               m_CombineOr(m_AllOnes(), m_UndefValue())))) {
         Align Alignment = II.getParamAlign(1).valueOrOne();
         StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false,
                                      Alignment);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 564d342256f41..6a71bfe26b7b8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1290,7 +1290,8 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
 
   // If any element of a constant divisor fixed width vector is zero or undef
   // the behavior is undefined and we can fold the whole op to poison.
-  if (match(Op1, m_ContainsVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
+  if (match(Op1,
+            m_ContainsVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
     return replaceInstUsesWith(I, PoisonValue::get(I.getType()));
   }
 
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 705d110e8b078..67bbb3e6a8809 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5493,8 +5493,9 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
   };
 
   Constant *C;
-  if (match(Op0, m_CombineAnd(m_Constant(C), m_ContainsVectorElement(m_UndefValue()),
-                              m_Unless(m_ConstantExpr())))) {
+  if (match(Op0,
+            m_CombineAnd(m_Constant(C), m_ContainsVectorElement(m_UndefValue()),
+                         m_Unless(m_ConstantExpr())))) {
     if (Constant *Repl = getFreezeVectorReplacement(C))
       return replaceInstUsesWith(I, Repl);
   }
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index e5b5413487b7e..6c74456f27a4e 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -816,7 +816,8 @@ static Value *NegateValue(Value *V, Instruction *BI,
     Instruction *TheNeg = dyn_cast<Instruction>(U);
 
     // We can't safely propagate a vector zero constant with poison/undef lanes.
-    if (match(TheNeg, m_BinOp(m_ContainsVectorElement(m_UndefValue()), m_Value())))
+    if (match(TheNeg,
+              m_BinOp(m_ContainsVectorElement(m_UndefValue()), m_Value())))
       continue;
 
     // Verify that the negate is in this function, V might be a constant expr.

>From 2ad30a612ec832cef95d074eca255a9fefa988ce Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Wed, 3 Jun 2026 09:28:35 -0500
Subject: [PATCH 06/10] Rename containsVectorElement ->
 containsMatchingVectorElement

---
 llvm/include/llvm/IR/Constant.h                 |  2 +-
 llvm/include/llvm/IR/PatternMatch.h             |  6 +++---
 llvm/lib/Analysis/ConstantFolding.cpp           |  9 +++++----
 llvm/lib/Analysis/ValueTracking.cpp             | 17 +++++++++--------
 llvm/lib/CodeGen/MachineFunction.cpp            |  2 +-
 llvm/lib/IR/ConstantFold.cpp                    |  2 +-
 llvm/lib/IR/Constants.cpp                       |  4 ++--
 .../Transforms/InstCombine/InstCombineCalls.cpp |  2 +-
 .../InstCombine/InstCombineMulDivRem.cpp        |  4 ++--
 .../InstCombine/InstCombineNegator.cpp          |  2 +-
 .../InstCombine/InstructionCombining.cpp        |  8 ++++----
 .../Instrumentation/MemorySanitizer.cpp         |  4 ++--
 llvm/lib/Transforms/Scalar/Reassociate.cpp      |  4 ++--
 llvm/unittests/IR/ConstantsTest.cpp             | 16 ++++++++--------
 14 files changed, 42 insertions(+), 40 deletions(-)

diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 3a179bad0a512..2723314f712f7 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -116,7 +116,7 @@ class Constant : public User {
   /// satisfies the given predicate. For scalable vectors, the predicate is
   /// only tested on the splat value.
   LLVM_ABI bool
-  containsVectorElement(function_ref<bool(Constant *)> PredFn) const;
+  containsMatchingVectorElement(function_ref<bool(Constant *)> PredFn) const;
 
   /// Return true if the value can vary between threads.
   LLVM_ABI bool isThreadDependent() const;
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index c5ef54966aae3..1c3522681832e 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -187,7 +187,7 @@ template <typename SPTy> struct containsvectorelement_match {
 
   template <typename ITy> bool match(ITy *V) const {
     auto *C = dyn_cast<Constant>(V);
-    return C && C->containsVectorElement(
+    return C && C->containsMatchingVectorElement(
                     [&](Constant *E) { return SubPattern.match(E); });
   }
 };
@@ -196,7 +196,7 @@ template <typename SPTy> struct containsvectorelement_match {
 /// subpattern. Any bindings in the subpattern will be bound to the first match.
 template <typename SPTy>
 inline containsvectorelement_match<SPTy>
-m_ContainsVectorElement(const SPTy &SubPattern) {
+m_ContainsMatchingVectorElement(const SPTy &SubPattern) {
   return SubPattern;
 }
 
@@ -204,7 +204,7 @@ m_ContainsVectorElement(const SPTy &SubPattern) {
 /// expression.
 inline auto m_ConstantExpr() {
   return m_CombineOr(m_Isa<ConstantExpr>(),
-                     m_ContainsVectorElement(m_Isa<ConstantExpr>()));
+                     m_ContainsMatchingVectorElement(m_Isa<ConstantExpr>()));
 }
 
 template <typename SubPattern_t> struct Splat_match {
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index b806d932d240c..6cf244843afb6 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -120,7 +120,7 @@ static bool foldMixesPoisonBits(Constant *C, unsigned NumSrcElt,
   // If element counts don't divide evenly, bail out if a poison source element
   // might span multiple destination lanes.
   if (NumSrcElt % NumDstElt != 0)
-    return match(C, m_ContainsVectorElement(m_Poison()));
+    return match(C, m_ContainsMatchingVectorElement(m_Poison()));
   unsigned Ratio = NumSrcElt / NumDstElt;
   for (unsigned i = 0; i != NumSrcElt; i += Ratio) {
     bool HasPoison = false;
@@ -151,7 +151,7 @@ static bool computePoisonDstLanes(Constant *C, unsigned NumSrcElt,
   // If element counts don't divide evenly, bail out if a poison source element
   // might span multiple destination lanes.
   if ((NumDstElt < NumSrcElt ? NumSrcElt % NumDstElt : NumDstElt % NumSrcElt))
-    return !match(C, m_ContainsVectorElement(m_Poison()));
+    return !match(C, m_ContainsMatchingVectorElement(m_Poison()));
   if (NumDstElt < NumSrcElt) {
     unsigned Ratio = NumSrcElt / NumDstElt;
     for (unsigned i = 0; i != NumDstElt; ++i) {
@@ -197,7 +197,8 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
 
       // Bitcasting a byte containing any poison bit to an integer or fp type
       // yields poison.
-      if (SrcEltTy->isByteTy() && match(C, m_ContainsVectorElement(m_Poison())))
+      if (SrcEltTy->isByteTy() &&
+          match(C, m_ContainsMatchingVectorElement(m_Poison())))
         return PoisonValue::get(DestTy);
 
       // If the vector is a vector of floating point or bytes, convert it to a
@@ -2315,7 +2316,7 @@ Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) {
   auto *OpVT = cast<VectorType>(Op->getType());
 
   // This is the same as the underlying binops - poison propagates.
-  if (match(Op, m_ContainsVectorElement(m_Poison())))
+  if (match(Op, m_ContainsMatchingVectorElement(m_Poison())))
     return PoisonValue::get(OpVT->getElementType());
 
   // Shortcut non-accumulating reductions.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 6855a20109b85..584243d2811b5 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7814,11 +7814,11 @@ static bool isGuaranteedNotToBeUndefOrPoison(
             return true;
       } else {
         if (includesUndef(Kind) &&
-            match(C, m_ContainsVectorElement(
+            match(C, m_ContainsMatchingVectorElement(
                          m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
           return false;
         if (includesPoison(Kind) &&
-            match(C, m_ContainsVectorElement(m_Poison())))
+            match(C, m_ContainsMatchingVectorElement(m_Poison())))
           return false;
         return !match(C, m_ConstantExpr());
       }
@@ -8852,7 +8852,7 @@ llvm::getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C) {
   // undefined elements, so replace those elements with the first safe constant
   // that we found.
   // TODO: in case of poison, it is safe; let's replace undefs only.
-  if (match(C, m_ContainsVectorElement(m_UndefValue()))) {
+  if (match(C, m_ContainsMatchingVectorElement(m_UndefValue()))) {
     assert(SafeReplacementConstant && "Replacement constant not set");
     C = Constant::replaceUndefsWith(C, SafeReplacementConstant);
   }
@@ -8879,14 +8879,15 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
     // purpose of identifying min/max. Disregard vector constants with undefined
     // elements because those can not be back-propagated for analysis.
     Value *OutputZeroVal = nullptr;
-    if (match(TrueVal,
-              m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
-                                              m_UndefValue())))) &&
+    if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(),
+                                    m_Unless(m_ContainsMatchingVectorElement(
+                                        m_UndefValue())))) &&
         !match(FalseVal, m_AnyZeroFP()))
       OutputZeroVal = TrueVal;
     else if (match(FalseVal,
-                   m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
-                                                   m_UndefValue())))) &&
+                   m_CombineAnd(m_AnyZeroFP(),
+                                m_Unless(m_ContainsMatchingVectorElement(
+                                    m_UndefValue())))) &&
              !match(TrueVal, m_AnyZeroFP()))
       OutputZeroVal = FalseVal;
 
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index 7d7a1ad274290..d3f07d2500f42 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -1564,7 +1564,7 @@ static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B,
     return false;
 
   bool ContainsUndefOrPoisonA =
-      match(A, m_ContainsVectorElement(m_UndefValue()));
+      match(A, m_ContainsMatchingVectorElement(m_UndefValue()));
 
   Type *IntTy = IntegerType::get(A->getContext(), StoreSize*8);
 
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 9c3d9e21c3f2e..f6eb629c7f050 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -359,7 +359,7 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
       return true;
 
     if (C->getType()->isVectorTy())
-      return !match(C, m_CombineOr(m_ContainsVectorElement(m_Poison()),
+      return !match(C, m_CombineOr(m_ContainsMatchingVectorElement(m_Poison()),
                                    m_ConstantExpr()));
 
     // TODO: Recursively analyze aggregates or other constants.
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index b947b78ed4929..0bb7669ceb41e 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -184,7 +184,7 @@ bool Constant::isNotMinSignedValue() const {
 
   // Check that vectors don't contain INT_MIN
   if (isa<FixedVectorType>(getType())) {
-    return !containsVectorElement(
+    return !containsMatchingVectorElement(
         [&](const auto *E) { return !E->isNotMinSignedValue(); });
   }
 
@@ -305,7 +305,7 @@ bool Constant::isElementWiseEqual(Value *Y) const {
   return CmpEq && (isa<PoisonValue>(CmpEq) || match(CmpEq, m_One()));
 }
 
-bool Constant::containsVectorElement(
+bool Constant::containsMatchingVectorElement(
     function_ref<bool(Constant *)> PredFn) const {
   if (!getType()->isVectorTy())
     return false;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index eb2c4c52c4bea..c531f5c2237bd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -396,7 +396,7 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
   if (auto *SplatPtr = getSplatValue(II.getArgOperand(1))) {
     // scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr
     if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) {
-      if (match(ConstMask, m_ContainsVectorElement(
+      if (match(ConstMask, m_ContainsMatchingVectorElement(
                                m_CombineOr(m_AllOnes(), m_UndefValue())))) {
         Align Alignment = II.getParamAlign(1).valueOrOne();
         StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false,
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 6a71bfe26b7b8..7f0a473d3ad77 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1290,8 +1290,8 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
 
   // If any element of a constant divisor fixed width vector is zero or undef
   // the behavior is undefined and we can fold the whole op to poison.
-  if (match(Op1,
-            m_ContainsVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
+  if (match(Op1, m_ContainsMatchingVectorElement(
+                     m_CombineOr(m_Zero(), m_UndefValue())))) {
     return replaceInstUsesWith(I, PoisonValue::get(I.getType()));
   }
 
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
index 7a9fc4a32a91b..ad2431b3c5b84 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
@@ -275,7 +275,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     // While this is normally not behind a use-check,
     // let's consider division to be special since it's costly.
     if (auto *Op1C = dyn_cast<Constant>(I->getOperand(1))) {
-      if (!match(Op1C, m_ContainsVectorElement(m_UndefValue())) &&
+      if (!match(Op1C, m_ContainsMatchingVectorElement(m_UndefValue())) &&
           Op1C->isNotMinSignedValue() && Op1C->isNotOneValue()) {
         Value *BO =
             Builder.CreateSDiv(I->getOperand(0), ConstantExpr::getNeg(Op1C),
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 67bbb3e6a8809..f312261ad0351 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5487,15 +5487,15 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
     if (!VTy)
       return nullptr;
     Constant *BestValue = Constant::getNullValue(VTy->getScalarType());
-    match(C, m_ContainsVectorElement(
+    match(C, m_ContainsMatchingVectorElement(
                  m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
     return Constant::replaceUndefsWith(C, BestValue);
   };
 
   Constant *C;
-  if (match(Op0,
-            m_CombineAnd(m_Constant(C), m_ContainsVectorElement(m_UndefValue()),
-                         m_Unless(m_ConstantExpr())))) {
+  if (match(Op0, m_CombineAnd(m_Constant(C),
+                              m_ContainsMatchingVectorElement(m_UndefValue()),
+                              m_Unless(m_ConstantExpr())))) {
     if (Constant *Repl = getFreezeVectorReplacement(C))
       return replaceInstUsesWith(I, Repl);
   }
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 103f5dd4e8246..35575b9222bbe 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -2175,8 +2175,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
 
     // Check for partially-undefined constant vectors
     // TODO: scalable vectors (this is hard because we do not have IRBuilder)
-    if (match(V, m_ContainsVectorElement(m_UndefValue())) && PropagateShadow &&
-        PoisonUndefVectors) {
+    if (match(V, m_ContainsMatchingVectorElement(m_UndefValue())) &&
+        PropagateShadow && PoisonUndefVectors) {
       unsigned NumElems = cast<FixedVectorType>(V->getType())->getNumElements();
       SmallVector<Constant *, 32> ShadowVector(NumElems);
       for (unsigned i = 0; i != NumElems; ++i) {
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index 6c74456f27a4e..5face8fecec02 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -816,8 +816,8 @@ static Value *NegateValue(Value *V, Instruction *BI,
     Instruction *TheNeg = dyn_cast<Instruction>(U);
 
     // We can't safely propagate a vector zero constant with poison/undef lanes.
-    if (match(TheNeg,
-              m_BinOp(m_ContainsVectorElement(m_UndefValue()), m_Value())))
+    if (match(TheNeg, m_BinOp(m_ContainsMatchingVectorElement(m_UndefValue()),
+                              m_Value())))
       continue;
 
     // Verify that the negate is in this function, V might be a constant expr.
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 8b7caad3212ff..8ad2e86b471f5 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -597,26 +597,26 @@ TEST(ConstantsTest, containsUndefElemTest) {
 
   {
     Constant *V1 = ConstantVector::get({C1, C2});
-    EXPECT_FALSE(match(V1, m_ContainsVectorElement(m_UndefValue())));
-    EXPECT_FALSE(match(V1, m_ContainsVectorElement(m_Poison())));
+    EXPECT_FALSE(match(V1, m_ContainsMatchingVectorElement(m_UndefValue())));
+    EXPECT_FALSE(match(V1, m_ContainsMatchingVectorElement(m_Poison())));
   }
 
   {
     Constant *V2 = ConstantVector::get({C1, CU});
-    EXPECT_TRUE(match(V2, m_ContainsVectorElement(m_UndefValue())));
-    EXPECT_FALSE(match(V2, m_ContainsVectorElement(m_Poison())));
+    EXPECT_TRUE(match(V2, m_ContainsMatchingVectorElement(m_UndefValue())));
+    EXPECT_FALSE(match(V2, m_ContainsMatchingVectorElement(m_Poison())));
   }
 
   {
     Constant *V3 = ConstantVector::get({C1, CP});
-    EXPECT_TRUE(match(V3, m_ContainsVectorElement(m_UndefValue())));
-    EXPECT_TRUE(match(V3, m_ContainsVectorElement(m_Poison())));
+    EXPECT_TRUE(match(V3, m_ContainsMatchingVectorElement(m_UndefValue())));
+    EXPECT_TRUE(match(V3, m_ContainsMatchingVectorElement(m_Poison())));
   }
 
   {
     Constant *V4 = ConstantVector::get({CU, CP});
-    EXPECT_TRUE(match(V4, m_ContainsVectorElement(m_UndefValue())));
-    EXPECT_TRUE(match(V4, m_ContainsVectorElement(m_Poison())));
+    EXPECT_TRUE(match(V4, m_ContainsMatchingVectorElement(m_UndefValue())));
+    EXPECT_TRUE(match(V4, m_ContainsMatchingVectorElement(m_Poison())));
   }
 }
 

>From 97cf05f2e7acfdd529df77ffbbddc9055069aaa7 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Thu, 4 Jun 2026 10:56:36 -0500
Subject: [PATCH 07/10] Restore
 Constant::contains{Undef,Poison,UndefOrPoison}Element and associated call
 sites

---
 llvm/include/llvm/IR/Constant.h               | 14 ++++++
 llvm/include/llvm/IR/PatternMatch.h           |  6 +--
 llvm/lib/Analysis/ConstantFolding.cpp         |  9 ++--
 llvm/lib/Analysis/ValueTracking.cpp           | 22 +++------
 llvm/lib/CodeGen/MachineFunction.cpp          |  5 +-
 llvm/lib/IR/ConstantFold.cpp                  |  4 +-
 llvm/lib/IR/Constants.cpp                     | 48 +++++++++++++++++--
 .../InstCombine/InstCombineMulDivRem.cpp      |  3 +-
 .../InstCombine/InstCombineNegator.cpp        |  2 +-
 .../InstCombine/InstructionCombining.cpp      | 12 +++--
 .../Instrumentation/MemorySanitizer.cpp       |  5 +-
 llvm/lib/Transforms/Scalar/Reassociate.cpp    |  5 +-
 llvm/unittests/IR/ConstantsTest.cpp           | 16 +++----
 13 files changed, 100 insertions(+), 51 deletions(-)

diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 2723314f712f7..ad00ac7673952 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -112,6 +112,20 @@ class Constant : public User {
   /// lane, the constants still match.
   LLVM_ABI bool isElementWiseEqual(Value *Y) const;
 
+  /// Return true if this is a vector constant that includes any undef or
+  /// poison elements. Since it is impossible to inspect a scalable vector
+  /// element- wise at compile time, this function returns true only if the
+  /// entire vector is undef or poison.
+  LLVM_ABI bool containsUndefOrPoisonElement() const;
+
+  /// Return true if this is a vector constant that includes any poison
+  /// elements.
+  LLVM_ABI bool containsPoisonElement() const;
+
+  /// Return true if this is a vector constant that includes any strictly undef
+  /// (not poison) elements.
+  LLVM_ABI bool containsUndefElement() const;
+
   /// Return true if this is a vector constant where at least one element
   /// satisfies the given predicate. For scalable vectors, the predicate is
   /// only tested on the splat value.
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 1c3522681832e..c16c0cc5999ba 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -181,9 +181,9 @@ inline auto m_ConstantInt() { return m_Isa<ConstantInt>(); }
 /// Match an arbitrary ConstantFP and ignore it.
 inline auto m_ConstantFP() { return m_Isa<ConstantFP>(); }
 
-template <typename SPTy> struct containsvectorelement_match {
+template <typename SPTy> struct ContainsMatchingVectorElement_match {
   SPTy SubPattern;
-  containsvectorelement_match(const SPTy &SP) : SubPattern(SP) {}
+  ContainsMatchingVectorElement_match(const SPTy &SP) : SubPattern(SP) {}
 
   template <typename ITy> bool match(ITy *V) const {
     auto *C = dyn_cast<Constant>(V);
@@ -195,7 +195,7 @@ template <typename SPTy> struct containsvectorelement_match {
 /// Match a vector constant where at least one of its elements matches the
 /// subpattern. Any bindings in the subpattern will be bound to the first match.
 template <typename SPTy>
-inline containsvectorelement_match<SPTy>
+inline ContainsMatchingVectorElement_match<SPTy>
 m_ContainsMatchingVectorElement(const SPTy &SubPattern) {
   return SubPattern;
 }
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 6cf244843afb6..c26791c458e3a 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -120,7 +120,7 @@ static bool foldMixesPoisonBits(Constant *C, unsigned NumSrcElt,
   // If element counts don't divide evenly, bail out if a poison source element
   // might span multiple destination lanes.
   if (NumSrcElt % NumDstElt != 0)
-    return match(C, m_ContainsMatchingVectorElement(m_Poison()));
+    return C->containsPoisonElement();
   unsigned Ratio = NumSrcElt / NumDstElt;
   for (unsigned i = 0; i != NumSrcElt; i += Ratio) {
     bool HasPoison = false;
@@ -151,7 +151,7 @@ static bool computePoisonDstLanes(Constant *C, unsigned NumSrcElt,
   // If element counts don't divide evenly, bail out if a poison source element
   // might span multiple destination lanes.
   if ((NumDstElt < NumSrcElt ? NumSrcElt % NumDstElt : NumDstElt % NumSrcElt))
-    return !match(C, m_ContainsMatchingVectorElement(m_Poison()));
+    return !C->containsPoisonElement();
   if (NumDstElt < NumSrcElt) {
     unsigned Ratio = NumSrcElt / NumDstElt;
     for (unsigned i = 0; i != NumDstElt; ++i) {
@@ -197,8 +197,7 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
 
       // Bitcasting a byte containing any poison bit to an integer or fp type
       // yields poison.
-      if (SrcEltTy->isByteTy() &&
-          match(C, m_ContainsMatchingVectorElement(m_Poison())))
+      if (SrcEltTy->isByteTy() && C->containsPoisonElement())
         return PoisonValue::get(DestTy);
 
       // If the vector is a vector of floating point or bytes, convert it to a
@@ -2316,7 +2315,7 @@ Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) {
   auto *OpVT = cast<VectorType>(Op->getType());
 
   // This is the same as the underlying binops - poison propagates.
-  if (match(Op, m_ContainsMatchingVectorElement(m_Poison())))
+  if (Op->containsPoisonElement())
     return PoisonValue::get(OpVT->getElementType());
 
   // Shortcut non-accumulating reductions.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 584243d2811b5..bd2ca3d4999d3 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7813,12 +7813,9 @@ static bool isGuaranteedNotToBeUndefOrPoison(
           if (isa<ConstantInt>(SplatC) || isa<ConstantFP>(SplatC))
             return true;
       } else {
-        if (includesUndef(Kind) &&
-            match(C, m_ContainsMatchingVectorElement(
-                         m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
+        if (includesUndef(Kind) && C->containsUndefElement())
           return false;
-        if (includesPoison(Kind) &&
-            match(C, m_ContainsMatchingVectorElement(m_Poison())))
+        if (includesPoison(Kind) && C->containsPoisonElement())
           return false;
         return !match(C, m_ConstantExpr());
       }
@@ -8852,7 +8849,7 @@ llvm::getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C) {
   // undefined elements, so replace those elements with the first safe constant
   // that we found.
   // TODO: in case of poison, it is safe; let's replace undefs only.
-  if (match(C, m_ContainsMatchingVectorElement(m_UndefValue()))) {
+  if (C->containsUndefOrPoisonElement()) {
     assert(SafeReplacementConstant && "Replacement constant not set");
     C = Constant::replaceUndefsWith(C, SafeReplacementConstant);
   }
@@ -8879,16 +8876,11 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
     // purpose of identifying min/max. Disregard vector constants with undefined
     // elements because those can not be back-propagated for analysis.
     Value *OutputZeroVal = nullptr;
-    if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(),
-                                    m_Unless(m_ContainsMatchingVectorElement(
-                                        m_UndefValue())))) &&
-        !match(FalseVal, m_AnyZeroFP()))
+    if (match(TrueVal, m_AnyZeroFP()) && !match(FalseVal, m_AnyZeroFP()) &&
+        !cast<Constant>(TrueVal)->containsUndefOrPoisonElement())
       OutputZeroVal = TrueVal;
-    else if (match(FalseVal,
-                   m_CombineAnd(m_AnyZeroFP(),
-                                m_Unless(m_ContainsMatchingVectorElement(
-                                    m_UndefValue())))) &&
-             !match(TrueVal, m_AnyZeroFP()))
+    else if (match(FalseVal, m_AnyZeroFP()) && !match(TrueVal, m_AnyZeroFP()) &&
+             !cast<Constant>(FalseVal)->containsUndefOrPoisonElement())
       OutputZeroVal = FalseVal;
 
     if (OutputZeroVal) {
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index d3f07d2500f42..49d8a19e5d126 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -54,7 +54,6 @@
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/ModuleSlotTracker.h"
-#include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/Value.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCSymbol.h"
@@ -80,7 +79,6 @@
 #include "LiveDebugValues/LiveDebugValues.h"
 
 using namespace llvm;
-using namespace llvm::PatternMatch;
 
 #define DEBUG_TYPE "codegen"
 
@@ -1563,8 +1561,7 @@ static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B,
   if (StoreSize != DL.getTypeStoreSize(B->getType()) || StoreSize > 128)
     return false;
 
-  bool ContainsUndefOrPoisonA =
-      match(A, m_ContainsMatchingVectorElement(m_UndefValue()));
+  bool ContainsUndefOrPoisonA = A->containsUndefOrPoisonElement();
 
   Type *IntTy = IntegerType::get(A->getContext(), StoreSize*8);
 
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index f6eb629c7f050..52b3e253992f7 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -359,8 +359,8 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
       return true;
 
     if (C->getType()->isVectorTy())
-      return !match(C, m_CombineOr(m_ContainsMatchingVectorElement(m_Poison()),
-                                   m_ConstantExpr()));
+      return !C->containsPoisonElement() &&
+             !match(C, m_ContainsMatchingVectorElement(m_Isa<ConstantExpr>()));
 
     // TODO: Recursively analyze aggregates or other constants.
     return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 0bb7669ceb41e..5b7e7f08ae40b 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -183,9 +183,13 @@ bool Constant::isNotMinSignedValue() const {
     return !CFP->getValueAPF().bitcastToAPInt().isMinSignedValue();
 
   // Check that vectors don't contain INT_MIN
-  if (isa<FixedVectorType>(getType())) {
-    return !containsMatchingVectorElement(
-        [&](const auto *E) { return !E->isNotMinSignedValue(); });
+  if (auto *VTy = dyn_cast<FixedVectorType>(getType())) {
+    for (unsigned I = 0, E = VTy->getNumElements(); I != E; ++I) {
+      Constant *Elt = getAggregateElement(I);
+      if (!Elt || !Elt->isNotMinSignedValue())
+        return false;
+    }
+    return true;
   }
 
   // Check for splats that aren't INT_MIN
@@ -305,6 +309,44 @@ bool Constant::isElementWiseEqual(Value *Y) const {
   return CmpEq && (isa<PoisonValue>(CmpEq) || match(CmpEq, m_One()));
 }
 
+static bool
+containsUndefinedElement(const Constant *C,
+                         function_ref<bool(const Constant *)> HasFn) {
+  if (auto *VTy = dyn_cast<VectorType>(C->getType())) {
+    if (HasFn(C))
+      return true;
+    if (isa<ConstantAggregateZero>(C))
+      return false;
+    if (isa<ScalableVectorType>(C->getType()))
+      return false;
+
+    for (unsigned i = 0, e = cast<FixedVectorType>(VTy)->getNumElements();
+         i != e; ++i) {
+      if (Constant *Elem = C->getAggregateElement(i))
+        if (HasFn(Elem))
+          return true;
+    }
+  }
+
+  return false;
+}
+
+bool Constant::containsUndefOrPoisonElement() const {
+  return containsUndefinedElement(
+      this, [&](const auto *C) { return isa<UndefValue>(C); });
+}
+
+bool Constant::containsPoisonElement() const {
+  return containsUndefinedElement(
+      this, [&](const auto *C) { return isa<PoisonValue>(C); });
+}
+
+bool Constant::containsUndefElement() const {
+  return containsUndefinedElement(this, [&](const auto *C) {
+    return isa<UndefValue>(C) && !isa<PoisonValue>(C);
+  });
+}
+
 bool Constant::containsMatchingVectorElement(
     function_ref<bool(Constant *)> PredFn) const {
   if (!getType()->isVectorTy())
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 7f0a473d3ad77..ea54662e5f710 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1290,7 +1290,8 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
 
   // If any element of a constant divisor fixed width vector is zero or undef
   // the behavior is undefined and we can fold the whole op to poison.
-  if (match(Op1, m_ContainsMatchingVectorElement(
+  if (isa<FixedVectorType>(I.getType()) &&
+      match(Op1, m_ContainsMatchingVectorElement(
                      m_CombineOr(m_Zero(), m_UndefValue())))) {
     return replaceInstUsesWith(I, PoisonValue::get(I.getType()));
   }
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
index ad2431b3c5b84..b0a0bcfbde19e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
@@ -275,7 +275,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     // While this is normally not behind a use-check,
     // let's consider division to be special since it's costly.
     if (auto *Op1C = dyn_cast<Constant>(I->getOperand(1))) {
-      if (!match(Op1C, m_ContainsMatchingVectorElement(m_UndefValue())) &&
+      if (!Op1C->containsUndefOrPoisonElement() &&
           Op1C->isNotMinSignedValue() && Op1C->isNotOneValue()) {
         Value *BO =
             Builder.CreateSDiv(I->getOperand(0), ConstantExpr::getNeg(Op1C),
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index f312261ad0351..83b1a028dc7ba 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5486,16 +5486,18 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
     auto *VTy = dyn_cast<FixedVectorType>(Ty);
     if (!VTy)
       return nullptr;
-    Constant *BestValue = Constant::getNullValue(VTy->getScalarType());
-    match(C, m_ContainsMatchingVectorElement(
-                 m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
+    Constant *BestValue;
+    if (!match(C, m_ContainsMatchingVectorElement(m_CombineAnd(
+                      m_Unless(m_Undef()), m_Constant(BestValue)))))
+      BestValue = Constant::getNullValue(VTy->getScalarType());
     return Constant::replaceUndefsWith(C, BestValue);
   };
 
   Constant *C;
   if (match(Op0, m_CombineAnd(m_Constant(C),
-                              m_ContainsMatchingVectorElement(m_UndefValue()),
-                              m_Unless(m_ConstantExpr())))) {
+                              m_Unless(m_ContainsMatchingVectorElement(
+                                  m_Isa<ConstantExpr>())))) &&
+      C->containsUndefOrPoisonElement()) {
     if (Constant *Repl = getFreezeVectorReplacement(C))
       return replaceInstUsesWith(I, Repl);
   }
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 35575b9222bbe..8e6a41560cca4 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -2175,8 +2175,9 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
 
     // Check for partially-undefined constant vectors
     // TODO: scalable vectors (this is hard because we do not have IRBuilder)
-    if (match(V, m_ContainsMatchingVectorElement(m_UndefValue())) &&
-        PropagateShadow && PoisonUndefVectors) {
+    if (isa<FixedVectorType>(V->getType()) && isa<Constant>(V) &&
+        cast<Constant>(V)->containsUndefOrPoisonElement() && PropagateShadow &&
+        PoisonUndefVectors) {
       unsigned NumElems = cast<FixedVectorType>(V->getType())->getNumElements();
       SmallVector<Constant *, 32> ShadowVector(NumElems);
       for (unsigned i = 0; i != NumElems; ++i) {
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index 5face8fecec02..1d90cd5fe87e7 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -816,8 +816,9 @@ static Value *NegateValue(Value *V, Instruction *BI,
     Instruction *TheNeg = dyn_cast<Instruction>(U);
 
     // We can't safely propagate a vector zero constant with poison/undef lanes.
-    if (match(TheNeg, m_BinOp(m_ContainsMatchingVectorElement(m_UndefValue()),
-                              m_Value())))
+    Constant *C;
+    if (match(TheNeg, m_BinOp(m_Constant(C), m_Value())) &&
+        C->containsUndefOrPoisonElement())
       continue;
 
     // Verify that the negate is in this function, V might be a constant expr.
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 8ad2e86b471f5..68beac981efdc 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -597,26 +597,26 @@ TEST(ConstantsTest, containsUndefElemTest) {
 
   {
     Constant *V1 = ConstantVector::get({C1, C2});
-    EXPECT_FALSE(match(V1, m_ContainsMatchingVectorElement(m_UndefValue())));
-    EXPECT_FALSE(match(V1, m_ContainsMatchingVectorElement(m_Poison())));
+    EXPECT_FALSE(V1->containsUndefOrPoisonElement());
+    EXPECT_FALSE(V1->containsPoisonElement());
   }
 
   {
     Constant *V2 = ConstantVector::get({C1, CU});
-    EXPECT_TRUE(match(V2, m_ContainsMatchingVectorElement(m_UndefValue())));
-    EXPECT_FALSE(match(V2, m_ContainsMatchingVectorElement(m_Poison())));
+    EXPECT_TRUE(V2->containsUndefOrPoisonElement());
+    EXPECT_FALSE(V2->containsPoisonElement());
   }
 
   {
     Constant *V3 = ConstantVector::get({C1, CP});
-    EXPECT_TRUE(match(V3, m_ContainsMatchingVectorElement(m_UndefValue())));
-    EXPECT_TRUE(match(V3, m_ContainsMatchingVectorElement(m_Poison())));
+    EXPECT_TRUE(V3->containsUndefOrPoisonElement());
+    EXPECT_TRUE(V3->containsPoisonElement());
   }
 
   {
     Constant *V4 = ConstantVector::get({CU, CP});
-    EXPECT_TRUE(match(V4, m_ContainsMatchingVectorElement(m_UndefValue())));
-    EXPECT_TRUE(match(V4, m_ContainsMatchingVectorElement(m_Poison())));
+    EXPECT_TRUE(V4->containsUndefOrPoisonElement());
+    EXPECT_TRUE(V4->containsPoisonElement());
   }
 }
 

>From de27777c1541c64c739d0dc4fad6f973c8ded9a0 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Thu, 4 Jun 2026 11:03:49 -0500
Subject: [PATCH 08/10] Remove now-unnecessary includes

---
 llvm/lib/Analysis/ConstantFolding.cpp                   | 2 --
 llvm/lib/Analysis/ValueTracking.cpp                     | 3 ++-
 llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 2 --
 llvm/unittests/IR/ConstantsTest.cpp                     | 2 --
 4 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index c26791c458e3a..959b46f8eff46 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -51,7 +51,6 @@
 #include "llvm/IR/IntrinsicsX86.h"
 #include "llvm/IR/NVVMIntrinsicUtils.h"
 #include "llvm/IR/Operator.h"
-#include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Support/Casting.h"
@@ -65,7 +64,6 @@
 #include <cstdint>
 
 using namespace llvm;
-using namespace llvm::PatternMatch;
 
 static cl::opt<bool> DisableFPCallFolding(
     "disable-fp-call-folding",
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index bd2ca3d4999d3..004849c0cee7c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7817,7 +7817,8 @@ static bool isGuaranteedNotToBeUndefOrPoison(
           return false;
         if (includesPoison(Kind) && C->containsPoisonElement())
           return false;
-        return !match(C, m_ConstantExpr());
+        return !match(C,
+                      m_ContainsMatchingVectorElement(m_Isa<ConstantExpr>()));
       }
     }
   }
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 8e6a41560cca4..c45ec68f3cd07 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -185,7 +185,6 @@
 #include "llvm/IR/IntrinsicsX86.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Module.h"
-#include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 #include "llvm/IR/ValueMap.h"
@@ -213,7 +212,6 @@
 #include <tuple>
 
 using namespace llvm;
-using namespace llvm::PatternMatch;
 
 #define DEBUG_TYPE "msan"
 
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 68beac981efdc..6716ec581bd06 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -16,12 +16,10 @@
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
-#include "llvm/IR/PatternMatch.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
-using namespace llvm::PatternMatch;
 
 namespace {
 

>From 3b6649744a4cb99f9a8b4d367b99b9dbe93cad36 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 5 Jun 2026 09:42:00 -0500
Subject: [PATCH 09/10] Restore Constant::containsConstantExpression with
 updated implementation

---
 llvm/include/llvm/IR/Constant.h                      |  7 +++++--
 llvm/include/llvm/IR/PatternMatch.h                  |  3 ++-
 llvm/lib/Analysis/ValueTracking.cpp                  |  3 +--
 llvm/lib/IR/ConstantFold.cpp                         |  3 +--
 llvm/lib/IR/Constants.cpp                            | 12 ++++++------
 .../Transforms/InstCombine/InstructionCombining.cpp  |  6 ++----
 6 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index ad00ac7673952..1013b8dace9a2 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -126,9 +126,12 @@ class Constant : public User {
   /// (not poison) elements.
   LLVM_ABI bool containsUndefElement() const;
 
+  /// Return true if this is a fixed width vector constant that includes
+  /// any constant expressions.
+  LLVM_ABI bool containsConstantExpression() const;
+
   /// Return true if this is a vector constant where at least one element
-  /// satisfies the given predicate. For scalable vectors, the predicate is
-  /// only tested on the splat value.
+  /// satisfies the given predicate. Scalable vectors are not checked.
   LLVM_ABI bool
   containsMatchingVectorElement(function_ref<bool(Constant *)> PredFn) const;
 
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index c16c0cc5999ba..b9cccaf48ed8b 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -193,7 +193,8 @@ template <typename SPTy> struct ContainsMatchingVectorElement_match {
 };
 
 /// Match a vector constant where at least one of its elements matches the
-/// subpattern. Any bindings in the subpattern will be bound to the first match.
+/// subpattern. Scalable vector constants are not matched. Any bindings in the
+/// subpattern will be bound to the first match.
 template <typename SPTy>
 inline ContainsMatchingVectorElement_match<SPTy>
 m_ContainsMatchingVectorElement(const SPTy &SubPattern) {
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 004849c0cee7c..8ff5b750203cc 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7817,8 +7817,7 @@ static bool isGuaranteedNotToBeUndefOrPoison(
           return false;
         if (includesPoison(Kind) && C->containsPoisonElement())
           return false;
-        return !match(C,
-                      m_ContainsMatchingVectorElement(m_Isa<ConstantExpr>()));
+        return !C->containsConstantExpression();
       }
     }
   }
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 52b3e253992f7..f8abd576f93c4 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -359,8 +359,7 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
       return true;
 
     if (C->getType()->isVectorTy())
-      return !C->containsPoisonElement() &&
-             !match(C, m_ContainsMatchingVectorElement(m_Isa<ConstantExpr>()));
+      return !C->containsPoisonElement() && !C->containsConstantExpression();
 
     // TODO: Recursively analyze aggregates or other constants.
     return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 5b7e7f08ae40b..8c3e7ab2fc525 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -347,15 +347,15 @@ bool Constant::containsUndefElement() const {
   });
 }
 
-bool Constant::containsMatchingVectorElement(
-    function_ref<bool(Constant *)> PredFn) const {
-  if (!getType()->isVectorTy())
+bool Constant::containsConstantExpression() const {
+  if (isa<ConstantInt>(this) || isa<ConstantFP>(this))
     return false;
 
-  if (Constant *SplatVal = getSplatValue())
-    if (PredFn(SplatVal))
-      return true;
+  return match(this, m_ContainsMatchingVectorElement(m_Isa<ConstantExpr>()));
+}
 
+bool Constant::containsMatchingVectorElement(
+    function_ref<bool(Constant *)> PredFn) const {
   if (auto *FVTy = dyn_cast<FixedVectorType>(getType())) {
     unsigned NumElts = FVTy->getNumElements();
     for (unsigned I = 0; I != NumElts; ++I) {
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 83b1a028dc7ba..96aece2a83f5e 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5494,10 +5494,8 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
   };
 
   Constant *C;
-  if (match(Op0, m_CombineAnd(m_Constant(C),
-                              m_Unless(m_ContainsMatchingVectorElement(
-                                  m_Isa<ConstantExpr>())))) &&
-      C->containsUndefOrPoisonElement()) {
+  if (match(Op0, m_Constant(C)) && C->containsUndefOrPoisonElement() &&
+      !C->containsConstantExpression()) {
     if (Constant *Repl = getFreezeVectorReplacement(C))
       return replaceInstUsesWith(I, Repl);
   }

>From 2b4cc3783e17fc821c136b6466040ba377c67fb2 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 5 Jun 2026 09:54:43 -0500
Subject: [PATCH 10/10] Update implementation of containsUndefinedElement to
 use containsMatchingVectorElement

---
 llvm/lib/IR/Constants.cpp | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 8c3e7ab2fc525..3fce4a90a8db1 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -312,20 +312,13 @@ bool Constant::isElementWiseEqual(Value *Y) const {
 static bool
 containsUndefinedElement(const Constant *C,
                          function_ref<bool(const Constant *)> HasFn) {
-  if (auto *VTy = dyn_cast<VectorType>(C->getType())) {
+  if (C->getType()->isVectorTy()) {
     if (HasFn(C))
       return true;
     if (isa<ConstantAggregateZero>(C))
       return false;
-    if (isa<ScalableVectorType>(C->getType()))
-      return false;
 
-    for (unsigned i = 0, e = cast<FixedVectorType>(VTy)->getNumElements();
-         i != e; ++i) {
-      if (Constant *Elem = C->getAggregateElement(i))
-        if (HasFn(Elem))
-          return true;
-    }
+    return C->containsMatchingVectorElement(HasFn);
   }
 
   return false;



More information about the llvm-commits mailing list