Yuqi Guo
2024-Oct-08 12:24 UTC
Question: Is CAREFUL_ALIGNMENT=1 needed for rsync on RISC-V
Hello, I'm using rsync on RISC-V machines. I notice that the developers of rsync seem to assume that only x86 CPUs can handle memory misalignments: ```c /* We know that the x86 can handle misalignment and has the same ?* byte order (LSB-first) as the 32-bit numbers we transmit. */ #if defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__ || __amd64 #define CAREFUL_ALIGNMENT 0 #endif #ifndef CAREFUL_ALIGNMENT #define CAREFUL_ALIGNMENT 1 #endif ``` Thus, when copying 4-bit integers (just an example), rsync uses direct copies on x86: ```c static inline uint32 IVALu(const uchar *buf, int pos) { ?? ?union { ?? ???? const uchar *b; ?? ???? const uint32 *num; ?? ?} u; ?? ?u.b = buf + pos; ?? ?return *u.num; } ``` On RISC-V (and any other architectures), it copies bytes one by one: ```c static inline uint32 IVALu(const uchar *buf, int pos) { ?? ?return UVAL(buf, pos) ?? ????? | UVAL(buf, pos + 1) << 8 ?? ????? | UVAL(buf, pos + 2) << 16 ?? ????? | UVAL(buf, pos + 3) << 24; } ``` However, it seems that RISC-V supports misaligned memory accesses. I tested the following code on a RISC-V machine. It worked well. ```c #include <stdio.h> int x; int arr[2], out[2]; int main() { ??????? arr[0]=0x11223344; ??????? arr[1]=0x55667788; ??????? out[0]=out[1]=0; ??????? x=*(arr); ??????? printf("x=%x\n",x); ??????? x= *(int*)((char *)arr +1); ??????? char *ptr=(char *)out+3; ??????? *(int*)ptr=*(int*)((char *)arr +3); ??????? printf("x2=%x\n",x); ??????? printf("out[0]=%x, out[1]=%x\n",out[0],out[1]); ??????? return 0; } ``` So, my question is, is CAREFUL_ALIGNMENT=1 necessary for RISC-V? Although misalignment accesses will suffer from a large time penalty on RISC-V, I guess it can still run faster than four UVAL calls. Best regards, Yuqi Guo