In a vacuum, the compiler's hands are completely tied by the Itanium ABI spec and separate compilation units. Unless you aggressively use the final keyword or instantiate objects strictly on the stack where provenance tracking is trivial, a standard compiler has to assume some dynamic library might override that interface at runtime.
The real magic happens when you turn on modern Link-Time Optimization (LTO / WPO). When the compiler can see the entire global class hierarchy at the linking stage, devirtualization goes from a defensive 'can I prove this is the only implementation?' to an aggressive profiling tool.
Even better is Speculative Devirtualization combined with Profile-Guided Optimization (PGO). If the compiler detects via runtime profiles that a specific virtual call resolves to ConcreteClassA 99% of the time, it will generate an explicit if (obj == ConcreteClassA) check to execute a direct, inlined call, leaving the slow vtable lookup purely as a fallback branch.
At a certain scale, devirtualization isn't just about avoiding a pointer dereference; it’s about preventing indirect branch mispredictions from poisoning the CPU instruction cache."