<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/73306>73306</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Move comparison before `umul.with.overflow` [instcombine?]
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
scottmcm
</td>
</tr>
</table>
<pre>
A bunch of containers have code enforcing object size limits that ends up looking like
```rust
let Some(total_bytes) = element_size.checked_mul(element_count) else { panic!() };
if total_bytes > (isize::MAX as usize) { panic!() };
```
in Rust, or in C++ something like
```cpp
unsigned long total_bytes;
if __builtin_uaddl_overflow(element_size, element_count, &total_bytes) { throw bad_alloc(); }
if total_bytes > (size_t)PTR_DIFF_MAX { throw bad_alloc(); }
```
It would be nice if LLVM could -- when `element_size` is a constant, as it often ends up being in templated code -- move the check before the multiplication so that the *overflow* handling could be removed, and it just be a normal multiplication instead. (Perhaps even an `nuw` one, by sinking it into the branch that cares about the result.)
An example in Alive2: <https://alive2.llvm.org/ce/z/X9ipzy>
```llvm
define {i64, i64} @src(i64 noundef %x) {
start:
%#0 = umul_overflow i64 noundef %x, 26
%_11.0.i = extractvalue {i64, i1, i24} %#0, 0
%_11.1.i = extractvalue {i64, i1, i24} %#0, 1
%_7.i.i = icmp ugt i64 %_11.0.i, 9223372036854775806
%_0.sroa.0.0.i.i = select i1 %_7.i.i, i64 0, i64 2
%#1 = insertvalue {i64, i64} poison, i64 %_0.sroa.0.0.i.i, 0
%#2 = insertvalue {i64, i64} %#1, i64 %_11.0.i, 1
%.pn.i = select i1 %_11.1.i, {i64, i64} { 0, -1 }, {i64, i64} %#2
%.fca.0.extract = extractvalue {i64, i64} %.pn.i, 0
%#3 = icmp eq i64 %.fca.0.extract, 0
br i1 %#3, label %bb2, label %bb4
bb4:
ret {i64, i64} %.pn.i
bb2:
call void #trap() noreturn nothrow memory(inaccessiblemem: write)
assume i1 0
}
=>
define {i64, i64} @tgt(i64 noundef %x) {
start:
%_11.0.i = mul i64 noundef %x, 26
%_7.i.i = icmp ugt i64 noundef %x, 354745078340568300
%#1 = insertvalue {i64, i64} poison, i64 2, 0
%#2 = insertvalue {i64, i64} %#1, i64 %_11.0.i, 1
br i1 %_7.i.i, label %bb2, label %bb4
bb4:
ret {i64, i64} %#2
bb2:
call void #trap() noreturn nothrow memory(inaccessiblemem: write)
assume i1 0
}
Transformation seems to be correct!
```
(It's based on <https://rust.godbolt.org/z/47WWG4b4T>, which was inspired by https://github.com/rust-lang/rust/pull/118228.)
This issue is basically the same as #56563 but for `umul.with.overflow` rather than for ordinary `mul`.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMV1tv2zYU_jX0y4EFiZRl-cEPdlIPBVqg6IK1bwYlHVlsKVLjxW766wdSjm9Js6LbgAFBbFM8l-87V3FrxU4hLslsTWb3E-5dp83S1tq5vu4nlW4elyuovKo70C3UWjkuFBoLHd8j1LpBQNVqUwu1A119wdqBFd8RpOiFs-A67gBVY8EPILX-Gu5J8RVJek_SFSnS8c9468YjiQ5-1z0SWjrtuNxWjw4toQsg7B5QYo_KbYONpO6w_orNtveS0PLpUa29cuE-SotA5msYuBI1oRmhZdQzvydsPVoTLVxYAcLeAKGlCOoJWxG2er_6DNyCjydR-FV9J0BH9Qo-BmT0DrQBoeCO0DWha7C6R9f9gIx6GMYTr2J8GpBa7S4dvfR_u628kE6oredNI7d6j6aV-nBByej8HdxQdAeEFrckz9fgOqMPUPFmy6XU9QiTsHVE-gptwcw2UP_h4eP2_u1msw3s_ZzGG-LG_28dHLSXDVQIStQIooV37_54D3U8nU7h0KECUqRXSIsUhAUe0tU6PiLlFoQD3TpUp3ysMARAKHDYD5I7bMaMnk6h13sE1yHEHIMKW23Gg95LJwYpau6EVmD1mOPhEaGrM_kr6LhqZLBQP2EwGPQ20R_VBIe-eOvCEw5Km57LW_VCWYe8SSDw-wFNxwcLuEcFPOJW_hDgahXjWz2CFSrWmHAglNPRr8rwUMDRz5obtMAr7UefDVovXRLCcUH8SgF-4_0gMdCzkmKPlLAVEHbXOTfYUBt0Q-iGx0eJlPs-0WZH6KZGQjffCd18Xojh-yNhb24CHO6ORw22QsUSFUUe_A8f83sgeWpNSBJR5KC0Vw22QOjs2zFBR2nruHHBkfgrEDQjlKWxTfjenwsBnqu5A1pcyG2zLEkTMXaYb87w2u259FeuZfE_HR0cTYWT9EZN9mtqsks180QctYi6H8DvXIRwdjRILChlbE5TVpSzfD6flekVojSxRvMkDdePyizK0J5FdjZyJB3Spy_0ms1s9EJZNM-hjMEatLBaPck_N31LEqGM_r3Wo_lLtWfol2Qlg3oR3hiK2OOe6Z6vR8DTLPafF--Mjl4aauuA6RjXV2N8UhGde4EAdg4u_vkE8NrAlVRljrCCbHgieYUyHFQVvfmdX9Zx-HmuEIPuFTevxOiFWM2lhL0WDRDKnOHDce4pbdB5o0Dpsb_32GvzGOpW8bpGa0UV2nIfOsfBCIenLgPArfU9BlhPHf80Cdj9qWm80iHczv1Ch7is9N7Ln2gNPyjGWyE2y-f5LJ2XLE9nRcnS9B9WEv0vC-eUUOc28O-m1Ll4_gcZ9WC4sm2Yr-PIRuwtOB3mbq2NwVBt2ctrCC3fOkLnFipusQGtno_AsLomO91UWrrjDAzjL59_-vRbXuUPIZnpHRw6UXdwCHuIsoMw2IRxfa1qJ1znq6TW_VHvVHK1O34ndDN4KQndZFlJaXk7sx86YUFY6zFsPxW3ItD8GKe85T2GFYhQNitmBYPKO2i1CStEmJXJQbguOS0vRQqGuw5N2BlUvKhNIxQ3j0Ei7NtFmoxmJ82SNQu24BNcZvM0LbMFK_NJt8xLxivKGp5ni6xdNCWWOa_SkjV5W1GaTcSSppRlGc3TRb7I86TNZkVB27zNaVM0mJI8xZ4LeVovJhHecs5YWkxigtr46kKpwsOInVAa3mTMMshMK7-zJE-lsM6etTjhJC7f6_gG0w_chLp72vF-yAiZrcM2Vuu-EgoJ2wQ73sjlKzGMu874MR2M_hJTbRMdtYRuIpC_AgAA__8PS-zV">