[llvm] r245171 - [InstCombine] Replace an and+icmp with a trunc+icmp
David Majnemer via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 16 00:09:18 PDT 2015
Author: majnemer
Date: Sun Aug 16 02:09:17 2015
New Revision: 245171
URL: http://llvm.org/viewvc/llvm-project?rev=245171&view=rev
Log:
[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.
Modified:
llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/trunk/test/Transforms/InstCombine/and-compare.ll
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=245171&r1=245170&r2=245171&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Sun Aug 16 02:09:17 2015
@@ -1447,6 +1447,23 @@ Instruction *InstCombiner::visitICmpInst
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<ConstantInt>(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: {
Modified: llvm/trunk/test/Transforms/InstCombine/and-compare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/and-compare.ll?rev=245171&r1=245170&r2=245171&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/and-compare.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/and-compare.ll Sun Aug 16 02:09:17 2015
@@ -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 ; <i1> [#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
+}
More information about the llvm-commits
mailing list