<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/132678>132678</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Pick more convenient constants in `phi` nodes [optimization]
</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>
I was looking at what's essentially `<=` on a 4-tuple in Rust, and ended up with the following IR: <https://llvm.godbolt.org/z/8zaYxd8qM> (That link includes that trunk `opt` doesn't change it.)
<details>
```llvm
; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read, inaccessiblemem: readwrite) uwtable
define noundef zeroext i1 @array_of_tuple_le(ptr noalias nocapture noundef readonly align 2 dereferenceable(8) %a, ptr noalias nocapture noundef readonly align 2 dereferenceable(8) %b) {
start:
%lhs.i.i.i.i = load i16, ptr %a, align 2, !noundef !24
%rhs.i.i.i.i = load i16, ptr %b, align 2, !noundef !24
%_5.i.i.i.i = icmp eq i16 %lhs.i.i.i.i, %rhs.i.i.i.i
br i1 %_5.i.i.i.i, label %bb6.i.i.i, label %bb8.split.loop.exit12.i
bb6.i.i.i: ; preds = %start
%_10.i.i.i = getelementptr inbounds nuw i8, ptr %a, i64 2
%_11.i.i.i = getelementptr inbounds nuw i8, ptr %b, i64 2
%lhs.i8.i.i.i = load i16, ptr %_10.i.i.i, align 2, !noundef !24
%rhs.i9.i.i.i = load i16, ptr %_11.i.i.i, align 2, !noundef !24
%_5.i10.not.i.i.i = icmp eq i16 %lhs.i8.i.i.i, %rhs.i9.i.i.i
br i1 %_5.i10.not.i.i.i, label %bb1.1.i, label %bb8.split.loop.exit14.i
bb1.1.i: ; preds = %bb6.i.i.i
%_22.1.i = getelementptr inbounds nuw i8, ptr %a, i64 4
%_25.1.i = getelementptr inbounds nuw i8, ptr %b, i64 4
%lhs.i.i.i.1.i = load i16, ptr %_22.1.i, align 2, !noundef !24
%rhs.i.i.i.1.i = load i16, ptr %_25.1.i, align 2, !noundef !24
%_5.i.i.i.1.i = icmp eq i16 %lhs.i.i.i.1.i, %rhs.i.i.i.1.i
br i1 %_5.i.i.i.1.i, label %bb6.i.i.1.i, label %bb8.split.loop.exit12.i
bb6.i.i.1.i: ; preds = %bb1.1.i
%_10.i.i.1.i = getelementptr inbounds nuw i8, ptr %a, i64 6
%_11.i.i.1.i = getelementptr inbounds nuw i8, ptr %b, i64 6
%lhs.i8.i.i.1.i = load i16, ptr %_10.i.i.1.i, align 2, !noundef !24
%rhs.i9.i.i.1.i = load i16, ptr %_11.i.i.1.i, align 2, !noundef !24
%_5.i10.not.i.i.1.i = icmp eq i16 %lhs.i8.i.i.1.i, %rhs.i9.i.i.1.i
br i1 %_5.i10.not.i.i.1.i, label %_ZN4core5slice3cmp13chaining_impl17hcb28312734696fd1E.exit, label %bb8.split.loop.exit14.i
bb8.split.loop.exit12.i: ; preds = %bb1.1.i, %start
%lhs.i.i.i.lcssa.i = phi i16 [ %lhs.i.i.i.i, %start ], [ %lhs.i.i.i.1.i, %bb1.1.i ]
%rhs.i.i.i.lcssa.i = phi i16 [ %rhs.i.i.i.i, %start ], [ %rhs.i.i.i.1.i, %bb1.1.i ]
%_6.i.i.i.le.i = icmp sle i16 %lhs.i.i.i.lcssa.i, %rhs.i.i.i.lcssa.i
%0 = zext i1 %_6.i.i.i.le.i to i8
br label %_ZN4core5slice3cmp13chaining_impl17hcb28312734696fd1E.exit
bb8.split.loop.exit14.i: ; preds = %bb6.i.i.1.i, %bb6.i.i.i
%lhs.i8.i.i.lcssa.i = phi i16 [ %lhs.i8.i.i.i, %bb6.i.i.i ], [ %lhs.i8.i.i.1.i, %bb6.i.i.1.i ]
%rhs.i9.i.i.lcssa.i = phi i16 [ %rhs.i9.i.i.i, %bb6.i.i.i ], [ %rhs.i9.i.i.1.i, %bb6.i.i.1.i ]
%narrow.i.i.le.i = icmp ult i16 %lhs.i8.i.i.lcssa.i, %rhs.i9.i.i.lcssa.i
%_0.sroa.0.0.i12.i.i.le.i = zext i1 %narrow.i.i.le.i to i8
br label %_ZN4core5slice3cmp13chaining_impl17hcb28312734696fd1E.exit
_ZN4core5slice3cmp13chaining_impl17hcb28312734696fd1E.exit: ; preds = %bb6.i.i.1.i, %bb8.split.loop.exit12.i, %bb8.split.loop.exit14.i
%_0.sroa.0.0.i = phi i8 [ %0, %bb8.split.loop.exit12.i ], [ %_0.sroa.0.0.i12.i.i.le.i, %bb8.split.loop.exit14.i ], [ 2, %bb6.i.i.1.i ]
%.not = icmp eq i8 %_0.sroa.0.0.i, 2
%1 = trunc i8 %_0.sroa.0.0.i to i1
%_0.sroa.0.0 = or i1 %.not, %1
ret i1 %_0.sroa.0.0
}
!24 = !{}
```
</details>
The part I want to draw attention to specifically is the end:
```llvm
bb8.split.loop.exit12.i: ; preds = %bb1.1.i, %start
; …
%0 = zext i1 %_6.i.i.i.le.i to i8
br label %_ZN4core5slice3cmp13chaining_impl17hcb28312734696fd1E.exit
bb8.split.loop.exit14.i: ; preds = %bb6.i.i.1.i, %bb6.i.i.i
; …
%_0.sroa.0.0.i12.i.i.le.i = zext i1 %narrow.i.i.le.i to i8
br label %_ZN4core5slice3cmp13chaining_impl17hcb28312734696fd1E.exit
_ZN4core5slice3cmp13chaining_impl17hcb28312734696fd1E.exit: ; preds = %bb6.i.i.1.i, %bb8.split.loop.exit12.i, %bb8.split.loop.exit14.i
%_0.sroa.0.0.i = phi i8 [ %0, %bb8.split.loop.exit12.i ], [ %_0.sroa.0.0.i12.i.i.le.i, %bb8.split.loop.exit14.i ], [ 2, %bb6.i.i.1.i ]
%.not = icmp eq i8 %_0.sroa.0.0.i, 2
%1 = trunc i8 %_0.sroa.0.0.i to i1
%_0.sroa.0.0 = or i1 %.not, %1
ret i1 %_0.sroa.0.0
}
```
That `2` came from `Option<bool>::None` in Rust, but it would be really nice if LLVM could notice that it being specifically 2 is not something that makes it to the output at all, and thus it could be changed to something more convenient for the logic.
Specifically, in this case the other two phi inputs are just `zext`ed `icmp`s, and the function is returning `i1`, so if it's changed to `1` then everything else in that block can be greatly simplified:
```llvm
_ZN4core5slice3cmp13chaining_impl17hcb28312734696fd1E.exit: ; preds = %bb6.i.i.1.i, %bb8.split.loop.exit12.i, %bb8.split.loop.exit14.i
%_0.sroa.0.0.i = phi i8 [ %0, %bb8.split.loop.exit12.i ], [ %_0.sroa.0.0.i12.i.i.le.i, %bb8.split.loop.exit14.i ], [ 1, %bb6.i.i.1.i ]
%1 = trunc nuw i8 %_0.sroa.0.0.i to i1
ret i1 %1
}
```
That way there's no need for the `eq`+`or`, and the `trunc` becomes `nuw` which could collapse into the phi and the predecessors too.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzsWU1v4zgS_TX0pTCCRMmyfPDBSTpAAzOzi9nBAruXgKLKFicUqSapVie_fkHK8rcdu3cGe9hODNjmx6ti1atHk2LWirVCXJDpA5k-TVjnam0WlmvnGt5MSl29LT5DzyxIrV-FWgNz0NfMETqzgNaicoJJ-QYkj0n6SNInksegFTDIfnJdKxGEgt866wh9BKYqQFVhBV0LvXA1uBphpaXUvQf__BtJl0DSx9q51pJ0Segzoc9Sfm2ita5KLV2kzZrQ53dCn4t39q9vVfHlF5J-AkKL32vmQAr1CkJx2VVowfkmZzr16h3UrfPeVRqtInTmgNdMrRGEiwidk3jpX-ljhY4JaUn6adOUx8PL-zGOeoDnTnEntIKlc8Y7C01nXWv02qC1oPTKIILSBnlnrP9k3xQHpTvVC1VBL6Q06DqjoMFGmzdCC2bWDTYeyyCrfMiEYpyjtaKUuNfVG-GQ0Dl0vWOlRBIvK1wJhQG_whW8o9H4zYFIgGQxM4a9vejVS8jJi0RCi9YZUJpJwby3nLWuM7v53opW8g2YFGsFFCo0uEKDimOwSIvCO0DolHlH_zS0MrzPHki8tI4Z52kQL8F3ydpGYvgHkj6B1KwCkeSj_dGXjRH_kdBk9IHQhGYjlPkYqrwR6mV6gCR40wJ-8WBHPg8g-6YDRGlCkvaB_EjJSpTBjzI_21pEtpXCRVLrNsJvwiU0IJJ4uZuSLuHGP8_p1mBlwyoInQ7RHxeZxHtrXKNDz0flfKyEKn1cLKiuB1EcZ0PkGdAdTvIdOOUJTghrcT2BW5_v4cT8I8zkLkyf0ySOlHYfUKQ45cj8Ekn2AY9IkUTJDUTJdkQZJtxOkzNE2bFtXDSlHvX7qLILHZ3ejVKeoOzqL7mS1cHhu7XjKuT0Dsht6ScfqUhyRkeSi0pySob8QvsNanIPUc6QJNn6uVeb302T_FhRvpsq-RlNuZbYnef368pV3ORO3CMpuEad4hx35pfJcwh7QJWXf_-acW1waqXgmPKmTVJeM6GEWr-IppXJrOYlLdKEztIsn-erKvkUGHWPLJ2n4zX2XWTcsOKD3WxXTpJbyzaBa2sxBG36cH7nDhhApk_h-_Gona2N5TDyRDOuWDQ3WTS3WXzJR4O4Twzrf5Ifi8rGpxNhGds3kHGAeR9_Vh7bcNpX2IZLfwZfLnIhu58L-UnEjjatvTr5iBSHe_UW6Rwzjgtvz5ETesxv4sf8JuNHBX7VuGLG6P4MVzrpzqjIGbLMz7HlJY6s0SyKozgSvnz38fdIdGz-r6HRfzE_nElvINR5zbrcm12I1S71xZjO-LqRo-Rfivx1X_ZB6HXG-M3hcK8pTux6hO3P9SSM9idxfm5syHlyJhhhmh53Jm9249gw2OBWiXZzfL5nT5uDut8vNzlL_KFy2zEe6rfHfkKfj0_-v9cIrRfgz9Az5byXlWE9MOdQhbO_02Bb5GIleLgGETZcaaCqhmPr8d3BX7uxpQ9APlFSxGSZ_x9o9rnl_hCdH6LzvxWdQ2EJl5IkjynJY-CsQVgZ3fiWv7VeQUj6WGotveSkS5Iuf9UK_dC9W9OycyAc9LqTFZQIBoPUKMERxAp-_vmfvwAPnUo73xhuPYWDEoVaH-oT9Qrl42h1g672_WF0w17R-jlOBwHTnWs7B8wBk3K8unV1F8bw0ZPh_rQKKrjFa7RB4Fp9RSVQOVhpEyClXgseDVH5x55Pwy0nuFpY4MziYN_VaMD1eqCkajtngRmEPzob4ulLmeQxVv6LJwTJY7tzFGE1Xs8KC8M1q3fOD058cugjWO3DJ4a77L2lkDz2QzyKAvyK5m1YGEqLg6fMQSk1fwXOlI_D2iBz8g2sL2mxEnhB_X_IwT1ykFyXg_3qHg731yp8V7TJ1VLt2ZtPvMHACqVBIVZbDnvGfQn0eSB5rM2GSSPnSB4Hfzx7SuS6QevbVNf7lr4WvN4UD9dSsjbwaVNxPtYjjs8ycrRWGwtO62hSLdJqns7ZBBfJLKOzeZFn6aRezFd8XtGsyvJZjkjn5ZzRaVUgxRLTtJpNxILGdBqnNIvzLIvTaJXMsnJVJmWxSiiljGQxNkzIKDxl0WY9EdZ2uEhSms-KSdgKbXhARKnCHkIvoZRMnyZm4Sf9VHZrS7JYCuvsDsYJJ3Hxd8FfTySBa2UdU876ciJ53NbCB0jpygds-qBbJxrxzoJATp8mnZGLw0dCa-Hqroy4bjbPhzZvP7VG_4HcEfocHLWEPm9W8nVB_xMAAP__hiLJfw">