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

    <tr>
        <th>Summary</th>
        <td>
            Superfluous `dynamic_cast` not optimized out
        </td>
    </tr>

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

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

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

<pre>
    ```c++
struct B
{
    virtual ~B() = default;
    void foo() {}
};

struct D : B
{
    void foo() {}
};

void bar(B* b)
{
    D* d = dynamic_cast<D*>(b);
}

void qux(B* b)
{
    D* d = dynamic_cast<D*>(b);

    if (d)
    {
        d->foo();
 return;
    }

    b->foo();
}
```
With x86-64 Clang (trunk) `-O3`, the preceding functions `bar` and `qux` does not get optimized to just `ret` ([Godbolt](https://godbolt.org/z/TveWY8fjW)):
```asm
bar(B*): # @bar(B*)
        test    rdi, rdi
        je .LBB0_1
        lea     rsi, [rip + typeinfo for B]
        lea rdx, [rip + typeinfo for D]
        xor     ecx, ecx
        jmp __dynamic_cast@PLT              # TAILCALL
.LBB0_1:
 ret
qux(B*):                              # @qux(B*)
        test rdi, rdi
        je      .LBB1_1
        lea     rsi, [rip + typeinfo for B]
        lea     rdx, [rip + typeinfo for D]
        xor     ecx, ecx
        jmp     __dynamic_cast@PLT              # TAILCALL
.LBB1_1:
        ret
typeinfo name for B:
        .asciz "1B"

typeinfo for B:
        .quad   vtable for __cxxabiv1::__class_type_info+16
        .quad   typeinfo name for B

typeinfo name for D:
        .asciz  "1D"

typeinfo for D:
        .quad   vtable for __cxxabiv1::__si_class_type_info+16
 .quad   typeinfo name for D
        .quad   typeinfo for B
```
Given that the code emitted for both `bar` and `qux` are identical, Clang is able to tell that the extra logic in `qux` is a no-op, but is unable to omit the `dynamic_cast` logic. However, using x86-64 GCC (trunk) with `-O1` and onwards, it emits optimal code ([Godbolt](https://godbolt.org/z/7vsozMGMW)):
```asm
bar(B*):
 ret
qux(B*):
        ret
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0Vk1v4zYQ_TX0ZWBDpj590MGy1mmBLLZoAwQ9GZRI2czSopcfjpNDf3sxkj-ixMl2F1vCACVy3uO8NxRpZq1ct0LkJC5IXI6Ydxtt8j_ZWnyV7TobVZo_5SQJ-l9NaIG_oCTB3DrjawfHN5IeHwAA9tI4zxT8UxCaEToDEpbARcO8ciR8Gaglh0brU1hakLQ8EZbn0MGCJZBwfn3ZH2HrgitmCM0KQudQETq7wlniHO8FPLVsK-tVzawj4QJnSPiJ0KyDntnPS16W-eYPv3yZM1Q2QGjGz7w4NuDGxsck_HS25lIDI5w37aAmrwTgUHUdfYk8bZD-9V66DRyyZJxEsFCsXWOCzvj2a1eWJBh_CTGYLsBtBOyMqAWX7Roa39ZO6tZiENYmCYC1HN_QwiQAroWFVjtYCwd65-RWPgsOTsODtw4DjXAYiKnGxY3mlVaOxCWh2ca5nSXhnNAloct1PzXRZk3o8pnQ5d1e3P-dNQ_3qBFlzl-pY3bbj1y2TR8HhIZAomA4PiiAE9Zhb7hE3dgN5h8ETG6LIlhNh-NKsK43tsORuDByB4QW4J52QraNhkYbwK_3LdDww0eg8g3ooE3Xi7oDYjfMcruD1WqwQ6Pgj9s7GDR0427---1ifnvb40_STpbivuufLp_G0coP29HnIeitzx-Y3DVMZ_pLne5L-z-4je1nHZ--dPzYzsafc2vZVhyVvQ6eMFvLZyCUTgtC6ctj4ZUnb5DfPON4JDtWqZ5-taoPB1bJfZdUOF-tasWsXSHTCqkILabJdZpryV5L5jxdvqelE1N-JOYK9L-IsfIjPe8LKb-j-KXY4TF7I_eiBbdhrjtGa80FiK10TvAOVWm3efcgZUaA5KJ1smYKd19_UEsLnUanwQmlLuzi4AwDpdeyBtm-IEIEtHqsd8hSeYcjvj2x6K3sCUgSDHZxEvRsE_hNP4q9MAj3Fq-B49Vxs1gMLo5H2esZf5me9Oj2kRluESpdJ972twJTvR8_cQ2ke6ufP998_vFr4Htn2ztf4pl4xPOQz8IZG4l8mgZRNguzJBpt8ljQII5nPGXVjIkZZ1GWNZSmWRbWCa_ZSOY0oFEwnQbTMEyjaBKLWchj1lRNxlJBAxIFYsukmii136LYkbTWizxNkyAZKVYJZbs_gZS24hG6SfxI4nJkcsSMK7-2JAqUtM5eWJx0SuR_-Z0wjfLa22t1xvv6cldr70beqPxVHaTb-GpS6y2hS6Q_duOd0Q-idoQuu6QsVgiT_jcAAP__Pivw2w">