| 1283 | } |
| 1284 | |
| 1285 | SZ_PUBLIC void sz_move_sve(sz_ptr_t target, sz_cptr_t source, sz_size_t length) { |
| 1286 | sz_size_t vec_len = svcntb(); // Vector length in bytes |
| 1287 | |
| 1288 | // When the buffer is small, there isn't much to innovate. |
| 1289 | if (length <= vec_len) { |
| 1290 | // Small buffer case: use mask to handle small writes |
| 1291 | svbool_t mask = svwhilelt_b8((sz_u64_t)0ull, (sz_u64_t)length); |
| 1292 | svuint8_t data = svld1_u8(mask, (sz_u8_t *)source); |
| 1293 | svst1_u8(mask, (sz_u8_t *)target, data); |
| 1294 | } |
| 1295 | // Slightly larger buffers |
| 1296 | else if (2 * length <= vec_len) { |
| 1297 | svbool_t mask_first = svptrue_b8(); |
| 1298 | svbool_t mask_second = svwhilelt_b8((sz_u64_t)vec_len, (sz_u64_t)length); |
| 1299 | svuint8_t data_first = svld1_u8(mask_first, (sz_u8_t *)(source)); |
| 1300 | svuint8_t data_second = svld1_u8(mask_second, (sz_u8_t *)(source + vec_len)); |
| 1301 | svst1_u8(mask_first, (sz_u8_t *)(target), data_first); |
| 1302 | svst1_u8(mask_second, (sz_u8_t *)(target + vec_len), data_second); |
| 1303 | } |
| 1304 | // For medium-sized buffers, check for overlap |
| 1305 | else { |
| 1306 | // Check if regions overlap with target after source |
| 1307 | int const overlapping = (target > source && target < source + length); |
| 1308 | |
| 1309 | if (overlapping) { |
| 1310 | // Backward traversal to avoid overwriting source data |
| 1311 | source += length; |
| 1312 | target += length; |
| 1313 | |
| 1314 | // Backward main loop |
| 1315 | for (; length >= vec_len; length -= vec_len) { |
| 1316 | source -= vec_len; |
| 1317 | target -= vec_len; |
| 1318 | svuint8_t data = svld1_u8(svptrue_b8(), (sz_u8_t const *)source); |
| 1319 | svst1_u8(svptrue_b8(), (sz_u8_t *)target, data); |
| 1320 | } |
| 1321 | |
| 1322 | // Backward tail |
| 1323 | if (length) { |
| 1324 | source -= length; |
| 1325 | target -= length; |
| 1326 | svbool_t mask = svwhilelt_b8((sz_u64_t)0ull, (sz_u64_t)length); |
| 1327 | svuint8_t data = svld1_u8(mask, (sz_u8_t const *)source); |
| 1328 | svst1_u8(mask, (sz_u8_t *)target, data); |
| 1329 | } |
| 1330 | } |
| 1331 | else { |
| 1332 | // Forward traversal (safe for non-overlapping or target < source) |
| 1333 | // Main loop: full vector copies |
| 1334 | for (; length >= vec_len; source += vec_len, target += vec_len, length -= vec_len) { |
| 1335 | svuint8_t data = svld1_u8(svptrue_b8(), (sz_u8_t const *)source); |
| 1336 | svst1_u8(svptrue_b8(), (sz_u8_t *)target, data); |
| 1337 | } |
| 1338 | |
| 1339 | // Tail: single masked copy for remainder |
| 1340 | if (length) { |
| 1341 | svbool_t mask = svwhilelt_b8((sz_u64_t)0ull, (sz_u64_t)length); |
| 1342 | svuint8_t data = svld1_u8(mask, (sz_u8_t const *)source); |
no outgoing calls
no test coverage detected
searching dependent graphs…