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

    <tr>
        <th>Summary</th>
        <td>
            Frame pointer corrupted by __cpuid after #85193
        </td>
    </tr>

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

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

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

<pre>
    "[InstCombine] Support and/or in getFreelyInvertedImpl using DeMorgan's Law" (https://github.com/llvm/llvm-project/pull/85193) in isolation is a correct and innocuous InstCombine patch, but it appears to be triggering a latent miscompilation bug that is particularly noticeable when using the cpuid instruction in the presence of register pressure.

## Context

The `cpuid` instruction writes to registers RAX, RBX, RCX, and RDX. Since RBX is used as the frame pointer (if enabled), it typically needs to be preserved, such as by exchanging it back and forth with another register. For example, clang's `__cpuid` macro has:

```
/* x86-64 uses %rbx as the base register, so preserve it. */
#define __cpuid(__leaf, __eax, __ebx, __ecx, __edx) \
    __asm("  xchgq  %%rbx,%q1\n" \
 "  cpuid\n" \
          "  xchgq  %%rbx,%q1" \
        : "=a"(__eax), "=r" (__ebx), "=c"(__ecx), "=d"(__edx) \
        : "0"(__leaf))
```
(https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/cpuid.h#L268)

## Reproducer

```
git clone https://github.com/pytorch/cpuinfo.git # commit 6543fec09b2f04ac4a666882998b534afc9c1349
cd cpuinfo/src
clang -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -O2 -I../include -I. x86/isa.c -msse4.2 -gmlt -c -o isa.o 
llvm-objdump -D -S isa.o | grep cpuid -A 1 -B 1
```

### clang at revision cf5cd98e74275ed6198b4bbe76cec250ade2c186:

```
      75: 48 87 f3 xchgq   %rbx, %rsi
      78: 0f a2 cpuid
      7a: 48 87 f3                      xchgq   %rbx, %rsi
 # Editor's note: this works; it is using %rsi as temporary storage, which happens to be available.
--
      99: 48 87 f3 xchgq   %rbx, %rsi
      9c: 0f a2                         cpuid
 9e: 48 87 f3                      xchgq   %rbx, %rsi
--
      ce: 48 87 cb                      xchgq   %rbx, %rcx
      d1: 0f a2 cpuid
      d3: 48 87 cb                      xchgq   %rbx, %rcx
      # This doesn't work, because %rcx is also modified by cpuid. As a result, %rbx is corrupted, and subsequent use of the frame pointer leads to a segfault or memory corruption.
--
     127: 48 87 f3 xchgq   %rbx, %rsi
     12a: 0f a2                         cpuid
 12c: 48 87 f3                      xchgq   %rbx, %rsi
--
     a54: 48 87 f3                      xchgq   %rbx, %rsi
     a57: 0f a2 cpuid
     a59: 48 87 f3                      xchgq   %rbx, %rsi
--
     a72: 48 87 f3                      xchgq   %rbx, %rsi
 a75: 0f a2                         cpuid
     a77: 48 87 f3 xchgq   %rbx, %rsi
```

### clang at the immediately preceding revision (6d30223f7c66ca07ea7ff40ffba426f2dc789e74) with the same compile command does not use %rcx:
```
      75: 48 87 f3 xchgq   %rbx, %rsi
      78: 0f a2 cpuid
      7a: 48 87 f3                      xchgq   %rbx, %rsi
--
 99: 48 87 f3                      xchgq   %rbx, %rsi
      9c: 0f a2 cpuid
      9e: 48 87 f3                      xchgq %rbx, %rsi
--
      ce: 4c 87 fb                      xchgq   %rbx, %r15
      d1: 0f a2                         cpuid
      d3: 4c 87 fb xchgq   %rbx, %r15
--
     122: 48 87 f3 xchgq   %rbx, %rsi
     125: 0f a2 cpuid
     127: 48 87 f3                      xchgq   %rbx, %rsi
--
 a55: 48 87 f3                      xchgq   %rbx, %rsi
     a58: 0f a2 cpuid
     a5a: 48 87 f3                      xchgq %rbx, %rsi
--
     a73: 48 87 f3                      xchgq   %rbx, %rsi
     a76: 0f a2                         cpuid
     a78: 48 87 f3 xchgq   %rbx, %rsi
```

N.B. Memory sanitizer with track-origins was used as a convenient way to increase register pressure, but I believe this could happen without sanitizers.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzUWE1v4zjS_jX0pSBDor4PPiTxa7wBZnaB9Bz6FlBUSeK0RKpJKrH31y9ISY4zk87Gm1xWMCKFFKueKlY9VSIzRrQScUfSW5LuN2yyndI7203aWCXrTaXq045QStLbe2nsnRoqIZGke_g2jaPSFpisCT0oDUJCi_agEfvTvXxCbbG-H8YeJiNkC3v8XemWSUJzA7-xZ0IpEFp01o6GxDeEHgg9tMJ2U7XlaiD00PdP6y0YtfoTuSX0ME59T-ihSKMyJrR0aoVRPbNCuSdgwJXWyD0yEFIqPqnJwAV8GJnlHaF3UE0WhAU2jsi0AaugQrBatC1qB5pBzyxKC4MwXA2jWPRUUwu2Y9YpHJm2gk890_0JpLKCI6t6hOcO5WK77RD4OAmHx1g98Rms9BOjRoOSI6gGNLbCWNR-0EwatyTck_Bm-UtjQmO4U9Li0V7O_NEhkCz0OkgWvlLzrIVFb9sq3cDDzXdn_sPtfLvzN-evh_33LXwTDs7D7Xdn3mSwBmY81EazAWFUQjqMhBaiAZTO2prQ0skQFuxpFJz1zhmI9epUb6V-ci_egZl452RWJ8Aj75hsnZeEhYrxHx5Ho7Tt4FnYDphUtkN9Rr8FF214ZMPYo5PGeyZbH1YkCx8fz04YGNcKOubD69KNWbj8Fq8eCL2BY5EFWeLMNUBoqqvjanXFDJ61e_jqbA4IuwVCvZB1j2psXJCtSGjx-Ngja9zKx0dkx-WhWh_4-lAfXUCT9G4WBQDw-MjMQGjhsgWOvGt_gkM3AyT0jtD0Z0TSO-nT6bzSvz6r_9vc-Xpf5ltrSOxFk3jP3M1Z5u3xWz9P6CWvFwMvZvh5CX89UZ8n3nDAhdpwfW_2Zul-b2_o9axS9aoi9DAwIQk9LBF16IUb_H9kNWrjxp1Htx2h8W80K170X2bnA45a1RNH_U7MtcIC75VEeAfpeLJKO57yemWjtm6Z08HVMAgLWZrEDfKwrGgTJownLMuyoqBlWVRpnLCGlzyKkwUlr2GRQ-jBaL6MOlMhaAyTwop_IYn3Aw5Kny7GgnkksJrxH4HSohXSkHhPIWikCtQgbOCpIVipIfgnheB-uyX0ICTvpxrdvy7H3IhhWw7BYAwmWwpBO_QWAg6BAjelYEbmd0hVf9bTMEKwh-DbOp3fQatxXCg1uIEIgluI3g6Gi73xrvP2Mgsan4Rx_MiblNdlgXlC8xTrLCqLKqkqzDOOnKYhq5HyqMjeZ5E5UvPUxWpSQJFDE6_JBefU8k9GvFpSuCVhA4wuGXs5yV7Je_P6D0qc0f9XC6u0p0ipLDqZthMGnpX-YUh866jXU72j4Xm1Jz8cRqWZPoGxSrPWs-1zJ3gHnSuZciV39sRE78rAUq6C4NKIsrzaKSV_ccqvrktnlfhZP72GzC_k8eoaefx4KaeO3tncOv4aJW6H_3DbWSs0rr-yfmN9f4OcTQaXRb496o2CQdWiEVi7AjxzGty4zkmjmXq7aqn8AtdNTaOdC7crzWaqDP6cXFfkRKvmjdagRzZXfgYG24ZNvQWlYWGWRaRQ8q14iWh-bbxElF0XLxHlXxowLE0-naiznPzXAcPS8mtB5_TToNnMeB_3_Kz4mh3-KKG7KBTDgLVgFvuTa9E41o7RzlRPaJHVcUhp3OQ8yzgLc2R50yRh01QsoVlDa54XJeaJa0R8--nEGhfbc__v74PLA5dtjk7hJcFeSsT_RnE4h0P56cia37nk7b_h_ThJX0HR3Eu7ij2j9FcU_dEAXql7Vf6-nr-wG72e3dJfe_WvbPmZKGBp-kUs9k7YsvTDYfshDou_BnKe_Tc8VnyWx_6xvd3C73NZXNttvRDPZbcNz-zlU5wBV_IJpXA1-JmdXKEVkmu8_FA9HyGs5xz3UGEv8Ann3o-rqa-XPs4rVJN9gWCWyrypd3FdxiXb4C7KoyjN8yguN90uamhTFBEvyrBKGxqyKi7LgmOdRlkdNXQjdjSkSRjTnNIwjYttE-c0rpo0KYom5kVGkhAHJvqta_S3SrcbYcyEuyIrinDTswp748-lKJX4DH7Sn0TtN3rnPw6qqTUkCXthrHmRYoXtcXd41Y-cmxjX8Swf5sCa-RQj9mdJm0n3u6u_Gz0q92noUf87AAD__1hCUic">