From b0765d6ac0140718cd8d5b896504fd89ce0594d2 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sun, 12 Jun 2011 22:48:00 +0000 Subject: [PATCH] InstCombine: Shrink ((zext X) & C1) == C2 to fold away the cast if the "zext" and the "and" have one use. llvm-svn: 132897 --- .../InstCombine/InstCombineCompares.cpp | 18 +++++++++++++++++- test/Transforms/InstCombine/icmp.ll | 10 ++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 92cbc1b7f18..5ddf23ba8e1 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1097,7 +1097,23 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, ConstantExpr::getZExt(RHS, Cast->getSrcTy())); } } - + + // If the LHS is an AND of a zext, and we have an equality compare, we can + // shrink the and/compare to the smaller type, eliminating the cast. + if (ZExtInst *Cast = dyn_cast(LHSI->getOperand(0))) { + const IntegerType *Ty = cast(Cast->getSrcTy()); + // Make sure we don't compare the upper bits, SimplifyDemandedBits + // should fold the icmp to true/false in that case. + if (ICI.isEquality() && RHSV.getActiveBits() <= Ty->getBitWidth()) { + Value *NewAnd = + Builder->CreateAnd(Cast->getOperand(0), + ConstantExpr::getTrunc(AndCST, Ty)); + NewAnd->takeName(LHSI); + return new ICmpInst(ICI.getPredicate(), NewAnd, + ConstantExpr::getTrunc(RHS, Ty)); + } + } + // If this is: (X >> C1) & C2 != C3 (where any shift and any compare // could exist), turn it into (X & (C2 << C1)) != (C3 << C1). This // happens a LOT in code produced by the C front-end, for bitfield diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index 1237adee74d..ecbba23091c 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -521,3 +521,13 @@ define i1 @test53(i32 %a, i32 %b) nounwind { %z = icmp eq i32 %x, %y ret i1 %z } + +; CHECK: @test54 +; CHECK-NEXT: %and = and i8 %a, -64 +; CHECK-NEXT icmp eq i8 %and, -128 +define i1 @test54(i8 %a) nounwind { + %ext = zext i8 %a to i32 + %and = and i32 %ext, 192 + %ret = icmp eq i32 %and, 128 + ret i1 %ret +}