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

    <tr>
        <th>Summary</th>
        <td>
            Missed optimization: right shift (>>) with first operand up-cast to longer types
        </td>
    </tr>

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

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

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

<pre>
    Clang missed some optimizations regarding right shift (`>>`), when the left operand has the same value but up-cast to different type widths. (For example, `int32_t` and `int64_t`.)

See the test code below. This test code were written for a GCC bug ([GCC bug 114406](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114406)), but it seems like Clang wasn't perfect in optimizing these tests.

The expected outcome for the test functions would be all optimized to simply `{ return true; }` statements. The actual results between GCC and Clang are noted in comments (GCC is a little worse in optimizing these).

```c
// Tested in Compiler Explorer (godbolt.org)
// GCC 13.2 x86-64 with '-Os' option
// Clang 18.1.0 x86-64 with '-Os' option

#include <stdbool.h>
#include <stdint.h>

bool test_rshift_2a(unsigned char count) {
  // Positive constants with different bit width
  long long a = 0x7FFFFFFF >> count;
  long long b = 0x7FFFFFFFLL >> count;
 unsigned long long c = 0x7FFFFFFFU >> count;
  unsigned long long d = 0x7FFFFFFFULL >> count;

  return a == b && c == d && (unsigned long long)b == d;
}
// test_rshift_2a
// Both GCC and Clang fail
// (Both do not recognize 0x7FFFFFFF and 0x7FFFFFFFLL are identical
// and that the load instructions can be merged.)

bool test_rshift_2b(unsigned char count) {
  // By the C standard, 0x80000000 should be interpreted as unsigned
  // but ultimately the width and signedness do not matter
  long long a = 0x80000000LL >> count;
  long long b = 0x80000000U >> count;
  long long c = 0x80000000 >> count;

  return a == b && b == c;
}
// test_rshift_2b
// Both GCC and Clang fail (details same as above)

bool test_rshift_4(uint32_t x, unsigned char count) {
  // 'x' is known to be positive despite the signed type up-cast
  uint32_t a = x >> count;
  int64_t b = (int64_t)x >> count;

  return a == (uint32_t)b && (int64_t)a == b;
}
// test_rshift_4
// Both GCC and Clang fail
// (Both missed that type width do not matter here; GCC also missed
// on SAR and SHR not merged.
// Interesting note: GCC can omit the (a == (uint32_t)b) comparison,
// but only when the ((int64_t)a == b) comparison is presented
// first. In this particular example, GCC missed as well.)

```

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJycV1Fv4roS_jXmZVQUnJCQBx4KXe5daa_u0e6e58pJhsRnHTuyJ4Xurz-yHSiwRadnEaKK42_GM98346lwTrYacc2WG7Z8momROmPXn46DMhZtUs4q07yut0roFnrpHDbgTI9gBpK9_ClIGu3AYitsI3ULVrYdgevknoDxFcsTln7y3zxhvGR8C4cONVCHoHBPYAa0QjfQCRcWnegRXoQaEaqRYBweauEIyEAj93u0qAnodUA4yIY6N_dOdsYCHkU_KPQOWJ5ITSl_JpYn4I3HlTwLK3N_juSJJY_x9xti8EzoCGrTIFSozGEO3zvpLlYPaBEOVhKhhr2xIOA_2y1UYxsCXW5OT4tFliU5Wz4xvuqIBsfSR8Z3jO_aup63epwb2zK-q8b2p1RKML5znTk8V2M7r1vJ0p1sWPo0mfFJC3nz6ZAEDrF3oOQPhMjKQTjNeEEwoN1jTSD1iR1PCHXoYnBufhn29w4BjwPWhA2YkWrPqg_rnIv9qOtI78GMqoEKQSh1so2NJ8XJflCvPsGs2IBFGq0GsiOydAOsePIMOBKEPWpyPqcIoqZRKLDoRkUOKqQDog7J9GTFqIRF0MafTWqoTR_wPtF-m3QgQEkihXAw1uF7MTNeXgXszxi-9fQcKIHv6CYvW9MPUqGFk_q9u9Y0lVEUKSuvkP4ki3TO4bjKH_IMDpI6YLx4-L9jvAjnMfoKEUNbrOaLefIR1IRNpa7V2CCwdOuoqYxR887X1PvvpabL1-HXYwKrzzbU5jMXjK9GHaq_gboTFmozamK8BFZsIgpgOvgfxkmSLwi10Y6EpyKc-60mK0mxJE9IZXQbfwSw9AmSY7GLH4gdYfKXbn5FVDeIL1_uYM4BvGHrG-yf99y9g21usfccn2xMgg8RemgFjOeM5_EUfqU5rVym--yR8bI673yzXjxdyeaGt8tXG0PdTeXshVRXexhfhW2N8RUFFmvTavkTLynx8Kt8-_qTDWqStbg257dSJyj2cCN87Tiy49QraqF9p-jRttjc9tpfZVj9GxluXoPTrW8puhG28X0xOa6S-AHXnRqV1IR2sOhLW7gz1zf2wg2jSPaCUEXbQcMhxojQ6Nwpc70gQntf4Kdz3JXrOxI_Ye7K9Fdln8P9PWmeBVd_THDVRwTnRdYgCalcvMKFA1GZF_wnAWSe_-m6hqPn88NqYLw4-pYpHfzQ5qD9fVQhDKde1aAbJMXLfTIZJodppjj3gZP3SOPxHhHTBDExx_jqNFLw8g7mHhUXIccGcO4QbybfePsQS9lvd4VpqIsVfR6sriUPHdpwowebypkJdWXQaPj2-DW4_PbfrxE9NYHLbZ99ZaIjf0_7C56lj8Gs7xuml7GtML66ly2vhdr0g7DSGc349sq6r2ij1evblOlnszuJvbLkZTRYdKjpJrC9tI7m8Nnb85uEJVmPSlwNnT6EKZXCwQGVuu195_kjPs6addqUaSlmuF4Ui6TMspIvZt26yEUhCrHCpMiXmJbLIiur5R6xLBd5ljczueYJz5KUJ4uMr7LFfL9P67zI0uWC16KuBcsS7IVUc6Veej-5zKRzI65XyzItZ0pUqFwY-DnXeIDwknHu53-79piHamwdyxIl_dR4tkKSFK7_F6O8_AfAc3g7-Mepn5dxUAg5PA_7F1O972xog_LcbLRqfTMxS-rGal6bnvGdP8j052Gw5i-sifFdOL5jfBfC-zsAAP___8vlxg">