diff options
author | Chris Lattner <sabre@nondot.org> | 2010-01-05 18:09:56 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-01-05 18:09:56 +0000 |
commit | 033574074d3c980057a0cb989d272ec72a8f9523 (patch) | |
tree | da014c262456114da3d4259f2bd4509515327f17 | |
parent | aceba31b7a04fd28680209b2677915378877bc13 (diff) | |
download | external_llvm-033574074d3c980057a0cb989d272ec72a8f9523.zip external_llvm-033574074d3c980057a0cb989d272ec72a8f9523.tar.gz external_llvm-033574074d3c980057a0cb989d272ec72a8f9523.tar.bz2 |
optimize comparisons against cttz/ctlz/ctpop, patch by Alastair Lynn!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@92745 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineCompares.cpp | 24 | ||||
-rw-r--r-- | test/Transforms/InstCombine/intrinsics.ll | 30 |
2 files changed, 49 insertions, 5 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 90ab4f4..abbc89b 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1418,11 +1418,33 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, } } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(LHSI)) { // Handle icmp {eq|ne} <intrinsic>, intcst. - if (II->getIntrinsicID() == Intrinsic::bswap) { + switch (II->getIntrinsicID()) { + case Intrinsic::bswap: Worklist.Add(II); ICI.setOperand(0, II->getOperand(1)); ICI.setOperand(1, ConstantInt::get(II->getContext(), RHSV.byteSwap())); return &ICI; + case Intrinsic::ctlz: + case Intrinsic::cttz: + // ctz(A) == bitwidth(a) -> A == 0 and likewise for != + if (RHSV == RHS->getType()->getBitWidth()) { + Worklist.Add(II); + ICI.setOperand(0, II->getOperand(1)); + ICI.setOperand(1, ConstantInt::get(RHS->getType(), 0)); + return &ICI; + } + break; + case Intrinsic::ctpop: + // popcount(A) == 0 -> A == 0 and likewise for != + if (RHS->isZero()) { + Worklist.Add(II); + ICI.setOperand(0, II->getOperand(1)); + ICI.setOperand(1, RHS); + return &ICI; + } + break; + default: + break; } } } diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index f899fc0..c63475c 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/test/Transforms/InstCombine/intrinsics.ll @@ -6,6 +6,8 @@ declare %overflow.result @llvm.uadd.with.overflow.i8(i8, i8) declare %overflow.result @llvm.umul.with.overflow.i8(i8, i8) declare double @llvm.powi.f64(double, i32) nounwind readonly declare i32 @llvm.cttz.i32(i32) nounwind readnone +declare i32 @llvm.ctlz.i32(i32) nounwind readnone +declare i32 @llvm.ctpop.i32(i32) nounwind readnone declare i8 @llvm.ctlz.i8(i8) nounwind readnone define i8 @test1(i8 %A, i8 %B) { @@ -99,8 +101,7 @@ entry: ; CHECK: volatile store double %V } -define i32 @cttz(i32 %a) -{ +define i32 @cttz(i32 %a) { entry: %or = or i32 %a, 8 %and = and i32 %or, -8 @@ -111,8 +112,7 @@ entry: ; CHECK-NEXT: ret i32 3 } -define i8 @ctlz(i8 %a) -{ +define i8 @ctlz(i8 %a) { entry: %or = or i8 %a, 32 %and = and i8 %or, 63 @@ -122,3 +122,25 @@ entry: ; CHECK-NEXT: entry: ; CHECK-NEXT: ret i8 2 } + +define void @cmp.simplify(i32 %a, i32 %b, i1* %c) { +entry: + %lz = tail call i32 @llvm.ctlz.i32(i32 %a) nounwind readnone + %lz.cmp = icmp eq i32 %lz, 32 + volatile store i1 %lz.cmp, i1* %c + %tz = tail call i32 @llvm.cttz.i32(i32 %a) nounwind readnone + %tz.cmp = icmp ne i32 %tz, 32 + volatile store i1 %tz.cmp, i1* %c + %pop = tail call i32 @llvm.ctpop.i32(i32 %b) nounwind readnone + %pop.cmp = icmp eq i32 %pop, 0 + volatile store i1 %pop.cmp, i1* %c + ret void +; CHECK: @cmp.simplify +; CHECK-NEXT: entry: +; CHECK-NEXT: %lz.cmp = icmp eq i32 %a, 0 +; CHECK-NEXT: volatile store i1 %lz.cmp, i1* %c +; CHECK-NEXT: %tz.cmp = icmp ne i32 %a, 0 +; CHECK-NEXT: volatile store i1 %tz.cmp, i1* %c +; CHECK-NEXT: %pop.cmp = icmp eq i32 %b, 0 +; CHECK-NEXT: volatile store i1 %pop.cmp, i1* %c +} |