While not addressing explicitly, modern languages do already perform cache-size aware optimizations. Namely, .NET runtime will base its heap sizes and allocation behavior based on CPU's cache size so that data is allocated closer together and further reads, and subsequent garbage collection are friendly to CPU's memory prefetching behavior.
On the other hand, register allocation is a much more complex problem to solve because there is no single heuristic that fits all CPUs (and even operating systems!) sharing the same micro-architecture. As a result, "good enough" sometimes is chosen unless the language relies on LLVM/GCC logic.
Alloc/GC: https://github.com/dotnet/runtime/blob/main/docs/design/core...
Reg alloc: https://github.com/dotnet/runtime/blob/main/docs/design/core...