From 99e941fd9a39fc6677ce297abacd1cfbd67c0838 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 20 Aug 2014 07:17:31 +0000 Subject: [PATCH] InstCombine: Annotate sub with nuw when we prove it's safe We can prove that a 'sub' can be a 'sub nuw' if the left-hand side is negative and the right-hand side is non-negative. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216045 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombine.h | 1 + .../InstCombine/InstCombineAddSub.cpp | 18 ++++++++++++++++++ test/Transforms/InstCombine/sub.ll | 14 +++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h index 8cb634c8a3e..9e1cc3cb4d2 100644 --- a/lib/Transforms/InstCombine/InstCombine.h +++ b/lib/Transforms/InstCombine/InstCombine.h @@ -251,6 +251,7 @@ private: bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS); bool WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS); bool WillNotOverflowSignedSub(Value *LHS, Value *RHS); + bool WillNotOverflowUnsignedSub(Value *LHS, Value *RHS); Value *EmitGEPOffset(User *GEP); Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN); Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef Mask); diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 22566ceb050..e7e6cdd63d1 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -988,6 +988,20 @@ bool InstCombiner::WillNotOverflowSignedSub(Value *LHS, Value *RHS) { return false; } +/// \brief Return true if we can prove that: +/// (sub LHS, RHS) === (sub nuw LHS, RHS) +bool InstCombiner::WillNotOverflowUnsignedSub(Value *LHS, Value *RHS) { + // If the LHS is negative and the RHS is non-negative, no unsigned wrap. + bool LHSKnownNonNegative, LHSKnownNegative; + bool RHSKnownNonNegative, RHSKnownNegative; + ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, DL, 0); + ComputeSignBit(RHS, RHSKnownNonNegative, RHSKnownNegative, DL, 0); + if (LHSKnownNegative && RHSKnownNonNegative) + return true; + + return false; +} + // Checks if any operand is negative and we can convert add to sub. // This function checks for following negative patterns // ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C)) @@ -1660,6 +1674,10 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { Changed = true; I.setHasNoSignedWrap(true); } + if (!I.hasNoUnsignedWrap() && WillNotOverflowUnsignedSub(Op0, Op1)) { + Changed = true; + I.setHasNoUnsignedWrap(true); + } return Changed ? &I : nullptr; } diff --git a/test/Transforms/InstCombine/sub.ll b/test/Transforms/InstCombine/sub.ll index 0d310a8deeb..c786ba44ea7 100644 --- a/test/Transforms/InstCombine/sub.ll +++ b/test/Transforms/InstCombine/sub.ll @@ -506,6 +506,18 @@ define i4 @test42(i4 %x, i4 %y) { ; CHECK-LABEL: @test42( ; CHECK-NEXT: [[AND:%.*]] = and i4 %y, 7 ; CHECK-NEXT: [[AND1:%.*]] = and i4 %x, 7 -; CHECK-NEXT: [[RET:%.*]] = sub nsw i4 %a, %b +; CHECK-NEXT: [[RET:%.*]] = sub nsw i4 [[AND]], [[AND1]] +; CHECK: ret i4 [[RET]] +} + +define i4 @test43(i4 %x, i4 %y) { + %a = or i4 %x, -8 + %b = and i4 %y, 7 + %c = sub i4 %a, %b + ret i4 %c +; CHECK-LABEL: @test43( +; CHECK-NEXT: [[OR:%.*]] = or i4 %x, -8 +; CHECK-NEXT: [[AND:%.*]] = and i4 %y, 7 +; CHECK-NEXT: [[RET:%.*]] = sub nuw i4 [[OR]], [[AND]] ; CHECK: ret i4 [[RET]] } -- 2.34.1