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 @@ -1314,6 +1314,17 @@ // X % C0 + (( X / C0 ) % C1) * C0 => X % (C0 * C1) if (Value *V = SimplifyAddWithRemainder(I)) return replaceInstUsesWith(I, V); + // ((X s/ C1) << C2) + X => X s% -C1 where -C1 is 1 << C2 + const APInt *C1, *C2; + if (match(LHS, m_Shl(m_SDiv(m_Specific(RHS), m_APInt(C1)), m_APInt(C2)))) { + APInt one(C2->getBitWidth(), 1); + APInt minusC1 = -(*C1); + if (minusC1 == (one << *C2)) { + Constant *NewRHS = ConstantInt::get(RHS->getType(), minusC1); + return BinaryOperator::CreateSRem(RHS, NewRHS); + } + } + // 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/add-shl-sdiv-to-srem.ll b/llvm/test/Transforms/InstCombine/add-shl-sdiv-to-srem.ll --- a/llvm/test/Transforms/InstCombine/add-shl-sdiv-to-srem.ll +++ b/llvm/test/Transforms/InstCombine/add-shl-sdiv-to-srem.ll @@ -3,9 +3,7 @@ define i8 @add-shl-sdiv-scalar0(i8 %x) { ; CHECK-LABEL: @add-shl-sdiv-scalar0( -; CHECK-NEXT: [[SD:%.*]] = sdiv i8 [[X:%.*]], -4 -; CHECK-NEXT: [[SL:%.*]] = shl i8 [[SD]], 2 -; CHECK-NEXT: [[RZ:%.*]] = add i8 [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem i8 [[X:%.*]], 4 ; CHECK-NEXT: ret i8 [[RZ]] ; %sd = sdiv i8 %x, -4 @@ -16,9 +14,7 @@ define i8 @add-shl-sdiv-scalar1(i8 %x) { ; CHECK-LABEL: @add-shl-sdiv-scalar1( -; CHECK-NEXT: [[SD:%.*]] = sdiv i8 [[X:%.*]], -64 -; CHECK-NEXT: [[SL:%.*]] = shl i8 [[SD]], 6 -; CHECK-NEXT: [[RZ:%.*]] = add i8 [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem i8 [[X:%.*]], 64 ; CHECK-NEXT: ret i8 [[RZ]] ; %sd = sdiv i8 %x, -64 @@ -29,9 +25,7 @@ define i32 @add-shl-sdiv-scalar2(i32 %x) { ; CHECK-LABEL: @add-shl-sdiv-scalar2( -; CHECK-NEXT: [[SD:%.*]] = sdiv i32 [[X:%.*]], -1073741824 -; CHECK-NEXT: [[SL:%.*]] = shl i32 [[SD]], 30 -; CHECK-NEXT: [[RZ:%.*]] = add i32 [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem i32 [[X:%.*]], 1073741824 ; CHECK-NEXT: ret i32 [[RZ]] ; %sd = sdiv i32 %x, -1073741824 @@ -44,9 +38,7 @@ define <3 x i8> @add-shl-sdiv-splat0(<3 x i8> %x) { ; CHECK-LABEL: @add-shl-sdiv-splat0( -; CHECK-NEXT: [[SD:%.*]] = sdiv <3 x i8> [[X:%.*]], -; CHECK-NEXT: [[SL:%.*]] = shl <3 x i8> [[SD]], -; CHECK-NEXT: [[RZ:%.*]] = add <3 x i8> [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem <3 x i8> [[X:%.*]], ; CHECK-NEXT: ret <3 x i8> [[RZ]] ; %sd = sdiv <3 x i8> %x, @@ -57,9 +49,7 @@ define <4 x i32> @add-shl-sdiv-splat1(<4 x i32> %x) { ; CHECK-LABEL: @add-shl-sdiv-splat1( -; CHECK-NEXT: [[SD:%.*]] = sdiv <4 x i32> [[X:%.*]], -; CHECK-NEXT: [[SL:%.*]] = shl <4 x i32> [[SD]], -; CHECK-NEXT: [[RZ:%.*]] = add <4 x i32> [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem <4 x i32> [[X:%.*]], ; CHECK-NEXT: ret <4 x i32> [[RZ]] ; %sd = sdiv <4 x i32> %x, @@ -70,9 +60,7 @@ define <2 x i64> @add-shl-sdiv-splat2(<2 x i64> %x) { ; CHECK-LABEL: @add-shl-sdiv-splat2( -; CHECK-NEXT: [[SD:%.*]] = sdiv <2 x i64> [[X:%.*]], -; CHECK-NEXT: [[SL:%.*]] = shl <2 x i64> [[SD]], -; CHECK-NEXT: [[RZ:%.*]] = add <2 x i64> [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem <2 x i64> [[X:%.*]], ; CHECK-NEXT: ret <2 x i64> [[RZ]] ; %sd = sdiv <2 x i64> %x, @@ -87,9 +75,7 @@ define i32 @add-shl-sdiv-i32-4-use0(i32 %x) { ; CHECK-LABEL: @add-shl-sdiv-i32-4-use0( ; CHECK-NEXT: call void @use32(i32 [[X:%.*]]) -; CHECK-NEXT: [[SD:%.*]] = sdiv i32 [[X]], -16 -; CHECK-NEXT: [[SL:%.*]] = shl i32 [[SD]], 4 -; CHECK-NEXT: [[RZ:%.*]] = add i32 [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem i32 [[X]], 16 ; CHECK-NEXT: ret i32 [[RZ]] ; call void @use32(i32 %x) @@ -103,8 +89,7 @@ ; CHECK-LABEL: @add-shl-sdiv-i32-use1( ; CHECK-NEXT: [[SD:%.*]] = sdiv i32 [[X:%.*]], -16 ; CHECK-NEXT: call void @use32(i32 [[SD]]) -; CHECK-NEXT: [[SL:%.*]] = shl i32 [[SD]], 4 -; CHECK-NEXT: [[RZ:%.*]] = add i32 [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem i32 [[X]], 16 ; CHECK-NEXT: ret i32 [[RZ]] ; %sd = sdiv i32 %x, -16 @@ -119,7 +104,7 @@ ; CHECK-NEXT: [[SD:%.*]] = sdiv i32 [[X:%.*]], -16 ; CHECK-NEXT: [[SL:%.*]] = shl i32 [[SD]], 4 ; CHECK-NEXT: call void @use32(i32 [[SL]]) -; CHECK-NEXT: [[RZ:%.*]] = add i32 [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem i32 [[X]], 16 ; CHECK-NEXT: ret i32 [[RZ]] ; %sd = sdiv i32 %x, -16 @@ -135,7 +120,7 @@ ; CHECK-NEXT: call void @use32(i32 [[SD]]) ; CHECK-NEXT: [[SL:%.*]] = shl i32 [[SD]], 4 ; CHECK-NEXT: call void @use32(i32 [[SL]]) -; CHECK-NEXT: [[RZ:%.*]] = add i32 [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem i32 [[X]], 16 ; CHECK-NEXT: ret i32 [[RZ]] ; %sd = sdiv i32 %x, -16 @@ -151,8 +136,7 @@ ; CHECK-LABEL: @add-shl-sdiv-use4( ; CHECK-NEXT: [[SD:%.*]] = sdiv <3 x i8> [[X:%.*]], ; CHECK-NEXT: call void @use3xi8(<3 x i8> [[SD]]) -; CHECK-NEXT: [[SL:%.*]] = shl <3 x i8> [[SD]], -; CHECK-NEXT: [[RZ:%.*]] = add <3 x i8> [[SL]], [[X]] +; CHECK-NEXT: [[RZ:%.*]] = srem <3 x i8> [[X]], ; CHECK-NEXT: ret <3 x i8> [[RZ]] ; %sd = sdiv <3 x i8> %x,