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

    <tr>
        <th>Summary</th>
        <td>
            [RISCV] Wrong register usage for `amocas.q.aqrl` inline assembly
        </td>
    </tr>

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

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

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

<pre>
    # Problem

Atomic Compare-and-Swap instructions (amocas) are part of the experimental _zacas1p0_ extension. For more information on `amocas` instructions, see _Chapter 16. "Zacas" Extension for Atomic Compare-and-Swap (CAS) Instructions, Version 1.0.0_, from the _The RISC-V Instruction Set Manual Volume I_.

During code generation from inline assembly, the compiler "self-sabotages" itself by using the wrong regsiters.

# Steps to reproduce

Suppose I have a file `bug.c`. I am trying to use the 128 bit version of `amocas` from inline assembly, like this:
```c
__int128 amocas_q_aqrl(__int128 *atom, __int128 value)
{
  __int128 ret = 0xcafe;
  __asm__ __volatile__(" amocas.q.aqrl  %1, %2, (%0)"
           : "+r"(atom), "+r"(ret)
 : "r"(value)
           : "memory");
    return ret + value;
}
```
I am compiling it like this:
```
clang -menable-experimental-extensions --target=riscv64 -march=rv64imafdc_zicsr_zifencei_zacas1p0 -c bug.c --gcc-toolchain=/usr/riscv64-linux-gnu-
```
I am getting the following error:
```
bug.c:4:24: error: register must be even
    4 | __asm__ __volatile__("  amocas.q.aqrl  %1, %2, (%0)"
      | ^
<inline asm>:1:23: note: instantiated into assembly here
 1 |           amocas.q.aqrl  a0, a3, (a2)
      | ^
1 error generated.
```
My setup is the following:
- Running on Linux 6.7.12-amd64 SMP PREEMPT_DYNAMIC Debian 6.7.12-1 (2024-04-24) x86_64
- For cross compilation, I have installed gcc-riscv64-linux-gnu version 4:14.1.0-2
- I have built llvm and clang from source. At the time of opening this issue, I am on branch `main`, last commit is https://github.com/llvm/llvm-project/commit/2190ffa0f7e874d04fd0f750142135faa5df5d6b
- I can also reproduce it with a pre-installed version of clang 17.0.5

Note that other variants of `amocas` work fine, for example:
```c
long amocas_d_aqrl(long *atom, long value)
{
  long ret = 0xcafe;
  __asm__ __volatile__("  amocas.d.aqrl  %1, %2, (%0)"
 : "+r"(atom), "+r"(ret)
           : "r"(value)
 : "memory");
  return ret + value;
}
```
The above compiles. Currently I have had this problem only with `amocas.q`, but it might be the case that `amocas.d` causes similar issues on riscv32.

# Current workaround

I can get this to compile by tricking the compiler into not using register "a3":
```c
__int128 amocas_q_aqrl(__int128 *atom, __int128 value)
{
  __int128 ret = 0xcafe;
  // must clobber "a3" register due to a compiler bug
  __asm__ __volatile__("  amocas.q.aqrl %1, %2, (%0)"
           : "+r"(atom), "+r"(ret)
           : "r"(value)
           : "memory", "a3");
    return ret + value;
}
```
I'm leaving this here in case somebody experiences a similar issue. I would've gladly looked more into it, but I've got no idea where to start.



