mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
[InstCombine] mark ADD with nuw if no unsigned overflow
Summary: As a starting step, we only use one simple heuristic: if the sign bits of both a and b are zero, we can prove "add a, b" do not unsigned overflow, and thus convert it to "add nuw a, b". Updated all affected tests and added two new tests (@zero_sign_bit and @zero_sign_bit2) in AddOverflow.ll Test Plan: make check-all Reviewers: eliben, rafael, meheff, chandlerc Reviewed By: chandlerc Subscribers: chandlerc, llvm-commits Differential Revision: http://reviews.llvm.org/D4144 llvm-svn: 211084
This commit is contained in:
parent
c1b16f1be2
commit
089dd5d55e
@ -247,6 +247,7 @@ private:
|
||||
bool DoXform = true);
|
||||
Instruction *transformSExtICmp(ICmpInst *ICI, Instruction &CI);
|
||||
bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS);
|
||||
bool WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS);
|
||||
Value *EmitGEPOffset(User *GEP);
|
||||
Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
|
||||
Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
|
||||
|
@ -965,6 +965,21 @@ bool InstCombiner::WillNotOverflowSignedAdd(Value *LHS, Value *RHS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// WillNotOverflowUnsignedAdd - Return true if we can prove that:
|
||||
/// (zext (add LHS, RHS)) === (add (zext LHS), (zext RHS))
|
||||
bool InstCombiner::WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS) {
|
||||
// There are different heuristics we can use for this. Here is a simple one.
|
||||
// If the sign bit of LHS and that of RHS are both zero, no unsigned wrap.
|
||||
bool LHSKnownNonNegative, LHSKnownNegative;
|
||||
bool RHSKnownNonNegative, RHSKnownNegative;
|
||||
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, DL, 0);
|
||||
ComputeSignBit(RHS, RHSKnownNonNegative, RHSKnownNegative, DL, 0);
|
||||
if (LHSKnownNonNegative && RHSKnownNonNegative)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
||||
bool Changed = SimplifyAssociativeOrCommutative(I);
|
||||
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
|
||||
@ -1240,10 +1255,17 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
||||
return BinaryOperator::CreateOr(A, B);
|
||||
}
|
||||
|
||||
// TODO(jingyue): Consider WillNotOverflowSignedAdd and
|
||||
// WillNotOverflowUnsignedAdd to reduce the number of invocations of
|
||||
// computeKnownBits.
|
||||
if (!I.hasNoSignedWrap() && WillNotOverflowSignedAdd(LHS, RHS)) {
|
||||
Changed = true;
|
||||
I.setHasNoSignedWrap(true);
|
||||
}
|
||||
if (!I.hasNoUnsignedWrap() && WillNotOverflowUnsignedAdd(LHS, RHS)) {
|
||||
Changed = true;
|
||||
I.setHasNoUnsignedWrap(true);
|
||||
}
|
||||
|
||||
return Changed ? &I : nullptr;
|
||||
}
|
||||
|
@ -12,6 +12,28 @@ define i16 @oppositesign(i16 %x, i16 %y) {
|
||||
ret i16 %c
|
||||
}
|
||||
|
||||
define i16 @zero_sign_bit(i16 %a) {
|
||||
; CHECK-LABEL: @zero_sign_bit(
|
||||
; CHECK-NEXT: and
|
||||
; CHECK-NEXT: add nuw
|
||||
; CHECK-NEXT: ret
|
||||
%1 = and i16 %a, 32767
|
||||
%2 = add i16 %1, 512
|
||||
ret i16 %2
|
||||
}
|
||||
|
||||
define i16 @zero_sign_bit2(i16 %a, i16 %b) {
|
||||
; CHECK-LABEL: @zero_sign_bit2(
|
||||
; CHECK-NEXT: and
|
||||
; CHECK-NEXT: and
|
||||
; CHECK-NEXT: add nuw
|
||||
; CHECK-NEXT: ret
|
||||
%1 = and i16 %a, 32767
|
||||
%2 = and i16 %b, 32767
|
||||
%3 = add i16 %1, %2
|
||||
ret i16 %3
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @ripple_nsw1
|
||||
; CHECK: add nsw i16 %a, %b
|
||||
define i16 @ripple_nsw1(i16 %x, i16 %y) {
|
||||
@ -45,7 +67,7 @@ define i32 @ripple_no_nsw1(i32 %x, i32 %y) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @ripple_no_nsw2
|
||||
; CHECK: add i16 %a, %b
|
||||
; CHECK: add nuw i16 %a, %b
|
||||
define i16 @ripple_no_nsw2(i16 %x, i16 %y) {
|
||||
; %a has at most one bit set
|
||||
%a = and i16 %y, 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt < %s -instcombine -S | grep "add nsw i32"
|
||||
; RUN: opt < %s -instcombine -S | grep "add nuw nsw i32"
|
||||
|
||||
define double @x(i32 %a, i32 %b) nounwind {
|
||||
%m = lshr i32 %a, 24
|
||||
|
@ -103,7 +103,7 @@ define i32 @test_simplify13(i32 %x) {
|
||||
; CHECK-LABEL: @test_simplify13(
|
||||
%ret = call i32 @ffs(i32 %x)
|
||||
; CHECK-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 false)
|
||||
; CHECK-NEXT: [[INC:%[a-z0-9]+]] = add nsw i32 [[CTTZ]], 1
|
||||
; CHECK-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1
|
||||
; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0
|
||||
; CHECK-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0
|
||||
ret i32 %ret
|
||||
@ -114,7 +114,7 @@ define i32 @test_simplify14(i32 %x) {
|
||||
; CHECK-LINUX-LABEL: @test_simplify14(
|
||||
%ret = call i32 @ffsl(i32 %x)
|
||||
; CHECK-LINUX-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 false)
|
||||
; CHECK-LINUX-NEXT: [[INC:%[a-z0-9]+]] = add nsw i32 [[CTTZ]], 1
|
||||
; CHECK-LINUX-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1
|
||||
; CHECK-LINUX-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0
|
||||
; CHECK-LINUX-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0
|
||||
ret i32 %ret
|
||||
@ -125,7 +125,7 @@ define i32 @test_simplify15(i64 %x) {
|
||||
; CHECK-LINUX-LABEL: @test_simplify15(
|
||||
%ret = call i32 @ffsll(i64 %x)
|
||||
; CHECK-LINUX-NEXT: [[CTTZ:%[a-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %x, i1 false)
|
||||
; CHECK-LINUX-NEXT: [[INC:%[a-z0-9]+]] = add nsw i64 [[CTTZ]], 1
|
||||
; CHECK-LINUX-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i64 [[CTTZ]], 1
|
||||
; CHECK-LINUX-NEXT: [[TRUNC:%[a-z0-9]+]] = trunc i64 [[INC]] to i32
|
||||
; CHECK-LINUX-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i64 %x, 0
|
||||
; CHECK-LINUX-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[TRUNC]], i32 0
|
||||
|
@ -281,7 +281,7 @@ define i32 @test15i(i32 %X) {
|
||||
; CHECK-NEXT: %t1 = shl i32 %X, 8
|
||||
; CHECK-NEXT: %1 = and i32 %t1, 512
|
||||
; CHECK-NEXT: %2 = xor i32 %1, 512
|
||||
; CHECK-NEXT: %3 = add nsw i32 %2, 577
|
||||
; CHECK-NEXT: %3 = add nuw nsw i32 %2, 577
|
||||
; CHECK-NEXT: ret i32 %3
|
||||
}
|
||||
|
||||
@ -294,7 +294,7 @@ define i32 @test15j(i32 %X) {
|
||||
; CHECK-LABEL: @test15j(
|
||||
; CHECK-NEXT: %t1 = shl i32 %X, 8
|
||||
; CHECK-NEXT: %1 = and i32 %t1, 512
|
||||
; CHECK-NEXT: %2 = add nsw i32 %1, 577
|
||||
; CHECK-NEXT: %2 = add nuw nsw i32 %1, 577
|
||||
; CHECK-NEXT: ret i32 %2
|
||||
}
|
||||
|
||||
@ -521,7 +521,7 @@ define i32 @test35(i32 %x) {
|
||||
; CHECK-LABEL: @test35(
|
||||
; CHECK: ashr i32 %x, 31
|
||||
; CHECK: and i32 {{.*}}, 40
|
||||
; CHECK: add nsw i32 {{.*}}, 60
|
||||
; CHECK: add nuw nsw i32 {{.*}}, 60
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
@ -1235,4 +1235,4 @@ define i32 @test75(i32 %x) {
|
||||
; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ult i32 %x, 68
|
||||
; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 68, i32 %x
|
||||
; CHECK-NEXT: ret i32 [[SEL]]
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user