This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix inline memcpy ICE (PR tree-optimization/86526)


On Mon, 16 Jul 2018, Jakub Jelinek wrote:

> Hi!
> 
> builtin_memcpy_read_str is a function meant to be called just as a callback
> and verifies that we don't cross a '\0' boundary in the string.  For
> inline_string_cmp, we've checked that the length returned from c_getstr
> is fine, so we can cross as many embedded NULs as there are within the
> TREE_STRING_LENGTH.
> 
> The rest of the patch is just a temporary to avoid using as_a twice in
> each loop iteration, and lots of formatting fixes, mostly to avoid trailing
> whitespace.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

> 2018-07-16  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/86526
> 	* builtins.c (expand_builtin_memcmp): Formatting fixes.
> 	(inline_expand_builtin_string_cmp): Likewise.
> 	(inline_string_cmp): Likewise.  Use c_readstr instead of
> 	builtin_memcpy_read_str.  Add unit_mode temporary.
> 
> 	* gcc.c-torture/compile/pr86526.c: New test.
> 
> --- gcc/builtins.c.jj	2018-07-16 09:42:25.743985945 +0200
> +++ gcc/builtins.c	2018-07-16 11:47:46.535014889 +0200
> @@ -4454,19 +4454,19 @@ expand_builtin_memcmp (tree exp, rtx tar
>    no_overflow = check_access (exp, /*dst=*/NULL_TREE, /*src=*/NULL_TREE,
>  			      len, /*maxread=*/NULL_TREE, size,
>  			      /*objsize=*/NULL_TREE);
> -  if (no_overflow) 
> +  if (no_overflow)
>      {
>        size = compute_objsize (arg2, 0);
>        no_overflow = check_access (exp, /*dst=*/NULL_TREE, /*src=*/NULL_TREE,
>  				  len,  /*maxread=*/NULL_TREE, size,
>  				  /*objsize=*/NULL_TREE);
> -    } 
> +    }
>  
> -  /* Due to the performance benefit, always inline the calls first 
> +  /* Due to the performance benefit, always inline the calls first
>       when result_eq is false.  */
>    rtx result = NULL_RTX;
> -   
> -  if (!result_eq && fcode != BUILT_IN_BCMP && no_overflow) 
> +
> +  if (!result_eq && fcode != BUILT_IN_BCMP && no_overflow)
>      {
>        result = inline_expand_builtin_string_cmp (exp, target, true);
>        if (result)
> @@ -6748,7 +6748,7 @@ expand_builtin_goacc_parlevel_id_size (t
>    return target;
>  }
>  
> -/* Expand a string compare operation using a sequence of char comparison 
> +/* Expand a string compare operation using a sequence of char comparison
>     to get rid of the calling overhead, with result going to TARGET if
>     that's convenient.
>  
> @@ -6757,7 +6757,7 @@ expand_builtin_goacc_parlevel_id_size (t
>     LENGTH is the number of chars to compare;
>     CONST_STR_N indicates which source string is the constant string;
>     IS_MEMCMP indicates whether it's a memcmp or strcmp.
> -   
> +  
>     to: (assume const_str_n is 2, i.e., arg2 is a constant string)
>  
>     target = var_str[0] - const_str[0];
> @@ -6772,41 +6772,38 @@ expand_builtin_goacc_parlevel_id_size (t
>    */
>  
>  static rtx
> -inline_string_cmp (rtx target, tree var_str, const char* const_str, 
> +inline_string_cmp (rtx target, tree var_str, const char *const_str,
>  		   unsigned HOST_WIDE_INT length,
>  		   int const_str_n, machine_mode mode,
> -		   bool is_memcmp) 
> +		   bool is_memcmp)
>  {
>    HOST_WIDE_INT offset = 0;
> -  rtx var_rtx_array 
> +  rtx var_rtx_array
>      = get_memory_rtx (var_str, build_int_cst (unsigned_type_node,length));
>    rtx var_rtx = NULL_RTX;
> -  rtx const_rtx = NULL_RTX; 
> -  rtx result = target ? target : gen_reg_rtx (mode); 
> -  rtx_code_label *ne_label = gen_label_rtx ();  
> +  rtx const_rtx = NULL_RTX;
> +  rtx result = target ? target : gen_reg_rtx (mode);
> +  rtx_code_label *ne_label = gen_label_rtx ();
>    tree unit_type_node = is_memcmp ? unsigned_char_type_node : char_type_node;
> +  scalar_int_mode unit_mode
> +    = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
>  
>    start_sequence ();
>  
>    for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
>      {
> -      var_rtx 
> +      var_rtx
>  	= adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
> -      const_rtx 
> -	= builtin_memcpy_read_str (CONST_CAST (char *, const_str),
> -				   offset,
> -    				   as_a <scalar_int_mode> 
> -				   TYPE_MODE (unit_type_node));
> +      const_rtx = c_readstr (const_str + offset, unit_mode);
>        rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
>        rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
> -  
> -      result = expand_simple_binop (mode, MINUS, op0, op1, 
> -			            result, is_memcmp ? 1 : 0, OPTAB_WIDEN);
> -      if (i < length - 1) 
> -        emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
> -            		         mode, true, ne_label);
> -      offset 
> -	+= GET_MODE_SIZE (as_a <scalar_int_mode> TYPE_MODE (unit_type_node));
> +
> +      result = expand_simple_binop (mode, MINUS, op0, op1,
> +				    result, is_memcmp ? 1 : 0, OPTAB_WIDEN);
> +      if (i < length - 1)
> +	emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
> +	    			 mode, true, ne_label);
> +      offset += GET_MODE_SIZE (unit_mode);
>      }
>  
>    emit_label (ne_label);
> @@ -6817,7 +6814,7 @@ inline_string_cmp (rtx target, tree var_
>    return result;
>  }
>  
> -/* Inline expansion a call to str(n)cmp, with result going to 
> +/* Inline expansion a call to str(n)cmp, with result going to
>     TARGET if that's convenient.
>     If the call is not been inlined, return NULL_RTX.  */
>  static rtx
> @@ -6829,7 +6826,7 @@ inline_expand_builtin_string_cmp (tree e
>    bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
>  
>    gcc_checking_assert (fcode == BUILT_IN_STRCMP
> -		       || fcode == BUILT_IN_STRNCMP 
> +		       || fcode == BUILT_IN_STRNCMP
>  		       || fcode == BUILT_IN_MEMCMP);
>  
>    tree arg1 = CALL_EXPR_ARG (exp, 0);
> @@ -6842,7 +6839,7 @@ inline_expand_builtin_string_cmp (tree e
>  
>    const char *src_str1 = c_getstr (arg1, &len1);
>    const char *src_str2 = c_getstr (arg2, &len2);
> - 
> +
>    /* If neither strings is constant string, the call is not qualify.  */
>    if (!src_str1 && !src_str2)
>      return NULL_RTX;
> @@ -6867,16 +6864,16 @@ inline_expand_builtin_string_cmp (tree e
>    if (is_ncmp && (len3 = tree_to_uhwi (len3_tree)) < length)
>      length = len3;
>  
> -  /* If the length of the comparision is larger than the threshold, 
> +  /* If the length of the comparision is larger than the threshold,
>       do nothing.  */
> -  if (length > (unsigned HOST_WIDE_INT) 
> +  if (length > (unsigned HOST_WIDE_INT)
>  	       PARAM_VALUE (BUILTIN_STRING_CMP_INLINE_LENGTH))
>      return NULL_RTX;
>  
>    machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
>  
>    /* Now, start inline expansion the call.  */
> -  return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1, 
> +  return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
>  			    (const_str_n == 1) ? src_str1 : src_str2, length,
>  			    const_str_n, mode, is_memcmp);
>  }
> @@ -7282,7 +7279,7 @@ expand_builtin (tree exp, rtx target, rt
>  	return target;
>        break;
>  
> -    /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it 
> +    /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
>         back to a BUILT_IN_STRCMP. Remember to delete the 3rd paramater
>         when changing it to a strcmp call.  */
>      case BUILT_IN_STRCMP_EQ:
> @@ -7291,7 +7288,7 @@ expand_builtin (tree exp, rtx target, rt
>  	return target;
>  
>        /* Change this call back to a BUILT_IN_STRCMP.  */
> -      TREE_OPERAND (exp, 1) 
> +      TREE_OPERAND (exp, 1)
>  	= build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP));
>  
>        /* Delete the last parameter.  */
> @@ -7317,7 +7314,7 @@ expand_builtin (tree exp, rtx target, rt
>  	return target;
>  
>        /* Change it back to a BUILT_IN_STRNCMP.  */
> -      TREE_OPERAND (exp, 1) 
> +      TREE_OPERAND (exp, 1)
>  	= build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP));
>        /* FALLTHROUGH */
>  
> --- gcc/testsuite/gcc.c-torture/compile/pr86526.c.jj	2018-07-16 11:50:30.756223270 +0200
> +++ gcc/testsuite/gcc.c-torture/compile/pr86526.c	2018-07-16 11:50:16.205203998 +0200
> @@ -0,0 +1,8 @@
> +/* PR tree-optimization/86526 */
> +
> +void
> +foo (char *x)
> +{
> +  if (__builtin_memcmp (x, "\0a", 3))
> +    __builtin_abort ();
> +}
> 
> 	Jakub
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]