diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index e624572e041..226126b39ed 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2948,6 +2948,24 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { Builder->CreateTrunc(B, A->getType())); } + // (A >> C) == (B >> C) --> (A^B) u< (1 << C) + // For lshr and ashr pairs. + if ((match(Op0, m_OneUse(m_LShr(m_Value(A), m_ConstantInt(Cst1)))) && + match(Op1, m_OneUse(m_LShr(m_Value(B), m_Specific(Cst1))))) || + (match(Op0, m_OneUse(m_AShr(m_Value(A), m_ConstantInt(Cst1)))) && + match(Op1, m_OneUse(m_AShr(m_Value(B), m_Specific(Cst1)))))) { + unsigned TypeBits = Cst1->getBitWidth(); + unsigned ShAmt = (unsigned)Cst1->getLimitedValue(TypeBits); + if (ShAmt < TypeBits && ShAmt != 0) { + ICmpInst::Predicate Pred = I.getPredicate() == ICmpInst::ICMP_NE + ? ICmpInst::ICMP_UGE + : ICmpInst::ICMP_ULT; + Value *Xor = Builder->CreateXor(A, B, I.getName() + ".unshifted"); + APInt CmpVal = APInt::getOneBitSet(TypeBits, ShAmt); + return new ICmpInst(Pred, Xor, Builder->getInt(CmpVal)); + } + } + // Transform "icmp eq (trunc (lshr(X, cst1)), cst" to // "icmp (and X, mask), cst" uint64_t ShAmt = 0; diff --git a/test/Transforms/InstCombine/compare-signs.ll b/test/Transforms/InstCombine/compare-signs.ll index cdf95abcec5..62cd5b3f94d 100644 --- a/test/Transforms/InstCombine/compare-signs.ll +++ b/test/Transforms/InstCombine/compare-signs.ll @@ -24,9 +24,9 @@ define i32 @test3(i32 %a, i32 %b) nounwind readnone { ; CHECK-LABEL: @test3( entry: -; CHECK: xor i32 %a, %b -; CHECK: lshr i32 %0, 31 -; CHECK: xor i32 %1, 1 +; CHECK: [[XOR1:%.*]] = xor i32 %a, %b +; CHECK: [[SHIFT:%.*]] = lshr i32 [[XOR1]], 31 +; CHECK: [[XOR2:%.*]] = xor i32 [[SHIFT]], 1 %0 = lshr i32 %a, 31 ; [#uses=1] %1 = lshr i32 %b, 31 ; [#uses=1] %2 = icmp eq i32 %0, %1 ; [#uses=1] @@ -34,7 +34,7 @@ entry: ret i32 %3 ; CHECK-NOT: icmp ; CHECK-NOT: zext -; CHECK: ret i32 %2 +; CHECK: ret i32 [[XOR2]] } ; Variation on @test3: checking the 2nd bit in a situation where the 5th bit diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index bd8128ffb1b..12a4744cc0f 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -523,12 +523,12 @@ define i1 @test52(i32 %x1) nounwind { ; PR9838 ; CHECK-LABEL: @test53( -; CHECK-NEXT: ashr exact -; CHECK-NEXT: ashr +; CHECK-NEXT: sdiv exact +; CHECK-NEXT: sdiv ; CHECK-NEXT: icmp define i1 @test53(i32 %a, i32 %b) nounwind { - %x = ashr exact i32 %a, 30 - %y = ashr i32 %b, 30 + %x = sdiv exact i32 %a, 30 + %y = sdiv i32 %b, 30 %z = icmp eq i32 %x, %y ret i1 %z } @@ -1336,3 +1336,23 @@ end: %res = phi i1 [%restrue, %true], [%resfalse, %false] ret i1 %res } + +; CHECK-LABEL: @icmp_lshr_lshr_eq +; CHECK: %z.unshifted = xor i32 %a, %b +; CHECK: %z = icmp ult i32 %z.unshifted, 1073741824 +define i1 @icmp_lshr_lshr_eq(i32 %a, i32 %b) nounwind { + %x = lshr i32 %a, 30 + %y = lshr i32 %b, 30 + %z = icmp eq i32 %x, %y + ret i1 %z +} + +; CHECK-LABEL: @icmp_ashr_ashr_ne +; CHECK: %z.unshifted = xor i32 %a, %b +; CHECK: %z = icmp ugt i32 %z.unshifted, 255 +define i1 @icmp_ashr_ashr_ne(i32 %a, i32 %b) nounwind { + %x = ashr i32 %a, 8 + %y = ashr i32 %b, 8 + %z = icmp ne i32 %x, %y + ret i1 %z +}