</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMV1tv2zoS_jXMy0CCREm2_OAH126AAJuDojnoYvdFGEkjmVuKVEnKSfrrF9TFl-ak2BaLxRqBFcnUcC7ffN8QrRWtItqy7APLDnc4uKM2W-zJkaqOhHelrl-3jCfwyehSUseiA4t20_fO6U5UsNddj4YCVHXw9Iw9CGWdGSontLLAeI6drtAyvgE0BD0aB7oBdySgl56M6Eg5lFB8xwpt3EcF0IsjZYVWIdxrA502BEI12nTorYJWwFbRbHcV3ezI-B4sERT7I_aODMSrEBjn_8TRCQ4fF-PQaAPvBcF4vt89eacffjD-hcz4dhxGYVT4J43R3RhP8eeR4PPD0z74cv0aPJGDR1QDSvii5dARPBThdSoPgxGqhUrXBC0pMlOco2GhpFAEaC11pXz1G_q9Kt31QpLxsVmSTWCx1A5bGoMUzj-D8hUG6y37N56NVi0Yaq1wZOyNA77ET456C06Dod7oeqjoesXT0PfaEjzAEU8ECI2Q5MtQDm1YsVUUwgNgB868jhtqGCyN-8Y8h1I4OM2J081t9d6LUoqv3oCwLFm8XEXTXzXdF4VQzpufjBXfCvxmJOP5-QfGd-h0582dn51QDsT4Zra5_jD9A5cVhhyw5ADRS4UNseRqBdquKKAoTlqiE5KKgvHcZ3xyIfwWehcAGM9ivyvjGZ-uOeNZ5LflfDF3_rBk5-vI-AczXvLJ6c305tVzQ-7s-fLW_NNtWG-Nd9Rp8zqu3VyFBD7awagpaP5hTs-ygK0PP-R-uh1rPWHQl1u4n5Vruq0kqhaCjhSWkoLr5g_OHW8hCByalhxLDkbY6rRKIejQVEf_4LRKRYdNXRXfRWVN8V00pCoSZ_KAoIIRkRAEbVUFTmtZHVEolhwYvx-sYfx-thtIoYaXoFVD8H6MLTm3dFCjpdTP_o6M0ea9QKeOSHYpS3bcf52X--4T1rNSN1gHJQGdSF1KkQJb73-Gst-GmbfLso-zv8n-3G8dSz6yZBd7XxPvotKO_NWTKion0FENQjl9bk44kpm5AeLR8uXzg38Yea8wmX1D_gNAb9yKpzwtDEh1-JfpfXwFS27oQdjbqpzrEcDnQSlfJ63gb77IsArXYcwD7OpVCk-Pn-DT548fHz_9WRz-8cfu8WEPByoFqmVd7L3lEU-DKA146nXgJV8Vq3TZwOtSZbS1cxOMhO2jnPlxzJ6UVINH4RvAncnQwyNOwziMAr7Ynk2Ug5AOpDx1gKqGqX1GsrR6MBWFsHNjApzoyLOq7klNUBUWhLWeDvYTK2sFpUFVHT31dr4dVmNlJFrnI-iE8-k8OteP_cvvGb9vhTsOZVh5Krr3fsyXoDf6X1Q5xu-nVxm_5_EmahqMmjXl67SO0qaOmnUWxSmPk6xBzOomq1flJcYKFaC0V3LjWeRZuCMg9IaCSwqvlGPKQrwOozC7lqc_tPPsgw60O5KBExqBytk3avOszVdohBpz4ycAesGul_SuyEivmrPA1IvAjA-vxGW8f1dY5CS8vy4qSzvVv9Duv6clb-Tir1Xl51ryW0riZyYs9ek80tgQ9oMxpJx8XXrhiPUE636aQ0Er-TqB5Vzd8NsM6nJwHkqdaI8jx47jEtoZH5f1tcdDhYMlC1Z0QqKZ2sb6fhl7NuFvxqTZtxFIaPSg6usVE65bcpO7Ti9R-VnMGVF9XcTkPMCN3Kq0m0e1s0Qwzj1x8v-f8WeihUm7KqnL8srLi9_1QD5uvERYDu0vgH3Wjv_FBPUfov5ns9T-Uqf_ylzF-LoDSXg6M7lXWxBqgrDVHflD2Xx28sOPBbyFr5_En_Uga8bXJ4JWYi1fQWr9lerlMOU0eN6emuVhXqgdKA2iJoTncVenwTo07rYJxu-7epvUm2SDd7SN1zzP8niV5HfHbZ1Gm03OsyhvsjyhdVSu401cV1Ec52laZndi64U1juIoXidJloerimgVbfK4zuM4K2OWRtShkKEXm1Cb9m4MaxvHcb5e30ksSdrxzMq5oudF6rg_wprtqFDl0FqWRlJYZy9mnHByPOz6M9oXlh3g78uZaILuYLGlURWuWGWE43TMvDmj3A1Gbn9ZMSeCYfx-jua05f8OAAD__0x_pTo">