Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1692,9 +1692,12 @@ Builder.CreateNot(Y, Y->getName() + ".not")); // 0 - (X sdiv C) -> (X sdiv -C) provided the negation doesn't overflow. - if (match(Op1, m_SDiv(m_Value(X), m_Constant(C))) && match(Op0, m_Zero()) && - C->isNotMinSignedValue() && !C->isOneValue()) { - auto *BO = BinaryOperator::CreateSDiv(X, ConstantExpr::getNeg(C)); + // TODO: This could be extended to match arbitrary vector constants. + const APInt *DivC; + if (match(Op0, m_Zero()) && match(Op1, m_SDiv(m_Value(X), m_APInt(DivC))) && + !DivC->isMinSignedValue() && *DivC != 1) { + Constant *NegDivC = ConstantInt::get(I.getType(), -(*DivC)); + Instruction *BO = BinaryOperator::CreateSDiv(X, NegDivC); BO->setIsExact(cast(Op1)->isExact()); return BO; } Index: llvm/trunk/test/Transforms/InstCombine/div.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/div.ll +++ llvm/trunk/test/Transforms/InstCombine/div.ll @@ -772,7 +772,8 @@ define <2 x i64> @test_exact_vec(<2 x i64> %x) { ; CHECK-LABEL: @test_exact_vec( -; CHECK-NEXT: [[NEG:%.*]] = sdiv exact <2 x i64> [[X:%.*]], +; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i64> [[X:%.*]], +; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i64> zeroinitializer, [[DIV]] ; CHECK-NEXT: ret <2 x i64> [[NEG]] ; %div = sdiv exact <2 x i64> %x, @@ -832,7 +833,8 @@ define <2 x i8> @negate_sdiv_vec_one_element(<2 x i8> %x) { ; CHECK-LABEL: @negate_sdiv_vec_one_element( -; CHECK-NEXT: [[NEG:%.*]] = sdiv <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[DIV]] ; CHECK-NEXT: ret <2 x i8> [[NEG]] ; %div = sdiv <2 x i8> %x, @@ -840,7 +842,7 @@ ret <2 x i8> %neg } -; Division by -1 may be UB and can't negate signed-min. +; Can't negate signed-min constant for any element of a vector. define <2 x i8> @negate_sdiv_vec_signed_min_elt(<2 x i8> %x) { ; CHECK-LABEL: @negate_sdiv_vec_signed_min_elt( @@ -853,7 +855,7 @@ ret <2 x i8> %neg } -; Can't negate signed-min constant for any element of a vector. +; Division by -1 may be UB and can't negate signed-min. define <2 x i8> @negate_sdiv_vec_signed_min_and_one_elt(<2 x i8> %x) { ; CHECK-LABEL: @negate_sdiv_vec_signed_min_and_one_elt(