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 @@ -4562,6 +4562,10 @@ Value *X, *Y; if (match(FalseVal, m_ZeroInt())) { + // !(X || Y) && X --> false (commuted 2 ways) + if (match(Cond, m_Not(m_c_LogicalOr(m_Specific(TrueVal), m_Value())))) + return ConstantInt::getFalse(Cond->getType()); + // (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)))) 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 @@ -127,10 +127,7 @@ define i1 @or_not_and(i1 %x, i1 %y) { ; CHECK-LABEL: @or_not_and( -; CHECK-NEXT: [[L_AND:%.*]] = or i1 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[L_AND]], true -; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT]], i1 [[X]], i1 false -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %l.and = or i1 %x, %y %not = xor i1 %l.and, true @@ -142,10 +139,7 @@ define <2 x i1> @or_not_and_vector(<2 x i1> %x, <2 x i1> %y) { ; CHECK-LABEL: @or_not_and_vector( -; CHECK-NEXT: [[L_AND:%.*]] = or <2 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[L_AND]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[NOT]], <2 x i1> [[X]], <2 x i1> zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %l.and = or <2 x i1> %x, %y %not = xor <2 x i1> %l.and, @@ -157,10 +151,7 @@ define <2 x i1> @or_not_and_vector_poison1(<2 x i1> %x, <2 x i1> %y) { ; CHECK-LABEL: @or_not_and_vector_poison1( -; CHECK-NEXT: [[L_AND:%.*]] = or <2 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[L_AND]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[NOT]], <2 x i1> [[X]], <2 x i1> zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %l.and = or <2 x i1> %x, %y %not = xor <2 x i1> %l.and, @@ -172,10 +163,7 @@ define <2 x i1> @or_not_and_vector_poison2(<2 x i1> %x, <2 x i1> %y) { ; CHECK-LABEL: @or_not_and_vector_poison2( -; CHECK-NEXT: [[L_AND:%.*]] = or <2 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[L_AND]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[NOT]], <2 x i1> [[X]], <2 x i1> -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %l.and = or <2 x i1> %x, %y %not = xor <2 x i1> %l.and, @@ -188,10 +176,7 @@ define i1 @logical_or_not_and(i1 %x, i1 %y) { ; CHECK-LABEL: @logical_or_not_and( -; CHECK-NEXT: [[L_AND:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]] -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[L_AND]], true -; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT]], i1 [[X]], i1 false -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %l.and = select i1 %x, i1 true, i1 %y %not = xor i1 %l.and, true @@ -202,12 +187,9 @@ ; !(X || Y) && Y --> false -define i1 @logical_or_not_and_comute_or(i1 %x, i1 %y) { -; CHECK-LABEL: @logical_or_not_and_comute_or( -; CHECK-NEXT: [[L_AND:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]] -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[L_AND]], true -; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT]], i1 [[Y]], i1 false -; CHECK-NEXT: ret i1 [[R]] +define i1 @logical_or_not_and_commute_or(i1 %x, i1 %y) { +; CHECK-LABEL: @logical_or_not_and_commute_or( +; CHECK-NEXT: ret i1 false ; %l.and = select i1 %x, i1 true, i1 %y %not = xor i1 %l.and, true @@ -219,10 +201,7 @@ define <3 x i1> @logical_or_not_and_vector1(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @logical_or_not_and_vector1( -; CHECK-NEXT: [[L_AND:%.*]] = select <3 x i1> [[X:%.*]], <3 x i1> , <3 x i1> [[Y:%.*]] -; CHECK-NEXT: [[NOT:%.*]] = xor <3 x i1> [[L_AND]], -; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[NOT]], <3 x i1> [[X]], <3 x i1> zeroinitializer -; CHECK-NEXT: ret <3 x i1> [[R]] +; CHECK-NEXT: ret <3 x i1> zeroinitializer ; %l.and = select <3 x i1> %x, <3 x i1> , <3 x i1> %y %not = xor <3 x i1> %l.and, @@ -230,18 +209,19 @@ ret <3 x i1> %r } +; TODO: this could transform to false ; vector case !(X || Y) && X --> false define <3 x i1> @logical_or_not_and_vector1_poison1(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @logical_or_not_and_vector1_poison1( ; CHECK-NEXT: [[L_AND:%.*]] = select <3 x i1> [[X:%.*]], <3 x i1> , <3 x i1> [[Y:%.*]] ; CHECK-NEXT: [[NOT:%.*]] = xor <3 x i1> [[L_AND]], -; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[NOT]], <3 x i1> [[X]], <3 x i1> +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[NOT]], <3 x i1> [[X]], <3 x i1> zeroinitializer ; CHECK-NEXT: ret <3 x i1> [[R]] ; %l.and = select <3 x i1> %x, <3 x i1> , <3 x i1> %y %not = xor <3 x i1> %l.and, - %r = select <3 x i1> %not, <3 x i1> %x, <3 x i1> + %r = select <3 x i1> %not, <3 x i1> %x, <3 x i1> ret <3 x i1> %r } @@ -249,10 +229,7 @@ define <3 x i1> @logical_or_not_and_vector1_poison2(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @logical_or_not_and_vector1_poison2( -; CHECK-NEXT: [[L_AND:%.*]] = select <3 x i1> [[X:%.*]], <3 x i1> , <3 x i1> [[Y:%.*]] -; CHECK-NEXT: [[NOT:%.*]] = xor <3 x i1> [[L_AND]], -; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[NOT]], <3 x i1> [[X]], <3 x i1> zeroinitializer -; CHECK-NEXT: ret <3 x i1> [[R]] +; CHECK-NEXT: ret <3 x i1> zeroinitializer ; %l.and = select <3 x i1> %x, <3 x i1> , <3 x i1> %y %not = xor <3 x i1> %l.and, @@ -264,10 +241,7 @@ define <3 x i1> @logical_or_not_and_vector1_poison3(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @logical_or_not_and_vector1_poison3( -; CHECK-NEXT: [[L_AND:%.*]] = select <3 x i1> [[X:%.*]], <3 x i1> , <3 x i1> [[Y:%.*]] -; CHECK-NEXT: [[NOT:%.*]] = xor <3 x i1> [[L_AND]], -; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[NOT]], <3 x i1> [[X]], <3 x i1> -; CHECK-NEXT: ret <3 x i1> [[R]] +; CHECK-NEXT: ret <3 x i1> zeroinitializer ; %l.and = select <3 x i1> %x, <3 x i1> , <3 x i1> %y %not = xor <3 x i1> %l.and,