diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -483,6 +483,16 @@ if (Instruction *Logic = foldShiftOfShiftedBinOp(I, Builder)) return Logic; + if (match(Op1, m_Or(m_Value(), m_SpecificInt(BitWidth - 1)))) { + BinaryOperator *NewShiftOp = BinaryOperator::Create( + I.getOpcode(), Op0, ConstantInt::get(Ty, BitWidth - 1)); + if (I.getOpcode() == Instruction::Shl) { + NewShiftOp->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); + NewShiftOp->setHasNoSignedWrap(I.hasNoSignedWrap()); + } + return NewShiftOp; + } + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/shift.ll b/llvm/test/Transforms/InstCombine/shift.ll --- a/llvm/test/Transforms/InstCombine/shift.ll +++ b/llvm/test/Transforms/InstCombine/shift.ll @@ -2067,3 +2067,47 @@ %shl = shl i32 2, %tz ret i32 %shl } + +; shift (X, amt | bitwidth - 1) -> shift (X, bitwidth - 1) +define i6 @shl_or7_eq_shl7(i6 %x, i6 %c) { +; CHECK-LABEL: @shl_or7_eq_shl7( +; CHECK-NEXT: [[Y:%.*]] = shl nsw i6 [[X:%.*]], 5 +; CHECK-NEXT: ret i6 [[Y]] +; + %amt = or i6 %c, 5 + ;; nsw not needed for transform, just check that we propegate. + %y = shl nsw i6 %x, %amt + ret i6 %y +} + +define <2 x i8> @lshr_vec_or7_eq_shl7(<2 x i8> %x, <2 x i8> %c) { +; CHECK-LABEL: @lshr_vec_or7_eq_shl7( +; CHECK-NEXT: [[Y:%.*]] = lshr <2 x i8> [[X:%.*]], +; CHECK-NEXT: ret <2 x i8> [[Y]] +; + %amt = or <2 x i8> %c, + %y = lshr <2 x i8> %x, %amt + ret <2 x i8> %y +} + +define <2 x i8> @ashr_vec_or7_eq_ashr7(<2 x i8> %x, <2 x i8> %c) { +; CHECK-LABEL: @ashr_vec_or7_eq_ashr7( +; CHECK-NEXT: [[Y:%.*]] = ashr <2 x i8> [[X:%.*]], +; CHECK-NEXT: ret <2 x i8> [[Y]] +; + %amt = or <2 x i8> %c, + %y = ashr <2 x i8> %x, %amt + ret <2 x i8> %y +} + +; Negative test not bitwidth - 1 +define <2 x i8> @ashr_vec_or6_fail(<2 x i8> %x, <2 x i8> %c) { +; CHECK-LABEL: @ashr_vec_or6_fail( +; CHECK-NEXT: [[AMT:%.*]] = or <2 x i8> [[C:%.*]], +; CHECK-NEXT: [[Y:%.*]] = ashr <2 x i8> [[X:%.*]], [[AMT]] +; CHECK-NEXT: ret <2 x i8> [[Y]] +; + %amt = or <2 x i8> %c, + %y = ashr <2 x i8> %x, %amt + ret <2 x i8> %y +}