<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/64906>64906</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            clang: My fight for HALO : results and ideas
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          kelbon
      </td>
    </tr>
</table>

<pre>
    Some time ago, I set out to write at least an efficient generator in C++20, the main problem, as expected, frame allocation

Therefore, for several iterations, I was looking for the guarantees missing for the compiler for optimizations 
 (https://github.com/llvm/llvm-project/issues/64542
https://github.com/llvm/llvm-project/issues/64507)

in the end, I managed to make sure that the allocations are optimized, as I expected, it was enough just to let the compiler know that calling the resume function does not change local variables and fields

The problem is that this feature does not exist either at the language level or at the level of its implementation.

I ended up having to do something like this:

[commit link](https://github.com/kelbon/kelcoro/commit/2e97bf410d14b39ec8db3325ddabc1aaff66d801)

See effect here:
https://godbolt.org/z/f39TxvGas (removing '-DDAO' flag enables 'assume' and removes allocations + enables other optimizations)

```C++
void some_method() {
    const auto* const address_before = X.address();
    handle.resume();
    const auto* const address_after = X.address();
    assume(address_before == address_after);
}
```
There are many problems:
1. invoking any function is a side effect, which will break 'assume'
2. it will not work for any non trivial object, std::string for example (operator== is an side effect)
3. debug overhead (and possibly release too in case of coroutines, because local variables == more stack to allocate and it will not be optimized on this stage)
4. it is really magic, that it is working, because it is not obvious for compiler what i really want to say
5. i cant declare a function with such properties, only boiler plate on call-site

So, first idea: we need an attribute to explicitly say, that function do not changes something. Examples:
local variables, fields of class where method exist, function inputs (const X& for example, which is really do not changed in 99.99% cases) or concrete names

So:

```C++
void some_method() {
 handle.resume();
    [[clang::assume_unchanged(X)]];  // assumes its unchanged since 'some_method' start
}
void println(forward_range_with_const_begin auto&& rng [[clang::assume_unchanged]]);

void log() [[clang::assume_unchanged(__locals, __fields)]];

```
Etc etc, its just pseudocode, but its really usefull in many cases, i think there are maybe more cases for this attribute then for 'assume' 'pure' and 'const' together


### Another problem:
 For some reason compiler thinks its good idea to create coroutine frame not as 'union' of all states which must be saved on suspend points, but as tuple of them. 
 https://godbolt.org/z/r3T6eM4fc

```C++

// instead of reusing allocated memory size grows

dd::generator<int> g() {
    co_yield 1;
}
// size - 112
dd::generator<int> g1 () {
    co_yield dd::elements_of(g());
}
// size - 168
dd::generator<int> g2 () {
 co_yield dd::elements_of(g());
    co_yield dd::elements_of(g());
}
// size - 224
dd::generator<int> g3 () {
 co_yield dd::elements_of(g());
    co_yield dd::elements_of(g());
 co_yield dd::elements_of(g());
}

```

Some of this problems as i understand must be resolved on language level: for example, allow 'consteval' on functions used on 'runtime' values (atleast for static functions)

Because now this code will be ill-formed when used:

```C++
struct awaiter {
  static consteval bool await_ready() { return true; }
...
};

```
Such information on front-end may be very usefull for removing 'never suspend' points
And no way to say 'await_suspend always returns false, so its never suspend really'


And last one: clang 16 bug https://godbolt.org/z/P85b7c3he

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEWFtv2zoS_jXMyyCGTcW3Bz8kTbNbYA_OAu1D3wxKHElsKNLgUHbdX78YUvKtQXN2u8ABArcSybl-881Qisg0DnEj5k9i_nyn-tj6sHlFW3p3V3p93Hz2HUI0HYJqvJAf4BMQRvB9hOjhEExEUBEsKoqgHGBdm8qgi9Cgw6CiD2AcfBDyScgnOWURsUXolHGwC7602PE7RYDfd1hF1PxYB8UqrfWVisY7MX0W08f8-6XFgLUPmDb6AIR7DMqCiazQeEfZ0IMisN6_Gtekfay36VVQLiISdIbocqny3c5YDOmF30XTmR9ZHGTFIOSqjXFHongU8kXIl8bEti8nle-EfLF2P_5zvwv-G1ZRyBdD1CMJ-bJ4mD_ILOi3hEyXQq4v42FcMh-dzm53yqkGNeenU68I1AeE2KqYtp1jSqACjo7msCuCT1d5MDFFEZ3vmxa-9ZTSbjFeR-zV-UNWUSlrOai8HJD6DqHuXcX6QHskcD5C1SrXILAhFvYqGFVaJFBOQ23QarpJ9wgUMDQ6YghqVJFdO4nF74YioIktBhjctco1vWJluEcL_ryQn2swkcB0O4sdupgCM7lU_4kDixr6HbRqn1zzoD2Q7zC2_GzNKyaLOKMXJ8X8qfJdZyJY417F_PnX8MlVl_9T-eCFfMnHhXyRuF6W9cNsqmcPZbHGaqXLopBzrVVZzZSq68VCr6azG2R8RuSCxCoC18zJvhsrvC69jRMfGiFffgj5UhfrL9_3_1DEiA_Y-eS3kMv75-fHP4VcQm1VA-hy3oRcKuJU8wonMR3hhF5gTcin0wGfMnRVYjeWi8U0_w3Ekd_uvdEp8FuOvddCroRcg1gO6wAAlXfMRH30Qj6OT1oHJNqWiTZAFM_wdTK8zDJEcSGiVU5bnGT4vrH-KxWqjhje1TCGa_WzZXz0StjlWbF8vonPBSWmcu6UO47lcgbkbALG7TMT8oZTSRoCBWT0iBOu-UNrqhYOxlooA6rXq_xmeXKSmIG3cOEdfHhNrMmynXcQg9kbZcGX3wahFDVbUzxSDCPp4nfFdccg87vcK4YAsFnu2q4BHsUENJZ9A36PoUWl-TRjbueJTGmPEJCbEUL0njtPxf_3NXBJ9dE4TM2hxEr19DMFDfo7TgZFVb1ytQ8wxoTtS7_LC_oEdptpiaJq8GTvQ4qUIQiorD1CpxpT5Sao4rDE4TOuubQrL7AOX-6N7ykF7MS3h3R4lHlQLtEyqWNWOp-AgYrfaqwsw0KdU34wsQXqq5ZhssMQTQ6Jd_YIpU_yd5bd9S7R-T2ZiFe0kgaB2gSKYDQqUTzCAcEhak6bijGYso-cAm4m1lQm2mMyb3T8oidcdAQ6s-oEPmZ0nEF8k6tsA3eLlF6riOCQ6iCTQ24HadcJ7W7Xx0RquWi_Crm4ROIZ_eeEXRmoGVHr9WS9FnKeoMXEBSk1rgoYEZzqkG6iddMX_jdue4-V0gz3VHHDy5WWa3bbu8F2IVdf-dD8mf-KJ4DM_wMbUeqEp91AxlVcm8sro5aM7xBv6CgZvwvGReuEXNU-HFTQ28CStgy4bQr4tsTGuIE5Fxz8wH3lXcOzxZc8eNZqfTOG6i8EYLtNKErg2W6HYeMiJm_mKT9-jBVgrPJURHkW2hH22ldeJ-iUfUxLA3J6wrq3liGTWHmAywcwTBTulceQE2sfS8ysk3YNMynT4LmYWnTp_VW7FXK568Op8wq5TJHm5-gbZBVXPuVfWeQ_eHS5F4-T-IhUeOG5mmf_gIqYCEbqSaZnrDTe60QAXOhVQOaME80OIzzXTpojlr3jOV4uuVqVtYyjiDTUW8fRLBFI7TOVUk87TLRuXKQxuoog9twyfM3x6CbjZP7eRBOKLwv846Gu3i_EMUSpNIyjyE3G1xCwT9eFsRto6LDz4QhkfiA0wR-uyl4P_e50DRLFB-OiKD5C8_bcsj0yHGH2RrfPxiRF9zCbyfdVzOCXSsajmMde2vpayNVg2NsTx7UNi9X7NsifbfjvDfi_mi3lw_tmF3-f2b_l6VukNbagbigZQ6fhkIvJQO80BorMHWMNBiRvhzK8vj5xo79pl1wNhxPt4F7ZVOLu1HSJeTDJEnIZehdNJq69sn26O6xUzF8P0lWeb2DV-fDNteBpGI_yddMQMPUOoyqCsfa-9qFDzYOAS4r_Uu-lGPoqgjook6b3c8kM9pycg9J7mzduAyp9PEMFAsY-8OzbI3fXU2Imk8k5Vb9sMZ95KjOOfUi3ohTH4F28Zyrs1JG93GM49xaO2eUFzeEew0ieHOaBP5P4R6fBeTio4zAtplaSfBnpVtmDOtLgCkGtLKU0k0-MfyV-6HOnS8HlL6uynFTv-NoJqSvDbAE8ur9H1v9ezctlVbTD0HmnN4VeF2t1h5vZYi2XxUrO1nftRpWo5sV6gfNFtZrPlnpdTJeqXq0Ws_l8usI7s5FTWUxXUsrZtChWkwdc47SYrtR0rQtdrMTDFDtl7MTafccW3KUvLZvFw3q6uLOqREvp45iUDg-QFoWUYv58FzbpG03ZNyQeptZQpLOUaKLFzTiKwB9HqE3TZoj_8_FffwK_5UnOxvzZg7so3fXBbn7n29B6uvhPAAAA___-d0cQ">