Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -4503,9 +4503,24 @@ if (match(TrueVal, m_One()) && match(FalseVal, m_ZeroInt())) return Cond; - // (X || Y) && (X || !Y) --> X (commuted 8 ways) Value *X, *Y; + if (match(Cond, m_LogicalOr(m_Value(X), m_Value(Y)))) { + // (X || Y) ? X : Y --> X + if ((X == TrueVal && Y == FalseVal) || (X == FalseVal && Y == TrueVal)) + return TrueVal; + + // !(X || Y) && X --> false (commuted 2 ways) + if (match(TrueVal, m_ZeroInt()) && (X == FalseVal || Y == FalseVal)) + 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,128 @@ %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 +} + +; (X || Y) ? X : Y --> X + +define i1 @select_or_same_op(i1 %x, i1 %y) { +; CHECK-LABEL: @select_or_same_op( +; CHECK-NEXT: ret i1 [[X:%.*]] +; + %or = or i1 %x, %y + %r = select i1 %or, i1 %x, i1 %y + ret i1 %r +} + +define i1 @select_or_same_op_commute(i1 %x, i1 %y) { +; CHECK-LABEL: @select_or_same_op_commute( +; CHECK-NEXT: ret i1 [[Y:%.*]] +; + %or = or i1 %x, %y + %r = select i1 %or, i1 %y, i1 %x + ret i1 %r +} + +define i1 @select_logic_or1_same_op(i1 %x, i1 %y) { +; CHECK-LABEL: @select_logic_or1_same_op( +; CHECK-NEXT: ret i1 [[X:%.*]] +; + %or = select i1 %x, i1 true, i1 %y + %r = select i1 %or, i1 %x, i1 %y + ret i1 %r +} + +define i1 @select_logic_or2_same_op(i1 %x, i1 %y) { +; CHECK-LABEL: @select_logic_or2_same_op( +; CHECK-NEXT: ret i1 [[X:%.*]] +; + %or = select i1 %y, i1 true, i1 %x + %r = select i1 %or, i1 %x, i1 %y + ret i1 %r +} + +; negative test - must have common operands + +define i1 @select_or_same_op_negatvie(i1 %x, i1 %y, i1 %z) { +; CHECK-LABEL: @select_or_same_op_negatvie( +; CHECK-NEXT: [[OR:%.*]] = or i1 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[OR]], i1 [[X]], i1 [[Z:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %or = or i1 %x, %y + %r = select i1 %or, i1 %x, i1 %z + ret i1 %r +}