From f90ab103b53befbaf755595ce84b6afd7898f64e Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 20 Jun 2021 09:41:59 -0400 Subject: [PATCH] [InstCombine] avoid infinite loops with select folds of constant expressions This pair of transforms was added recently with: 8591640379ac9175a And could lead to conflicting folds: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35399 --- .../InstCombine/InstCombineSelect.cpp | 6 ++-- test/Transforms/InstCombine/select-and-or.ll | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 2308cdfe0e1..eadc826c719 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2709,13 +2709,15 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { // DeMorgan in select form: !a && !b --> !(a || b) // select !a, !b, false --> not (select a, true, b) if (match(&SI, m_LogicalAnd(m_Not(m_Value(A)), m_Not(m_Value(B)))) && - (CondVal->hasOneUse() || TrueVal->hasOneUse())) + (CondVal->hasOneUse() || TrueVal->hasOneUse()) && + !match(A, m_ConstantExpr()) && !match(B, m_ConstantExpr())) return BinaryOperator::CreateNot(Builder.CreateSelect(A, One, B)); // DeMorgan in select form: !a || !b --> !(a && b) // select !a, true, !b --> not (select a, b, false) if (match(&SI, m_LogicalOr(m_Not(m_Value(A)), m_Not(m_Value(B)))) && - (CondVal->hasOneUse() || FalseVal->hasOneUse())) + (CondVal->hasOneUse() || FalseVal->hasOneUse()) && + !match(A, m_ConstantExpr()) && !match(B, m_ConstantExpr())) return BinaryOperator::CreateNot(Builder.CreateSelect(A, B, Zero)); // select (select a, true, b), true, b -> select a, true, b diff --git a/test/Transforms/InstCombine/select-and-or.ll b/test/Transforms/InstCombine/select-and-or.ll index 5d6352e3484..8cd473525ae 100644 --- a/test/Transforms/InstCombine/select-and-or.ll +++ b/test/Transforms/InstCombine/select-and-or.ll @@ -420,3 +420,31 @@ define i1 @not_false_not_use3(i1 %x, i1 %y) { %r = select i1 %notx, i1 false, i1 %noty ret i1 %r } + +; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35399 + +@g1 = external global i16 +@g2 = external global i16 + +define i1 @demorgan_select_infloop1(i1 %L) { +; CHECK-LABEL: @demorgan_select_infloop1( +; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true +; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true), i1 false +; CHECK-NEXT: ret i1 [[C15]] +; + %not.L = xor i1 %L, true + %C15 = select i1 %not.L, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true), i1 false + ret i1 %C15 +} + + +define i1 @demorgan_select_infloop2(i1 %L) { +; CHECK-LABEL: @demorgan_select_infloop2( +; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true +; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true) +; CHECK-NEXT: ret i1 [[C15]] +; + %not.L = xor i1 %L, true + %C15 = select i1 %not.L, i1 true, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true) + ret i1 %C15 +}