diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1369,6 +1369,13 @@ } } + // (A & 2^C1) + A => A & (2^C1 - 1) iff bit C1 in A is a sign bit + if (match(&I, m_c_Add(m_And(m_Value(A), m_APInt(C1)), m_Deferred(A))) && + C1->isPowerOf2() && (ComputeNumSignBits(A) > C1->countLeadingZeros())) { + Constant *NewMask = ConstantInt::get(RHS->getType(), *C1 - 1); + return BinaryOperator::CreateAnd(A, NewMask); + } + // A+B --> A|B iff A and B have no bits set in common. if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT)) return BinaryOperator::CreateOr(LHS, RHS); diff --git a/llvm/test/Transforms/InstCombine/modulo.ll b/llvm/test/Transforms/InstCombine/modulo.ll --- a/llvm/test/Transforms/InstCombine/modulo.ll +++ b/llvm/test/Transforms/InstCombine/modulo.ll @@ -4,9 +4,7 @@ ; PR21929 define i32 @modulo2(i32 %x) { ; CHECK-LABEL: @modulo2( -; CHECK-NEXT: [[REM_I:%.*]] = srem i32 [[X:%.*]], 2 -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[REM_I]], 2 -; CHECK-NEXT: [[RET_I:%.*]] = add nsw i32 [[TMP1]], [[REM_I]] +; CHECK-NEXT: [[RET_I:%.*]] = and i32 [[X:%.*]], 1 ; CHECK-NEXT: ret i32 [[RET_I]] ; %rem.i = srem i32 %x, 2 @@ -18,9 +16,7 @@ define <2 x i32> @modulo2_vec(<2 x i32> %x) { ; CHECK-LABEL: @modulo2_vec( -; CHECK-NEXT: [[REM_I:%.*]] = srem <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[REM_I]], -; CHECK-NEXT: [[RET_I:%.*]] = add nsw <2 x i32> [[TMP1]], [[REM_I]] +; CHECK-NEXT: [[RET_I:%.*]] = and <2 x i32> [[X:%.*]], ; CHECK-NEXT: ret <2 x i32> [[RET_I]] ; %rem.i = srem <2 x i32> %x, @@ -62,9 +58,7 @@ define i32 @modulo4(i32 %x) { ; CHECK-LABEL: @modulo4( -; CHECK-NEXT: [[REM_I:%.*]] = srem i32 [[X:%.*]], 4 -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[REM_I]], 4 -; CHECK-NEXT: [[RET_I:%.*]] = add nsw i32 [[TMP1]], [[REM_I]] +; CHECK-NEXT: [[RET_I:%.*]] = and i32 [[X:%.*]], 3 ; CHECK-NEXT: ret i32 [[RET_I]] ; %rem.i = srem i32 %x, 4 @@ -76,9 +70,7 @@ define <2 x i32> @modulo4_vec(<2 x i32> %x) { ; CHECK-LABEL: @modulo4_vec( -; CHECK-NEXT: [[REM_I:%.*]] = srem <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[REM_I]], -; CHECK-NEXT: [[RET_I:%.*]] = add nsw <2 x i32> [[TMP1]], [[REM_I]] +; CHECK-NEXT: [[RET_I:%.*]] = and <2 x i32> [[X:%.*]], ; CHECK-NEXT: ret <2 x i32> [[RET_I]] ; %rem.i = srem <2 x i32> %x, @@ -120,9 +112,7 @@ define i32 @modulo32(i32 %x) { ; CHECK-LABEL: @modulo32( -; CHECK-NEXT: [[REM_I:%.*]] = srem i32 [[X:%.*]], 32 -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[REM_I]], 32 -; CHECK-NEXT: [[RET_I:%.*]] = add nsw i32 [[TMP1]], [[REM_I]] +; CHECK-NEXT: [[RET_I:%.*]] = and i32 [[X:%.*]], 31 ; CHECK-NEXT: ret i32 [[RET_I]] ; %rem.i = srem i32 %x, 32 @@ -134,9 +124,7 @@ define <2 x i32> @modulo32_vec(<2 x i32> %x) { ; CHECK-LABEL: @modulo32_vec( -; CHECK-NEXT: [[REM_I:%.*]] = srem <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[REM_I]], -; CHECK-NEXT: [[RET_I:%.*]] = add nsw <2 x i32> [[TMP1]], [[REM_I]] +; CHECK-NEXT: [[RET_I:%.*]] = and <2 x i32> [[X:%.*]], ; CHECK-NEXT: ret <2 x i32> [[RET_I]] ; %rem.i = srem <2 x i32> %x,