LICM starts with an *empty* AST, and then merges in each sub-loop. While the add code is appropriate for sub-loop 2 and up, it's utterly unnecessary for sub-loop 1. If the AST starts off empty, we can just clone/move the contents of the subloop into the containing AST.
It passes the LLVM regression tests and helps to reduce the runtime of 'opt -basicaa -licm out.opt.ll’ from 130ms to 74ms and the runtime of 'opt -basicaa -licm out.opt2.ll’ from 117ms to 68ms.
Extracting this code as a helper function would make it much cleaner.
The other option would be to turn add(AST&) into add(AST&&) - e.g. move the parameter.
You might also get away with special casing the copy into an empty AST.
The general point of each of my comments above is that the complexity in ownership in the new code is high and it would be nice to reduce that if possible.