From: Dinesh Dwivedi Date: Mon, 2 Jun 2014 07:57:24 +0000 (+0000) Subject: Added inst combine tarnsform for (1 << X) & C pattrens where C is (some PowerOf2... X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ce5d35a9d0a6d72850c4bed564f5d16e9d4d9863;p=platform%2Fupstream%2Fllvm.git Added inst combine tarnsform for (1 << X) & C pattrens where C is (some 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 --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 79cd1fb..3d90a37 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -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; @@ -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, @@ -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; @@ -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, diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index fd7514d..dcfff99 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -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 @@ -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