Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -4503,9 +4503,22 @@ if (match(TrueVal, m_One()) && match(FalseVal, m_ZeroInt())) return Cond; - // (X || Y) && (X || !Y) --> X (commuted 8 ways) Value *X, *Y; + + if (match(TrueVal, m_ZeroInt())) { + // !(X || Y) && X --> false (commuted 2 ways) + if (match(Cond, m_LogicalOr(m_Value(X), m_Value(Y))) && + (FalseVal == X || FalseVal == Y)) + return TrueVal; + } + if (match(FalseVal, m_ZeroInt())) { + // !(X || Y) && X --> false (commuted 2 ways) + if (match(Cond, m_Not(m_LogicalOr(m_Value(X), m_Value(Y)))) && + (TrueVal == X || TrueVal == Y)) + return FalseVal; + + // (X || Y) && (X || !Y) --> X (commuted 8 ways) if (match(Cond, m_c_LogicalOr(m_Value(X), m_Not(m_Value(Y)))) && match(TrueVal, m_c_LogicalOr(m_Specific(X), m_Specific(Y)))) return X; Index: llvm/test/Transforms/InstSimplify/select-logical.ll =================================================================== --- llvm/test/Transforms/InstSimplify/select-logical.ll +++ llvm/test/Transforms/InstSimplify/select-logical.ll @@ -122,3 +122,77 @@ %and = select i1 %xorynot, i1 %xorz, i1 false ret i1 %and } + +; !(X || Y) && X --> false + +define i1 @logical_not_or_and(i1 %x, i1 %y) { +; CHECK-LABEL: @logical_not_or_and( +; CHECK-NEXT: ret i1 false +; + %l.and = select i1 %x, i1 true, i1 %y + %not = xor i1 %l.and, true + %r = select i1 %not, i1 %x, i1 false + ret i1 %r +} + + +; !(X || Y) && Y --> false + +define i1 @logical_not_or_and_case1(i1 %x, i1 %y) { +; CHECK-LABEL: @logical_not_or_and_case1( +; CHECK-NEXT: ret i1 false +; + %l.and = select i1 %x, i1 true, i1 %y + %not = xor i1 %l.and, true + %r = select i1 %not, i1 %y, i1 false + ret i1 %r +} + +; negative test - must have common operands + +define i1 @logical_not_or_and_negative1(i1 %x, i1 %y, i1 %z) { +; CHECK-LABEL: @logical_not_or_and_negative1( +; CHECK-NEXT: [[OR:%.*]] = or i1 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[OR]], i1 false, i1 [[Z:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %or = or i1 %x, %y + %r = select i1 %or, i1 false, i1 %z + ret i1 %r +} + + +; another way for !(X || Y) && X --> false + +define i1 @logical_not_or_and_case2(i1 %x, i1 %y) { +; CHECK-LABEL: @logical_not_or_and_case2( +; CHECK-NEXT: ret i1 false +; + %or = or i1 %x, %y + %r = select i1 %or, i1 false, i1 %x + ret i1 %r +} + +; another way for !(X || Y) && Y --> false + +define i1 @logical_not_or_and_case3(i1 %x, i1 %y) { +; CHECK-LABEL: @logical_not_or_and_case3( +; CHECK-NEXT: ret i1 false +; + %or = or i1 %x, %y + %r = select i1 %or, i1 false, i1 %y + ret i1 %r +} + +; negative test - must have common operands + +define i1 @logical_not_or_and_negative2(i1 %x, i1 %y, i1 %z) { +; CHECK-LABEL: @logical_not_or_and_negative2( +; CHECK-NEXT: [[OR:%.*]] = or i1 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[OR]], i1 false, i1 [[Z:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %or = or i1 %x, %y + %r = select i1 %or, i1 false, i1 %z + ret i1 %r +}