InstSimplify: Compute comparison ranges for left shift instructions

'shl nuw CI, x' produces [CI, CI << CLZ(CI)]
'shl nsw CI, x' produces [CI << CLO(CI)-1, CI] if CI is negative
'shl nsw CI, x' produces [CI, CI << CLZ(CI)-1] if CI is non-negative

llvm-svn: 216570
This commit is contained in:
David Majnemer 2014-08-27 18:03:46 +00:00
parent 74a46c24f3
commit d6d1671c1e
2 changed files with 43 additions and 0 deletions

View File

@ -1993,6 +1993,22 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
Upper = Upper + 1;
assert(Upper != Lower && "Upper part of range has wrapped!");
}
} else if (match(LHS, m_NUWShl(m_ConstantInt(CI2), m_Value()))) {
// 'shl nuw CI2, x' produces [CI2, CI2 << CLZ(CI2)]
Lower = CI2->getValue();
Upper = Lower.shl(Lower.countLeadingZeros()) + 1;
} else if (match(LHS, m_NSWShl(m_ConstantInt(CI2), m_Value()))) {
if (CI2->isNegative()) {
// 'shl nsw CI2, x' produces [CI2 << CLO(CI2)-1, CI2]
unsigned ShiftAmount = CI2->getValue().countLeadingOnes() - 1;
Lower = CI2->getValue().shl(ShiftAmount);
Upper = CI2->getValue() + 1;
} else {
// 'shl nsw CI2, x' produces [CI2, CI2 << CLZ(CI2)-1]
unsigned ShiftAmount = CI2->getValue().countLeadingZeros() - 1;
Lower = CI2->getValue();
Upper = CI2->getValue().shl(ShiftAmount) + 1;
}
} else if (match(LHS, m_LShr(m_Value(), m_ConstantInt(CI2)))) {
// 'lshr x, CI2' produces [0, UINT_MAX >> CI2].
APInt NegOne = APInt::getAllOnesValue(Width);

View File

@ -982,3 +982,30 @@ define i1 @icmp_known_bits(i4 %x, i4 %y) {
; CHECK-LABEL: @icmp_known_bits
; CHECK-NEXT: ret i1 false
}
define i1 @icmp_shl_nuw_1(i64 %a) {
%shl = shl nuw i64 1, %a
%cmp = icmp ne i64 %shl, 0
ret i1 %cmp
; CHECK-LABEL: @icmp_shl_nuw_1
; CHECK-NEXT: ret i1 true
}
define i1 @icmp_shl_nsw_neg1(i64 %a) {
%shl = shl nsw i64 -1, %a
%cmp = icmp sge i64 %shl, 3
ret i1 %cmp
; CHECK-LABEL: @icmp_shl_nsw_neg1
; CHECK-NEXT: ret i1 false
}
define i1 @icmp_shl_nsw_1(i64 %a) {
%shl = shl nsw i64 1, %a
%cmp = icmp sge i64 %shl, 0
ret i1 %cmp
; CHECK-LABEL: @icmp_shl_nsw_1
; CHECK-NEXT: ret i1 true
}