[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