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

Sean Clarke via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 2 08:02:27 PDT 2026


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

>From 7a7a80f81fc8e998091c81348ab97321486c565f 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 1/5] 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 3fd4de926683c..dde7d718fd7c4 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 82a570e8a1446..97bb1437d9ec6 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -103,23 +103,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 7846e66896d5e..20e4fa809001f 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 7b1550a10f134..0937b79382373 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7815,11 +7815,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());
       }
     }
   }
@@ -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 (C->containsUndefOrPoisonElement()) {
+  if (match(C, m_AnyVectorElement(m_UndefValue()))) {
     assert(SafeReplacementConstant && "Replacement constant not set");
     C = Constant::replaceUndefsWith(C, SafeReplacementConstant);
   }
@@ -8878,11 +8878,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 902a2b4c5e992..53ec2f9a70406 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -203,13 +203,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
@@ -329,21 +324,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;
     }
   }
@@ -351,34 +344,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 dd1444197cf5d..88fb1bb7eef9a 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 021a850860b34..dc87a86f5ac01 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 30088fc78d255..e540fc158cb4a 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5497,21 +5497,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 ea6c394740f22..8946698cfb6b7 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -818,9 +818,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 8da7b53d18074873c98f8371febe3022927e6154 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 2/5] 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 97bb1437d9ec6..95806f77327b1 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -103,7 +103,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 0937b79382373..92d253f2e15d4 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7815,7 +7815,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;
@@ -8878,9 +8880,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 53ec2f9a70406..61cc1d65ee3a2 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -204,7 +204,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
@@ -327,7 +328,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 88fb1bb7eef9a..1a52531021c84 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 e540fc158cb4a..8ce292e1524b9 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5498,12 +5498,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 881eaf47f31a4a703d301ba6de795c3ed6147545 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 3/5] 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 95806f77327b1..ffc99ed7ce865 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -105,7 +105,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 08ff76689d518bc5f13fb70304a6082efbe1aa25 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 4/5] 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 ffc99ed7ce865..38d5327ecdbc7 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -106,7 +106,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 20e4fa809001f..7b6fa961e1526 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 92d253f2e15d4..ab50967e513dc 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7816,10 +7816,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());
       }
@@ -8853,7 +8853,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);
   }
@@ -8880,12 +8880,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 61cc1d65ee3a2..2a2436983f143 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -204,7 +204,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(); });
   }
 
@@ -325,7 +325,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 1a52531021c84..b40e0bf7f5df1 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 dc87a86f5ac01..ba68c8a895bfa 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 8ce292e1524b9..d64865f2f4ac4 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5498,13 +5498,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 8946698cfb6b7..0a7d88d3afb0d 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -818,7 +818,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 fde18d86e9195abf367825c064bcefb4b304c76c 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 5/5] 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 38d5327ecdbc7..8c09aa2ed39dc 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -106,7 +106,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 ab50967e513dc..d7a23e26bfb16 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7819,7 +7819,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());
       }
@@ -8880,8 +8881,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 2a2436983f143..068b0fca67130 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -325,7 +325,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 b40e0bf7f5df1..a6c5acae9cdea 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 ba68c8a895bfa..2d3ddee16c433 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 d64865f2f4ac4..ae61aab5b848c 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5504,8 +5504,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 0a7d88d3afb0d..d8caec10cf43f 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -818,7 +818,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.



More information about the llvm-commits mailing list