There is an easy way to implement dynamic programming, using a hash table.
The idea is that the recursive procedure stores a huge giant table, containing all values computed so far. Whenever the recursive procedure is called, it first checks whether the value is already in the table, and if so, the value is immediately returned. Otherwise, the body of the procedure is executed, and the result is stored in the table.
This kind of memoization can be enabled, for a specific procedure, using the decorator
@memoize in Python, and perhaps similar metaprogramming mechanisms are available in other languages.
Since the table takes up space, it is not clear that this kind of memoization is advantageous in every situation. For example, it might be that the function is easy to compute, and using a hash table would make it significantly slower (since memory access is small). Perhaps a certain code is trying to keep a certain table in cache, and using memoization would interfere with this effort. Perhaps using a table would interfere with security in some way, since it will reveal whether a function is called with the same value as before or not. There are probably many other reasons for the compiler not to perform such an optimization automatically.