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 <ja...@redhat.com> > > 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 <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)