Skip to content

Commit

Permalink
Added inst combine tarnsform for (1 << X) & C pattrens where C is (so…
Browse files Browse the repository at this point in the history
…me PowerOf2 - 1)

This patch can handles following cases from http://nondot.org/sabre/LLVMNotes/InstCombine.txt
  "((1 << X) & 7) == 0" ==> "X > 2"
  "((1 << X) & 7) != 0" ==> "X < 3".

Differential Revision: http://reviews.llvm.org/D3678

llvm-svn: 210007
  • Loading branch information
dkdwivedi committed Jun 2, 2014
1 parent 43e127b commit ce5d35a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
32 changes: 24 additions & 8 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Expand Up @@ -2540,7 +2540,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// bit is set. If the comparison is against zero, then this is a check
// to see if *that* bit is set.
APInt Op0KnownZeroInverted = ~Op0KnownZero;
if (~Op1KnownZero == 0 && Op0KnownZeroInverted.isPowerOf2()) {
if (~Op1KnownZero == 0) {
// If the LHS is an AND with the same constant, look through it.
Value *LHS = nullptr;
ConstantInt *LHSC = nullptr;
Expand All @@ -2550,11 +2550,19 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {

// If the LHS is 1 << x, and we know the result is a power of 2 like 8,
// then turn "((1 << x)&8) == 0" into "x != 3".
// or turn "((1 << x)&7) == 0" into "x > 2".
Value *X = nullptr;
if (match(LHS, m_Shl(m_One(), m_Value(X)))) {
unsigned CmpVal = Op0KnownZeroInverted.countTrailingZeros();
return new ICmpInst(ICmpInst::ICMP_NE, X,
ConstantInt::get(X->getType(), CmpVal));
APInt ValToCheck = Op0KnownZeroInverted;
if (ValToCheck.isPowerOf2()) {
unsigned CmpVal = ValToCheck.countTrailingZeros();
return new ICmpInst(ICmpInst::ICMP_NE, X,
ConstantInt::get(X->getType(), CmpVal));
} else if ((++ValToCheck).isPowerOf2()) {
unsigned CmpVal = ValToCheck.countTrailingZeros() - 1;
return new ICmpInst(ICmpInst::ICMP_UGT, X,
ConstantInt::get(X->getType(), CmpVal));
}
}

// If the LHS is 8 >>u x, and we know the result is a power of 2 like 1,
Expand All @@ -2577,7 +2585,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// bit is set. If the comparison is against zero, then this is a check
// to see if *that* bit is set.
APInt Op0KnownZeroInverted = ~Op0KnownZero;
if (~Op1KnownZero == 0 && Op0KnownZeroInverted.isPowerOf2()) {
if (~Op1KnownZero == 0) {
// If the LHS is an AND with the same constant, look through it.
Value *LHS = nullptr;
ConstantInt *LHSC = nullptr;
Expand All @@ -2587,11 +2595,19 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {

// If the LHS is 1 << x, and we know the result is a power of 2 like 8,
// then turn "((1 << x)&8) != 0" into "x == 3".
// or turn "((1 << x)&7) != 0" into "x < 3".
Value *X = nullptr;
if (match(LHS, m_Shl(m_One(), m_Value(X)))) {
unsigned CmpVal = Op0KnownZeroInverted.countTrailingZeros();
return new ICmpInst(ICmpInst::ICMP_EQ, X,
ConstantInt::get(X->getType(), CmpVal));
APInt ValToCheck = Op0KnownZeroInverted;
if (ValToCheck.isPowerOf2()) {
unsigned CmpVal = ValToCheck.countTrailingZeros();
return new ICmpInst(ICmpInst::ICMP_EQ, X,
ConstantInt::get(X->getType(), CmpVal));
} else if ((++ValToCheck).isPowerOf2()) {
unsigned CmpVal = ValToCheck.countTrailingZeros();
return new ICmpInst(ICmpInst::ICMP_ULT, X,
ConstantInt::get(X->getType(), CmpVal));
}
}

// If the LHS is 8 >>u x, and we know the result is a power of 2 like 1,
Expand Down
17 changes: 17 additions & 0 deletions llvm/test/Transforms/InstCombine/icmp.ll
Expand Up @@ -166,6 +166,14 @@ define i1 @test17(i32 %x) nounwind {
; CHECK-NEXT: %cmp = icmp ne i32 %x, 3
}

define i1 @test17a(i32 %x) nounwind {
%shl = shl i32 1, %x
%and = and i32 %shl, 7
%cmp = icmp eq i32 %and, 0
ret i1 %cmp
; CHECK-LABEL: @test17a(
; CHECK-NEXT: %cmp = icmp ugt i32 %x, 2
}

define i1 @test18(i32 %x) nounwind {
%sh = lshr i32 8, %x
Expand Down Expand Up @@ -194,6 +202,15 @@ define i1 @test20(i32 %x) nounwind {
; CHECK-NEXT: %cmp = icmp eq i32 %x, 3
}

define i1 @test20a(i32 %x) nounwind {
%shl = shl i32 1, %x
%and = and i32 %shl, 7
%cmp = icmp ne i32 %and, 0
ret i1 %cmp
; CHECK-LABEL: @test20a(
; CHECK-NEXT: %cmp = icmp ult i32 %x, 3
}

define i1 @test21(i8 %x, i8 %y) {
; CHECK-LABEL: @test21(
; CHECK-NOT: or i8
Expand Down

0 comments on commit ce5d35a

Please sign in to comment.