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

    <tr>
        <th>Summary</th>
        <td>
            [GISel] Missing combines to expose common subexpressions and eliminate them
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            llvm:globalisel
      </td>
    </tr>

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

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

<pre>
    When running GISel on the given input IR, we end up generating essentially a one-to-one mapping with the input IR whereas most of the computation is just duplicated.
SDISel performs a much better job by doing `instcombine`-like optimizations that allow it to simplify the IR and eventually exposes the CSE opportunity.

This is not that surprising given that historically GISel has had a garbage in garbage out approach, but it may make sense to strengthen GISel combines for optimized builds.

Note: I observed this with AMDGPU but I suspect it affects all backends.

# To Reproduce #

Download the attached IR or copy paste the snippet below and run
```bash
llc -O3 -march=amdgcn -mcpu=gfx942  -mtriple amdgcn-amd-hmcsa -global-isel=<0|1> repro.ll -o <sd|g>isel.s 
```

# Result #

GISel ends up generating two `fdiv` instructions whereas SDISel is able to CSE the whole thing and produces just one.

GISel:
```asm
        v_div_scale_f32 v1, s[0:1], v0, v0, 1.0
        v_mov_b32_e32 v7, v2
        v_mov_b32_e32 v2, v3
 v_mov_b32_e32 v3, v4
        v_rcp_f32_e32 v4, v1
        v_div_scale_f32 v5, vcc, 1.0, v0, 1.0
        v_fma_f32 v8, -v1, v4, 1.0
 v_fmac_f32_e32 v4, v8, v4
        v_mul_f32_e32 v8, v5, v4
 v_fma_f32 v9, -v1, v8, v5
        v_fmac_f32_e32 v8, v9, v4
 v_fma_f32 v1, -v1, v8, v5
        v_div_fmas_f32 v5, v1, v4, v8
 v_div_fixup_f32 v5, v5, v0, 1.0
        v_div_fmas_f32 v1, v1, v4, v8
 v_div_fixup_f32 v0, v1, v0, 1.0
```

SDISel:
```asm
 v_div_scale_f32 v1, s[0:1], v0, v0, 1.0
        v_rcp_f32_e32 v6, v1
 s_nop 0
        v_fma_f32 v7, -v1, v6, 1.0
        v_fmac_f32_e32 v6, v7, v6
        v_div_scale_f32 v7, vcc, 1.0, v0, 1.0
        v_mul_f32_e32 v8, v7, v6
        v_fma_f32 v9, -v1, v8, v7
        v_fmac_f32_e32 v8, v9, v6
        v_fma_f32 v1, -v1, v8, v7
        v_div_fmas_f32 v1, v1, v6, v8
        v_div_fixup_f32 v0, v1, v0, 1.0
```

# IR Snippet #
```llvm
define void @foo(<1 x float> %in, ptr %out, ptr %out2) {
 %t1174 = insertvalue [4 x <1 x float>] zeroinitializer, <1 x float> %in, 0
 %t1175 = insertvalue [4 x <1 x float>] %t1174, <1 x float> %in, 1
  %t1176 = insertvalue [4 x <1 x float>] %t1175, <1 x float> %in, 2
  %t1177 = insertvalue [4 x <1 x float>] %t1176, <1 x float> %in, 3
  %t1178 = insertvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] zeroinitializer, [4 x <1 x float>] %t1177, 0, 0, 0, 0
  %t1179 = insertvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] %t1178, [4 x <1 x float>] %t1177, 0, 0, 1, 0
  %t1180 = insertvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] %t1179, [4 x <1 x float>] %t1177, 0, 0, 2, 0
  %t1181 = insertvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] %t1180, [4 x <1 x float>] %t1177, 0, 0, 3, 0
  %t1182 = insertvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] %t1181, [4 x <1 x float>] %t1177, 1, 0, 0, 0
  %t1183 = insertvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] %t1182, [4 x <1 x float>] %t1177, 1, 0, 1, 0
  %t1184 = insertvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] %t1183, [4 x <1 x float>] %t1177, 1, 0, 2, 0
  %t1185 = insertvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] %t1184, [4 x <1 x float>] %t1177, 1, 0, 3, 0
  %t1186 = extractvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] %t1178, 0, 0, 0, 0, 0
  %t1187 = fdiv <1 x float> splat (float 1.000000e+00), %t1186
  %t1188 = extractvalue [2 x [1 x [4 x [1 x [4 x <1 x float>]]]]] %t1178, 0, 0, 0, 0, 1
  %t1189 = fdiv <1 x float> splat (float 1.000000e+00), %t1188

  store <1 x float> %t1187, ptr %out
  store <1 x float> %t1189, ptr %out2
  ret void
}
```

# Note #

SDISel is essentially able to do the equivalent of:
```bash
opt -passes=instcombine,early-cse -S repro.ll -o -
```

Which yields:
```llvm
define void @foo(<1 x float> %in, ptr %out, ptr %out2) {
  %t1187 = fdiv <1 x float> splat (float 1.000000e+00), %in
 store <1 x float> %t1187, ptr %out, align 4
  store <1 x float> %t1187, ptr %out2, align 4
  ret void
}
```

