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

    <tr>
        <th>Summary</th>
        <td>
            [flang] TRIM of a character variable allocates a heap temporary
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            flang
      </td>
    </tr>

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

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

<pre>
    `TRIM(x)` is lowered to the runtime call `_FortranATrim`, which heap-allocates the result; the caller then frees it. This happens for every `trim` that is not inside a character comparison (those are handled by `ExpressionSimplification`, #154593). For example:

```fortran
subroutine s(a, b, n)
  character(len=*), intent(in) :: a, b
  integer, intent(in) :: n
  character(len=64) :: name
  name = trim(a) // '/' // trim(b)
  call sub(trim(name), n)
end subroutine
```

`flang -O2 -emit-llvm -S` gives three `_FortranATrim` calls and three `free`s.

When the operand is a character variable, `TRIM(x)` is equivalent to the substring `x(1:LEN_TRIM(x))`, which does not need a copy. Lowering
`hlfir.char_trim` of a variable to a substring with an inline `LEN_TRIM` would avoid the runtime call and the heap allocation; a consumer that needs its own copy (actual argument) would get a stack temporary from bufferization instead, which LLVM can often remove.

In SPEC CPU2017 527.cam4_r this pattern (`physics_update`, a diagnostic label built on every call) accounts for about 1% of runtime on x86-64: `_FortranATrim` plus the associated `malloc`/`free` and descriptor setup.

Assisted-by: Copilot
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJx0VU1v4zYQ_TX0ZWBDpmRJPvjgTdbAAtl20d22x2BEjSS2FKmSIyfpry9IKXGK3QWMRLbm482b90gMQfeW6CQOH4SUiiw9KTc2JKQUh_sNzjw4f7r9vmlc-3ISZfbtt0-fhayfhTyKMgMdwLgn8tQCO-CBwM-W9Uig0BgQZfZ4cZ492vM3r0dRZkLewdOg1QAD4bRFY5xCprAkU5gNi_xD-hZLkI-PFjpPFEDzDr4NOsCA00Q2QOc80JX8S2zFSwfgATkis45B26BbAgQ1oEfF5EG5cUKvg7MgZM2DCwToCQa0raEWmlTs4_PkKQTt7Fc9TkZ3WiFrZ9cRhMz3h-JwzIU87uASYTzjOBkS-Vlk6VNmy6dbCBDZOcyNdzNrSxCErDEWauIfG-nMznBDKWRtyIr8XshzfCnvQFsmy0LWOoZDbJSfYS0Sk2NAH1N_Fmt_0qMs3gfhSCkuPoDI7yHxmuAeQciLkBcQskpP1esPa0zzNkhcf5ibyPDyKtVdJlnHJdvCjZL3lL0x2Bm0PWx_lbClUfPWmOsI269xy72-JtV4oh_pLCEIgLa9xUQRiTILu6X-n1FYUWhuIh8DdfifUK7oNTaG0r5_JH36Z9ZXNGT5Vf1hbgJ7bfuY8CxkvRf5-eHjL4_vk1P-zQeto0WrlqiNANz0soOHaCtt-4WHwXTa7yK0x1eVuw7wDWLsj--6P2keAC1oa6LaRJm9gSgzeHKzaQGvTrffe3ZhjJI9YbVn1H3-IWGzYR6TKXEBHE0ZwD3ZhDs6ChXPaAB9P49JhMe1YU8cQTKqv4FpnJxH_wKddyM0c9eR1_-mVtG0TNjeKHp4-OMzKLTgOiYLnkZ3pXWLnyx8_fLxDu6-_C6zfQUHWe0UjsVjBKkDTMhMPnldlNk0vAStwuM8tci07gGh1dhbF1grMNiQgWbWhsHZ9XSJzMRBUCk3W14OHmzczLAX8hCX8Uqis_Bcl9uyiGb6kTAnMy-nHYbglEamNsaNieuE6HLTalpHS0F5PbHzEIjnaZ38HIIOTO22eYm97tykjeNNe8rbY37EDZ321VGW-0NeFJvhVHWIdUFNh11Hqqqrqqhq1VWHOiuRWtzok8xkuc_kXmaFlMVOHQ75oaoa7DJVF7IVRUYjarOLNtw53290CDOdZF7kZbZJzIX1TknOXa8Tf4oJ22bugygyowOHWwnWbNJFtGQc7iHKdJH3916E24WBi0TflLSZvTkNzFOIJ1k6lnrNw9zslBuFvMSO67_t5N1fpFjIS5ogCHlZh7ie5H8BAAD__x3WR54">