From 8f77dcadffe06502027bdb2701cd3653ecca919b Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 25 May 2018 19:18:09 +0000 Subject: [PATCH] Recommit r333226 "[ValueTracking] Teach computeKnownBits that the result of an absolute value pattern that uses nsw flag is always positive." Libfuzzer tests have been fixed to prevent being optimized. Original commit message: If the nsw flag is used in the absolute value then it is undefined for INT_MIN. For all other value it will produce a positive number. So we can assume the result is positive. This breaks some InstCombine abs/nabs combining tests because we simplify the second compare from known bits rather than as the whole pattern. Looks like we can probably fix it by adding a neg+abs/nabs combine to just swap the select operands. N Differential Revision: https://reviews.llvm.org/D47041 llvm-svn: 333300 --- llvm/lib/Analysis/ValueTracking.cpp | 6 ++++++ llvm/test/Transforms/InstCombine/abs-1.ll | 11 +++++++++++ llvm/test/Transforms/InstCombine/abs_abs.ll | 16 ++++++++-------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 7f33c67b8ab8..5f5d1be9baa8 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(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 2a94001b69d1..ee6b6674c0bb 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 a48c33e72778..5985d6054667 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