From a80d668215be2b9a0f564d85d0506e6a3dbe7ba2 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 9 Jan 2009 07:47:06 +0000 Subject: [PATCH] Implement rdar://6480391, extending of equality icmp's to avoid a truncation. I noticed this in the code compiled for a routine using std::map, which produced this code: %25 = tail call i32 @memcmp(i8* %24, i8* %23, i32 6) nounwind readonly %.lobit.i = lshr i32 %25, 31 ; [#uses=1] %tmp.i = trunc i32 %.lobit.i to i8 ; [#uses=1] %toBool = icmp eq i8 %tmp.i, 0 ; [#uses=1] br i1 %toBool, label %bb3, label %bb4 which compiled to: call L_memcmp$stub shrl $31, %eax testb %al, %al jne LBB1_11 ## with this change, we compile it to: call L_memcmp$stub testl %eax, %eax js LBB1_11 This triggers all the time in common code, with patters like this: %169 = and i32 %ply, 1 ; [#uses=1] %170 = trunc i32 %169 to i8 ; [#uses=1] %toBool = icmp ne i8 %170, 0 ; [#uses=1] %7 = lshr i32 %6, 24 ; [#uses=1] %9 = trunc i32 %7 to i8 ; [#uses=1] %10 = icmp ne i8 %9, 0 ; [#uses=1] etc git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61985 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 22 +++++++++++++++++++ test/Transforms/InstCombine/cast.ll | 22 ++++++++++++++++--- test/Transforms/InstCombine/icmp.ll | 1 - 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index f59874b1a5a..c1a8eab95b5 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -6343,6 +6343,28 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, const APInt &RHSV = RHS->getValue(); switch (LHSI->getOpcode()) { + case Instruction::Trunc: + if (ICI.isEquality() && LHSI->hasOneUse()) { + // Simplify icmp eq (trunc x to i8), 42 -> icmp eq x, 42|highbits if all + // of the high bits truncated out of x are known. + unsigned DstBits = LHSI->getType()->getPrimitiveSizeInBits(), + SrcBits = LHSI->getOperand(0)->getType()->getPrimitiveSizeInBits(); + APInt Mask(APInt::getHighBitsSet(SrcBits, SrcBits-DstBits)); + APInt KnownZero(SrcBits, 0), KnownOne(SrcBits, 0); + ComputeMaskedBits(LHSI->getOperand(0), Mask, KnownZero, KnownOne); + + // If all the high bits are known, we can do this xform. + if ((KnownZero|KnownOne).countLeadingOnes() >= SrcBits-DstBits) { + // Pull in the high bits from known-ones set. + APInt NewRHS(RHS->getValue()); + NewRHS.zext(SrcBits); + NewRHS |= KnownOne; + return new ICmpInst(ICI.getPredicate(), LHSI->getOperand(0), + ConstantInt::get(NewRHS)); + } + } + break; + case Instruction::Xor: // (icmp pred (xor X, XorCST), CI) if (ConstantInt *XorCST = dyn_cast(LHSI->getOperand(1))) { // If this is a comparison that tests the signbit (X < 0) or (x > -1), diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index dc5e92800f4..9361ff24e9b 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -1,7 +1,5 @@ ; Tests to make sure elimination of casts is working correctly -; RUN: llvm-as < %s | opt -instcombine | llvm-dis | \ -; RUN: grep %c | notcast -; END. +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep %c | notcast @inbuf = external global [32832 x i8] ; <[32832 x i8]*> [#uses=1] @@ -238,3 +236,21 @@ define i16 @test35(i16 %a) { ret i16 %c2 } +; icmp sgt i32 %a, -1 +; rdar://6480391 +define i1 @test36(i32 %a) { + %b = lshr i32 %a, 31 + %c = trunc i32 %b to i8 + %d = icmp eq i8 %c, 0 + ret i1 %d +} + +; ret i1 false +define i1 @test37(i32 %a) { + %b = lshr i32 %a, 31 + %c = or i32 %b, 512 + %d = trunc i32 %c to i8 + %e = icmp eq i8 %d, 11 + ret i1 %e +} + diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index bb69ba3be47..27136d69438 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -1,5 +1,4 @@ ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep icmp -; END. define i32 @test1(i32 %X) { entry: