I’ve seen register used and even used correctly. It doesn’t mean what people think it means though. The register keyword just means ‘this variable may not alias, taking the address of it is ill-formed’. The compiler ignores it after the front end (unless you also use the GNU extension to place the value in a specific register), but the non-aliasing definition is important.
It sounds as if volatile is deprecated for use in any situations other than the ones that volatile was intended for, which is great. I wonder what this will do for C interoperability though. C11 introduced _Atomic as both a type qualifier and a type specifier but then did something monumentally stupid and made all of the functions in stdatomic.h take a volatile (not _Atomic) qualified pointer. This was a disaster for ABIs because it meant that _Atomic(T) had to have the same representation as T, whereas C++‘s std::atomic<T> is explicitly allowed to have a different representation (so that it can use an inline lock for types that don’t have atomic hardware operations, without that you have to use a lock pool and an _Atomic(T) / std::atomic<T> in shared memory may not actually be atomic). Maybe C2x will fix this.
This is a good thing, but will surely make some people I know who use C look at C++ as even more questionable. Sadly, their solution for problems in the embedded world is often to just make everything volatile “so the compiler doesn’t mess with it”. As you might expect, a lot of the time the core problem is not the compiler’s fault.