Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -1085,6 +1085,22 @@ } Value *llvm::SimplifySDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) { + // If two operands are negation and no signed overflow, return -1. + if (isKnownNegation(Op0, Op1)) { + bool nsw = true; + + // Op0 is no signed wrap. + if (match(Op0, m_Sub(m_Value(), m_Value()))) + nsw &= (cast(Op0))->hasNoSignedWrap(); + + // Op1 is no signed wrap. + if (match(Op1, m_Sub(m_Value(), m_Value()))) + nsw &= (cast(Op1))->hasNoSignedWrap(); + + if (nsw) + return Constant::getAllOnesValue(Op0->getType()); + } + return ::SimplifySDivInst(Op0, Op1, Q, RecursionLimit); } Index: llvm/test/Transforms/InstCombine/sdiv.ll =================================================================== --- llvm/test/Transforms/InstCombine/sdiv.ll +++ llvm/test/Transforms/InstCombine/sdiv.ll @@ -2,9 +2,7 @@ define i32 @negated_operand(i32 %x) { ; CHECK-LABEL: @negated_operand( -; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[NEGX]], [[X]] -; CHECK-NEXT: ret i32 [[DIV]] +; CHECK-NEXT: ret i32 -1 ; %negx = sub nsw i32 0, %x %div = sdiv i32 %negx, %x @@ -13,9 +11,7 @@ define <2 x i32> @negated_operand_commute_vec(<2 x i32> %x) { ; CHECK-LABEL: @negated_operand_commute_vec( -; CHECK-NEXT: [[NEGX:%.*]] = sub nsw <2 x i32> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i32> [[NEGX]], [[X]] -; CHECK-NEXT: ret <2 x i32> [[DIV]] +; CHECK-NEXT: ret <2 x i32> ; %negx = sub nsw <2 x i32> zeroinitializer, %x %div = sdiv <2 x i32> %negx, %x @@ -24,10 +20,7 @@ define i32 @knownnegation(i32 %x, i32 %y) { ; CHECK-LABEL: @knownnegation( -; CHECK-NEXT: [[XY:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[YX:%.*]] = sub nsw i32 [[Y]], [[X]] -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[XY]], [[YX]] -; CHECK-NEXT: ret i32 [[DIV]] +; CHECK-NEXT: ret i32 -1 ; %xy = sub nsw i32 %x, %y %yx = sub nsw i32 %y, %x @@ -37,10 +30,7 @@ define <2 x i32> @knownnegation_commute_vec(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @knownnegation_commute_vec( -; CHECK-NEXT: [[XY:%.*]] = sub nsw <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[YX:%.*]] = sub nsw <2 x i32> [[Y]], [[X]] -; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i32> [[XY]], [[YX]] -; CHECK-NEXT: ret <2 x i32> [[DIV]] +; CHECK-NEXT: ret <2 x i32> ; %xy = sub nsw <2 x i32> %x, %y %yx = sub nsw <2 x i32> %y, %x