Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1181,8 +1181,27 @@ break; case Instruction::Shl: + // (1 << X) & C -> (x < lg(C+1))? (1 << X) : 0, if (C+1) is power of 2. + // (1 << X) & C -> (x == lg(C))? (1 << X) : 0, if (C) is power of 2. + if (ConstantInt *COp0LHS = dyn_cast(Op0LHS)) { + if (COp0LHS->isOne()) { + CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE; + if (AndRHSMask.isPowerOf2()) + Pred = CmpInst::ICMP_EQ; + else if ((AndRHSMask + 1).isPowerOf2()) + Pred = CmpInst::ICMP_ULT; + + if (Pred != CmpInst::BAD_ICMP_PREDICATE) { + Constant *COp1 = ConstantInt::get(Op0RHS->getType(), + AndRHSMask.ceilLogBase2()); + Value *NewICmp = Builder->CreateICmp(Pred, Op0RHS, COp1); + Constant *Zero = Constant::getNullValue(I.getType()); + return SelectInst::Create(NewICmp, Op0I, Zero); + } + } + } + break; case Instruction::LShr: - // (1 << x) & 1 --> zext(x == 0) // (1 >> x) & 1 --> zext(x == 0) if (AndRHSMask == 1 && Op0LHS == AndRHS) { Value *NewICmp = Index: test/Transforms/InstCombine/icmp.ll =================================================================== --- test/Transforms/InstCombine/icmp.ll +++ test/Transforms/InstCombine/icmp.ll @@ -163,7 +163,7 @@ %cmp = icmp eq i32 %and, 0 ret i1 %cmp ; CHECK-LABEL: @test17( -; CHECK-NEXT: %cmp = icmp ne i32 %x, 3 +; CHECK-NEXT: icmp ne i32 %x, 3 } @@ -182,7 +182,7 @@ %cmp = icmp eq i32 %and, 8 ret i1 %cmp ; CHECK-LABEL: @test19( -; CHECK-NEXT: %cmp = icmp eq i32 %x, 3 +; CHECK-NEXT: icmp eq i32 %x, 3 } define i1 @test20(i32 %x) nounwind { @@ -191,7 +191,7 @@ %cmp = icmp ne i32 %and, 0 ret i1 %cmp ; CHECK-LABEL: @test20( -; CHECK-NEXT: %cmp = icmp eq i32 %x, 3 +; CHECK-NEXT: icmp eq i32 %x, 3 } define i1 @test21(i8 %x, i8 %y) { Index: test/Transforms/InstCombine/shift.ll =================================================================== --- test/Transforms/InstCombine/shift.ll +++ test/Transforms/InstCombine/shift.ll @@ -858,3 +858,39 @@ %b = ashr <2 x i65> %sext, ret <2 x i65> %b } + +; (!((1 << X) & 0x3)) -> (!(X < 2)) +define i32 @test65(i32 %x) { +entry: + %shl = shl i32 1, %x + %and = and i32 %shl, 3 + %tobool = icmp eq i32 %and, 0 + %x. = select i1 %tobool, i32 %x, i32 3 + ret i32 %x. +; CHECK-LABEL: @test65( +; CHECK: icmp ugt i32 %x, 1 +} + +; ((1 << X) & 0x7) -> (X < 3) +define i32 @test66(i32 %x) { +entry: + %shl = shl i32 1, %x + %and = and i32 %shl, 7 + %tobool = icmp eq i32 %and, 0 + %.x = select i1 %tobool, i32 3, i32 %x + ret i32 %.x +; CHECK-LABEL: @test66( +; CHECK: icmp ult i32 %x, 3 +} + +; ((1 << X) & 0x8) -> (X == 3) +define i32 @test67(i32 %x) { +entry: + %shl = shl i32 1, %x + %and = and i32 %shl, 8 + %tobool = icmp eq i32 %and, 0 + %.x = select i1 %tobool, i32 2, i32 %x + ret i32 %.x +; CHECK-LABEL: @test67( +; CHECK: icmp ne i32 %x, 3 +}