Index: lib/Transforms/InstCombine/InstCombineMulDivRem.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1330,6 +1330,12 @@ return &I; } + // ((X % Y) % Y) -> (X % Y) + Value *X, *Y; + if (match(Op1, m_Value(Y)) && match(Op0, m_SRem(m_Value(X), m_Specific(Y)))) { + return ReplaceInstUsesWith(I, Op0); + } + // If the sign bits of both operands are zero (i.e. we can prove they are // unsigned inputs), turn this into a urem. if (I.getType()->isIntegerTy()) { Index: test/Transforms/InstCombine/rem.ll =================================================================== --- test/Transforms/InstCombine/rem.ll +++ test/Transforms/InstCombine/rem.ll @@ -213,3 +213,12 @@ %R = urem <2 x i64> %V, ret <2 x i64> %R } + +define i32 @test21(i32 %x, i32 %n) { +; CHECK-LABEL: @test21( +; CHECK-NEXT: %mod = srem i32 %x, %n +; CHECK-NEXT: ret i32 %mod + %mod = srem i32 %x, %n + %mod1 = srem i32 %mod, %n + ret i32 %mod1 +}