forked from OSchip/llvm-project
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. llvm-svn: 216045
This commit is contained in:
parent
298f63803b
commit
42158f3eea
|
@ -251,6 +251,7 @@ private:
|
||||||
bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS);
|
bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS);
|
||||||
bool WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS);
|
bool WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS);
|
||||||
bool WillNotOverflowSignedSub(Value *LHS, Value *RHS);
|
bool WillNotOverflowSignedSub(Value *LHS, Value *RHS);
|
||||||
|
bool WillNotOverflowUnsignedSub(Value *LHS, Value *RHS);
|
||||||
Value *EmitGEPOffset(User *GEP);
|
Value *EmitGEPOffset(User *GEP);
|
||||||
Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
|
Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
|
||||||
Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
|
Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
|
||||||
|
|
|
@ -988,6 +988,20 @@ bool InstCombiner::WillNotOverflowSignedSub(Value *LHS, Value *RHS) {
|
||||||
return false;
|
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.
|
// Checks if any operand is negative and we can convert add to sub.
|
||||||
// This function checks for following negative patterns
|
// This function checks for following negative patterns
|
||||||
// ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C))
|
// ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C))
|
||||||
|
@ -1660,6 +1674,10 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||||
Changed = true;
|
Changed = true;
|
||||||
I.setHasNoSignedWrap(true);
|
I.setHasNoSignedWrap(true);
|
||||||
}
|
}
|
||||||
|
if (!I.hasNoUnsignedWrap() && WillNotOverflowUnsignedSub(Op0, Op1)) {
|
||||||
|
Changed = true;
|
||||||
|
I.setHasNoUnsignedWrap(true);
|
||||||
|
}
|
||||||
|
|
||||||
return Changed ? &I : nullptr;
|
return Changed ? &I : nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -506,6 +506,18 @@ define i4 @test42(i4 %x, i4 %y) {
|
||||||
; CHECK-LABEL: @test42(
|
; CHECK-LABEL: @test42(
|
||||||
; CHECK-NEXT: [[AND:%.*]] = and i4 %y, 7
|
; CHECK-NEXT: [[AND:%.*]] = and i4 %y, 7
|
||||||
; CHECK-NEXT: [[AND1:%.*]] = and i4 %x, 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]]
|
; CHECK: ret i4 [[RET]]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue