Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -3071,6 +3071,10 @@ Constant *C; if (match(NotVal, m_AShr(m_Constant(C), m_Value(Y))) && match(C, m_Negative())) { + // There's a correctness subtlety here: we matched a negative constant, + // but the safe constant LHS for a shift is returned as zero, so it does + // not conform with the negative predicate constraint. Get the 'not' + // constant and then replace any undef elements with 0. Constant *NewC = ConstantExpr::getNot(C); if (C->getType()->isVectorTy()) NewC = getSafeVectorConstantForBinop(Instruction::LShr, NewC, false); @@ -3079,8 +3083,15 @@ // ~(C >>u Y) --> ~C >>s Y (when inverting the replicated sign bits) if (match(NotVal, m_LShr(m_Constant(C), m_Value(Y))) && - match(C, m_NonNegative())) - return BinaryOperator::CreateAShr(ConstantExpr::getNot(C), Y); + match(C, m_NonNegative())) { + // Unlike the similar pattern above, we matched a non-negative constant, + // so the safe constant LHS for a shift ("0") is ok. So we replace undef + // first, then 'not' that to create a safe and correct constant operand. + if (C->getType()->isVectorTy()) + C = getSafeVectorConstantForBinop(Instruction::LShr, C, false); + Constant *NewC = ConstantExpr::getNot(C); + return BinaryOperator::CreateAShr(NewC, Y); + } // ~(X + C) --> -(C + 1) - X if (match(Op0, m_Add(m_Value(X), m_Constant(C)))) Index: llvm/test/Transforms/InstCombine/vector-xor.ll =================================================================== --- llvm/test/Transforms/InstCombine/vector-xor.ll +++ llvm/test/Transforms/InstCombine/vector-xor.ll @@ -172,7 +172,7 @@ define <4 x i32> @test_v4i32_not_lshr_nonnegative_const_undef(<4 x i32> %a0) { ; CHECK-LABEL: @test_v4i32_not_lshr_nonnegative_const_undef( -; CHECK-NEXT: [[TMP1:%.*]] = ashr <4 x i32> , [[A0:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = ashr <4 x i32> , [[A0:%.*]] ; CHECK-NEXT: ret <4 x i32> [[TMP1]] ; %1 = lshr <4 x i32> , %a0