Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -3066,6 +3066,21 @@ } } } + + // (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 getConstant(RHSC->getType(), 0, false); + } + 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,31 @@ ; CHECK-NEXT: --> 0 ret void } + +define i64 @test8(i64 %a) { +; CHECK-LABEL: @test8 + %t0 = udiv i64 %a, 56 + %t1 = udiv i64 %t0, 56 +; CHECK: %t1 +; CHECK-NEXT: --> (%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: %t1 +; CHECK-NEXT: --> 0 + ret i64 %t1 +} + +define i64 @test10(i64 %a, i64 %b) { +; CHECK-LABEL: @test9 + %t0 = udiv i64 %a, 100000000000000 + %t1 = udiv i64 %t0, 100000000000000 + %t2 = mul i64 %b, %t1 +; CHECK: %t2 +; CHECK-NEXT: --> 0 + ret i64 %t2 +}