I think I used to understand this, but it's been a long time since I had to write any serious LaTeX, so I don't anymore. I found this snippet in my personal _quick-build-latex_ script from over a decade ago:
if [ -z "$(find . -name "*.bib" -print0)" ]; then
# Just two runs, to cover TOC building, etc.
pdflatex -interaction=nonstopmode "$SOURCE_FILE" && \
pdflatex -interaction=nonstopmode "$SOURCE_FILE"
else
pdflatex -interaction=nonstopmode "$SOURCE_FILE" && \
bibtex "$SOURCE_FILE" && \
pdflatex -interaction=nonstopmode "$SOURCE_FILE" && \
pdflatex -interaction=nonstopmode "$SOURCE_FILE"
fi
So I guess if you're using bibtex, then you need to run it three times, but otherwise only twice?This is to say... I'm glad those days are gone.
There can still be cases where a fourth run is necessary, theoretically a fifth run. There are even cases where you get into an infinite loop, for example if you use the vref package. It will "cleverly" replace references to things like "figure 3 on the next page" or "figure 3 on page 8". When the reference is expanded, it might cause the figure to move to the following page, which means the reference is then contracted to "on page 8", which means the figure moves back to the original place again, in which case the reference must be updated, and so on ...
LaTeX will usually tell you by including a warning in the output ("LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right."), which no one reads, because it is so verbose. Not having that warning is not a guarantee that it's now stable either, so our Makefile actually compares the PDF files minus variable bytes like timestamps to know whether the build converged.