Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,17 @@ static void computeKnownBitsFromLerpPattern(const Value *Op0, const Value *Op1,
KnownOut.Zero.setHighBits(MinimumNumberOfLeadingZeros);
}

static bool isKnownNonNegativeFromMin(const Value *Op0, const Value *Op1) {

Value *V;

if (match(Op1, m_SMin(m_Specific(Op0), m_Value(V))) ||
match(Op1, m_SMin(m_Value(V), m_Specific(Op0))))
return true;

return false;
}

static void computeKnownBitsAddSub(bool Add, const Value *Op0, const Value *Op1,
bool NSW, bool NUW,
const APInt &DemandedElts,
Expand All @@ -499,8 +510,9 @@ static void computeKnownBitsAddSub(bool Add, const Value *Op0, const Value *Op1,
KnownOut = KnownBits::computeForAddSub(Add, NSW, NUW, Known2, KnownOut);

if (!Add && NSW && !KnownOut.isNonNegative() &&
isImpliedByDomCondition(ICmpInst::ICMP_SLE, Op1, Op0, Q.CxtI, Q.DL)
.value_or(false))
(isImpliedByDomCondition(ICmpInst::ICMP_SLE, Op1, Op0, Q.CxtI, Q.DL)
.value_or(false) ||
isKnownNonNegativeFromMin(Op0, Op1)))
Comment thread
user1342234 marked this conversation as resolved.
Outdated
KnownOut.makeNonNegative();

if (Add)
Expand Down
51 changes: 51 additions & 0 deletions llvm/test/Transforms/InstCombine/sext-nonneg-sub.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

; Test that b - smin(b, a) is recognized as non-negative
define i64 @func1(i32 %a, i32 %b) {
; CHECK-LABEL: define i64 @func1(
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = tail call i32 @llvm.smin.i32(i32 [[B]], i32 [[A]])
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[B]], [[SPEC_SELECT]]
; CHECK-NEXT: [[CONV:%.*]] = zext nneg i32 [[SUB]] to i64
; CHECK-NEXT: ret i64 [[CONV]]
;
entry:
%spec.select = tail call i32 @llvm.smin.i32(i32 %b, i32 %a)
%sub = sub nsw i32 %b, %spec.select
%conv = sext i32 %sub to i64
ret i64 %conv
}

; Test commutative smin pattern: a - smin(a, b) should also optimize
Comment thread
user1342234 marked this conversation as resolved.
Outdated
define i64 @smin_commutative(i32 %a, i32 %b) {
; CHECK-LABEL: define i64 @smin_commutative(
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[A]], i32 [[B]])
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], [[MIN]]
; CHECK-NEXT: [[EXT:%.*]] = zext nneg i32 [[SUB]] to i64
; CHECK-NEXT: ret i64 [[EXT]]
;
%min = call i32 @llvm.smin.i32(i32 %a, i32 %b)
%sub = sub nsw i32 %a, %min
%ext = sext i32 %sub to i64
ret i64 %ext
}


Comment thread
user1342234 marked this conversation as resolved.
; NEGATIVE TEST: unguarded subtraction should NOT optimize
define i64 @neg_unguarded_sub(i32 %a, i32 %b) {
; CHECK-LABEL: define i64 @neg_unguarded_sub(
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[B]], [[A]]
; CHECK-NEXT: [[EXT:%.*]] = sext i32 [[SUB]] to i64
; CHECK-NEXT: ret i64 [[EXT]]
;
%sub = sub nsw i32 %b, %a
%ext = sext i32 %sub to i64
ret i64 %ext
}


declare i32 @llvm.smin.i32(i32, i32)
Comment thread
user1342234 marked this conversation as resolved.
Outdated
Loading