diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1015,6 +1015,12 @@ (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))) return BinaryOperator::CreateNeg(Op0); + // -X / Y --> -(X / Y) + Value *Y; + if (match(&I, m_SDiv(m_OneUse(m_NSWSub(m_Zero(), m_Value(X))), m_Value(Y)))) + return BinaryOperator::CreateNSWNeg( + Builder.CreateSDiv(X, Y, I.getName(), I.isExact())); + // X / INT_MIN --> X == INT_MIN if (match(Op1, m_SignMask())) return new ZExtInst(Builder.CreateICmpEQ(Op0, Op1), I.getType()); @@ -1043,12 +1049,6 @@ Value *NarrowOp = Builder.CreateSDiv(Op0Src, NarrowDivisor); return new SExtInst(NarrowOp, Op0->getType()); } - - // -X / Y --> -(X / Y) - Value *Y; - if (match(&I, m_SDiv(m_OneUse(m_NSWSub(m_Zero(), m_Value(X))), m_Value(Y)))) - return BinaryOperator::CreateNSWNeg( - Builder.CreateSDiv(X, Y, I.getName(), I.isExact())); // -X / C --> X / -C (if the negation doesn't overflow). // TODO: This could be enhanced to handle arbitrary vector constants by diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll --- a/llvm/test/Transforms/InstCombine/div.ll +++ b/llvm/test/Transforms/InstCombine/div.ll @@ -492,7 +492,7 @@ define i8 @sdiv_negated_dividend_constant_divisor_smin(i8 %x) { ; CHECK-LABEL: @sdiv_negated_dividend_constant_divisor_smin( ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], -128 -; CHECK-NEXT: [[D:%.*]] = zext i1 [[TMP1]] to i8 +; CHECK-NEXT: [[D:%.*]] = sext i1 [[TMP1]] to i8 ; CHECK-NEXT: ret i8 [[D]] ; %neg = sub nsw i8 0, %x @@ -503,7 +503,7 @@ define <2 x i8> @sdiv_negated_dividend_constant_divisor_vec_splat_smin(<2 x i8> %x) { ; CHECK-LABEL: @sdiv_negated_dividend_constant_divisor_vec_splat_smin( ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[D:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8> +; CHECK-NEXT: [[D:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i8> ; CHECK-NEXT: ret <2 x i8> [[D]] ; %neg = sub nsw <2 x i8> zeroinitializer, %x @@ -522,9 +522,9 @@ define <2 x i64> @sdiv_negated_dividend_constant_divisor_vec(<2 x i64> %x) { ; CHECK-LABEL: @sdiv_negated_dividend_constant_divisor_vec( -; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i64> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i64> [[NEG]], -; CHECK-NEXT: ret <2 x i64> [[DIV]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i64> [[X:%.*]], +; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i64> zeroinitializer, [[DIV]] +; CHECK-NEXT: ret <2 x i64> [[NEG]] ; %neg = sub nsw <2 x i64> zeroinitializer, %x %div = sdiv <2 x i64> %neg, @@ -533,9 +533,9 @@ define <2 x i64> @sdiv_exact_negated_dividend_constant_divisor_vec(<2 x i64> %x) { ; CHECK-LABEL: @sdiv_exact_negated_dividend_constant_divisor_vec( -; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i64> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i64> [[NEG]], -; CHECK-NEXT: ret <2 x i64> [[DIV]] +; 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]] ; %neg = sub nsw <2 x i64> zeroinitializer, %x %div = sdiv exact <2 x i64> %neg, @@ -546,9 +546,9 @@ define <2 x i8> @sdiv_exact_negated_dividend_constant_divisor_vec_overflow(<2 x i8> %x) { ; CHECK-LABEL: @sdiv_exact_negated_dividend_constant_divisor_vec_overflow( -; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i8> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i8> [[NEG]], -; CHECK-NEXT: ret <2 x i8> [[DIV]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i8> zeroinitializer, [[DIV]] +; CHECK-NEXT: ret <2 x i8> [[NEG]] ; %neg = sub nsw <2 x i8> zeroinitializer, %x %div = sdiv exact <2 x i8> %neg,