Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -3066,6 +3066,19 @@ } } } + + // (A/B)/C --> A/(B*C) if safe and B*C can be folded. + if (const SCEVUDivExpr *OtherDiv = dyn_cast(LHS)) { + if (auto DivisorConstant = dyn_cast(OtherDiv->getRHS())) { + bool Overflow = false; + APInt NewRHS = + DivisorConstant->getAPInt().umul_ov(RHSC->getAPInt(), Overflow); + if (!Overflow) { + return getUDivExpr(OtherDiv->getLHS(), getConstant(NewRHS)); + } + } + } + // (A+B)/C --> (A/C + B/C) if safe and A/C and B/C can be folded. if (const SCEVAddExpr *A = dyn_cast(LHS)) { SmallVector Operands; Index: llvm/test/Analysis/ScalarEvolution/fold.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/fold.ll +++ llvm/test/Analysis/ScalarEvolution/fold.ll @@ -98,3 +98,19 @@ ; CHECK-NEXT: --> 0 ret void } + +define i64 @test8(i64 %a) { +; CHECK-LABEL: @test8 + %t0 = udiv i64 %a, 56 + %t1 = udiv i64 %t0, 56 +; CHECK: --> (%a /u 3136) + ret i64 %t1 +} + +define i64 @test9(i64 %a) { +; CHECK-LABEL: @test9 + %t0 = udiv i64 %a, 100000000000000 + %t1 = udiv i64 %t0, 100000000000000 +; CHECK: ((%a /u 100000000000000) /u 100000000000000) + ret i64 %t1 +}