[repro.ll.txt](https://github.com/user-attachments/files/18411275/repro.ll.txt)

</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzEWF1zozoS_TXySxcuEGDwgx8ce3IrD3d3K7lb9zEloDGaERIjCSeeX78lYY_xRzJJdlI35bIDap0-3To0UjNj-EYiLkh6Q9L1hPW2UXrxvVRCtQXaSaGq3eLvBiXoXkouN_DH3QMKUBJsg7DhW5TAZddbuLsndAVPCCgr6DvYoETNrJuDxqC0nAmxAwZKYmBVoCRCy7rOGTxx23jAAxQ8NaiRGWiVsaBqP1iqtusts1xJ4Aa-9sZC1XeCl8xiNSXh8mHt2XWoa6VbAwzavmygQGtRw1dVQLGDSjmXZBZyaWyp2oJLJLMwEPwbguosb_kP78SAbZgFJoR6Am7BKjC87QSvd57P3T0wWQFuUdreB4fPnTJo_Ojq4QuorlPa9pLbnaNHwuVfDTeOvFR2QDe97jQ3jtKQTX-34cYqzUuPOqS8YQYaVgGDDdMF27hk_fxX9RZY12nFysYtQ9Fbx7hlO2jZNwSD0qAPwGqUG-tWdIDdJ8BArfQheqyg6LmozJ70v5RFEi_hDlRhUG-xAuvi8Mu2_HP9x3_-6z3egelNh6X3zeoaS2tc-qBg5TeUP_EIjeEvBffYaVX1JQKh8TCyVk9SKFb5DDJrWdlg5RKtNJSq20HHjEU_aiTvOrRQoFsetxC6lw5lFg6fgpmGhEshSgj-HUPQMl02JF6zttqUEoK27HoSrzf18zyhAEFrNe8EwjAesLYKmrY0DIKNUAUTATcoSLwm8Sok2Soi8RfQLoSpEBAoIPHKVCRbbUj8xZlODYzpHEO_R9MLewx6WAiXn7Pnxj4pp9O64lsyC8HpVfflIM3DA7KXPDfACuGX2AnPJeipUe5G45BcevbJ3j84SuJ05J7EyzFZZloSLmH_t32s-PbRlEzgYx1T2EZOY4akNyGJlxFJ1-56Gx6_o2l4Mr9V28cipo_oZmfejr5sQL2By875SOxHkpOpuuwcq8Eg8QbRa-RTb1KWB54vkq5bNszI3WgwRD142Jt6m_Lce36FZNuLo9lgkB7NRr7mY18HwzNW5TnU_CpU9Csol5i6ZWacl1GQ23wA9Gb8ue_GdunLeTuFjd4IG47sRrBnz88g9-tq_f9leiKl2VFK5lGqDl5QRzZO8-wFIZXnuNne_BWhZm8V6hVxXYN_TWPZGzX2AuIVqWVv1MTsqIlT6_dKw5XWu3t42L8X9uX1YCPE1omkwppLhK3iFZAkrJUiNCfxKoJnqIVi1lV1QlMunZ_Oanehent6RQmdA8luHGlCUxtFWQIkXrsSjdpumegRSHqTwDOcgZN0DT9QKy652xHxH6gd9osUwpGP9B0-DrReBR_q5N509n709FV0OkbP3o8-exU9HqPn19CpQ09vouEnuby68Dz-XF2lX1HOhiU7-xoRnX8C0UMOPsIwOmeYh5_HcP4RhvSCYfRpDPPwIwzjC4b08xhGb2cYvazDPP48hvQjDC91eLWg_h6G8UcYXurwajn-PQyTjzC81OFQ0vHZalZ-Srm5KHXnDIay704wF5XcdIK513Tu77h3uv9DQm_CkNChWOzjGEPm_0RQ4zdlPv8tQeXDtgXAHfXx2ovOJ_BsH_LLCfPzrYqbodH6PY9zma2v753cKf94KD2eK0-6N_szZqX8ERO_93zLBEoLqj7blO-P36qzEHTMGDQkXo9bLnSFTItdUBqE4OHkKB1cMvy74WUDO46iMmeePm1r9_tEzKU_RrxnoekKmOAbCcm7RULPJ_9y-dObQ_qn9tn6k1LeWNv5VNNbQm833DZ9MS1VS-htb1AHQ3umRWkNobc1F-h-ozyJIup2hrcnkHROwuWkWsTVPJ6zCS6iLJ7ls4Qm-aRZZCmLZ3VSh4xW6SybYzyfRXUahtksKVieT_iChjQNoyiJkiij-TRK5skcS0wLFmFRFyQJsWVcTJ0apkpvJtyYHhcRpfMwnQhWoDC-z0mpF0y8HNo6vqtDKUnXE71wI0HRbwxJQsGNNUc4y63wjdKhX5Ku4U9ufN_uZwvNqn0H0N1qlQTTF_jcaTTG92x8t1Dwlks2NLHaSa_F4pVEe6bDT9Bp9RVLS-itj8wnewhuu6D_CwAA___AfRJJ">