<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/71080>71080</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Register-or-memory inline assembly constraints generate suboptimal code
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
davidben
</td>
</tr>
</table>
<pre>
If I'm understanding GCC inline assembly syntax correctly (I may not be), a constraint like `"r"(x)` means that `x` must be passed into a register, `"m"(x)` means it must be passed in as memory, and `"rm"(x)` allows the compiler to pick whichever is more convenient.
Since the programmer does not necessarily know whether `x` is in a register or was spilled to memory, an `"rm"` constraint seems preferable when possible, since it allows the compiler freedom to generate code as it like. GCC seems to generate good code given `"rm"`, but clang seems to just interpret it as `"m"` in my testing:
```
void RegisterInputConstraint(int x, int *y) {
// This is free
__asm__ volatile("nop" : /* no outputs */ : "r"(x));
// This forces the compiler to load from y.
__asm__ volatile("nop" : /* no outputs */ : "r"(*y));
}
void MemoryInputConstraint(int x, int *y) {
// This forces the compiler to stash x to memory.
__asm__ volatile("nop" : /* no outputs */ : "m"(x));
// This is free.
__asm__ volatile("nop" : /* no outputs */ : "m"(*y));
}
void RegisterOrMemoryInputConstraint(int x, int *y) {
// This should be free, but Clang treats it as "m"
__asm__ volatile("nop" : /* no outputs */ : "rm"(x));
// This is free.
__asm__ volatile("nop" : /* no outputs */ : "rm"(*y));
}
```
https://godbolt.org/z/saWv77Yhh
This seems like a missed optimization.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyslltv6zYMxz-N_EI0sOXc_OCHnhYZ-jAM2AYMeypki7F1qoshykl8Pv0gOW3S9pxhlwBBbhLJP3-kRAsi1VnEmq2-sNVjJsbQO19LcVCyQZs1Tk710x6eGN8YGK1ET0FYqWwHPz08gLJaWQRBhKbRE9BkgzhB67zHNugJGN8-gRETWBegQcYrxh9AQOssBS-UDaDVCwJb54xzzzhnfHuK29Y5GBSWIPQixPVT-muk6AeGGFKCssGBAI-dooA--p49me95UuGzPQgCg8b5KQmz8lXKBw9Ca3eMYhBaZwal0UNwMKj2BY69ans8oAdFYJyPW-wBrUIbFix_ZPn9_P6bsi0mH4N3nRfGoAfpkBIeiy0SCa_0BC_WHeHYY-jRvyWvKAl-Sxech6MgoEFpjTLquU7lXSbr_Jo5IRqCweMevWg0xlAWBkekGo3RnJJUFb6b-N4jSmdiwA4tehHiooyNEE1iRRepP-Y419s65-S8t1MH_KgxRm7GAK0WtrtYf41VUzagHzyGpIquCx3ZWDATBKSgbMfK-2vscef8Sj8PTkn49czwyQ5jeHgjw_g28jlFIfEL4_cT4xWwzZfZGACA8R3jO_i9jwWhROO8-PwsyDw_w8FpEVQkuWWcWzcwzoGV97PpPVgHbgzDGChGiM7mxXcngFes_EHUvfMtfu5G7YSEvXcGpsXF8FaiziyudbHN4zXoRPbn1IL_l-sPMqQgqIfTpdVvmaf5Z_DPJV_cqubmX-F9bdxf_G1AU-9GLeOdmPr4fAAf0gEMHkWg1_N2VnrDvvpvwG8Z-m-hv782-hAGijdLUtY52TgdFs53jO--Mb4j8cdhs_mz769LNiNO91iacwKMSpPHDUEZ9U0E5ewik3Upq7ISGdbFutpWy-WqyrO-bptNu63afFnuG75aF8VmKbd5Wa1FUa74UmSq5jkviyLnxSYvi3whBS9xX-aF2IqlbCu2zNEIpRdaH0xUmymiEetNkW_zTIsGNaXpz7nFI6TFiGb1mPk62tw1Y0dsmWtFgS5eggoa69dmvHP-bj6Pnx4JLlOHLlOAxiYBEDrNgmz0uv7AV4V-bBatM4zvYtTzx93g3VdsA-O7pJUY36Vc_goAAP__Z5as5Q">