From d266087e8dba9e8fd4984e1cb85c20376e2c8ea3 Mon Sep 17 00:00:00 2001 From: Naveen Saini Date: Fri, 27 Aug 2021 11:56:01 +0800 Subject: [PATCH 2/2] This patch is a fix for #1788. It is a port of the following llvm 11.0 commit: https://reviews.llvm.org/D81698 This also needed part of another llvm 11.0 commit: https://reviews.llvm.org/D72975 Upstream-Status: Backport [https://github.com/llvm/llvm-project/commit/aeb50448019ce1b1002f3781f9647d486320d83c] Signed-off-by: Naveen Saini --- llvm/include/llvm/IR/PatternMatch.h | 22 ++++++++++++--- .../InstCombine/InstructionCombining.cpp | 27 +++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 6621fc9f819c..fb7ad93519f6 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -152,8 +152,10 @@ inline match_combine_and m_CombineAnd(const LTy &L, const RTy &R) { struct apint_match { const APInt *&Res; + bool AllowUndef; - apint_match(const APInt *&R) : Res(R) {} + apint_match(const APInt *&Res, bool AllowUndef) + : Res(Res), AllowUndef(AllowUndef) {} template bool match(ITy *V) { if (auto *CI = dyn_cast(V)) { @@ -162,7 +164,8 @@ struct apint_match { } if (V->getType()->isVectorTy()) if (const auto *C = dyn_cast(V)) - if (auto *CI = dyn_cast_or_null(C->getSplatValue())) { + if (auto *CI = dyn_cast_or_null( + C->getSplatValue(AllowUndef))) { Res = &CI->getValue(); return true; } @@ -192,7 +195,20 @@ struct apfloat_match { /// Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. -inline apint_match m_APInt(const APInt *&Res) { return Res; } +inline apint_match m_APInt(const APInt *&Res) { + // Forbid undefs by default to maintain previous behavior. + return apint_match(Res, /* AllowUndef */ false); +} + +/// Match APInt while allowing undefs in splat vector constants. +inline apint_match m_APIntAllowUndef(const APInt *&Res) { + return apint_match(Res, /* AllowUndef */ true); +} + +/// Match APInt while forbidding undefs in splat vector constants. +inline apint_match m_APIntForbidUndef(const APInt *&Res) { + return apint_match(Res, /* AllowUndef */ false); +} /// Match a ConstantFP or splatted ConstantVector, binding the /// specified pointer to the contained APFloat. diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index bf32996d96e2..40a246b9d7a7 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -925,8 +925,31 @@ Instruction *InstCombiner::FoldOpIntoSelect(Instruction &Op, SelectInst *SI) { if (auto *CI = dyn_cast(SI->getCondition())) { if (CI->hasOneUse()) { Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1); - if ((SI->getOperand(1) == Op0 && SI->getOperand(2) == Op1) || - (SI->getOperand(2) == Op0 && SI->getOperand(1) == Op1)) + + // FIXME: This is a hack to avoid infinite looping with min/max patterns. + // We have to ensure that vector constants that only differ with + // undef elements are treated as equivalent. + auto areLooselyEqual = [](Value *A, Value *B) { + if (A == B) + return true; + + // Test for vector constants. + Constant *ConstA, *ConstB; + if (!match(A, m_Constant(ConstA)) || !match(B, m_Constant(ConstB))) + return false; + + // TODO: Deal with FP constants? + if (!A->getType()->isIntOrIntVectorTy() || A->getType() != B->getType()) + return false; + + // Compare for equality including undefs as equal. + auto *Cmp = ConstantExpr::getCompare(ICmpInst::ICMP_EQ, ConstA, ConstB); + const APInt *C; + return match(Cmp, m_APIntAllowUndef(C)) && C->isOneValue(); + }; + + if ((areLooselyEqual(TV, Op0) && areLooselyEqual(FV, Op1)) || + (areLooselyEqual(FV, Op0) && areLooselyEqual(TV, Op1))) return nullptr; } } -- 2.17.1