Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -4479,6 +4479,11 @@ return ConstantVector::get(NewC); } + // select C, not(C), C -> 0 + if (match(TrueVal, m_ZExtOrSExtOrSelf(m_Not(m_Specific(Cond)))) && + match(FalseVal, m_ZExtOrSExtOrSelf(m_Specific(Cond)))) + return Constant::getNullValue(TrueVal->getType()); + if (Value *V = simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse)) return V; Index: llvm/test/Transforms/InstSimplify/select.ll =================================================================== --- llvm/test/Transforms/InstSimplify/select.ll +++ llvm/test/Transforms/InstSimplify/select.ll @@ -1066,3 +1066,82 @@ %v = select <2 x i1> %cond, <2 x i32> %x, <2 x i32> poison ret <2 x i32> %v } + +define i32 @select_cond_not_cond_cond1(i1 %cond) { +; CHECK-LABEL: @select_cond_not_cond_cond1( +; CHECK-NEXT: ret i32 0 +; + %z = zext i1 %cond to i32 + %not_cond = xor i1 %cond, true + %s = sext i1 %not_cond to i32 + %v = select i1 %cond, i32 %s, i32 %z + ret i32 %v +} + +define i32 @select_cond_not_cond_cond2(i1 %cond) { +; CHECK-LABEL: @select_cond_not_cond_cond2( +; CHECK-NEXT: ret i32 0 +; + %z = sext i1 %cond to i32 + %not_cond = xor i1 %cond, true + %s = sext i1 %not_cond to i32 + %v = select i1 %cond, i32 %s, i32 %z + ret i32 %v +} + +define i32 @select_cond_not_cond_cond3(i1 %cond) { +; CHECK-LABEL: @select_cond_not_cond_cond3( +; CHECK-NEXT: ret i32 0 +; + %z = sext i1 %cond to i32 + %not_cond = xor i1 %cond, true + %s = zext i1 %not_cond to i32 + %v = select i1 %cond, i32 %s, i32 %z + ret i32 %v +} + +define i32 @select_cond_not_cond_cond4(i1 %cond) { +; CHECK-LABEL: @select_cond_not_cond_cond4( +; CHECK-NEXT: ret i32 0 +; + %z = zext i1 %cond to i32 + %not_cond = xor i1 %cond, true + %s = zext i1 %not_cond to i32 + %v = select i1 %cond, i32 %s, i32 %z + ret i32 %v +} + +define i1 @select_cond_not_cond_cond5(i1 %cond) { +; CHECK-LABEL: @select_cond_not_cond_cond5( +; CHECK-NEXT: ret i1 false +; + %not_cond = xor i1 %cond, true + %v = select i1 %cond, i1 %not_cond, i1 %cond + ret i1 %v +} + +define <2 x i32> @select_cond_not_cond_cond_vec(<2 x i1> %cond) { +; CHECK-LABEL: @select_cond_not_cond_cond_vec( +; CHECK-NEXT: ret <2 x i32> zeroinitializer +; + %z = zext <2 x i1> %cond to <2 x i32> + %not_cond = xor <2 x i1> %cond, + %s = sext <2 x i1> %not_cond to <2 x i32> + %v = select <2 x i1> %cond, <2 x i32> %s, <2 x i32> %z + ret <2 x i32> %v +} + +define i32 @select_cond_not_cond_cond_neg(i1 %cond) { +; CHECK-LABEL: @select_cond_not_cond_cond_neg( +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[COND:%.*]] to i32 +; CHECK-NEXT: [[NOT_COND:%.*]] = xor i1 [[COND]], true +; CHECK-NEXT: [[S:%.*]] = sext i1 [[NOT_COND]] to i32 +; CHECK-NEXT: [[V:%.*]] = select i1 [[COND]], i32 [[Z]], i32 [[S]] +; CHECK-NEXT: ret i32 [[V]] +; + %z = zext i1 %cond to i32 + %not_cond = xor i1 %cond, true + %s = sext i1 %not_cond to i32 + %v = select i1 %cond, i32 %z, i32 %s + ret i32 %v +}