As far as I know, there are only two properties of register that are mandatory according to the C standard: you can't take the address, and you can't use it with _Alignas. So your compiler must issue a diagnostic for code such as the following:
register int foo;
&foo; // constraint violation
register int bar[3]; // basically useless but not an error by itself
bar; // constraint violation, decays to pointer
bar[1]; // likewise
register _Alignas(16) int baz; // constraint violation
(Incidentally, gcc actually allows register int bar[3]; bar[1]; without a diagnostic; but it doesn't claim to be a conforming C implementation unless you use -pedantic, and in that case you do get a warning as you should.)
Note that a "diagnostic" need not be an error; a warning suffices. So for the above code snippets, if you want, you can issue a warning and then proceed to handle them in any way that you wish (e.g. by otherwise ignoring the register declaration).
And of course, since it is a keyword, you must issue a diagnostic if it appears where not syntactically allowed, e.g. as an identifier.
int register;
void register(void);
Everything else is at your discretion as the implementer. You can ignore it completely if you choose, and for the most part, that's what modern compilers do.
The standard's intended meaning for register is to "suggest that
access to the object be as fast as possible." Traditionally, this might be used in a register allocation pass. If you are in a situation where you have run out of machine registers and need to spill some variables into memory, then you might give priority to register variables and try to spill non-register variables first. For instance, if you have
int a,b,c,d,e,f,g,h;
register int r;
then you might prefer to spill any or all of a,...,h instead of r, if possible.
That would be reasonable for a compiler of the 1970s or 1980s. On the other hand, modern optimizing compilers will have sophisticated heuristics to decide how to allocate registers, that in many cases are more accurate than the programmer's assumptions. So a modern compiler would be more likely to rely entirely on its own algorithm and disregard the register hint.
The "entry in a symbol table" remark might be from the same source (Expert C Programming - Deep C Secrets) as mentioned in Why is the 'auto' keyword useful for compiler writers in C?. It is not very clearly worded. The only sense I can make of it is that the compiler does need to keep track of which storage class specifiers were used to declare an object, e.g. to issue required diagnostics as noted above. So whatever data structure you use to associate the name and type of an object will need to have a flag to indicate if it was declared register, and that may be what they mean by "symbol table".