Index: lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCompares.cpp +++ lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1607,7 +1607,8 @@ // preferable because it allows the C2 << Y expression to be hoisted out of a // loop if Y is invariant and X is not. if (Shift->hasOneUse() && C1.isNullValue() && Cmp.isEquality() && - !Shift->isArithmeticShift() && !isa(Shift->getOperand(0))) { + !C2.isSignMask() && !Shift->isArithmeticShift() && + !isa(Shift->getOperand(0))) { // Compute C2 << Y. Value *NewShift = IsShl ? Builder.CreateLShr(And->getOperand(1), Shift->getOperand(1)) Index: test/Transforms/InstCombine/icmp-shl-and.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/icmp-shl-and.ll @@ -0,0 +1,17 @@ +; RUN: opt %s -instcombine -S | FileCheck %s + +; CHECK-LABEL: foo +; CHECK: [[SUB:%.*]] = add nsw i32 %x, -1 +; CHECK-NEXT: [[SHL:%.*]] = shl i32 %y, [[SUB]] +; CHECK-NEXT icmp slt i32 [[SHL]], 0 + +define dso_local i32 @foo(i32 %x, i32 %y, i32 %a, i32 %b) { +entry: + %sub = sub nsw i32 %x, 1 + %shl = shl i32 %y, %sub + %and = and i32 %shl, -2147483648 + %tobool = icmp ne i32 %and, 0 + %selv = select i1 %tobool, i32 %a, i32 %b + ret i32 %selv +} +