Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -992,6 +992,12 @@ return X; } + // (X << C1) / X -> 1 << C1 + const APInt *C = nullptr; + if (((IsSigned && match(Op0, m_NSWShl(m_Value(X), m_APInt(C)))) || + (!IsSigned && match(Op0, m_NUWShl(m_Value(X), m_APInt(C))))) && X == Op1) + return ConstantInt::get(X->getType(), APInt(C->getBitWidth(), 1).shl(*C)); + // (X rem Y) / Y -> 0 if ((IsSigned && match(Op0, m_SRem(m_Value(), m_Specific(Op1)))) || (!IsSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1))))) Index: test/Transforms/InstSimplify/reassociate.ll =================================================================== --- test/Transforms/InstSimplify/reassociate.ll +++ test/Transforms/InstSimplify/reassociate.ll @@ -158,6 +158,16 @@ ret i32 %mul } +define i32 @sdiv6(i32 %x, i32 %y) { +; CHECK-LABEL: @sdiv6( +; CHECK: ret i32 4 +; +; (X << C1) / X -> 1 << C1 + %shl = shl nsw i32 %x, 2 + %r = sdiv i32 %shl, %x + ret i32 %r +} + define i32 @udiv1(i32 %x, i32 %y) { ; CHECK-LABEL: @udiv1( @@ -211,6 +221,16 @@ ret i32 %mul } +define i32 @udiv6(i32 %x, i32 %y) { +; CHECK-LABEL: @udiv6( +; CHECK: ret i32 4 +; +; (X << C1) / X -> 1 << C1 + %shl = shl nuw i32 %x, 2 + %r = udiv i32 %shl, %x + ret i32 %r +} + define i16 @trunc1(i32 %x) { ; CHECK-LABEL: @trunc1( ; CHECK: ret i16 1