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

    <tr>
        <th>Summary</th>
        <td>
            functions marked with `nocapture` do not inline properly.
        </td>
    </tr>

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

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

    <tr>
      <th>Reporter</th>
      <td>
          python-ast-person
      </td>
    </tr>
</table>

<pre>
    The optimiser does not preserve `nocapture` annotations when inlining functions. The use of `nocapture` for `@no_capture` would be valid if the user knows the pointer stored into @G will never be read from
Example:
Input to `opt`:
```
declare void @example()

@G = external global ptr

define void @no_capture(ptr nocapture %in ) {
entry:
    store ptr %in, ptr @G
    ret void
}

define void @square() local_unnamed_addr #0 {
entry:
 %local_var = alloca i32 
    store i32 10, ptr %local_var
    call void @no_capture(ptr %local_var)
    call void @example()
    ret void 
}
```
Expected output:
```
declare void @example() local_unnamed_addr

define void @no_capture(ptr nocapture %in) local_unnamed_addr #0 {
  store ptr %in, ptr @G, align 8
  ret void
}

define void @square() local_unnamed_addr {
  %local_var = alloca i32, align 4
  store ptr %local_var, ptr @G, align 8
  call void @example()
  ret void
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) }
```
Received output:
```
declare void @example() local_unnamed_addr

define void @no_capture(ptr nocapture %in) local_unnamed_addr #0 {
  store ptr %in, ptr @G, align 8
  ret void
}

define void @square() local_unnamed_addr {
  %local_var = alloca i32, align 4
  store i32 10, ptr %local_var, align 4 ; unnecessary store
  store ptr %local_var, ptr @G, align 8
  call void @example()
  ret void
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) }
```

The code does optimise properly if `@no_capture` has the `noinline` attribute. Example of output with `noinline`:
```
declare void @example() local_unnamed_addr

define void @no_capture(ptr nocapture %in) local_unnamed_addr #0 {
  store ptr %in, ptr @G, align 8
  ret void
}

define void @square() local_unnamed_addr {
  %local_var = alloca i32, align 4
  call void @no_capture(ptr nonnull %local_var)
 tail call void @example()
  ret void
}

attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) }
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsV01z4jgQ_TXi0hXKyHaAgw_JMEztdWvvKdlqsHbklrclQfj3W7IhkAxhtvYje0kVZSxZr_XUH9KT8t5sCbES5aMoVxMVQ-u46g-hdXSnfLjrkb2jSe30ofqtRXB9MJ3xyKAdeiAXoGf0yDsEcZ-Ra1QfIqO4z0ARuaCCceRh3yKBIWvI0BY2kZqhfwrJaPQIbvMDfuM49YkiI_d00b930WqoEXbKGg1mA2E0wvCd3N4Pzd4ZCsjgg2PUYCg4EEX2DfbGWiDcIScTjErDhl0nspXIHr4-q663KPKHsf0L9TFAgt5nrg-JzelTeh9_Q1NjYxUj7JzRaSI8WpILIZdHxPhMJES-AnwOyKQsbK2rlYU-8OU4jRtDZ3sXLpCLPjC8uAqELA2BkEsQ88cRjBT48EIVAEY_pDnG4UJ-GRtF9u08iDEMEx55zFc3CPk_ouLj-sC6RtmnSKQ61E9K6zRNnr1LSMhyhOwUD85QNrXB5BLeck59s-yF8AXyPLJR1r7vqleYUzR-gF2J2KVP4K1TXsf_63OPTUANLoY-hr-VJlfc-A8y4i_F5XZiyC-grNkSLE6j_9UMOZO4kQ9nEsVVyheRvcn857G-uTYVAps6BvRHD-artADoog89uy2jT9vhhhGBHGMT2ac3f6AGyEXaG9LD5sMYIhN02Dk-CLnYswk4EOZth53IH4AcDT2GVNOg96a2-OpTKvXrefgrNmh2n3n4cXl4Y386Q0DkjxCJMIVT8WHEfib0zxN6fCaZ0DiNo-w4qRDo2fXI9pBEwDWp0KpRDQzSYpAfozI5rX0KxxM_6Y-xYmBvQvsG8FlF_2EV3T67yRFFa985w4My9mMLYcyJ_6kiJrrK9TJfqglWs3km5XKeL7JJW0k5W-hyvlTlvc6KRV3KUs3LIqsX82ZWazkxlcxkPpOz2UxKWS6nm3IhZabrYoYoVT1PruuUsVNrd93U8XZivI9YzcusKCZW1Wj9cE2QknAPw0chZbo1cJUwd3XcelFk1vjgz1aCCRarF8EPneLvqC-K7KJatRsuFEcXn2p7OolsqzaE3qc6lGsh11sT2lhPG9cJuU5zHf_uena_YxOEXA8MvZDrYQV_BgAA__8caP6A">