[llvm] 1e5f814 - [InstCombine] Fix infinite recursion in ashr/xor vector fold.

David Green via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 4 02:24:32 PDT 2021


Author: David Green
Date: 2021-11-04T09:24:27Z
New Revision: 1e5f814302f8c24bdcc6f79623b86bd32231278f

URL: https://github.com/llvm/llvm-project/commit/1e5f814302f8c24bdcc6f79623b86bd32231278f
DIFF: https://github.com/llvm/llvm-project/commit/1e5f814302f8c24bdcc6f79623b86bd32231278f.diff

LOG: [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

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/test/Transforms/InstCombine/xor-ashr.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index d3b5cf3fa4b4e..7e40e358b6a22 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -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()));

diff  --git a/llvm/test/Transforms/InstCombine/xor-ashr.ll b/llvm/test/Transforms/InstCombine/xor-ashr.ll
index 570a2b33fd59a..7ec863fd119cb 100644
--- a/llvm/test/Transforms/InstCombine/xor-ashr.ll
+++ b/llvm/test/Transforms/InstCombine/xor-ashr.ll
@@ -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) {


        


More information about the llvm-commits mailing list