This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: I386 strlen "fix" (giveup)
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 ----