Skip to content

Commit 24f5235

Browse files
committed
[ValueTracking] Add basic computeKnownBits support for llvm.abs intrinsic
This includes basic support for computeKnownBits on abs. I've left FIXMEs for more complicated things we could do. Differential Revision: https://reviews.llvm.org/D84963
1 parent 896f797 commit 24f5235

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

llvm/lib/Analysis/ValueTracking.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,17 @@ static void computeKnownBitsFromOperator(const Operator *I,
16421642
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
16431643
switch (II->getIntrinsicID()) {
16441644
default: break;
1645+
case Intrinsic::abs:
1646+
computeKnownBits(I->getOperand(0), Known2, Depth + 1, Q);
1647+
// Otherwise, if this call is undefined for INT_MIN, the result is
1648+
// positive.
1649+
if (match(II->getArgOperand(1), m_One()))
1650+
Known.Zero.setSignBit();
1651+
// Absolute value preserves trailing zero count.
1652+
Known.Zero.setLowBits(Known2.Zero.countTrailingOnes());
1653+
// FIXME: Handle known negative/non-negative input?
1654+
// FIXME: Calculate the negated Known bits and combine them?
1655+
break;
16451656
case Intrinsic::bitreverse:
16461657
computeKnownBits(I->getOperand(0), DemandedElts, Known2, Depth + 1, Q);
16471658
Known.Zero |= Known2.Zero.reverseBits();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -instcombine -S | FileCheck %s
3+
4+
declare i32 @llvm.abs.i32(i32, i1)
5+
6+
define i1 @abs_nsw_must_be_positive(i32 %x) {
7+
; CHECK-LABEL: @abs_nsw_must_be_positive(
8+
; CHECK-NEXT: ret i1 true
9+
;
10+
%abs = call i32 @llvm.abs.i32(i32 %x, i1 true)
11+
%c2 = icmp sge i32 %abs, 0
12+
ret i1 %c2
13+
}
14+
15+
; Negative test, no nsw provides no information about the sign bit of the result.
16+
define i1 @abs_nonsw(i32 %x) {
17+
; CHECK-LABEL: @abs_nonsw(
18+
; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
19+
; CHECK-NEXT: [[C2:%.*]] = icmp sgt i32 [[ABS]], -1
20+
; CHECK-NEXT: ret i1 [[C2]]
21+
;
22+
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
23+
%c2 = icmp sge i32 %abs, 0
24+
ret i1 %c2
25+
}
26+
27+
; abs preserves trailing zeros so the second and is unneeded
28+
define i32 @abs_trailing_zeros(i32 %x) {
29+
; CHECK-LABEL: @abs_trailing_zeros(
30+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], -4
31+
; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[AND]], i1 false)
32+
; CHECK-NEXT: ret i32 [[ABS]]
33+
;
34+
%and = and i32 %x, -4
35+
%abs = call i32 @llvm.abs.i32(i32 %and, i1 false)
36+
%and2 = and i32 %abs, -2
37+
ret i32 %and2
38+
}
39+
40+
; negative test, can't remove the second and based on trailing zeroes.
41+
; FIXME: Could remove the first and using demanded bits.
42+
define i32 @abs_trailing_zeros_negative(i32 %x) {
43+
; CHECK-LABEL: @abs_trailing_zeros_negative(
44+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], -2
45+
; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[AND]], i1 false)
46+
; CHECK-NEXT: [[AND2:%.*]] = and i32 [[ABS]], -4
47+
; CHECK-NEXT: ret i32 [[AND2]]
48+
;
49+
%and = and i32 %x, -2
50+
%abs = call i32 @llvm.abs.i32(i32 %and, i1 false)
51+
%and2 = and i32 %abs, -4
52+
ret i32 %and2
53+
}

0 commit comments

Comments
 (0)