mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 02:52:53 +02:00
[ValueTracking] Use KnownOnes to provide a better bound on known zeros for ctlz/cttz intrinics
This patch uses KnownOnes of the input of ctlz/cttz to bound the value that can be returned from these intrinsics. This makes these intrinsics more similar to the handling for ctpop which already uses known bits to produce a similar bound. Differential Revision: https://reviews.llvm.org/D32521 llvm-svn: 302444
This commit is contained in:
parent
f8aa5f043e
commit
dc461c9a16
@ -1392,12 +1392,25 @@ static void computeKnownBitsFromOperator(const Operator *I, KnownBits &Known,
|
||||
Known.Zero |= Known2.Zero.byteSwap();
|
||||
Known.One |= Known2.One.byteSwap();
|
||||
break;
|
||||
case Intrinsic::ctlz:
|
||||
case Intrinsic::cttz: {
|
||||
unsigned LowBits = Log2_32(BitWidth)+1;
|
||||
case Intrinsic::ctlz: {
|
||||
computeKnownBits(I->getOperand(0), Known2, Depth + 1, Q);
|
||||
// If we have a known 1, its position is our upper bound.
|
||||
unsigned PossibleLZ = Known2.One.countLeadingZeros();
|
||||
// If this call is undefined for 0, the result will be less than 2^n.
|
||||
if (II->getArgOperand(1) == ConstantInt::getTrue(II->getContext()))
|
||||
LowBits -= 1;
|
||||
PossibleLZ = std::min(PossibleLZ, BitWidth - 1);
|
||||
unsigned LowBits = Log2_32(PossibleLZ)+1;
|
||||
Known.Zero.setBitsFrom(LowBits);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::cttz: {
|
||||
computeKnownBits(I->getOperand(0), Known2, Depth + 1, Q);
|
||||
// If we have a known 1, its position is our upper bound.
|
||||
unsigned PossibleTZ = Known2.One.countTrailingZeros();
|
||||
// If this call is undefined for 0, the result will be less than 2^n.
|
||||
if (II->getArgOperand(1) == ConstantInt::getTrue(II->getContext()))
|
||||
PossibleTZ = std::min(PossibleTZ, BitWidth - 1);
|
||||
unsigned LowBits = Log2_32(PossibleTZ)+1;
|
||||
Known.Zero.setBitsFrom(LowBits);
|
||||
break;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -instcombine -S < %s | FileCheck %s
|
||||
|
||||
%overflow.result = type {i8, i1}
|
||||
@ -283,10 +284,7 @@ define i32 @cttz(i32 %a) {
|
||||
|
||||
define i1 @cttz_knownbits(i32 %arg) {
|
||||
; CHECK-LABEL: @cttz_knownbits(
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i32 [[ARG:%.*]], 4
|
||||
; CHECK-NEXT: [[CNT:%.*]] = call i32 @llvm.cttz.i32(i32 [[OR]], i1 true)
|
||||
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[CNT]], 4
|
||||
; CHECK-NEXT: ret i1 [[RES]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%or = or i32 %arg, 4
|
||||
%cnt = call i32 @llvm.cttz.i32(i32 %or, i1 true) nounwind readnone
|
||||
@ -294,6 +292,19 @@ define i1 @cttz_knownbits(i32 %arg) {
|
||||
ret i1 %res
|
||||
}
|
||||
|
||||
define i1 @cttz_knownbits2(i32 %arg) {
|
||||
; CHECK-LABEL: @cttz_knownbits2(
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i32 [[ARG:%.*]], 4
|
||||
; CHECK-NEXT: [[CNT:%.*]] = call i32 @llvm.cttz.i32(i32 [[OR]], i1 true)
|
||||
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[CNT]], 2
|
||||
; CHECK-NEXT: ret i1 [[RES]]
|
||||
;
|
||||
%or = or i32 %arg, 4
|
||||
%cnt = call i32 @llvm.cttz.i32(i32 %or, i1 true) nounwind readnone
|
||||
%res = icmp eq i32 %cnt, 2
|
||||
ret i1 %res
|
||||
}
|
||||
|
||||
define i8 @ctlz(i8 %a) {
|
||||
; CHECK-LABEL: @ctlz(
|
||||
; CHECK-NEXT: ret i8 2
|
||||
@ -306,10 +317,7 @@ define i8 @ctlz(i8 %a) {
|
||||
|
||||
define i1 @ctlz_knownbits(i8 %arg) {
|
||||
; CHECK-LABEL: @ctlz_knownbits(
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i8 [[ARG:%.*]], 32
|
||||
; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctlz.i8(i8 [[OR]], i1 true)
|
||||
; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[CNT]], 4
|
||||
; CHECK-NEXT: ret i1 [[RES]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%or = or i8 %arg, 32
|
||||
%cnt = call i8 @llvm.ctlz.i8(i8 %or, i1 true) nounwind readnone
|
||||
@ -317,6 +325,19 @@ define i1 @ctlz_knownbits(i8 %arg) {
|
||||
ret i1 %res
|
||||
}
|
||||
|
||||
define i1 @ctlz_knownbits2(i8 %arg) {
|
||||
; CHECK-LABEL: @ctlz_knownbits2(
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i8 [[ARG:%.*]], 32
|
||||
; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctlz.i8(i8 [[OR]], i1 true)
|
||||
; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[CNT]], 2
|
||||
; CHECK-NEXT: ret i1 [[RES]]
|
||||
;
|
||||
%or = or i8 %arg, 32
|
||||
%cnt = call i8 @llvm.ctlz.i8(i8 %or, i1 true) nounwind readnone
|
||||
%res = icmp eq i8 %cnt, 2
|
||||
ret i1 %res
|
||||
}
|
||||
|
||||
define void @cmp.simplify(i32 %a, i32 %b, i1* %c) {
|
||||
%lz = tail call i32 @llvm.ctlz.i32(i32 %a, i1 false) nounwind readnone
|
||||
%lz.cmp = icmp eq i32 %lz, 32
|
||||
|
Loading…
Reference in New Issue
Block a user