[InstCombine] Fix infinite recursion in ashr/xor vector fold.

The added test has poison lanes due to the vector shuffle. This can
cause an infinite loop of combines in instcombine where it folds
xor(ashr, -1) -> select (icmp slt 0), -1, 0 -> sext (icmp slt 0) -> xor(ashr, -1).
We usually prevent this by checking that the xor constant is not -1,
but with vectors some of the lanes may be -1, some may be poison. So
this changes the way we detect that from "!C1->isAllOnesValue()" to
"!match(C1, m_AllOnes())", which is more able to detect that some of the
lanes are poison.

Fixes PR52397
This commit is contained in:
David Green 2021-11-04 09:24:27 +00:00
parent 341cc1b411
commit 1e5f814302
2 changed files with 18 additions and 1 deletions

View File

@ -3601,7 +3601,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
if (match(Op0, m_OneUse(m_TruncOrSelf(
m_AShr(m_Value(X), m_APIntAllowUndef(CA))))) &&
*CA == X->getType()->getScalarSizeInBits() - 1 &&
!C1->isAllOnesValue()) {
!match(C1, m_AllOnes())) {
assert(!C1->isZeroValue() && "Unexpected xor with 0");
Value *ICmp =
Builder.CreateICmpSGT(X, Constant::getAllOnesValue(X->getType()));

View File

@ -90,6 +90,23 @@ define i8 @wrongimm(i16 %add) {
ret i8 %x
}
; Some of the lanes of the xor/ashr are unused, becoming poison.
define <4 x i32> @vectorpoison(<6 x i32> %0) {
; CHECK-LABEL: @vectorpoison(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[NEG:%.*]] = ashr <6 x i32> [[TMP0:%.*]], <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31>
; CHECK-NEXT: [[SHR:%.*]] = xor <6 x i32> [[NEG]], <i32 -1, i32 -1, i32 -1, i32 poison, i32 poison, i32 poison>
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <6 x i32> [[SHR]], <6 x i32> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 2>
; CHECK-NEXT: ret <4 x i32> [[TMP1]]
;
entry:
%neg = xor <6 x i32> %0, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
%shr = ashr <6 x i32> %neg, <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31>
%1 = shufflevector <6 x i32> %shr, <6 x i32> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 2>
ret <4 x i32> %1
}
; One use
define i16 @extrause(i16 %add) {