https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95151
Bug ID: 95151 Summary: Add cmpmemM pattern for -minline-all-stringops Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: hjl.tools at gmail dot com CC: crazylht at gmail dot com Target Milestone: --- Target: i386,x86-64 'cmpmemM' Block compare instruction, with five operands like the operands of 'cmpstrM'. The two memory blocks specified are compared byte by byte in lexicographic order starting at the beginning of each block. Unlike 'cmpstrM' the instruction can prefetch any bytes in the two memory blocks. Also unlike 'cmpstrM' the comparison will not stop if both bytes are zero. The effect of the instruction is to store a value in operand 0 whose sign indicates the result of the comparison. We should add (define_expand "cmpmemsi" [(set (match_operand:SI 0 "register_operand" "") (compare:SI (match_operand:BLK 1 "memory_operand" "") (match_operand:BLK 2 "memory_operand" "") ) ) (use (match_operand 3 "general_operand")) (use (match_operand 4 "immediate_operand"))] "" { if (ix86_expand_cmpmem (operands[0], operands[1], operands[2], operands[3])) DONE; else FAIL; }) which can be expanded to sysdeps/i386/memcmp.S in glibc: movl BLK1(%esp), %esi cfi_rel_offset (esi, 0) movl BLK2(%esp), %edi movl LEN(%esp), %ecx cld /* Set direction of comparison. */ xorl %eax, %eax /* Default result. */ repe /* Compare at most %ecx bytes. */ cmpsb jz L(1) /* If even last byte was equal we return 0. */ /* The memory blocks are not equal. So result of the last subtraction is present in the carry flag. It is set when the byte in block #2 is bigger. In this case we have to return -1 (=0xffffffff), else 1. */ sbbl %eax, %eax /* This is tricky. %eax == 0 and carry is set or not depending on last subtraction. */ /* At this point %eax == 0, if the byte of block #1 was bigger, and 0xffffffff if the last byte of block #2 was bigger. The latter case is already correct but the former needs a little adjustment. Note that the following operation does not change 0xffffffff. */ orb $1, %al /* Change 0 to 1. */ L(1):