summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp6
-rw-r--r--llvm/test/Transforms/InstCombine/abs-1.ll11
-rw-r--r--llvm/test/Transforms/InstCombine/abs_abs.ll16
3 files changed, 25 insertions, 8 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 7f33c67b8ab..5f5d1be9baa 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1078,6 +1078,12 @@ static void computeKnownBitsFromOperator(const Operator *I, KnownBits &Known,
// leading zero bits.
MaxHighZeros =
std::max(Known.countMinLeadingZeros(), Known2.countMinLeadingZeros());
+ } else if (SPF == SPF_ABS) {
+ // RHS from matchSelectPattern returns the negation part of abs pattern.
+ // If the negate has an NSW flag we can assume the sign bit of the result
+ // will be 0 because that makes abs(INT_MIN) undefined.
+ if (cast<Instruction>(RHS)->hasNoSignedWrap())
+ MaxHighZeros = 1;
}
// Only known if known in both the LHS and RHS.
diff --git a/llvm/test/Transforms/InstCombine/abs-1.ll b/llvm/test/Transforms/InstCombine/abs-1.ll
index 2a94001b69d..ee6b6674c0b 100644
--- a/llvm/test/Transforms/InstCombine/abs-1.ll
+++ b/llvm/test/Transforms/InstCombine/abs-1.ll
@@ -293,3 +293,14 @@ define <2 x i8> @negate_nabs(<2 x i8> %x) {
%r = sub <2 x i8> zeroinitializer, %s
ret <2 x i8> %r
}
+
+define i1 @abs_must_be_positive(i32 %x) {
+; CHECK-LABEL: @abs_must_be_positive(
+; CHECK-NEXT: ret i1 true
+;
+ %negx = sub nsw i32 0, %x
+ %c = icmp sge i32 %x, 0
+ %sel = select i1 %c, i32 %x, i32 %negx
+ %c2 = icmp sge i32 %sel, 0
+ ret i1 %c2
+}
diff --git a/llvm/test/Transforms/InstCombine/abs_abs.ll b/llvm/test/Transforms/InstCombine/abs_abs.ll
index a48c33e7277..5985d605466 100644
--- a/llvm/test/Transforms/InstCombine/abs_abs.ll
+++ b/llvm/test/Transforms/InstCombine/abs_abs.ll
@@ -933,8 +933,8 @@ define i32 @nabs_abs_x09(i32 %x) {
; CHECK-LABEL: @nabs_abs_x09(
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X]]
-; CHECK-NEXT: [[COND1:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]]
-; CHECK-NEXT: ret i32 [[COND1]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]]
+; CHECK-NEXT: ret i32 [[COND]]
;
%cmp = icmp sgt i32 %x, -1
%sub = sub nsw i32 0, %x
@@ -949,8 +949,8 @@ define i32 @nabs_abs_x10(i32 %x) {
; CHECK-LABEL: @nabs_abs_x10(
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X]]
-; CHECK-NEXT: [[COND1:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]]
-; CHECK-NEXT: ret i32 [[COND1]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]]
+; CHECK-NEXT: ret i32 [[COND]]
;
%cmp = icmp sgt i32 %x, 0
%sub = sub nsw i32 0, %x
@@ -965,8 +965,8 @@ define i32 @nabs_abs_x11(i32 %x) {
; CHECK-LABEL: @nabs_abs_x11(
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X]]
-; CHECK-NEXT: [[COND1:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]]
-; CHECK-NEXT: ret i32 [[COND1]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]]
+; CHECK-NEXT: ret i32 [[COND]]
;
%cmp = icmp slt i32 %x, 0
%sub = sub nsw i32 0, %x
@@ -981,8 +981,8 @@ define i32 @nabs_abs_x12(i32 %x) {
; CHECK-LABEL: @nabs_abs_x12(
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X]]
-; CHECK-NEXT: [[COND1:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]]
-; CHECK-NEXT: ret i32 [[COND1]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]]
+; CHECK-NEXT: ret i32 [[COND]]
;
%cmp = icmp slt i32 %x, 1
%sub = sub nsw i32 0, %x
OpenPOWER on IntegriCloud