diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h index 931576651224..2b6a6e4141b9 100644 --- a/llvm/include/llvm/IR/Constant.h +++ b/llvm/include/llvm/IR/Constant.h @@ -86,6 +86,12 @@ public: /// floating-point constant with all NaN elements. bool isNaN() const; + /// Return true if this constant and a constant 'Y' are element-wise equal. + /// This is identical to just comparing the pointers, with the exception that + /// for vectors, if only one of the constants has an `undef` element in some + /// lane, the constants still match. + bool isElementWiseEqual(Value *Y) const; + /// Return true if this is a vector constant that includes any undefined /// elements. bool containsUndefElement() const; diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index ee0c1e1f5f66..f792f01efc1a 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -22,6 +22,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" @@ -250,6 +251,20 @@ bool Constant::isNaN() const { return true; } +bool Constant::isElementWiseEqual(Value *Y) const { + // Are they fully identical? + if (this == Y) + return true; + // They may still be identical element-wise (if they have `undef`s). + auto *Cy = dyn_cast(Y); + if (!Cy) + return false; + return PatternMatch::match(ConstantExpr::getICmp(ICmpInst::Predicate::ICMP_EQ, + const_cast(this), + Cy), + PatternMatch::m_One()); +} + bool Constant::containsUndefElement() const { if (!getType()->isVectorTy()) return false; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index d5de10c32c4e..50f6b2bdfd81 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1296,18 +1296,6 @@ tryToReuseConstantFromSelectInComparison(SelectInst &Sel, ICmpInst &Cmp, // FIXME: are there any magic icmp predicate+constant pairs we must not touch? - auto ConstantsAreElementWiseEqual = [](Constant *Cx, Value *Y) { - // Are they fully identical? - if (Cx == Y) - return true; - // They may still be identical element-wise (if they have `undef`s). - auto *Cy = dyn_cast(Y); - if (!Cy) - return false; - return match(ConstantExpr::getICmp(ICmpInst::Predicate::ICMP_EQ, Cx, Cy), - m_One()); - }; - Value *SelVal0, *SelVal1; // We do not care which one is from where. match(&Sel, m_Select(m_Value(), m_Value(SelVal0), m_Value(SelVal1))); // At least one of these values we are selecting between must be a constant @@ -1317,10 +1305,8 @@ tryToReuseConstantFromSelectInComparison(SelectInst &Sel, ICmpInst &Cmp, return nullptr; // Does this constant C match any of the `select` values? - auto MatchesSelectValue = [ConstantsAreElementWiseEqual, SelVal0, - SelVal1](Constant *C) { - return ConstantsAreElementWiseEqual(C, SelVal0) || - ConstantsAreElementWiseEqual(C, SelVal1); + auto MatchesSelectValue = [SelVal0, SelVal1](Constant *C) { + return C->isElementWiseEqual(SelVal0) || C->isElementWiseEqual(SelVal1); }; // If C0 *already* matches true/false value of select, we are done.