From 7d1726e81c86af4ac9d43aac75559b088ab58e41 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 7 Apr 2021 12:11:23 -0400 Subject: [PATCH] [InstCombine] avoid infinite loop from partial undef vectors This fixes the examples from D99674 and https://llvm.org/PR49878 The matchers succeed on partial undef/poison vector constants, but the transform creates a full 'not' (-1) constant, so it would undo a demanded vector elements change triggered by the extractelement. Differential Revision: https://reviews.llvm.org/D100044 --- .../InstCombine/InstCombineSelect.cpp | 6 +++-- .../InstCombine/select-extractelement.ll | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 854e2bf97d6..1552c9f2e48 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2654,13 +2654,15 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { auto *One = ConstantInt::getTrue(SelType); auto *Zero = ConstantInt::getFalse(SelType); + // We match the "full" 0 or 1 constant here to avoid a potential infinite + // loop with vectors that may have undefined/poison elements. // select a, false, b -> select !a, b, false - if (match(TrueVal, m_Zero())) { + if (match(TrueVal, m_Specific(Zero))) { Value *NotCond = Builder.CreateNot(CondVal, "not." + CondVal->getName()); return SelectInst::Create(NotCond, FalseVal, Zero); } // select a, b, true -> select !a, true, b - if (match(FalseVal, m_One())) { + if (match(FalseVal, m_Specific(One))) { Value *NotCond = Builder.CreateNot(CondVal, "not." + CondVal->getName()); return SelectInst::Create(NotCond, One, TrueVal); } diff --git a/test/Transforms/InstCombine/select-extractelement.ll b/test/Transforms/InstCombine/select-extractelement.ll index fb3f4fa830a..5bfb42c3e87 100644 --- a/test/Transforms/InstCombine/select-extractelement.ll +++ b/test/Transforms/InstCombine/select-extractelement.ll @@ -209,5 +209,28 @@ define <4 x i32> @extract_cond_type_mismatch(<4 x i32> %x, <4 x i32> %y, <5 x i1 ret <4 x i32> %r } +; This would infinite loop because a select transform would create +; a complete -1 vector constant and demanded elements would change +; it back to partial undef. + +define i32 @inf_loop_partial_undef(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @inf_loop_partial_undef( +; CHECK-NEXT: [[T5:%.*]] = add nsw <2 x i32> [[Y:%.*]], +; CHECK-NEXT: [[T6:%.*]] = icmp sge <2 x i32> [[T5]], [[X:%.*]] +; CHECK-NEXT: [[AB:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[T7:%.*]] = select <2 x i1> [[AB]], <2 x i1> [[T6]], <2 x i1> +; CHECK-NEXT: [[P:%.*]] = select <2 x i1> [[T7]], <2 x i32> , <2 x i32> [[Y]] +; CHECK-NEXT: [[T11:%.*]] = extractelement <2 x i32> [[P]], i32 0 +; CHECK-NEXT: ret i32 [[T11]] +; + %t5 = add nsw <2 x i32> %y, + %t6 = icmp slt <2 x i32> %t5, %x + %ab = and <2 x i1> %a, %b + %t7 = select <2 x i1> %ab, <2 x i1> %t6, <2 x i1> + %t10 = xor <2 x i1> %t7, + %p = select <2 x i1> %t10, <2 x i32> zeroinitializer, <2 x i32> %y + %t11 = extractelement <2 x i32> %p, i32 0 + ret i32 %t11 +} attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }