https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77718
Bug ID: 77718 Summary: expand_builtin_memcmp swaps args Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: acsawdey at gcc dot gnu.org CC: bernds at gcc dot gnu.org Target Milestone: --- Created attachment 39674 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39674&action=edit test case If you have a memcmp call that has const string args but one or both of them are shorter than the constant length given, the builtin expansion machinery will get called to expand the builtin, but the arguments given are reversed so the result is unexpected. The attached test will provoke this condition. In expand_buildin_memcmp () the following code is where this happens: by_pieces_constfn constfn = NULL; const char *src_str = c_getstr (arg1); if (src_str == NULL) src_str = c_getstr (arg2); else std::swap (arg1_rtx, arg2_rtx); /* If SRC is a string constant and block move would be done by pieces, we can avoid loading the string from memory and only stored the computed constants. */ if (src_str && CONST_INT_P (len_rtx) && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1) constfn = builtin_memcpy_read_str; rtx result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx, TREE_TYPE (len), target, result_eq, constfn, CONST_CAST (char *, src_str)); If you have arg1 a const str, then you get the swap of arg1_rtx and arg2_rtx. Normally this would be hidden because ccp folding earlier would have evaluated the memcmp to a const value since all args are const. However that folding does not happen when one/both of the strings are shorter than the given length since that is an undefined situation. Thus we come in here and get this swap but in this case result_eq won't be set. I think the solution might be to only do the swap when result_eq is set.