Ah, but there's a different and very important reason to use digitalRead() instead of accessing AVR registers.
With that bounce library, or without it (using millis() yourself for debouncing) the code you write is pretty certain to work on any Arduino compatible board. You can choose to use the library or not, and your code will run on any of those boards. You may never need to move to another board, but others might re-use your code on a different board.
But if you use code which accesses AVR registers instead of digitalRead(), your code will only work on other boards based on AVR chips, perhaps only the exact same model of chip. You, or others, can't move your project to a different board without re-writing it. But digitalRead() will work on any Arduino compatible board without alteration.
So, that debounce library could be described as a "convenience" library, performing functions you could do yourself using other standard Arduino functions. It provides a convenient, hopefully bug-free way to do the same thing. It allows code re-use, which is generally a good thing.
Functions like digitalRead() are part of a library called the Arduino Core. The Core library is different for each type of chip, but it looks exactly the same to the user. For example, the code inside digitalRead() will be completely different for the esp8266 Core compared to the ATmega328 Core. But from the outside they look identical. So the Core, and libraries like it, are "hardware abstraction" libraries which enable the same sketch to run on different chips by completely hiding, or abstracting, the differences between those chips.