<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/73336>73336</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Recursive call stack makes release build 4x slower
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
JohelEGP
</td>
</tr>
</table>
<pre>
In analyzing [cppfront][] with [Clang Build Analyzer][], I noticed a very odd item:
```output
**** Functions that took longest to compile:
8037 ms: cpp2::primary_expression_node::is_fold_expression() const (/home/johel/Documents/C++/Forks/hsutter/waarudo/source/cppfront.cpp)
417 ms: void cpp2::iteration_statement_node::visit<cpp2::sema>(cpp2::sema&, ... (/home/johel/Documents/C++/Forks/hsutter/waarudo/source/cppfront.cpp)
```
These are only the first two items.
`primary_expression_node::is_fold_expression` is exorbitantly expensive to compile.
I have a matrix of compilers (Clang, GCC) × [configuration][]s (`Debug`, `Release`).
Only Clang `Release` is affected, its compilation time increasing by 145 s.
Normally:
| [Configuration][] | Clang 18 | GCC 14 |
|:------------------|:---------|:-------|
| `Debug` | 25 s | 47 s |
| `Release` | 199 s | 95 s |
With the patch below:
| [Configuration][] | Clang 18 | GCC 14 |
|:------------------|:---------|:-------|
| `Debug` | 25 s | 47 s |
| `Release` | 54 s | 95 s |
This git patch removes the offending call that makes it expensive to optimize.
```diff
diff --git a/source/parse.h b/source/parse.h
index 103f9ce..bae5e7f 100644
--- a/source/parse.h
+++ b/source/parse.h
@@ -1556,7 +1556,7 @@ auto primary_expression_node::is_fold_expression() const
break;case identifier:
return *std::get<identifier>(expr) == "...";
break;case expression_list:
- return std::get<expression_list>(expr)->is_fold_expression();
+ return false; // std::get<expression_list>(expr)->is_fold_expression();
break;case id_expression:
return std::get<id_expression>(expr)->is_fold_expression();
break;default: ; // the others can't contain folds
```
Analyzing with this patch drops the offending function from the default output.
I suspect this is due to the recursive nature of `primary_expression_node::is_fold_expression`.
This is the stack when first breaking at the offending call while debugging `regression-tests/pure2-print.cpp2`.
![1700837777](https://github.com/llvm/llvm-project/assets/21071787/2af73103-af7b-4d45-8863-ce503a61eb36)
>From level 18 to 1, those are all calls to `is_fold_expression` members.
And if `primary_expression_node` contains an `expression_list_node`, that can repeat, ad infinitum.
[cppfront]: https://github.com/hsutter/cppfront/tree/4bd0c0438f2d3fa65d3e65a55b17c3a296bd8bc3
[Clang Build Analyzer]: https://github.com/aras-p/ClangBuildAnalyzer
[Configuration]: https://cmake.org/cmake/help/latest/variable/CMAKE_CONFIGURATION_TYPES.html
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzcV09v47oR_zT0ZSBBIvXHPvhgO9EiLbr7sN2i6CmgpJHFF0kUSMpO3qcvRrIVxckGeN2ihwqCTXL44wznv6S16tghblm8Z_HdSg6u1mb7F11jc__lt1Wuy5ftQweyk83LH6o7Aov3Rd9XRneOxXcTDM7K1UQ5NLI7wn5QTQm7EYJm3sX4AR6g004VWIKEE5oX0GUJymHLxI4FdyzYsSSYXj24fnCXRf76QjZ0hVO6s-Bq6cBp_QSN7o5oaQKFbnvV4HwgwDoQKbSWiR0Ufc-JIna9Ua00L4_43Bu0VunusdMlTkRlHyvdlAsi42vGN1DozjoYJ1mtW2Q8-510xXh2p4uhxc5ZxrMD4_vxzTJtnmiltoNzaBjPzlKaodSMZ1YPpqAjrgr1i75nfHOVG6LwKvdJq3IhvHJoJOng0TrpkNgupD8pqxwTh9f9FlvJxD3j65s1npBVfN__39xpNu40_VGjRZAGQXfNC7gaoVKGzHjWo1dYf8b9WXslASgL-KxNrpzsXPMC-NxjZ9UJF25yZTD-PkAtTwgSWumMegZdXbcZSwoa3ZsU9uVwIG9gB8E26RgSuqvUcZiMMnv8CGJJcIf5cKRb8wOwJPiODUqL48LmIsA3UsAUPm920CVkVWHhsCS4cvYi08gKnGoRVFcYlJbCM3-BMIrBvrnXV21a2TQvr0GWHsZw_VBqIOokSrgeJ18OBwgjGs5wJnbeu-dm_c10CYaFTuD1IQqPwc6TKB0nt9CFdpbQcLOZsDTZxDfQ8feflKfIzXrpihpybPT5_1spcbSAfqyUH7WycFTuohSDrT6hHdWkqwq7kvyqkE0z5dtWPqEF5d6Gk-6datUf6N8EeqmqalqiEXgeMZLLRNFLY9GvIf9gcUKqrsRnCANRbQr0_VxijGkFYRAkUTRt8Tzvw1Ov5WPKXPtPmLAoYFEAXhjHlBNTYHz_Op6IcnAafqFwzIkdIDcon5jYF9IiqBI7pyqFZlG1Lo9BN5gOGN9ZV05MjkjZfQmizE4sx6Qk7pi4A8a57_uMcyb2P-O7uEKjrJuZezfMbzi_gy3Ye0zc_0wJsyRkibccKtlYZGIPjGeMZ_91jh_pfLn7Z2p_p_M3oF-SosRKDg0pHRYXH6PO1VRwCtkxnjpyHSdVB3S2_bCO7ubu7DwlOGUvwVwa3d-GcnXpn6Ayuh1pF1FgarluSqIdbI-Fm05VFsphDHjCGSwGM2aATrqByngF_1Gp9heZSE3yWieLJzjX2F16glFvJD_1fO9z07lWDd0kH45HNVVRg8cLC8-hHZuYfjDIvd6oqTHhr7wZD1m8D9MgWIs0TdOxYV3XzvXUgE3WOSpXD7lf6JbxrGlO1z-vN_p3LBzjmbQWR048DNIwXac0lFUqwkB4skpzLyqj2FuvE-EVGAdCJiHmIplbpIyM0uAJGyo0TkNIZd_V-tIp0V3pwpZoLAk-bn1abHM01y5g15WgPjVNElzdzILsaOdNyF23TcJIR94JBnuUjpZkCaqrVKfc0L7xn5vPBbGDT1T62lDOGJ45g5Sso7wMiiAS64qXopJJXApMYhnHeZgWQvJNkpfrvBAz2599i3wugjTSej21uwQf0TN4Pvm2Q3h3ZEFF0tfmeB3T5bChcxtJvsh4dpJGybwh0uFvu7_ePx6-fc0evvzj--7Hw7evjz_-9dv93_3atc2q3IpyIzZyhdvJP9dBuF7V23gTxGITpDJGLjEPeBXlaRIXuA7SKs1xpbY84CIMeRTGQRAmfhGuU0xkWSRFmkepZFGArVSNT15M8q6UtQNuUyFEsmpkjo0dPw057_AMI5FKSny3MtvR8_PhaFkUkIvY11Occg1uv8_pYYzQKaKn9sFM3Qrko3miZ7CNPqNZDabZ_umYG8WimBvF_ncAAAD__7CKfqw">