[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