Commit 57d5bc88 authored by David Majnemer's avatar David Majnemer
Browse files

InstCombine: Annotate sub with nsw when we prove it's safe

We can prove that a 'sub' can be a 'sub nsw' under certain conditions:
- The sign bits of the operands is the same.
- Both operands have more than 1 sign bit.

The subtraction cannot be a signed overflow in either case.

llvm-svn: 216037
parent fd1f0f17
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -250,6 +250,7 @@ private:
  Instruction *transformSExtICmp(ICmpInst *ICI, Instruction &CI);
  bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS);
  bool WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS);
  bool WillNotOverflowSignedSub(Value *LHS, Value *RHS);
  Value *EmitGEPOffset(User *GEP);
  Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
  Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
+39 −1
Original line number Diff line number Diff line
@@ -956,6 +956,38 @@ bool InstCombiner::WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS) {
  return false;
}

/// \brief Return true if we can prove that:
///    (sub LHS, RHS)  === (sub nsw LHS, RHS)
/// This basically requires proving that the add in the original type would not
/// overflow to change the sign bit or have a carry out.
/// TODO: Handle this for Vectors.
bool InstCombiner::WillNotOverflowSignedSub(Value *LHS, Value *RHS) {
  // If LHS and RHS each have at least two sign bits, the subtraction
  // cannot overflow.
  if (ComputeNumSignBits(LHS) > 1 && ComputeNumSignBits(RHS) > 1)
    return true;

  if (IntegerType *IT = dyn_cast<IntegerType>(LHS->getType())) {
    unsigned BitWidth = IT->getBitWidth();
    APInt LHSKnownZero(BitWidth, 0);
    APInt LHSKnownOne(BitWidth, 0);
    computeKnownBits(LHS, LHSKnownZero, LHSKnownOne);

    APInt RHSKnownZero(BitWidth, 0);
    APInt RHSKnownOne(BitWidth, 0);
    computeKnownBits(RHS, RHSKnownZero, RHSKnownOne);

    // Subtraction of two 2's compliment numbers having identical signs will
    // never overflow.
    if ((LHSKnownOne[BitWidth - 1] && RHSKnownOne[BitWidth - 1]) ||
        (LHSKnownZero[BitWidth - 1] && RHSKnownZero[BitWidth - 1]))
      return true;

    // TODO: implement logic similar to checkRippleForAdd
  }
  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))
@@ -1623,7 +1655,13 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
        return ReplaceInstUsesWith(I, Res);
      }

  return nullptr;
  bool Changed = false;
  if (!I.hasNoSignedWrap() && WillNotOverflowSignedSub(Op0, Op1)) {
    Changed = true;
    I.setHasNoSignedWrap(true);
  }

  return Changed ? &I : nullptr;
}

Instruction *InstCombiner::visitFSub(BinaryOperator &I) {
+1 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ define i32 @test_simplify3(i8* %mem1, i8* %mem2) {
; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32
; CHECK: [[LOAD2:%[a-z]+]] = load i8* %mem2, align 1
; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32
; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]]
; CHECK: [[RET:%[a-z]+]] = sub nsw i32 [[ZEXT1]], [[ZEXT2]]
  ret i32 %ret
; CHECK: ret i32 [[RET]]
}
+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ define i32 @test1(i8* %str2) {
; CHECK-LABEL: @test1(
; CHECK: %strcmpload = load i8* %str
; CHECK: %1 = zext i8 %strcmpload to i32
; CHECK: %2 = sub i32 0, %1
; CHECK: %2 = sub nsw i32 0, %1
; CHECK: ret i32 %2

  %str1 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0
+2 −2
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ define i32 @test1(i8* %str2) {
; CHECK-LABEL: @test1(
; CHECK: %strcmpload = load i8* %str
; CHECK: %1 = zext i8 %strcmpload to i32
; CHECK: %2 = sub i32 0, %1
; CHECK: %2 = sub nsw i32 0, %1
; CHECK: ret i32 %2

  %str1 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0
@@ -73,7 +73,7 @@ define i32 @test6(i8* %str1, i8* %str2) {
; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32
; CHECK: [[LOAD2:%[a-z]+]] = load i8* %str2, align 1
; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32
; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]]
; CHECK: [[RET:%[a-z]+]] = sub nsw i32 [[ZEXT1]], [[ZEXT2]]
; CHECK: ret i32 [[RET]]

  %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 1)
Loading