I386 strlen "fix" (giveup)

Richard Henderson rth@cygnus.com
Wed Mar 8 11:24:00 GMT 2000


On Wed, Mar 08, 2000 at 01:34:42PM +0100, Jan Hubicka wrote:
> It looks like my original approach.  I guess it will fail on
> main(char *c)
> {
>   return strlen (({c++;}));
> }
> The problem is related to double-expanding parameters.

Ah yes.  Ok, so we don't do that.  This one I've checked in.


r~



        * builtins.c (expand_builtin_strlen): Be prepared for strlensi
        to fail.  Don't pre-expand the source operand.

        * i386.md (strlensi): Initialize eoschar and align before use.

Index: builtins.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/builtins.c,v
retrieving revision 1.33
diff -c -p -d -r1.33 builtins.c
*** builtins.c	2000/03/06 18:03:54	1.33
--- builtins.c	2000/03/08 18:33:49
*************** expand_builtin_strlen (exp, target, mode
*** 1334,1346 ****
      return 0;
    else
      {
        tree src = TREE_VALUE (arglist);
        tree len = c_strlen (src);
  
        int align
  	= get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
  
!       rtx result, src_rtx, char_rtx;
        enum machine_mode insn_mode = value_mode, char_mode;
        enum insn_code icode = CODE_FOR_nothing;
  
--- 1334,1347 ----
      return 0;
    else
      {
+       rtx pat;
        tree src = TREE_VALUE (arglist);
        tree len = c_strlen (src);
  
        int align
  	= get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
  
!       rtx result, src_reg, char_rtx, before_strlen;
        enum machine_mode insn_mode = value_mode, char_mode;
        enum insn_code icode = CODE_FOR_nothing;
  
*************** expand_builtin_strlen (exp, target, mode
*** 1352,1359 ****
        if (align == 0)
  	return 0;
  
!       /* Call a function if we can't compute strlen in the right mode.  */
! 
        while (insn_mode != VOIDmode)
  	{
  	  icode = strlen_optab->handlers[(int) insn_mode].insn_code;
--- 1353,1359 ----
        if (align == 0)
  	return 0;
  
!       /* Bail out if we can't compute strlen in the right mode.  */
        while (insn_mode != VOIDmode)
  	{
  	  icode = strlen_optab->handlers[(int) insn_mode].insn_code;
*************** expand_builtin_strlen (exp, target, mode
*** 1373,1393 ****
  	     && REGNO (result) >= FIRST_PSEUDO_REGISTER))
  	result = gen_reg_rtx (insn_mode);
  
!       /* Make sure the operands are acceptable to the predicates.  */
! 
!       if (! (*insn_data[(int)icode].operand[0].predicate) (result, insn_mode))
! 	result = gen_reg_rtx (insn_mode);
!       src_rtx = memory_address (BLKmode,
! 				expand_expr (src, NULL_RTX, ptr_mode,
! 					     EXPAND_NORMAL));
  
!       if (! (*insn_data[(int)icode].operand[1].predicate) (src_rtx, Pmode))
! 	src_rtx = copy_to_mode_reg (Pmode, src_rtx);
  
        /* Check the string is readable and has an end.  */
        if (current_function_check_memory_usage)
  	emit_library_call (chkr_check_str_libfunc, 1, VOIDmode, 2,
! 			   src_rtx, Pmode,
  			   GEN_INT (MEMORY_USE_RO),
  			   TYPE_MODE (integer_type_node));
  
--- 1373,1391 ----
  	     && REGNO (result) >= FIRST_PSEUDO_REGISTER))
  	result = gen_reg_rtx (insn_mode);
  
!       /* Make a place to hold the source address.  We will not expand
! 	 the actual source until we are sure that the expansion will
! 	 not fail -- there are trees that cannot be expanded twice.  */
!       src_reg = gen_reg_rtx (Pmode);
  
!       /* Mark the beginning of the strlen sequence so we can emit the
! 	 source operand later.  */
!       before_strlen = get_last_insn();
  
        /* Check the string is readable and has an end.  */
        if (current_function_check_memory_usage)
  	emit_library_call (chkr_check_str_libfunc, 1, VOIDmode, 2,
! 			   src_reg, Pmode,
  			   GEN_INT (MEMORY_USE_RO),
  			   TYPE_MODE (integer_type_node));
  
*************** expand_builtin_strlen (exp, target, mode
*** 1396,1415 ****
        if (! (*insn_data[(int)icode].operand[2].predicate) (char_rtx, char_mode))
  	char_rtx = copy_to_mode_reg (char_mode, char_rtx);
  
!       emit_insn (GEN_FCN (icode) (result,
! 				  gen_rtx_MEM (BLKmode, src_rtx),
! 				  char_rtx, GEN_INT (align)));
  
        /* Return the value in the proper mode for this function.  */
        if (GET_MODE (result) == value_mode)
! 	return result;
        else if (target != 0)
! 	{
! 	  convert_move (target, result, 0);
! 	  return target;
! 	}
        else
! 	return convert_to_mode (value_mode, result, 0);
      }
  }
  
--- 1394,1423 ----
        if (! (*insn_data[(int)icode].operand[2].predicate) (char_rtx, char_mode))
  	char_rtx = copy_to_mode_reg (char_mode, char_rtx);
  
!       pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
! 			     char_rtx, GEN_INT (align));
!       if (! pat)
! 	return 0;
!       emit_insn (pat);
! 
!       /* Now that we are assured of success, expand the source.  */
!       start_sequence ();
!       pat = expand_expr (src, src_reg, ptr_mode, EXPAND_SUM);
!       if (pat != src_reg)
! 	emit_move_insn (src_reg, pat);
!       pat = gen_sequence ();
!       end_sequence ();
!       emit_insn_after (pat, before_strlen);
  
        /* Return the value in the proper mode for this function.  */
        if (GET_MODE (result) == value_mode)
! 	target = result;
        else if (target != 0)
! 	convert_move (target, result, 0);
        else
! 	target = convert_to_mode (value_mode, result, 0);
! 
!       return target;
      }
  }
  
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.140
diff -c -p -d -r1.140 i386.md
*** i386.md	2000/03/01 11:15:52	1.140
--- i386.md	2000/03/08 18:33:51
***************
*** 8591,8597 ****
    ""
    "
  {
!   rtx out, addr, eoschar, align, scratch1, scratch2, scratch3;
  
    /* The generic case of strlen expander is long.  Avoid it's
       expanding unless TARGET_INLINE_ALL_STRINGOPS.  */
--- 8591,8599 ----
    ""
    "
  {
!   rtx out, addr, scratch1, scratch2, scratch3;
!   rtx eoschar = operands[2];
!   rtx align = operands[3];
  
    /* The generic case of strlen expander is long.  Avoid it's
       expanding unless TARGET_INLINE_ALL_STRINGOPS.  */
***************
*** 8603,8610 ****
  
    out = operands[0];
    addr = force_reg (Pmode, XEXP (operands[1], 0));
-   eoschar = operands[2];
-   align = operands[3];
    scratch1 = gen_reg_rtx (SImode);
  
    if (TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1
--- 8605,8610 ----


More information about the Gcc-patches mailing list