[llvm] [IR][NFC] Introduce Constant::containsVectorElement and corresponding matcher m_ContainsVectorElement (PR #200502)
Sean Clarke via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 2 08:02:27 PDT 2026
https://github.com/xarkenz updated https://github.com/llvm/llvm-project/pull/200502
>From 7a7a80f81fc8e998091c81348ab97321486c565f Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 29 May 2026 16:30:19 -0500
Subject: [PATCH 1/5] Add Constant::anyVectorElement and corresponding matcher
m_AnyVectorElement
---
llvm/include/llvm/Analysis/VectorUtils.h | 5 --
llvm/include/llvm/IR/Constant.h | 19 +-----
llvm/include/llvm/IR/PatternMatch.h | 22 +++++--
llvm/lib/Analysis/ConstantFolding.cpp | 10 +--
llvm/lib/Analysis/ValueTracking.cpp | 14 ++---
llvm/lib/Analysis/VectorUtils.cpp | 25 --------
llvm/lib/CodeGen/MachineFunction.cpp | 4 +-
llvm/lib/IR/ConstantFold.cpp | 2 +-
llvm/lib/IR/Constants.cpp | 61 ++++---------------
.../InstCombine/InstCombineCalls.cpp | 2 +-
.../InstCombine/InstCombineMulDivRem.cpp | 12 +---
.../InstCombine/InstCombineNegator.cpp | 2 +-
.../InstCombine/InstructionCombining.cpp | 12 +---
.../Instrumentation/MemorySanitizer.cpp | 5 +-
llvm/lib/Transforms/Scalar/Reassociate.cpp | 4 +-
llvm/unittests/IR/ConstantsTest.cpp | 18 +++---
16 files changed, 67 insertions(+), 150 deletions(-)
diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h
index 3fd4de926683c..dde7d718fd7c4 100644
--- a/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/llvm/include/llvm/Analysis/VectorUtils.h
@@ -487,11 +487,6 @@ LLVM_ABI bool maskIsAllZeroOrUndef(Value *Mask);
/// lanes can be assumed active.
LLVM_ABI bool maskIsAllOneOrUndef(Value *Mask);
-/// Given a mask vector of i1, Return true if any of the elements of this
-/// predicate mask are known to be true or undef. That is, return true if at
-/// least one lane can be assumed active.
-LLVM_ABI bool maskContainsAllOneOrUndef(Value *Mask);
-
/// Given a mask vector of the form <Y x i1>, return an APInt (of bitwidth Y)
/// for each lane which may be active.
LLVM_ABI APInt possiblyDemandedEltsInMask(Value *Mask);
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 82a570e8a1446..97bb1437d9ec6 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -103,23 +103,8 @@ class Constant : public User {
/// lane, the constants still match.
LLVM_ABI bool isElementWiseEqual(Value *Y) const;
- /// Return true if this is a vector constant that includes any undef or
- /// poison elements. Since it is impossible to inspect a scalable vector
- /// element- wise at compile time, this function returns true only if the
- /// entire vector is undef or poison.
- LLVM_ABI bool containsUndefOrPoisonElement() const;
-
- /// Return true if this is a vector constant that includes any poison
- /// elements.
- LLVM_ABI bool containsPoisonElement() const;
-
- /// Return true if this is a vector constant that includes any strictly undef
- /// (not poison) elements.
- LLVM_ABI bool containsUndefElement() const;
-
- /// Return true if this is a fixed width vector constant that includes
- /// any constant expressions.
- LLVM_ABI bool containsConstantExpression() const;
+ /// Return true if this is a vector constant where at least one element satisfies the given predicate. For scalable vectors, the predicate is tested on the value as a whole.
+ LLVM_ABI bool anyVectorElement(function_ref<bool(Constant *)> PredFn) const;
/// Return true if the value can vary between threads.
LLVM_ABI bool isThreadDependent() const;
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index e6650e73ec0ac..c618948eee873 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -181,16 +181,27 @@ inline auto m_ConstantInt() { return m_Isa<ConstantInt>(); }
/// Match an arbitrary ConstantFP and ignore it.
inline auto m_ConstantFP() { return m_Isa<ConstantFP>(); }
-struct constantexpr_match {
+template <typename SPTy> struct anyvectorelement_match {
+ SPTy SubPattern;
+ anyvectorelement_match(const SPTy &SP) : SubPattern(SP) {}
+
template <typename ITy> bool match(ITy *V) const {
auto *C = dyn_cast<Constant>(V);
- return C && (isa<ConstantExpr>(C) || C->containsConstantExpression());
+ return C && C->anyVectorElement([&](Constant *E) { return SubPattern.match(E); });
}
};
+/// Match a vector constant where at least one of its elements matches the subpattern. Any bindings in the subpattern will be bound to the first match.
+template <typename SPTy>
+inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
+ return SubPattern;
+}
+
/// Match a constant expression or a constant that contains a constant
/// expression.
-inline constantexpr_match m_ConstantExpr() { return constantexpr_match(); }
+inline auto m_ConstantExpr() {
+ return m_CombineOr(m_Isa<ConstantExpr>(), m_AnyVectorElement(m_Isa<ConstantExpr>()));
+}
template <typename SubPattern_t> struct Splat_match {
SubPattern_t SubPattern;
@@ -884,13 +895,12 @@ inline match_bind<const BasicBlock> m_BasicBlock(const BasicBlock *&V) {
struct immconstant_ty {
template <typename ITy> static bool isImmConstant(ITy *V) {
if (auto *CV = dyn_cast<Constant>(V)) {
- if (!isa<ConstantExpr>(CV) && !CV->containsConstantExpression())
+ if (!match(CV, m_ConstantExpr()))
return true;
if (CV->getType()->isVectorTy()) {
if (auto *Splat = CV->getSplatValue(/*AllowPoison=*/true)) {
- if (!isa<ConstantExpr>(Splat) &&
- !Splat->containsConstantExpression()) {
+ if (!match(Splat, m_ConstantExpr())) {
return true;
}
}
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 7846e66896d5e..20e4fa809001f 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -51,6 +51,7 @@
#include "llvm/IR/IntrinsicsX86.h"
#include "llvm/IR/NVVMIntrinsicUtils.h"
#include "llvm/IR/Operator.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
@@ -64,6 +65,7 @@
#include <cstdint>
using namespace llvm;
+using namespace llvm::PatternMatch;
static cl::opt<bool> DisableFPCallFolding(
"disable-fp-call-folding",
@@ -118,7 +120,7 @@ static bool foldMixesPoisonBits(Constant *C, unsigned NumSrcElt,
// If element counts don't divide evenly, bail out if a poison source element
// might span multiple destination lanes.
if (NumSrcElt % NumDstElt != 0)
- return C->containsPoisonElement();
+ return match(C, m_AnyVectorElement(m_Poison()));
unsigned Ratio = NumSrcElt / NumDstElt;
for (unsigned i = 0; i != NumSrcElt; i += Ratio) {
bool HasPoison = false;
@@ -149,7 +151,7 @@ static bool computePoisonDstLanes(Constant *C, unsigned NumSrcElt,
// If element counts don't divide evenly, bail out if a poison source element
// might span multiple destination lanes.
if ((NumDstElt < NumSrcElt ? NumSrcElt % NumDstElt : NumDstElt % NumSrcElt))
- return !C->containsPoisonElement();
+ return !match(C, m_AnyVectorElement(m_Poison()));
if (NumDstElt < NumSrcElt) {
unsigned Ratio = NumSrcElt / NumDstElt;
for (unsigned i = 0; i != NumDstElt; ++i) {
@@ -195,7 +197,7 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
// Bitcasting a byte containing any poison bit to an integer or fp type
// yields poison.
- if (SrcEltTy->isByteTy() && C->containsPoisonElement())
+ if (SrcEltTy->isByteTy() && match(C, m_AnyVectorElement(m_Poison())))
return PoisonValue::get(DestTy);
// If the vector is a vector of floating point or bytes, convert it to a
@@ -2313,7 +2315,7 @@ Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) {
auto *OpVT = cast<VectorType>(Op->getType());
// This is the same as the underlying binops - poison propagates.
- if (Op->containsPoisonElement())
+ if (match(Op, m_AnyVectorElement(m_Poison())))
return PoisonValue::get(OpVT->getElementType());
// Shortcut non-accumulating reductions.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 7b1550a10f134..0937b79382373 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7815,11 +7815,11 @@ static bool isGuaranteedNotToBeUndefOrPoison(
if (isa<ConstantInt>(SplatC) || isa<ConstantFP>(SplatC))
return true;
} else {
- if (includesUndef(Kind) && C->containsUndefElement())
+ if (includesUndef(Kind) && match(C, m_AnyVectorElement(m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
return false;
- if (includesPoison(Kind) && C->containsPoisonElement())
+ if (includesPoison(Kind) && match(C, m_AnyVectorElement(m_Poison())))
return false;
- return !C->containsConstantExpression();
+ return !match(C, m_ConstantExpr());
}
}
}
@@ -8851,7 +8851,7 @@ llvm::getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C) {
// undefined elements, so replace those elements with the first safe constant
// that we found.
// TODO: in case of poison, it is safe; let's replace undefs only.
- if (C->containsUndefOrPoisonElement()) {
+ if (match(C, m_AnyVectorElement(m_UndefValue()))) {
assert(SafeReplacementConstant && "Replacement constant not set");
C = Constant::replaceUndefsWith(C, SafeReplacementConstant);
}
@@ -8878,11 +8878,9 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
// purpose of identifying min/max. Disregard vector constants with undefined
// elements because those can not be back-propagated for analysis.
Value *OutputZeroVal = nullptr;
- if (match(TrueVal, m_AnyZeroFP()) && !match(FalseVal, m_AnyZeroFP()) &&
- !cast<Constant>(TrueVal)->containsUndefOrPoisonElement())
+ if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(m_UndefValue())))) && !match(FalseVal, m_AnyZeroFP()))
OutputZeroVal = TrueVal;
- else if (match(FalseVal, m_AnyZeroFP()) && !match(TrueVal, m_AnyZeroFP()) &&
- !cast<Constant>(FalseVal)->containsUndefOrPoisonElement())
+ else if (match(FalseVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(m_UndefValue())))) && !match(TrueVal, m_AnyZeroFP()))
OutputZeroVal = FalseVal;
if (OutputZeroVal) {
diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp
index 402bef65c2f13..84cd368c470d6 100644
--- a/llvm/lib/Analysis/VectorUtils.cpp
+++ b/llvm/lib/Analysis/VectorUtils.cpp
@@ -1308,31 +1308,6 @@ bool llvm::maskIsAllOneOrUndef(Value *Mask) {
return true;
}
-bool llvm::maskContainsAllOneOrUndef(Value *Mask) {
- assert(isa<VectorType>(Mask->getType()) &&
- isa<IntegerType>(Mask->getType()->getScalarType()) &&
- cast<IntegerType>(Mask->getType()->getScalarType())->getBitWidth() ==
- 1 &&
- "Mask must be a vector of i1");
-
- auto *ConstMask = dyn_cast<Constant>(Mask);
- if (!ConstMask)
- return false;
- if (ConstMask->isAllOnesValue() || isa<UndefValue>(ConstMask))
- return true;
- if (isa<ScalableVectorType>(ConstMask->getType()))
- return false;
- for (unsigned
- I = 0,
- E = cast<FixedVectorType>(ConstMask->getType())->getNumElements();
- I != E; ++I) {
- if (auto *MaskElt = ConstMask->getAggregateElement(I))
- if (MaskElt->isAllOnesValue() || isa<UndefValue>(MaskElt))
- return true;
- }
- return false;
-}
-
/// TODO: This is a lot like known bits, but for
/// vectors. Is there something we can common this with?
APInt llvm::possiblyDemandedEltsInMask(Value *Mask) {
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index 49d8a19e5d126..ea01c3241e84d 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -54,6 +54,7 @@
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSymbol.h"
@@ -79,6 +80,7 @@
#include "LiveDebugValues/LiveDebugValues.h"
using namespace llvm;
+using namespace llvm::PatternMatch;
#define DEBUG_TYPE "codegen"
@@ -1561,7 +1563,7 @@ static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B,
if (StoreSize != DL.getTypeStoreSize(B->getType()) || StoreSize > 128)
return false;
- bool ContainsUndefOrPoisonA = A->containsUndefOrPoisonElement();
+ bool ContainsUndefOrPoisonA = match(A, m_AnyVectorElement(m_UndefValue()));
Type *IntTy = IntegerType::get(A->getContext(), StoreSize*8);
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index f8abd576f93c4..80e00cb7cc1af 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -359,7 +359,7 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
return true;
if (C->getType()->isVectorTy())
- return !C->containsPoisonElement() && !C->containsConstantExpression();
+ return !match(C, m_CombineOr(m_AnyVectorElement(m_Poison()), m_ConstantExpr()));
// TODO: Recursively analyze aggregates or other constants.
return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 902a2b4c5e992..53ec2f9a70406 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -203,13 +203,8 @@ bool Constant::isNotMinSignedValue() const {
return !CFP->getValueAPF().bitcastToAPInt().isMinSignedValue();
// Check that vectors don't contain INT_MIN
- if (auto *VTy = dyn_cast<FixedVectorType>(getType())) {
- for (unsigned I = 0, E = VTy->getNumElements(); I != E; ++I) {
- Constant *Elt = getAggregateElement(I);
- if (!Elt || !Elt->isNotMinSignedValue())
- return false;
- }
- return true;
+ if (isa<FixedVectorType>(getType())) {
+ return !anyVectorElement([&](const auto *E) { return !E->isNotMinSignedValue(); });
}
// Check for splats that aren't INT_MIN
@@ -329,21 +324,19 @@ bool Constant::isElementWiseEqual(Value *Y) const {
return CmpEq && (isa<PoisonValue>(CmpEq) || match(CmpEq, m_One()));
}
-static bool
-containsUndefinedElement(const Constant *C,
- function_ref<bool(const Constant *)> HasFn) {
- if (auto *VTy = dyn_cast<VectorType>(C->getType())) {
- if (HasFn(C))
+bool Constant::anyVectorElement(function_ref<bool(Constant *)> PredFn) const {
+ if (!getType()->isVectorTy())
+ return false;
+
+ if (Constant *SplatVal = getSplatValue())
+ if (PredFn(SplatVal))
return true;
- if (isa<ConstantAggregateZero>(C))
- return false;
- if (isa<ScalableVectorType>(C->getType()))
- return false;
- for (unsigned i = 0, e = cast<FixedVectorType>(VTy)->getNumElements();
- i != e; ++i) {
- if (Constant *Elem = C->getAggregateElement(i))
- if (HasFn(Elem))
+ if (auto *FVTy = dyn_cast<FixedVectorType>(getType())) {
+ unsigned NumElts = FVTy->getNumElements();
+ for (unsigned I = 0; I != NumElts; ++I) {
+ if (Constant *Elem = getAggregateElement(I))
+ if (PredFn(Elem))
return true;
}
}
@@ -351,34 +344,6 @@ containsUndefinedElement(const Constant *C,
return false;
}
-bool Constant::containsUndefOrPoisonElement() const {
- return containsUndefinedElement(
- this, [&](const auto *C) { return isa<UndefValue>(C); });
-}
-
-bool Constant::containsPoisonElement() const {
- return containsUndefinedElement(
- this, [&](const auto *C) { return isa<PoisonValue>(C); });
-}
-
-bool Constant::containsUndefElement() const {
- return containsUndefinedElement(this, [&](const auto *C) {
- return isa<UndefValue>(C) && !isa<PoisonValue>(C);
- });
-}
-
-bool Constant::containsConstantExpression() const {
- if (isa<ConstantInt>(this) || isa<ConstantFP>(this))
- return false;
-
- if (auto *VTy = dyn_cast<FixedVectorType>(getType())) {
- for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
- if (isa<ConstantExpr>(getAggregateElement(i)))
- return true;
- }
- return false;
-}
-
/// Constructor to create a '0' constant of arbitrary type.
Constant *Constant::getNullValue(Type *Ty) {
switch (Ty->getTypeID()) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index dd1444197cf5d..88fb1bb7eef9a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -396,7 +396,7 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
if (auto *SplatPtr = getSplatValue(II.getArgOperand(1))) {
// scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr
if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) {
- if (maskContainsAllOneOrUndef(ConstMask)) {
+ if (match(ConstMask, m_AnyVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
Align Alignment = II.getParamAlign(1).valueOrOne();
StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false,
Alignment);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 021a850860b34..dc87a86f5ac01 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1290,16 +1290,8 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
// If any element of a constant divisor fixed width vector is zero or undef
// the behavior is undefined and we can fold the whole op to poison.
- auto *Op1C = dyn_cast<Constant>(Op1);
- Type *Ty = I.getType();
- auto *VTy = dyn_cast<FixedVectorType>(Ty);
- if (Op1C && VTy) {
- unsigned NumElts = VTy->getNumElements();
- for (unsigned i = 0; i != NumElts; ++i) {
- Constant *Elt = Op1C->getAggregateElement(i);
- if (Elt && (Elt->isNullValue() || isa<UndefValue>(Elt)))
- return replaceInstUsesWith(I, PoisonValue::get(Ty));
- }
+ if (match(Op1, m_AnyVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
+ return replaceInstUsesWith(I, PoisonValue::get(I.getType()));
}
if (Instruction *Phi = foldBinopWithPhiOperands(I))
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
index b0a0bcfbde19e..45d15cfe27fdb 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
@@ -275,7 +275,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
// While this is normally not behind a use-check,
// let's consider division to be special since it's costly.
if (auto *Op1C = dyn_cast<Constant>(I->getOperand(1))) {
- if (!Op1C->containsUndefOrPoisonElement() &&
+ if (!match(Op1C, m_AnyVectorElement(m_UndefValue())) &&
Op1C->isNotMinSignedValue() && Op1C->isNotOneValue()) {
Value *BO =
Builder.CreateSDiv(I->getOperand(0), ConstantExpr::getNeg(Op1C),
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 30088fc78d255..e540fc158cb4a 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5497,21 +5497,13 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
auto *VTy = dyn_cast<FixedVectorType>(Ty);
if (!VTy)
return nullptr;
- unsigned NumElts = VTy->getNumElements();
Constant *BestValue = Constant::getNullValue(VTy->getScalarType());
- for (unsigned i = 0; i != NumElts; ++i) {
- Constant *EltC = C->getAggregateElement(i);
- if (EltC && !match(EltC, m_Undef())) {
- BestValue = EltC;
- break;
- }
- }
+ match(C, m_AnyVectorElement(m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
return Constant::replaceUndefsWith(C, BestValue);
};
Constant *C;
- if (match(Op0, m_Constant(C)) && C->containsUndefOrPoisonElement() &&
- !C->containsConstantExpression()) {
+ if (match(Op0, m_CombineAnd(m_Constant(C), m_AnyVectorElement(m_UndefValue()), m_Unless(m_ConstantExpr())))) {
if (Constant *Repl = getFreezeVectorReplacement(C))
return replaceInstUsesWith(I, Repl);
}
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index c45ec68f3cd07..e133840db0e01 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -185,6 +185,7 @@
#include "llvm/IR/IntrinsicsX86.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueMap.h"
@@ -212,6 +213,7 @@
#include <tuple>
using namespace llvm;
+using namespace llvm::PatternMatch;
#define DEBUG_TYPE "msan"
@@ -2173,8 +2175,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// Check for partially-undefined constant vectors
// TODO: scalable vectors (this is hard because we do not have IRBuilder)
- if (isa<FixedVectorType>(V->getType()) && isa<Constant>(V) &&
- cast<Constant>(V)->containsUndefOrPoisonElement() && PropagateShadow &&
+ if (match(V, m_AnyVectorElement(m_UndefValue())) && PropagateShadow &&
PoisonUndefVectors) {
unsigned NumElems = cast<FixedVectorType>(V->getType())->getNumElements();
SmallVector<Constant *, 32> ShadowVector(NumElems);
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index ea6c394740f22..8946698cfb6b7 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -818,9 +818,7 @@ static Value *NegateValue(Value *V, Instruction *BI,
Instruction *TheNeg = dyn_cast<Instruction>(U);
// We can't safely propagate a vector zero constant with poison/undef lanes.
- Constant *C;
- if (match(TheNeg, m_BinOp(m_Constant(C), m_Value())) &&
- C->containsUndefOrPoisonElement())
+ if (match(TheNeg, m_BinOp(m_AnyVectorElement(m_UndefValue()), m_Value())))
continue;
// Verify that the negate is in this function, V might be a constant expr.
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 6716ec581bd06..1e330a364df6b 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -16,10 +16,12 @@
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
+using namespace llvm::PatternMatch;
namespace {
@@ -595,26 +597,26 @@ TEST(ConstantsTest, containsUndefElemTest) {
{
Constant *V1 = ConstantVector::get({C1, C2});
- EXPECT_FALSE(V1->containsUndefOrPoisonElement());
- EXPECT_FALSE(V1->containsPoisonElement());
+ EXPECT_FALSE(match(V1, m_AnyVectorElement(m_UndefValue())));
+ EXPECT_FALSE(match(V1, m_AnyVectorElement(m_Poison())));
}
{
Constant *V2 = ConstantVector::get({C1, CU});
- EXPECT_TRUE(V2->containsUndefOrPoisonElement());
- EXPECT_FALSE(V2->containsPoisonElement());
+ EXPECT_TRUE(match(V2, m_AnyVectorElement(m_UndefValue())));
+ EXPECT_FALSE(match(V2, m_AnyVectorElement(m_Poison())));
}
{
Constant *V3 = ConstantVector::get({C1, CP});
- EXPECT_TRUE(V3->containsUndefOrPoisonElement());
- EXPECT_TRUE(V3->containsPoisonElement());
+ EXPECT_TRUE(match(V3, m_AnyVectorElement(m_UndefValue())));
+ EXPECT_TRUE(match(V3, m_AnyVectorElement(m_Poison())));
}
{
Constant *V4 = ConstantVector::get({CU, CP});
- EXPECT_TRUE(V4->containsUndefOrPoisonElement());
- EXPECT_TRUE(V4->containsPoisonElement());
+ EXPECT_TRUE(match(V4, m_AnyVectorElement(m_UndefValue())));
+ EXPECT_TRUE(match(V4, m_AnyVectorElement(m_Poison())));
}
}
>From 8da7b53d18074873c98f8371febe3022927e6154 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 29 May 2026 16:32:48 -0500
Subject: [PATCH 2/5] Format with clang-format
---
llvm/include/llvm/IR/Constant.h | 4 +++-
llvm/include/llvm/IR/PatternMatch.h | 9 ++++++---
llvm/lib/Analysis/ValueTracking.cpp | 13 ++++++++++---
llvm/lib/IR/ConstantFold.cpp | 3 ++-
llvm/lib/IR/Constants.cpp | 5 +++--
.../lib/Transforms/InstCombine/InstCombineCalls.cpp | 3 ++-
.../Transforms/InstCombine/InstructionCombining.cpp | 6 ++++--
7 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 97bb1437d9ec6..95806f77327b1 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -103,7 +103,9 @@ class Constant : public User {
/// lane, the constants still match.
LLVM_ABI bool isElementWiseEqual(Value *Y) const;
- /// Return true if this is a vector constant where at least one element satisfies the given predicate. For scalable vectors, the predicate is tested on the value as a whole.
+ /// Return true if this is a vector constant where at least one element
+ /// satisfies the given predicate. For scalable vectors, the predicate is
+ /// tested on the value as a whole.
LLVM_ABI bool anyVectorElement(function_ref<bool(Constant *)> PredFn) const;
/// Return true if the value can vary between threads.
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index c618948eee873..7fadd23a85566 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -187,11 +187,13 @@ template <typename SPTy> struct anyvectorelement_match {
template <typename ITy> bool match(ITy *V) const {
auto *C = dyn_cast<Constant>(V);
- return C && C->anyVectorElement([&](Constant *E) { return SubPattern.match(E); });
+ return C && C->anyVectorElement(
+ [&](Constant *E) { return SubPattern.match(E); });
}
};
-/// Match a vector constant where at least one of its elements matches the subpattern. Any bindings in the subpattern will be bound to the first match.
+/// Match a vector constant where at least one of its elements matches the
+/// subpattern. Any bindings in the subpattern will be bound to the first match.
template <typename SPTy>
inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
return SubPattern;
@@ -200,7 +202,8 @@ inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
/// Match a constant expression or a constant that contains a constant
/// expression.
inline auto m_ConstantExpr() {
- return m_CombineOr(m_Isa<ConstantExpr>(), m_AnyVectorElement(m_Isa<ConstantExpr>()));
+ return m_CombineOr(m_Isa<ConstantExpr>(),
+ m_AnyVectorElement(m_Isa<ConstantExpr>()));
}
template <typename SubPattern_t> struct Splat_match {
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 0937b79382373..92d253f2e15d4 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7815,7 +7815,9 @@ static bool isGuaranteedNotToBeUndefOrPoison(
if (isa<ConstantInt>(SplatC) || isa<ConstantFP>(SplatC))
return true;
} else {
- if (includesUndef(Kind) && match(C, m_AnyVectorElement(m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
+ if (includesUndef(Kind) &&
+ match(C, m_AnyVectorElement(
+ m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
return false;
if (includesPoison(Kind) && match(C, m_AnyVectorElement(m_Poison())))
return false;
@@ -8878,9 +8880,14 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
// purpose of identifying min/max. Disregard vector constants with undefined
// elements because those can not be back-propagated for analysis.
Value *OutputZeroVal = nullptr;
- if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(m_UndefValue())))) && !match(FalseVal, m_AnyZeroFP()))
+ if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(
+ m_UndefValue())))) &&
+ !match(FalseVal, m_AnyZeroFP()))
OutputZeroVal = TrueVal;
- else if (match(FalseVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(m_UndefValue())))) && !match(TrueVal, m_AnyZeroFP()))
+ else if (match(FalseVal,
+ m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(
+ m_UndefValue())))) &&
+ !match(TrueVal, m_AnyZeroFP()))
OutputZeroVal = FalseVal;
if (OutputZeroVal) {
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 80e00cb7cc1af..c997cbaa68fa8 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -359,7 +359,8 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
return true;
if (C->getType()->isVectorTy())
- return !match(C, m_CombineOr(m_AnyVectorElement(m_Poison()), m_ConstantExpr()));
+ return !match(
+ C, m_CombineOr(m_AnyVectorElement(m_Poison()), m_ConstantExpr()));
// TODO: Recursively analyze aggregates or other constants.
return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 53ec2f9a70406..61cc1d65ee3a2 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -204,7 +204,8 @@ bool Constant::isNotMinSignedValue() const {
// Check that vectors don't contain INT_MIN
if (isa<FixedVectorType>(getType())) {
- return !anyVectorElement([&](const auto *E) { return !E->isNotMinSignedValue(); });
+ return !anyVectorElement(
+ [&](const auto *E) { return !E->isNotMinSignedValue(); });
}
// Check for splats that aren't INT_MIN
@@ -327,7 +328,7 @@ bool Constant::isElementWiseEqual(Value *Y) const {
bool Constant::anyVectorElement(function_ref<bool(Constant *)> PredFn) const {
if (!getType()->isVectorTy())
return false;
-
+
if (Constant *SplatVal = getSplatValue())
if (PredFn(SplatVal))
return true;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 88fb1bb7eef9a..1a52531021c84 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -396,7 +396,8 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
if (auto *SplatPtr = getSplatValue(II.getArgOperand(1))) {
// scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr
if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) {
- if (match(ConstMask, m_AnyVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
+ if (match(ConstMask,
+ m_AnyVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
Align Alignment = II.getParamAlign(1).valueOrOne();
StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false,
Alignment);
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index e540fc158cb4a..8ce292e1524b9 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5498,12 +5498,14 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
if (!VTy)
return nullptr;
Constant *BestValue = Constant::getNullValue(VTy->getScalarType());
- match(C, m_AnyVectorElement(m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
+ match(C, m_AnyVectorElement(
+ m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
return Constant::replaceUndefsWith(C, BestValue);
};
Constant *C;
- if (match(Op0, m_CombineAnd(m_Constant(C), m_AnyVectorElement(m_UndefValue()), m_Unless(m_ConstantExpr())))) {
+ if (match(Op0, m_CombineAnd(m_Constant(C), m_AnyVectorElement(m_UndefValue()),
+ m_Unless(m_ConstantExpr())))) {
if (Constant *Repl = getFreezeVectorReplacement(C))
return replaceInstUsesWith(I, Repl);
}
>From 881eaf47f31a4a703d301ba6de795c3ed6147545 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 29 May 2026 16:43:56 -0500
Subject: [PATCH 3/5] Fix misleading documentation for
Constant::anyVectorElement
---
llvm/include/llvm/IR/Constant.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 95806f77327b1..ffc99ed7ce865 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -105,7 +105,7 @@ class Constant : public User {
/// Return true if this is a vector constant where at least one element
/// satisfies the given predicate. For scalable vectors, the predicate is
- /// tested on the value as a whole.
+ /// only tested on the splat value.
LLVM_ABI bool anyVectorElement(function_ref<bool(Constant *)> PredFn) const;
/// Return true if the value can vary between threads.
>From 08ff76689d518bc5f13fb70304a6082efbe1aa25 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Mon, 1 Jun 2026 10:52:45 -0500
Subject: [PATCH 4/5] Renamed anyVectorElement/m_AnyVectorElement to
containsVectorElement/m_ContainsVectorElement
---
llvm/include/llvm/IR/Constant.h | 2 +-
llvm/include/llvm/IR/PatternMatch.h | 10 +++++-----
llvm/lib/Analysis/ConstantFolding.cpp | 8 ++++----
llvm/lib/Analysis/ValueTracking.cpp | 10 +++++-----
llvm/lib/CodeGen/MachineFunction.cpp | 2 +-
llvm/lib/IR/ConstantFold.cpp | 2 +-
llvm/lib/IR/Constants.cpp | 4 ++--
.../Transforms/InstCombine/InstCombineCalls.cpp | 2 +-
.../InstCombine/InstCombineMulDivRem.cpp | 2 +-
.../InstCombine/InstCombineNegator.cpp | 2 +-
.../InstCombine/InstructionCombining.cpp | 4 ++--
.../Instrumentation/MemorySanitizer.cpp | 2 +-
llvm/lib/Transforms/Scalar/Reassociate.cpp | 2 +-
llvm/unittests/IR/ConstantsTest.cpp | 16 ++++++++--------
14 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index ffc99ed7ce865..38d5327ecdbc7 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -106,7 +106,7 @@ class Constant : public User {
/// Return true if this is a vector constant where at least one element
/// satisfies the given predicate. For scalable vectors, the predicate is
/// only tested on the splat value.
- LLVM_ABI bool anyVectorElement(function_ref<bool(Constant *)> PredFn) const;
+ LLVM_ABI bool containsVectorElement(function_ref<bool(Constant *)> PredFn) const;
/// Return true if the value can vary between threads.
LLVM_ABI bool isThreadDependent() const;
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 7fadd23a85566..43ed066bfa0e4 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -181,13 +181,13 @@ inline auto m_ConstantInt() { return m_Isa<ConstantInt>(); }
/// Match an arbitrary ConstantFP and ignore it.
inline auto m_ConstantFP() { return m_Isa<ConstantFP>(); }
-template <typename SPTy> struct anyvectorelement_match {
+template <typename SPTy> struct containsvectorelement_match {
SPTy SubPattern;
- anyvectorelement_match(const SPTy &SP) : SubPattern(SP) {}
+ containsvectorelement_match(const SPTy &SP) : SubPattern(SP) {}
template <typename ITy> bool match(ITy *V) const {
auto *C = dyn_cast<Constant>(V);
- return C && C->anyVectorElement(
+ return C && C->containsVectorElement(
[&](Constant *E) { return SubPattern.match(E); });
}
};
@@ -195,7 +195,7 @@ template <typename SPTy> struct anyvectorelement_match {
/// Match a vector constant where at least one of its elements matches the
/// subpattern. Any bindings in the subpattern will be bound to the first match.
template <typename SPTy>
-inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
+inline containsvectorelement_match<SPTy> m_ContainsVectorElement(const SPTy &SubPattern) {
return SubPattern;
}
@@ -203,7 +203,7 @@ inline anyvectorelement_match<SPTy> m_AnyVectorElement(const SPTy &SubPattern) {
/// expression.
inline auto m_ConstantExpr() {
return m_CombineOr(m_Isa<ConstantExpr>(),
- m_AnyVectorElement(m_Isa<ConstantExpr>()));
+ m_ContainsVectorElement(m_Isa<ConstantExpr>()));
}
template <typename SubPattern_t> struct Splat_match {
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 20e4fa809001f..7b6fa961e1526 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -120,7 +120,7 @@ static bool foldMixesPoisonBits(Constant *C, unsigned NumSrcElt,
// If element counts don't divide evenly, bail out if a poison source element
// might span multiple destination lanes.
if (NumSrcElt % NumDstElt != 0)
- return match(C, m_AnyVectorElement(m_Poison()));
+ return match(C, m_ContainsVectorElement(m_Poison()));
unsigned Ratio = NumSrcElt / NumDstElt;
for (unsigned i = 0; i != NumSrcElt; i += Ratio) {
bool HasPoison = false;
@@ -151,7 +151,7 @@ static bool computePoisonDstLanes(Constant *C, unsigned NumSrcElt,
// If element counts don't divide evenly, bail out if a poison source element
// might span multiple destination lanes.
if ((NumDstElt < NumSrcElt ? NumSrcElt % NumDstElt : NumDstElt % NumSrcElt))
- return !match(C, m_AnyVectorElement(m_Poison()));
+ return !match(C, m_ContainsVectorElement(m_Poison()));
if (NumDstElt < NumSrcElt) {
unsigned Ratio = NumSrcElt / NumDstElt;
for (unsigned i = 0; i != NumDstElt; ++i) {
@@ -197,7 +197,7 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
// Bitcasting a byte containing any poison bit to an integer or fp type
// yields poison.
- if (SrcEltTy->isByteTy() && match(C, m_AnyVectorElement(m_Poison())))
+ if (SrcEltTy->isByteTy() && match(C, m_ContainsVectorElement(m_Poison())))
return PoisonValue::get(DestTy);
// If the vector is a vector of floating point or bytes, convert it to a
@@ -2315,7 +2315,7 @@ Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) {
auto *OpVT = cast<VectorType>(Op->getType());
// This is the same as the underlying binops - poison propagates.
- if (match(Op, m_AnyVectorElement(m_Poison())))
+ if (match(Op, m_ContainsVectorElement(m_Poison())))
return PoisonValue::get(OpVT->getElementType());
// Shortcut non-accumulating reductions.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 92d253f2e15d4..ab50967e513dc 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7816,10 +7816,10 @@ static bool isGuaranteedNotToBeUndefOrPoison(
return true;
} else {
if (includesUndef(Kind) &&
- match(C, m_AnyVectorElement(
+ match(C, m_ContainsVectorElement(
m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
return false;
- if (includesPoison(Kind) && match(C, m_AnyVectorElement(m_Poison())))
+ if (includesPoison(Kind) && match(C, m_ContainsVectorElement(m_Poison())))
return false;
return !match(C, m_ConstantExpr());
}
@@ -8853,7 +8853,7 @@ llvm::getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C) {
// undefined elements, so replace those elements with the first safe constant
// that we found.
// TODO: in case of poison, it is safe; let's replace undefs only.
- if (match(C, m_AnyVectorElement(m_UndefValue()))) {
+ if (match(C, m_ContainsVectorElement(m_UndefValue()))) {
assert(SafeReplacementConstant && "Replacement constant not set");
C = Constant::replaceUndefsWith(C, SafeReplacementConstant);
}
@@ -8880,12 +8880,12 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
// purpose of identifying min/max. Disregard vector constants with undefined
// elements because those can not be back-propagated for analysis.
Value *OutputZeroVal = nullptr;
- if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(
+ if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
m_UndefValue())))) &&
!match(FalseVal, m_AnyZeroFP()))
OutputZeroVal = TrueVal;
else if (match(FalseVal,
- m_CombineAnd(m_AnyZeroFP(), m_Unless(m_AnyVectorElement(
+ m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
m_UndefValue())))) &&
!match(TrueVal, m_AnyZeroFP()))
OutputZeroVal = FalseVal;
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index ea01c3241e84d..bb2616c565c1a 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -1563,7 +1563,7 @@ static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B,
if (StoreSize != DL.getTypeStoreSize(B->getType()) || StoreSize > 128)
return false;
- bool ContainsUndefOrPoisonA = match(A, m_AnyVectorElement(m_UndefValue()));
+ bool ContainsUndefOrPoisonA = match(A, m_ContainsVectorElement(m_UndefValue()));
Type *IntTy = IntegerType::get(A->getContext(), StoreSize*8);
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index c997cbaa68fa8..beb55b3c7147d 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -360,7 +360,7 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
if (C->getType()->isVectorTy())
return !match(
- C, m_CombineOr(m_AnyVectorElement(m_Poison()), m_ConstantExpr()));
+ C, m_CombineOr(m_ContainsVectorElement(m_Poison()), m_ConstantExpr()));
// TODO: Recursively analyze aggregates or other constants.
return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 61cc1d65ee3a2..2a2436983f143 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -204,7 +204,7 @@ bool Constant::isNotMinSignedValue() const {
// Check that vectors don't contain INT_MIN
if (isa<FixedVectorType>(getType())) {
- return !anyVectorElement(
+ return !containsVectorElement(
[&](const auto *E) { return !E->isNotMinSignedValue(); });
}
@@ -325,7 +325,7 @@ bool Constant::isElementWiseEqual(Value *Y) const {
return CmpEq && (isa<PoisonValue>(CmpEq) || match(CmpEq, m_One()));
}
-bool Constant::anyVectorElement(function_ref<bool(Constant *)> PredFn) const {
+bool Constant::containsVectorElement(function_ref<bool(Constant *)> PredFn) const {
if (!getType()->isVectorTy())
return false;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 1a52531021c84..b40e0bf7f5df1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -397,7 +397,7 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
// scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr
if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) {
if (match(ConstMask,
- m_AnyVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
+ m_ContainsVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
Align Alignment = II.getParamAlign(1).valueOrOne();
StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false,
Alignment);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index dc87a86f5ac01..ba68c8a895bfa 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1290,7 +1290,7 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
// If any element of a constant divisor fixed width vector is zero or undef
// the behavior is undefined and we can fold the whole op to poison.
- if (match(Op1, m_AnyVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
+ if (match(Op1, m_ContainsVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
return replaceInstUsesWith(I, PoisonValue::get(I.getType()));
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
index 45d15cfe27fdb..7a9fc4a32a91b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
@@ -275,7 +275,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
// While this is normally not behind a use-check,
// let's consider division to be special since it's costly.
if (auto *Op1C = dyn_cast<Constant>(I->getOperand(1))) {
- if (!match(Op1C, m_AnyVectorElement(m_UndefValue())) &&
+ if (!match(Op1C, m_ContainsVectorElement(m_UndefValue())) &&
Op1C->isNotMinSignedValue() && Op1C->isNotOneValue()) {
Value *BO =
Builder.CreateSDiv(I->getOperand(0), ConstantExpr::getNeg(Op1C),
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 8ce292e1524b9..d64865f2f4ac4 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5498,13 +5498,13 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
if (!VTy)
return nullptr;
Constant *BestValue = Constant::getNullValue(VTy->getScalarType());
- match(C, m_AnyVectorElement(
+ match(C, m_ContainsVectorElement(
m_CombineAnd(m_Unless(m_Undef()), m_Constant(BestValue))));
return Constant::replaceUndefsWith(C, BestValue);
};
Constant *C;
- if (match(Op0, m_CombineAnd(m_Constant(C), m_AnyVectorElement(m_UndefValue()),
+ if (match(Op0, m_CombineAnd(m_Constant(C), m_ContainsVectorElement(m_UndefValue()),
m_Unless(m_ConstantExpr())))) {
if (Constant *Repl = getFreezeVectorReplacement(C))
return replaceInstUsesWith(I, Repl);
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index e133840db0e01..103f5dd4e8246 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -2175,7 +2175,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// Check for partially-undefined constant vectors
// TODO: scalable vectors (this is hard because we do not have IRBuilder)
- if (match(V, m_AnyVectorElement(m_UndefValue())) && PropagateShadow &&
+ if (match(V, m_ContainsVectorElement(m_UndefValue())) && PropagateShadow &&
PoisonUndefVectors) {
unsigned NumElems = cast<FixedVectorType>(V->getType())->getNumElements();
SmallVector<Constant *, 32> ShadowVector(NumElems);
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index 8946698cfb6b7..0a7d88d3afb0d 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -818,7 +818,7 @@ static Value *NegateValue(Value *V, Instruction *BI,
Instruction *TheNeg = dyn_cast<Instruction>(U);
// We can't safely propagate a vector zero constant with poison/undef lanes.
- if (match(TheNeg, m_BinOp(m_AnyVectorElement(m_UndefValue()), m_Value())))
+ if (match(TheNeg, m_BinOp(m_ContainsVectorElement(m_UndefValue()), m_Value())))
continue;
// Verify that the negate is in this function, V might be a constant expr.
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 1e330a364df6b..8b7caad3212ff 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -597,26 +597,26 @@ TEST(ConstantsTest, containsUndefElemTest) {
{
Constant *V1 = ConstantVector::get({C1, C2});
- EXPECT_FALSE(match(V1, m_AnyVectorElement(m_UndefValue())));
- EXPECT_FALSE(match(V1, m_AnyVectorElement(m_Poison())));
+ EXPECT_FALSE(match(V1, m_ContainsVectorElement(m_UndefValue())));
+ EXPECT_FALSE(match(V1, m_ContainsVectorElement(m_Poison())));
}
{
Constant *V2 = ConstantVector::get({C1, CU});
- EXPECT_TRUE(match(V2, m_AnyVectorElement(m_UndefValue())));
- EXPECT_FALSE(match(V2, m_AnyVectorElement(m_Poison())));
+ EXPECT_TRUE(match(V2, m_ContainsVectorElement(m_UndefValue())));
+ EXPECT_FALSE(match(V2, m_ContainsVectorElement(m_Poison())));
}
{
Constant *V3 = ConstantVector::get({C1, CP});
- EXPECT_TRUE(match(V3, m_AnyVectorElement(m_UndefValue())));
- EXPECT_TRUE(match(V3, m_AnyVectorElement(m_Poison())));
+ EXPECT_TRUE(match(V3, m_ContainsVectorElement(m_UndefValue())));
+ EXPECT_TRUE(match(V3, m_ContainsVectorElement(m_Poison())));
}
{
Constant *V4 = ConstantVector::get({CU, CP});
- EXPECT_TRUE(match(V4, m_AnyVectorElement(m_UndefValue())));
- EXPECT_TRUE(match(V4, m_AnyVectorElement(m_Poison())));
+ EXPECT_TRUE(match(V4, m_ContainsVectorElement(m_UndefValue())));
+ EXPECT_TRUE(match(V4, m_ContainsVectorElement(m_Poison())));
}
}
>From fde18d86e9195abf367825c064bcefb4b304c76c Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Mon, 1 Jun 2026 10:57:21 -0500
Subject: [PATCH 5/5] Format with clang-format
---
llvm/include/llvm/IR/Constant.h | 3 ++-
llvm/include/llvm/IR/PatternMatch.h | 3 ++-
llvm/lib/Analysis/ValueTracking.cpp | 8 +++++---
llvm/lib/CodeGen/MachineFunction.cpp | 3 ++-
llvm/lib/IR/ConstantFold.cpp | 4 ++--
llvm/lib/IR/Constants.cpp | 3 ++-
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 4 ++--
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 3 ++-
llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 5 +++--
llvm/lib/Transforms/Scalar/Reassociate.cpp | 3 ++-
10 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 38d5327ecdbc7..8c09aa2ed39dc 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -106,7 +106,8 @@ class Constant : public User {
/// Return true if this is a vector constant where at least one element
/// satisfies the given predicate. For scalable vectors, the predicate is
/// only tested on the splat value.
- LLVM_ABI bool containsVectorElement(function_ref<bool(Constant *)> PredFn) const;
+ LLVM_ABI bool
+ containsVectorElement(function_ref<bool(Constant *)> PredFn) const;
/// Return true if the value can vary between threads.
LLVM_ABI bool isThreadDependent() const;
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 43ed066bfa0e4..c5ef54966aae3 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -195,7 +195,8 @@ template <typename SPTy> struct containsvectorelement_match {
/// Match a vector constant where at least one of its elements matches the
/// subpattern. Any bindings in the subpattern will be bound to the first match.
template <typename SPTy>
-inline containsvectorelement_match<SPTy> m_ContainsVectorElement(const SPTy &SubPattern) {
+inline containsvectorelement_match<SPTy>
+m_ContainsVectorElement(const SPTy &SubPattern) {
return SubPattern;
}
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ab50967e513dc..d7a23e26bfb16 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7819,7 +7819,8 @@ static bool isGuaranteedNotToBeUndefOrPoison(
match(C, m_ContainsVectorElement(
m_CombineAnd(m_UndefValue(), m_Unless(m_Poison())))))
return false;
- if (includesPoison(Kind) && match(C, m_ContainsVectorElement(m_Poison())))
+ if (includesPoison(Kind) &&
+ match(C, m_ContainsVectorElement(m_Poison())))
return false;
return !match(C, m_ConstantExpr());
}
@@ -8880,8 +8881,9 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
// purpose of identifying min/max. Disregard vector constants with undefined
// elements because those can not be back-propagated for analysis.
Value *OutputZeroVal = nullptr;
- if (match(TrueVal, m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
- m_UndefValue())))) &&
+ if (match(TrueVal,
+ m_CombineAnd(m_AnyZeroFP(), m_Unless(m_ContainsVectorElement(
+ m_UndefValue())))) &&
!match(FalseVal, m_AnyZeroFP()))
OutputZeroVal = TrueVal;
else if (match(FalseVal,
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index bb2616c565c1a..7d7a1ad274290 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -1563,7 +1563,8 @@ static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B,
if (StoreSize != DL.getTypeStoreSize(B->getType()) || StoreSize > 128)
return false;
- bool ContainsUndefOrPoisonA = match(A, m_ContainsVectorElement(m_UndefValue()));
+ bool ContainsUndefOrPoisonA =
+ match(A, m_ContainsVectorElement(m_UndefValue()));
Type *IntTy = IntegerType::get(A->getContext(), StoreSize*8);
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index beb55b3c7147d..9c3d9e21c3f2e 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -359,8 +359,8 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
return true;
if (C->getType()->isVectorTy())
- return !match(
- C, m_CombineOr(m_ContainsVectorElement(m_Poison()), m_ConstantExpr()));
+ return !match(C, m_CombineOr(m_ContainsVectorElement(m_Poison()),
+ m_ConstantExpr()));
// TODO: Recursively analyze aggregates or other constants.
return false;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 2a2436983f143..068b0fca67130 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -325,7 +325,8 @@ bool Constant::isElementWiseEqual(Value *Y) const {
return CmpEq && (isa<PoisonValue>(CmpEq) || match(CmpEq, m_One()));
}
-bool Constant::containsVectorElement(function_ref<bool(Constant *)> PredFn) const {
+bool Constant::containsVectorElement(
+ function_ref<bool(Constant *)> PredFn) const {
if (!getType()->isVectorTy())
return false;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index b40e0bf7f5df1..a6c5acae9cdea 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -396,8 +396,8 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
if (auto *SplatPtr = getSplatValue(II.getArgOperand(1))) {
// scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr
if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) {
- if (match(ConstMask,
- m_ContainsVectorElement(m_CombineOr(m_AllOnes(), m_UndefValue())))) {
+ if (match(ConstMask, m_ContainsVectorElement(
+ m_CombineOr(m_AllOnes(), m_UndefValue())))) {
Align Alignment = II.getParamAlign(1).valueOrOne();
StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false,
Alignment);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index ba68c8a895bfa..2d3ddee16c433 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1290,7 +1290,8 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
// If any element of a constant divisor fixed width vector is zero or undef
// the behavior is undefined and we can fold the whole op to poison.
- if (match(Op1, m_ContainsVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
+ if (match(Op1,
+ m_ContainsVectorElement(m_CombineOr(m_Zero(), m_UndefValue())))) {
return replaceInstUsesWith(I, PoisonValue::get(I.getType()));
}
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index d64865f2f4ac4..ae61aab5b848c 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5504,8 +5504,9 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
};
Constant *C;
- if (match(Op0, m_CombineAnd(m_Constant(C), m_ContainsVectorElement(m_UndefValue()),
- m_Unless(m_ConstantExpr())))) {
+ if (match(Op0,
+ m_CombineAnd(m_Constant(C), m_ContainsVectorElement(m_UndefValue()),
+ m_Unless(m_ConstantExpr())))) {
if (Constant *Repl = getFreezeVectorReplacement(C))
return replaceInstUsesWith(I, Repl);
}
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index 0a7d88d3afb0d..d8caec10cf43f 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -818,7 +818,8 @@ static Value *NegateValue(Value *V, Instruction *BI,
Instruction *TheNeg = dyn_cast<Instruction>(U);
// We can't safely propagate a vector zero constant with poison/undef lanes.
- if (match(TheNeg, m_BinOp(m_ContainsVectorElement(m_UndefValue()), m_Value())))
+ if (match(TheNeg,
+ m_BinOp(m_ContainsVectorElement(m_UndefValue()), m_Value())))
continue;
// Verify that the negate is in this function, V might be a constant expr.
More information about the llvm-commits
mailing list