https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116140
--- Comment #10 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Alex Coplan <acop...@gcc.gnu.org>: https://gcc.gnu.org/g:f97d86242b86e4ad2bef3623c97e91481840a210 commit r15-3583-gf97d86242b86e4ad2bef3623c97e91481840a210 Author: Alex Coplan <alex.cop...@arm.com> Date: Fri Aug 2 09:52:50 2024 +0100 c++: Ensure ANNOTATE_EXPRs remain outermost expressions in conditions [PR116140] For the testcase added with this patch, we would end up losing the: #pragma GCC unroll 4 and emitting "warning: ignoring loop annotation". That warning comes from tree-cfg.cc:replace_loop_annotate, and means that we failed to process the ANNOTATE_EXPR in tree-cfg.cc:replace_loop_annotate_in_block. That function walks backwards over the GIMPLE in an exiting BB for a loop, skipping over the final gcond, and looks for any ANNOTATE_EXPRS immediately preceding the gcond. The function documents the following pre-condition: /* [...] We assume that the annotations come immediately before the condition in BB, if any. */ now looking at the exiting BB of the loop, we have: <bb 8> : D.4524 = .ANNOTATE (iftmp.1, 1, 4); retval.0 = D.4524; if (retval.0 != 0) goto <bb 3>; [INV] else goto <bb 9>; [INV] and crucially there is an intervening assignment between the gcond and the preceding .ANNOTATE ifn call. To see where this comes from, we can look to the IR given by -fdump-tree-original: if (<<cleanup_point ANNOTATE_EXPR <first != last && !use_find(short int*)::<lambda(short int)>::operator() (&pred, *first), unroll 4>>>) goto <D.4518>; else goto <D.4516>; here the problem is that we've wrapped a CLEANUP_POINT_EXPR around the ANNOTATE_EXPR, meaning the ANNOTATE_EXPR is no longer the outermost expression in the condition. The CLEANUP_POINT_EXPR gets added by the following call chain: finish_while_stmt_cond -> maybe_convert_cond -> condition_conversion -> fold_build_cleanup_point_expr this patch chooses to fix the issue by first introducing a new helper class (annotate_saver) to save and restore outer chains of ANNOTATE_EXPRs and then using it in maybe_convert_cond. With this patch, we don't get any such warning and the loop gets unrolled as expected at -O2. gcc/cp/ChangeLog: PR libstdc++/116140 * semantics.cc (anotate_saver): New. Use it ... (maybe_convert_cond): ... here, to ensure any ANNOTATE_EXPRs remain the outermost expression(s) of the condition. gcc/testsuite/ChangeLog: PR libstdc++/116140 * g++.dg/ext/pragma-unroll-lambda.C: New test.