On Fri, 22 Jan 2021, Jakub Jelinek wrote:
> Hi!
>
> As mentioned in the PR, the compiler behaves differently during strncmp
> and strncasecmp folding between 32-bit and 64-bit hosts targeting 64-bit
> target. I think that is highly undesirable.
>
> The culprit is the host_size_t_cst_p predicate that is used by
> fold_const_call, which punts if the target size_t constants don't fit into
> host size_t. This patch gets rid of that behavior, instead it punts the
> same when it doesn't fit into uhwi.
>
> The predicate was used for strncmp and strncasecmp folding and for bcmp,
> memcmp and
> memchr folding.
> The constant is in all cases compared to 0, we can do that whether it fits
> into size_t or unsigned HOST_WIDE_INT, then it is used in s2 <= s0 or
> s2 <= s1 comparisons where s0 and s1 already have uhwi type and represent
> the sizes of the objects.
> The important difference is for strn{,case}cmp folding, we pass that s2
> value as the last argument to the host functions comparing the c_getstr
> results. If s2 fits into size_t, then my patch makes no difference,
> but if it is larger, we know the 2 c_getstr objects need to fit into the
> host address space, so larger s2 should just act essentially as strcmp
> or strcasecmp; as none of those objects can occupy 100% of the address
> space, using MIN (SIZE_MAX, s2) achieves that.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK.
Thanks,
Richard.
> 2021-01-22 Jakub Jelinek <[email protected]>
>
> PR testsuite/98771
> * fold-const-call.c (host_size_t_cst_p): Renamed to ...
> (size_t_cst_p): ... this. Check and store unsigned HOST_WIDE_INT
> value rather than host size_t.
> (fold_const_call): Change type of s2 from size_t to
> unsigned HOST_WIDE_INT. Use size_t_cst_p instead of
> host_size_t_cst_p. For strncmp calls, pass MIN (s2, SIZE_MAX)
> instead of s2 as last argument.
>
> --- gcc/fold-const-call.c.jj 2021-01-04 10:25:37.902244366 +0100
> +++ gcc/fold-const-call.c 2021-01-22 11:23:31.571000548 +0100
> @@ -53,16 +53,15 @@ complex_cst_p (tree t)
> return TREE_CODE (t) == COMPLEX_CST;
> }
>
> -/* Return true if ARG is a constant in the range of the host size_t.
> +/* Return true if ARG is a size_type_node constant.
> Store it in *SIZE_OUT if so. */
>
> static inline bool
> -host_size_t_cst_p (tree t, size_t *size_out)
> +size_t_cst_p (tree t, unsigned HOST_WIDE_INT *size_out)
> {
> if (types_compatible_p (size_type_node, TREE_TYPE (t))
> && integer_cst_p (t)
> - && (wi::min_precision (wi::to_wide (t), UNSIGNED)
> - <= sizeof (size_t) * CHAR_BIT))
> + && tree_fits_uhwi_p (t))
> {
> *size_out = tree_to_uhwi (t);
> return true;
> @@ -1767,23 +1766,22 @@ fold_const_call (combined_fn fn, tree ty
> {
> const char *p0, *p1;
> char c;
> - unsigned HOST_WIDE_INT s0, s1;
> - size_t s2 = 0;
> + unsigned HOST_WIDE_INT s0, s1, s2 = 0;
> switch (fn)
> {
> case CFN_BUILT_IN_STRNCMP:
> - if (!host_size_t_cst_p (arg2, &s2))
> + if (!size_t_cst_p (arg2, &s2))
> return NULL_TREE;
> if (s2 == 0
> && !TREE_SIDE_EFFECTS (arg0)
> && !TREE_SIDE_EFFECTS (arg1))
> return build_int_cst (type, 0);
> else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
> - return build_int_cst (type, strncmp (p0, p1, s2));
> + return build_int_cst (type, strncmp (p0, p1, MIN (s2, SIZE_MAX)));
> return NULL_TREE;
>
> case CFN_BUILT_IN_STRNCASECMP:
> - if (!host_size_t_cst_p (arg2, &s2))
> + if (!size_t_cst_p (arg2, &s2))
> return NULL_TREE;
> if (s2 == 0
> && !TREE_SIDE_EFFECTS (arg0)
> @@ -1791,13 +1789,13 @@ fold_const_call (combined_fn fn, tree ty
> return build_int_cst (type, 0);
> else if ((p0 = c_getstr (arg0))
> && (p1 = c_getstr (arg1))
> - && strncmp (p0, p1, s2) == 0)
> + && strncmp (p0, p1, MIN (s2, SIZE_MAX)) == 0)
> return build_int_cst (type, 0);
> return NULL_TREE;
>
> case CFN_BUILT_IN_BCMP:
> case CFN_BUILT_IN_MEMCMP:
> - if (!host_size_t_cst_p (arg2, &s2))
> + if (!size_t_cst_p (arg2, &s2))
> return NULL_TREE;
> if (s2 == 0
> && !TREE_SIDE_EFFECTS (arg0)
> @@ -1811,7 +1809,7 @@ fold_const_call (combined_fn fn, tree ty
> return NULL_TREE;
>
> case CFN_BUILT_IN_MEMCHR:
> - if (!host_size_t_cst_p (arg2, &s2))
> + if (!size_t_cst_p (arg2, &s2))
> return NULL_TREE;
> if (s2 == 0
> && !TREE_SIDE_EFFECTS (arg0)
>
> Jakub
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)