<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/141822>141822</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Is CMN safe when the subtraction is nsw?
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
AZero13
</td>
</tr>
</table>
<pre>
In C,
bool cmp(int a, int b) {
return a > -b;
}
yeilds
define i1 @cmn_nsw(i32 %a, i32 %b) {
; CHECK-LABEL: cmn_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: neg w8, w1
; CHECK-NEXT: cmp w0, w8
; CHECK-NEXT: cset w0, gt
; CHECK-NEXT: ret
%sub = sub nsw i32 0, %b
%cmp = icmp sgt i32 %a, %sub
ret i1 %cmp
}
Now, because no fwrapv, the sub is assumed to be nsw.
However, this would mean no signed wrap.
For 0 - b to be signed wrap, b would have to be a value that fits in the realm of possible signed integers, and cause a wrap.
The only value for b that fits is 0x80000000, and therefore:
Iff b is 0x80000000, then 0 - b is signed wrap.
Therefore,
if 0 - b is not signed wrap, or nsw, b is not 0x80000000
Which means in theory I could do this:
define i1 @cmn_nsw(i32 %a, i32 %b) {
; CHECK-LABEL: cmn_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: cmn w0, w1
; CHECK-NEXT: cset w0, gt
; CHECK-NEXT: ret
%sub = sub nsw i32 0, %b
%cmp = icmp sgt i32 %a, %sub
ret i1 %cmp
}
However, alive2 says:
define i1 @src(i32 %a, i32 %b) {
; CHECK-LABEL: cmn_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: cmn w0, w1
; CHECK-NEXT: cset w0, gt
; CHECK-NEXT: ret
%sub = sub nsw i32 0, %b
%cmp = icmp sgt i32 %a, %sub
ret i1 %cmp
}
define i1 @tgt(i32 %a, i32 %b) {
; CHECK-LABEL: cmn_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: cmn w0, w1
; CHECK-NEXT: cset w0, gt
; CHECK-NEXT: ret
%isNotMin = icmp ne i32 %b, -2147483648
call void @llvm.assume(i1 %isNotMin)
%sub = sub i32 0, %b
%cmp = icmp sgt i32 %a, %sub
ret i1 %cmp
}
ERROR: Source is more defined than target
Example:
i32 %a = #x00000003 (3)
i32 %b = #x80000000 (2147483648, -2147483648)
Source:
i32 %sub = poison
i1 %cmp = poison
Target:
i1 %isNotMin = #x0 (0)
void = UB triggered!
I know I am thinking of multiple levels at once, but the question is, if I am checking if it is safe to turn cmp into cmn, is it safe to just look at the no signed wrap flag?
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzcVsFu4zYQ_Rr6MrAhkZYtH3RwnBhrdDcF0hQteikoaSRxQ5EuSVnJ3xck5cTJJuipi8XqIoJ882bmkZwht1a0CrEg2RXJrmd8cJ02xfYvNDpls1LXT8VBwY7QHZBkS5JtqbWEqj8SmgvlgPsVPygJ3QBZX5Fka9ANRgEHwm5gXhLmJ8n6OhI8oZC1jeMaG6EQRApkmVS9-lvZ0RMzCoRmkTuOL-gJu4Ldp5vdL_PP26ubz4Rt4WzKtpfrfiV-hO4J3QeecpG8gc1vb_68n7AKWxhz73dMP8JU_RHGJGDyDzEW3QRq3bsgg37eh5bZoQTCrsH_lR1DysE05D2BvFcPEn5gWweXIkWSADXogp7B4lL3Wz16aIkVHyyC0tCMhh9PftJ1GLwLC9zaoccanIYSfTiLaP5Jj3hCE9HCwqgHWUOPXHmqcIpq8IQTfq8NJDCHcmK6QIQwJoKOn3BCcDhxOSC4jjtohLMgVIjMIJc96AaO2lpRymcyoRy2aKwn5KqGmBm_DOO-Q9BKPk3cjTY-ohcPFpLHPInfmcZ1aLDRBuNBOTQNlN8iXYdqylDYdwS4f2ahO5JsRfMCVtq91UMbCGd_94K4cBcI_-hE1QXFz8po8wQHqIKQtQ77EkP-4e5V1avznfn4Xv3nnQH4_tfm4txzKU5IwfKnSea3SltT_QQqf3eJX2noWvcTaPj6pAp7q90XoV5k8uk-p7WDOU2X62XOVkvfUaDiUsJJi9oLIuWpX8Sq7IVJLwkJ3by3Vf_PNt3c3f1655P7TQ-mQl-mem0Q4vb5sskVOG7akLg3eOT9UU5V9OwtxEAoe5xqGwNCcxYTOUvyjDkXQI-5kOiNYsGWJNsY1yt3Z1WOWlit_Hx6qcXztK_XMfJonX6zbSFkH0cS_cXtYdfw-xU4I9oWDdaEppHsAA9Kj3AA3vuyrB6Ean0H6wfpxFEiSDyhtMAdaFVhqPuDC93unwGtE1qBCH1NNJGl6rAKLKIB4ULL4U1oneGx5TMSyml_foOZ9agz5OtgHUitH7xD7-R1y4ZG8paw_awuWL1hGz7DIl0v82WW04zNumKzWpd8RVdVs642K8oxS6psVeYsT9OKrfOZKGhCsySjeZpnScYWq6ysNyxLaM3z5SYvyTLBngu5CMdZm3YmrB2wSJdpTulM8hKlDa9QShWOEFYJpf5RagpvNC-H1vr7IKyzLzROOInFwcLuy23Md_SNeXrROMOrSczQX9l-NhhZdM4dQw0PVaEVrhvKRaV7QveeePrNj0Z_xcoRug_hWEL3U7yngv4bAAD___ipKA4">