Hi, on s390 a strcat is already decomposed by fold_builtin_strcat into a strlen and a strcpy. Due to that 3 strlenopt testcases currently fail: strlenopt-17g.c, strlenopt-4.c, strlenopt-4g.c.
For strlenopt-4.c no optimization is expected anyway (stpcpy disabled). So this can easily be fixed by adding s390 specific scan values. The other two probably could be fixed by modifying the strlen optimization to be able to reconstruct the strcat semantics. The attached quick hack fixes strlenopt-17g.c for s390 without regressions on x86_64. For strlenopt-4g.c I only could get it working with setting (too) many dont_invalidate flags on strinfos. Otherwise the information needed to reconstruct the strcat semantics don't survive long enough. Perhaps we can remove the strcat folding relying on the strlen optimization pass to catch all relevant cases? Bye, -Andreas- Index: gcc/tree-ssa-strlen.c =================================================================== *** gcc/tree-ssa-strlen.c.orig --- gcc/tree-ssa-strlen.c *************** get_string_length (strinfo si) *** 397,403 **** callee = gimple_call_fndecl (stmt); gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL); lhs = gimple_call_lhs (stmt); ! gcc_assert (builtin_decl_implicit_p (BUILT_IN_STRCPY)); /* unshare_strinfo is intentionally not called here. The (delayed) transformation of strcpy or strcat into stpcpy is done at the place of the former strcpy/strcat call and so can affect all the strinfos --- 397,403 ---- callee = gimple_call_fndecl (stmt); gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL); lhs = gimple_call_lhs (stmt); ! gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY)); /* unshare_strinfo is intentionally not called here. The (delayed) transformation of strcpy or strcat into stpcpy is done at the place of the former strcpy/strcat call and so can affect all the strinfos *************** handle_builtin_strcpy (enum built_in_fun *** 1115,1127 **** dsi->writable = true; dsi->dont_invalidate = true; ! if (dsi->length == NULL_TREE) { /* If string length of src is unknown, use delayed length computation. If string lenth of dst will be needed, it can be computed by transforming this strcpy call into stpcpy and subtracting dst from the return value. */ ! dsi->stmt = stmt; return; } --- 1115,1144 ---- dsi->writable = true; dsi->dont_invalidate = true; ! if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && dsi->length == NULL_TREE) { + strinfo psi; + /* If string length of src is unknown, use delayed length computation. If string lenth of dst will be needed, it can be computed by transforming this strcpy call into stpcpy and subtracting dst from the return value. */ ! psi = get_strinfo (dsi->prev); ! if (psi ! && psi->next == dsi->idx ! && psi->first == dsi->first ! && psi->endptr == dsi->ptr) ! { ! strinfo npsi = unshare_strinfo (psi); ! npsi->stmt = stmt; ! npsi->next = 0; ! npsi->length = NULL_TREE; ! npsi->endptr = NULL_TREE; ! npsi->dont_invalidate = true; ! } ! else ! dsi->stmt = stmt; ! return; }