diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4555,9 +4555,14 @@ if (match(TrueVal, m_One()) && match(FalseVal, m_ZeroInt())) return Cond; - // (X || Y) && (X || !Y) --> X (commuted 8 ways) + // (X || Y) ? false : X --> false (commuted 2 ways) + if (match(Cond, m_c_LogicalOr(m_Specific(FalseVal), m_Value())) && + match(TrueVal, m_ZeroInt())) + return ConstantInt::getFalse(Cond->getType()); + Value *X, *Y; if (match(FalseVal, m_ZeroInt())) { + // (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; diff --git a/llvm/test/Transforms/InstSimplify/select-logical.ll b/llvm/test/Transforms/InstSimplify/select-logical.ll --- a/llvm/test/Transforms/InstSimplify/select-logical.ll +++ b/llvm/test/Transforms/InstSimplify/select-logical.ll @@ -289,98 +289,85 @@ } -; (X | Y) ? false && X --> false +; (X | Y) ? false : X --> false define i1 @or_select_false_x_case1(i1 %x, i1 %y) { ; CHECK-LABEL: @or_select_false_x_case1( -; CHECK-NEXT: [[OR:%.*]] = or i1 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[OR]], i1 false, i1 [[X]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %or = or i1 %x, %y %r = select i1 %or, i1 false, i1 %x ret i1 %r } -; (X | Y) ? false && X --> false +; (X | Y) ? false : X --> false define i1 @or_select_false_x_case2(i1 %x, i1 %y) { ; CHECK-LABEL: @or_select_false_x_case2( -; CHECK-NEXT: [[OR:%.*]] = or i1 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[OR]], i1 false, i1 [[Y]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %or = or i1 %x, %y %r = select i1 %or, i1 false, i1 %y ret i1 %r } -; vector case (X | Y) ? false && X --> false +; vector case (X | Y) ? false : X --> false define <2 x i1> @or_select_false_x_vector(<2 x i1> %x, <2 x i1> %y) { ; CHECK-LABEL: @or_select_false_x_vector( -; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[OR]], <2 x i1> zeroinitializer, <2 x i1> [[X]] -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %or = or <2 x i1> %x, %y %r = select <2 x i1> %or, <2 x i1> , <2 x i1> %x ret <2 x i1> %r } -; vector poison case (X | Y) ? false && X --> false +; vector poison case (X | Y) ? false : X --> false define <2 x i1> @or_select_false_x_vector_poison(<2 x i1> %x, <2 x i1> %y) { ; CHECK-LABEL: @or_select_false_x_vector_poison( -; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[OR]], <2 x i1> , <2 x i1> [[X]] -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %or = or <2 x i1> %x, %y %r = select <2 x i1> %or, <2 x i1> , <2 x i1> %x ret <2 x i1> %r } -; (X || Y) ? false && X --> false +; (X || Y) ? false : X --> false define i1 @logical_or_select_false_x_case1(i1 %x, i1 %y) { ; CHECK-LABEL: @logical_or_select_false_x_case1( -; CHECK-NEXT: [[OR:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[OR]], i1 false, i1 [[X]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %or = select i1 %x, i1 true, i1 %y %r = select i1 %or, i1 false, i1 %x ret i1 %r } -; (X || Y) ? false && X --> false +; (X || Y) ? false : X --> false define i1 @logical_or_select_false_x_case2(i1 %x, i1 %y) { ; CHECK-LABEL: @logical_or_select_false_x_case2( -; CHECK-NEXT: [[OR:%.*]] = select i1 [[Y:%.*]], i1 true, i1 [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[OR]], i1 false, i1 [[X]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %or = select i1 %y, i1 true, i1 %x %r = select i1 %or, i1 false, i1 %x ret i1 %r } -; vector case (X || Y) ? false && X --> false +; vector case (X || Y) ? false : X --> false define <2 x i1> @logical_or_select_false_x_vector(<2 x i1> %x, <2 x i1> %y) { ; CHECK-LABEL: @logical_or_select_false_x_vector( -; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i1> , <2 x i1> [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[OR]], <2 x i1> zeroinitializer, <2 x i1> [[X]] -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %or = select <2 x i1> %y, <2 x i1> , <2 x i1> %x %r = select <2 x i1> %or, <2 x i1> , <2 x i1> %x ret <2 x i1> %r } -; vector poison case (X || Y) ? false && X --> false +; TODO: this could transform to false +; vector poison case (X || Y) ? false : X --> false define <2 x i1> @logical_or_select_false_x_vector_poison1(<2 x i1> %x, <2 x i1> %y) { ; CHECK-LABEL: @logical_or_select_false_x_vector_poison1( @@ -393,13 +380,11 @@ ret <2 x i1> %r } -; vector poison case (X || Y) ? false && X --> false +; vector poison case (X || Y) ? false : X --> false define <2 x i1> @logical_or_select_false_x_vector_poison2(<2 x i1> %x, <2 x i1> %y) { ; CHECK-LABEL: @logical_or_select_false_x_vector_poison2( -; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i1> , <2 x i1> [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[OR]], <2 x i1> , <2 x i1> [[X]] -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %or = select <2 x i1> %y, <2 x i1> , <2 x i1> %x %r = select <2 x i1> %or, <2 x i1> , <2 x i1> %x