diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -922,7 +922,31 @@ if (auto *CI = dyn_cast(SI->getCondition())) { if (CI->hasOneUse()) { Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1); - if ((TV == Op0 && FV == Op1) || (FV == Op0 && TV == 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; } } diff --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll --- a/llvm/test/Transforms/InstCombine/minmax-fold.ll +++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll @@ -1448,3 +1448,18 @@ %r = trunc i32 %u7 to i8 ret i8 %r } + +define i8 @PR46271(<2 x i8> %x) { +; CHECK-LABEL: @PR46271( +; CHECK-NEXT: [[A:%.*]] = icmp sgt <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[B:%.*]] = select <2 x i1> [[A]], <2 x i8> [[X]], <2 x i8> +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i8> [[B]], i32 1 +; CHECK-NEXT: [[R:%.*]] = xor i8 [[TMP1]], -1 +; CHECK-NEXT: ret i8 [[R]] +; + %a = icmp sgt <2 x i8> %x, + %b = select <2 x i1> %a, <2 x i8> %x, <2 x i8> + %not = xor <2 x i8> %b, + %r = extractelement <2 x i8> %not, i32 1 + ret i8 %r +}