<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Jonas,<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Dec 19, 2020, at 20:11, Jonas Paulsson via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" class="">llvm-dev@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi,<br class=""><br class="">It seems that omnetpp runs ~10% faster with gcc than with clang on SystemZ. This is due to the small function printAddressTable which contains a loop with a single statement. It is run in "express-mode", which means that the function will contain mainly an empty loop, which GCC removes (or at least makes an early exit) while clang emits the loop to be iterated over.<br class=""><br class="">The loop is iterating with an std::iterator over an std::map. GCC has recently changed behavior to remove most (but not intentional ones) empty loops, and I wonder if clang should do the same? There was a discussion in the GCC community (<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89713" class="">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89713</a>) which resulted in this change to assume that loops are finite based on the "forward progress guarantee" of the standard, IIUC.<br class=""><br class="">For instance, this function:<br class=""><br class="">#include <map><br class="">void fun(std::map<int, int> &M) {<br class="">  for (std::map<int, int>::iterator I = M.begin(); I != M.end(); I++)<br class="">    ;<br class="">}<br class=""><br class="">will result in an empty function by GCC, while clang generates the empty loop to be iterated over.<br class=""><br class="">I see a comment in LoopDeletion.cpp:<br class=""><br class="">/// A loop is considered dead if it does not impact the observable behavior of<br class="">/// the program other than finite running time. This never removes a loop that<br class="">/// might be infinite (unless it is never executed), as doing so could change<br class="">/// the halting/non-halting nature of a program.<br class=""><br class="">This loop does pass the isLoopDead() check in LoopDeletion.cpp:204, but the loop is not deleted since ScalarEvolution cannot resolve the trip count.<br class=""><br class="">This is of course very important for performance in general and in particular for the profits of loop unswitching and other passes producing empty loops. So I wonder if it is the case that we could start doing this as well in llvm?<br class=""></div></div></blockquote></div><br class=""><div class=""><br class=""></div><div class="">Thanks for sharing this case! I am also looking into this, as we are seeing similar differences on other platforms.</div><div class=""><br class=""></div><div class="">Atmn’s patch gets us a little closer by lifting the restriction you mentioned. But there are a few other problems to tackle, including allowing deletion of loops with sub-loops (<a href="https://reviews.llvm.org/D93716" class="">https://reviews.llvm.org/D93716</a>) and changes to hoist a loop-invariant condition out the the loop (currently it appears LLVM fails to determine that the location the condition value is loaded from does not alias any operations in the loop).</div><div class=""><br class=""></div><div class="">Cheers,</div><div class="">Florian </div></body></html>