From: David Majnemer Date: Tue, 9 Jul 2013 07:50:59 +0000 (+0000) Subject: InstCombine: add more transforms X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=377a5c1a87b879b7a05a635ed7bbf125b0b61e28;p=oota-llvm.git InstCombine: add more transforms C1-X (X|(C2-1)) == C1 C1-X >u C2 -> (X|C2) == C1 X-C1 (X & -C2) == C1 X-C1 >u C2 -> (X & ~C2) == C1 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185909 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index f4734461a62..d843842cb3a 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1512,6 +1512,30 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, return R; break; + case Instruction::Sub: { + ConstantInt *LHSC = dyn_cast(LHSI->getOperand(0)); + if (!LHSC) break; + const APInt &LHSV = LHSC->getValue(); + + // C1-X (X|(C2-1)) == C1 + // iff C1 & (C2-1) == C2-1 + // C2 is a power of 2 + if (ICI.getPredicate() == ICmpInst::ICMP_ULT && LHSI->hasOneUse() && + RHSV.isPowerOf2() && (LHSV & (RHSV - 1)) == (RHSV - 1)) + return new ICmpInst(ICmpInst::ICMP_EQ, + Builder->CreateOr(LHSI->getOperand(1), RHSV - 1), + LHSC); + + // C1-X >u C2 -> (X|C2) == C1 + // iff C1 & C2 == C2 + // C2+1 is a power of 2 + if (ICI.getPredicate() == ICmpInst::ICMP_UGT && LHSI->hasOneUse() && + (RHSV + 1).isPowerOf2() && (LHSV & RHSV) == RHSV) + return new ICmpInst(ICmpInst::ICMP_NE, + Builder->CreateOr(LHSI->getOperand(1), RHSV), LHSC); + break; + } + case Instruction::Add: // Fold: icmp pred (add X, C1), C2 if (!ICI.isEquality()) { @@ -1708,6 +1732,24 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, default: break; } + + // X-C1 (X & -C2) == C1 + // iff C1 & (C2-1) == 0 + // C2 is a power of 2 + if (ICI.getPredicate() == ICmpInst::ICMP_ULT && LHSI->hasOneUse() && + RHSV.isPowerOf2() && (LHSV & (RHSV - 1)) == 0) + return new ICmpInst(ICmpInst::ICMP_EQ, + Builder->CreateAnd(LHSI->getOperand(0), -RHSV), + ConstantExpr::getNeg(LHSC)); + + // X-C1 >u C2 -> (X & ~C2) == C1 + // iff C1 & C2 == 0 + // C2+1 is a power of 2 + if (ICI.getPredicate() == ICmpInst::ICMP_UGT && LHSI->hasOneUse() && + (RHSV + 1).isPowerOf2() && (LHSV & RHSV) == 0) + return new ICmpInst(ICmpInst::ICMP_NE, + Builder->CreateAnd(LHSI->getOperand(0), ~RHSV), + ConstantExpr::getNeg(LHSC)); } } return 0; diff --git a/test/Transforms/InstCombine/2007-01-27-AndICmp.ll b/test/Transforms/InstCombine/2007-01-27-AndICmp.ll index 4d1b982f676..6298a072333 100644 --- a/test/Transforms/InstCombine/2007-01-27-AndICmp.ll +++ b/test/Transforms/InstCombine/2007-01-27-AndICmp.ll @@ -1,8 +1,8 @@ ; RUN: opt < %s -instcombine -S | grep "ugt.*, 1" define i1 @test(i32 %tmp1030) { - %tmp1037 = icmp ne i32 %tmp1030, 40 ; [#uses=1] - %tmp1039 = icmp ne i32 %tmp1030, 41 ; [#uses=1] + %tmp1037 = icmp ne i32 %tmp1030, 39 ; [#uses=1] + %tmp1039 = icmp ne i32 %tmp1030, 40 ; [#uses=1] %tmp1042 = and i1 %tmp1037, %tmp1039 ; [#uses=1] ret i1 %tmp1042 } diff --git a/test/Transforms/InstCombine/and.ll b/test/Transforms/InstCombine/and.ll index 8492df9a120..3d36bfb404d 100644 --- a/test/Transforms/InstCombine/and.ll +++ b/test/Transforms/InstCombine/and.ll @@ -186,9 +186,9 @@ define i1 @test25(i32 %A) { } define i1 @test26(i32 %A) { - %B = icmp ne i32 %A, 50 ; [#uses=1] - %C = icmp ne i32 %A, 51 ; [#uses=1] - ;; (A-50) > 1 + %B = icmp ne i32 %A, 49 ; [#uses=1] + %C = icmp ne i32 %A, 50 ; [#uses=1] + ;; (A-49) > 1 %D = and i1 %B, %C ; [#uses=1] ret i1 %D } diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index cf8305df2a9..aaac9b64939 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -1123,3 +1123,43 @@ define i1 @icmp_add_ult_2(i32 %X) { %cmp = icmp ult i32 %add, 2 ret i1 %cmp } + +; CHECK: @icmp_add_X_-14_ult_2 +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 %X, -2 +; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp eq i32 [[AND]], 14 +; CHECK-NEXT: ret i1 [[CMP]] +define i1 @icmp_add_X_-14_ult_2(i32 %X) { + %add = add i32 %X, -14 + %cmp = icmp ult i32 %add, 2 + ret i1 %cmp +} + +; CHECK: @icmp_sub_3_X_ult_2 +; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %X, 1 +; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp eq i32 [[OR]], 3 +; CHECK-NEXT: ret i1 [[CMP]] +define i1 @icmp_sub_3_X_ult_2(i32 %X) { + %add = sub i32 3, %X + %cmp = icmp ult i32 %add, 2 + ret i1 %cmp +} + +; CHECK: @icmp_add_X_-14_uge_2 +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 %X, -2 +; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 [[AND]], 14 +; CHECK-NEXT: ret i1 [[CMP]] +define i1 @icmp_add_X_-14_uge_2(i32 %X) { + %add = add i32 %X, -14 + %cmp = icmp uge i32 %add, 2 + ret i1 %cmp +} + +; CHECK: @icmp_sub_3_X_uge_2 +; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %X, 1 +; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 [[OR]], 3 +; CHECK-NEXT: ret i1 [[CMP]] +define i1 @icmp_sub_3_X_uge_2(i32 %X) { + %add = sub i32 3, %X + %cmp = icmp uge i32 %add, 2 + ret i1 %cmp +}