<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/60742>60742</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Failure to recognise partially unrolled memcpy loops
</td>
</tr>
<tr>
<th>Labels</th>
<td>
missed-optimization
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
RKSimon
</td>
</tr>
</table>
<pre>
https://simd.godbolt.org/z/rvvEzW971
```
using T = int __attribute__((ext_vector_type(4)));
void copyme(T* __restrict dst, const T* __restrict src, unsigned N) {
while(N--) {
*dst++ = *src++;
}
}
```
is recognized as a memcpy loop:
```
define void @copyme(ptr noalias nocapture noundef writeonly %dst, ptr noalias nocapture noundef readonly %src, i32 noundef %N) {
entry:
%tobool.not2 = icmp eq i32 %N, 0
br i1 %tobool.not2, label %while.end, label %while.body.preheader
while.body.preheader: ; preds = %entry
%0 = zext i32 %N to i64
%1 = shl nuw nsw i64 %0, 4
tail call void @llvm.memcpy.p0.p0.i64(ptr align 16 %dst, ptr align 16 %src, i64 %1, i1 false), !tbaa !6
br label %while.end
while.end: ; preds = %while.body.preheader, %entry
ret void
}
```
But this fails if the loop has been partially unrolled:
```
using T = int __attribute__((ext_vector_type(4)));
void copyme2(T* __restrict dst, const T* __restrict src, unsigned N) {
while(N--) {
*dst++ = *src++;
*dst++ = *src++;
}
}
```
```
define void @copyme2(ptr noalias nocapture noundef writeonly %dst, ptr noalias nocapture noundef readonly %src, i32 noundef %N) {
entry:
%tobool.not6 = icmp eq i32 %N, 0
br i1 %tobool.not6, label %while.end, label %while.body
while.body: ; preds = %entry, %while.body
%N.addr.09 = phi i32 [ %dec, %while.body ], [ %N, %entry ]
%src.addr.08 = phi ptr [ %incdec.ptr2, %while.body ], [ %src, %entry ]
%dst.addr.07 = phi ptr [ %incdec.ptr3, %while.body ], [ %dst, %entry ]
%dec = add i32 %N.addr.09, -1
%incdec.ptr = getelementptr inbounds <4 x i32>, ptr %src.addr.08, i64 1
%0 = load <4 x i32>, ptr %src.addr.08, align 16, !tbaa !6
%incdec.ptr1 = getelementptr inbounds <4 x i32>, ptr %dst.addr.07, i64 1
store <4 x i32> %0, ptr %dst.addr.07, align 16, !tbaa !6
%incdec.ptr2 = getelementptr inbounds <4 x i32>, ptr %src.addr.08, i64 2
%1 = load <4 x i32>, ptr %incdec.ptr, align 16, !tbaa !6
%incdec.ptr3 = getelementptr inbounds <4 x i32>, ptr %dst.addr.07, i64 2
store <4 x i32> %1, ptr %incdec.ptr1, align 16, !tbaa !6
%tobool.not = icmp eq i32 %dec, 0
br i1 %tobool.not, label %while.end, label %while.body, !llvm.loop !9
while.end: ; preds = %while.body, %entry
ret void
}
```
vs:
```
define void @copyme(ptr noalias nocapture noundef writeonly %dst, ptr noalias nocapture noundef readonly %src, i32 noundef %N) {
entry:
%tobool.not2 = icmp eq i32 %N, 0
br i1 %tobool.not2, label %while.end, label %while.body.preheader
while.body.preheader: ; preds = %entry
%0 = zext i32 %N to i64
%1 = shl nuw nsw i64 %0, 5
tail call void @llvm.memcpy.p0.p0.i64(ptr align 16 %dst, ptr align 16 %src, i64 %1, i1 false), !tbaa !6
br label %while.end
while.end: ; preds = %while.body.preheader, %entry
ret void
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWE9v6rgX_TRmc0WUOATIggWUx-YndfGbJ80SOfEFPHLsjO3QRz_9yE4IUCil1XujGWmqqIB9_xyfax9fYNaKrUKckWxBsuWANW6nzez___tNVFoNCs0Ps51ztSXpnNAVoSsrKh5tNS-0dJE2W0JXr4SuzH7_7fX3fJKQeEniefd_HHdP-NhYobbwHYCkSxDKwXrNnDOiaByu14ROCZ3iD7feY-m0WbtDjYROR4Tm3ZMu2kB7LTiUuj5U3uA7oXNYrw1aZ0TpgFtH6BOUWlkHbyetKf1ko8K6OTwTmgOZdIEBAF52Qvqwz8Ph5Ryh8xB6QegiLIHQeQjnB3psPgSZLDsC-jeXTAgLBku9VeIVOTALDCqsyvoAUuvac33Li-NGKISwejKKewJqZ0BpJgWzoHTJatcYBKUbxXEDL0Y41EoegNCs4-a-h0HGjw4dXyKl_TSh2SVrqJw59KDBGzhdaC0jpR1tq11WNeCfIU7r_wTx0b4wIJI3Xt5AsgKlHw8liVDxG6N-i0a1wR0yjqYNeXMmnQNJF1Ab5LYrX9YiP8GOw8Qr_nA9UnAaxHh0ZpQEI7uToJoXUPbFzwdvD6-3dExIKJmUfcGk3FdRW-eojv3jA7f1Y1JsFSTjN0U6Hz6Wok2WhPcJbJi0GM7HExCauIIx_zo-I_cGj2c0-Y9p2LaP_F1ReJPrgOWSXYMuEHH_YCwaB24nLGyYkBbEBtwOw6GAHbNQICqomXGCSXmARhktJfL3DsyvEBz6NypOy_jDsvMZ2w8l6hHtof908Rl_SXzGnxKf8wvvbPThI_WOKLVH6G2asL7niHFuojgPHvVOtCvLFoFkLK98gWTLMNiaPJ-fzzB3im1N2UWf9tF9wTpXoUqOZVQ7Qz_K0hXvnTzcui7P5H6e9KM83a56Lw-WIT7jvK__kT7vNkzOjE9Zg88WHUqsUDk_IlTh96Av09MIfvhoJP123NCX1B11Orm6W6Rm_NEIR_F_T9ovECdfgXxWhSvI1mmDl579JXfb_VN46U-imF7dzHcpPgH4NOL0JzFMP2A4uQk3eRDvScZuaV-nDvfU73Pi1wIJnU24pQlN8mtF7HqMO83D11uGvf2vX_5F_fIXrq2f2ktn_9Je-qtN8kcbfsBnKc_TnA1wlown43SaZqN8sJslRYab8XSaFVOK8SSblsh5kucxy8uSZ2wgZjSmaUyTUTKKs1EeJcUE6YTjhk43Wc5LMoqxYkJGgVhttgNhbYOzcTwZ0UFYtQ0_ElBaCWuRD3XtRCVemRNaEUpJthyYmfceFs3W-hIJ6-wpnhNO4mzFhPRnx-njN2CLNzr686_DdtAY-eZXiK1wu6aISl0RuvIpupdhbfQfWDpCVwG_JXQVlvBXAAAA__8RGdzP">