diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index d843842cb3a..fd2b68a9ecd 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1564,13 +1564,23 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, } } - // X-C1 (X & -2) == C1 - // iff C1 & 1 == 0 + // X-C1 (X & -C2) == C1 + // iff C1 & (C2-1) == 0 + // C2 is a power of 2 if (ICI.getPredicate() == ICmpInst::ICMP_ULT && LHSI->hasOneUse() && - LHSV[0] == 0 && RHSV == 2) + 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)); } break; } @@ -1732,24 +1742,6 @@ 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/icmp.ll b/test/Transforms/InstCombine/icmp.ll index aaac9b64939..fbf7f3d6c33 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -1163,3 +1163,61 @@ define i1 @icmp_sub_3_X_uge_2(i32 %X) { %cmp = icmp uge 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 +} + +; CHECK: @icmp_and_X_-16_eq-16 +; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ugt i32 %X, -17 +; CHECK-NEXT: ret i1 [[CMP]] +define i1 @icmp_and_X_-16_eq-16(i32 %X) { + %and = and i32 %X, -16 + %cmp = icmp eq i32 %and, -16 + ret i1 %cmp +} + +; CHECK: @icmp_and_X_-16_ne-16 +; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ult i32 %X, -16 +; CHECK-NEXT: ret i1 [[CMP]] +define i1 @icmp_and_X_-16_ne-16(i32 %X) { + %and = and i32 %X, -16 + %cmp = icmp ne i32 %and, -16 + ret i1 %cmp +} diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index 41f8aa9ee81..aac8803398f 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -272,11 +272,10 @@ define i1 @test19(i32 %A) { define i1 @test19a(i32 %A) { ; CHECK: @test19a -; CHECK-NEXT: and i32 %A, -4 -; CHECK-NEXT: icmp eq i32 +; CHECK-NEXT: icmp ugt i32 %A, -5 ; CHECK-NEXT: ret i1 %B = ashr i32 %A, 2 ; [#uses=1] - ;; (X & -4) == -4 + ;; X >u ~4 %C = icmp eq i32 %B, -1 ; [#uses=1] ret i1 %C }