From: David Majnemer Date: Sun, 16 Aug 2015 07:09:17 +0000 (+0000) Subject: [InstCombine] Replace an and+icmp with a trunc+icmp X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2363b41211d441306afa9d21555b6d73fa930425;p=oota-llvm.git [InstCombine] Replace an and+icmp with a trunc+icmp Bitwise arithmetic can obscure a simple sign-test. If replacing the mask with a truncate is preferable if the type is legal because it permits us to rephrase the comparison more explicitly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245171 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 95bba3c7af7..9ce1c3fc41b 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1447,6 +1447,23 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, ICI.getPredicate() == ICmpInst::ICMP_EQ ? ICmpInst::ICMP_UGT : ICmpInst::ICMP_ULE, LHSI->getOperand(0), SubOne(RHS)); + + // (icmp eq (and %A, C), 0) -> (icmp sgt (trunc %A), -1) + // iff C is a power of 2 + if (ICI.isEquality() && LHSI->hasOneUse() && match(RHS, m_Zero())) { + if (auto *CI = dyn_cast(LHSI->getOperand(1))) { + const APInt &AI = CI->getValue(); + int32_t ExactLogBase2 = AI.exactLogBase2(); + if (ExactLogBase2 != -1 && DL.isLegalInteger(ExactLogBase2 + 1)) { + Type *NTy = IntegerType::get(ICI.getContext(), ExactLogBase2 + 1); + Value *Trunc = Builder->CreateTrunc(LHSI->getOperand(0), NTy); + return new ICmpInst(ICI.getPredicate() == ICmpInst::ICMP_EQ + ? ICmpInst::ICMP_SGE + : ICmpInst::ICMP_SLT, + Trunc, Constant::getNullValue(NTy)); + } + } + } break; case Instruction::Or: { diff --git a/test/Transforms/InstCombine/and-compare.ll b/test/Transforms/InstCombine/and-compare.ll index 037641b90ad..53ea81d1c0d 100644 --- a/test/Transforms/InstCombine/and-compare.ll +++ b/test/Transforms/InstCombine/and-compare.ll @@ -1,6 +1,9 @@ ; RUN: opt < %s -instcombine -S | \ ; RUN: FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + ; Should be optimized to one and. define i1 @test1(i32 %a, i32 %b) { ; CHECK-LABEL: @test1( @@ -13,3 +16,23 @@ define i1 @test1(i32 %a, i32 %b) { %tmp = icmp ne i32 %tmp1, %tmp3 ; [#uses=1] ret i1 %tmp } + +define zeroext i1 @test2(i64 %A) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: %[[trunc:.*]] = trunc i64 %A to i8 +; CHECK-NEXT: %[[icmp:.*]] = icmp sgt i8 %[[trunc]], -1 +; CHECK-NEXT: ret i1 %[[icmp]] + %and = and i64 %A, 128 + %cmp = icmp eq i64 %and, 0 + ret i1 %cmp +} + +define zeroext i1 @test3(i64 %A) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: %[[trunc:.*]] = trunc i64 %A to i8 +; CHECK-NEXT: %[[icmp:.*]] = icmp slt i8 %[[trunc]], 0 +; CHECK-NEXT: ret i1 %[[icmp]] + %and = and i64 %A, 128 + %cmp = icmp ne i64 %and, 0 + ret i1 %cmp +}