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

    <tr>
        <th>Summary</th>
        <td>
            IRCE introduces UB by changing order of condition checks
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            miscompilation,
            loopoptim
      </td>
    </tr>

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

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

<pre>
    IRCE reorders order of condition checks. For example see this minimized test case from `IRCE/bad_expander.ll`:
```llvm
define void @test_03(i1 %maybe_exit, i64 %num) {
entry:
  br label %loop

loop:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %guarded ]
  %iv.next = add i64 %iv, 1
  br i1 %maybe_exit, label %range_check, label %exit

range_check:
  %rc = icmp slt i64 %iv.next, %num
  br i1 %rc, label %guarded, label %exit

guarded:
  %dummy = add i64 %iv.next, 0
  %tmp7 = icmp slt i64 %iv.next, 42
  br i1 %tmp7, label %loop, label %exit

exit:
  ret void
}
```

If `%maybe_exit` is false, the function returns straight away.
However, IRCE gives us this:
```llvm
entry:
  %0 = add i64 %num, -9223372036854775807
  %smax = call i64 @llvm.smax.i64(i64 %0, i64 1)
  %1 = sub i64 %num, %smax
  %smin = call i64 @llvm.smin.i64(i64 %num, i64 0)
  %smax1 = call i64 @llvm.smax.i64(i64 %smin, i64 -1)
  %2 = add nsw i64 %smax1, 1
  %3 = mul i64 %1, %2
  %smin2 = call i64 @llvm.smin.i64(i64 %3, i64 42)
  %exit.mainloop.at = call i64 @llvm.smax.i64(i64 %smin2, i64 0)
  %4 = icmp slt i64 0, %exit.mainloop.at
  br i1 %4, label %loop.preheader, label %main.pseudo.exit

loop.preheader:
  br label %loop

loop:
  %iv = phi i64 [ %iv.next, %guarded ], [ 0, %loop.preheader ]
  %iv.next = add i64 %iv, 1
  %rc = icmp slt i64 %iv.next, %num
  %or.cond = select i1 %maybe_exit, i1 true, i1 false
  br i1 %or.cond, label %guarded, label %exit.loopexit4
```

So we branch first on a value derived from `%num`. If that's `poison`, we end up triggering UB.
Either the condition or the variables used by the hoisted condition must be frozen.

cc @max-quazan @nikic @serguei-katkov
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJytVk1zozgQ_TX4ogolBIb44MMkmdTOdbfmnBLQBk1AYvThxPn12xL4AzzJZKe2TBnUar1-LXU_KFV92H77-_4r0aB0DdqQcCNqRyola2GFkqRqoXo2MXlUmsAr74cOiAEgthWG9EKKXrxBTSwYSypugOy06kmUU48csceS10_wOnCJyHHX4USUfonoQ0S_-Odwdd2-H0017IQEsleiJlFGPeoTTSN2KxISsXXPDyUgnLARuyciz7xRuj5iGxIVdyMGSKsPpyCElJp0vITO-3ZKDVPw8B_GZ1f0EHsSpQ9kaMWIv74j1AfDqQCMlocwxongHkt4tZNH4zjuYB18LiGDT8DldX3kLfZ-VXJB81dJnqhrLht4CscxswfHi5Qu_WaZ6SowEFU_ENPZM43LDPxmLgnpahZwSvJDEkefGYHa9f3hehdO4emFr-2H4nd0M3ZF1S-bEQsH_BHTMD7T1GBD9U0uxcOiVC-Xftv5Op-fWE4J9sWOdwZ8WNtiQzhZhVZCbKelIcZqLprWEv7CD_GI9Zd6gT1ovya0ZCP2YIgzoc8-6phltSMdutzj0CH35GbDWJoWjKb57TorivUtLS6WmZ6_hpUV77pxaRYCxX4mRoPvwxGRHvsvwda7wEgCgHHlIvQEP4sm5HvRhJxHm0D8iM7jedDks6Q98BHnZkGcnfZMmhdyWoDosyZFYxo8e9cdvZIpQbbIjn02vfRICgt6RspXVNxzIX0Vx9z-l0TZOzuWXXfVSd8W4a66K7tqrXjQ0AKvx8o9TXmQeDDgahUvG26x7H_U6Q_leJLsY65zFn8k2H8gqThSOvYv17FPoIPK_lL20Wa1g-lx1JPlcUxQnxLn2CfsH7IPBO0fRV4A8bmsWrITGl_pKFuc7HnngOA-oSjVpxf8lFpOY4JKaFssGFYYPzMoYZQMLvceETBfN2BComkQRDbk-92ke18FSqQOOnn-5lCjYc-14GUXdBDjlodgbRHc4vDs3jskWoYvjzeQ8WVGVeXbBBvk5qfjb1z6kRTPIpgN6MaBuHnm9lntV7BN8pwlSYq_Vb1N60264SsrbAfjZ5JAqVW1q5DQ9ztPp2rxXevTefe7aeV0t22tHYKGs0e8GszYlXhyqGmPQcfH282g1Q8sBxwKYxwYfFgXa5au2m1WQkrXyW5XVkkBeZbxosjzmjGoaMXqahXO2myxwiPGemEQfRAd90zQMBYi8yWgBit6b1o_rMSWUcbohrKE0nWaxLeM5QXb3WZlBownG9wjwFbu4qAzSjcrvQ1US9cYLz94EuY8yY0RjQQINBCfO9sqvZVOqqHD6jOrkNg2ZPUvnyoKNA">