[tree-ssa] fix Bugs 15109, 15108, 14472 and most likely 14440

Steven Bosscher stevenb@suse.de
Fri May 14 15:25:00 GMT 2004


On Friday 07 May 2004 02:05, Steven Bosscher wrote:
> Hi,
>
> They're all really the same bug and should be duplicates.
> All we have to do is look through NOP_EXPRs.

As Diego pointed out, we should be using STRIP_NOPS.  Just looking
through NOP_EXPRs is actually not safe:

=============================
// PR14441
short t();
int f()
{
 return t();
}
=============================

(gdb) p debug_generic_stmt (ret_var)
<retval>_2 = (int<D0>)T.0<D1454>_1;
(gdb) p debug_tree (ret_var->exp.operands[1])
 <nop_expr 0x2a9565e180
    type <integer_type 0x2a955c09a0 int SI
    arg 0 <ssa_name 0x2a959a69c0
        type <integer_type 0x2a955c07e0 short int HI>>
       >>

Ignoring the NOP here apparently just happened to work because we
don't have this covered in the test suite.  In general, it is not
safe to ignore NOPs that change the machine mode.

In the cases that STRIP_NOPS strips, it is safe to ignore the NOP:

=============================
// PR14472
enum t
{
  GS_OK,
  GS_DONE
};
enum t f();
int g()
{
  return f();
}
=============================

(gdb) p debug_generic_stmt (ret_var)
<retval>_2 = (int<D0>)T.0<D1457>_1;
(gdb) p debug_tree (ret_var->exp.operands[1])
 <nop_expr 0x2a9565e180
    type <integer_type 0x2a955c09a0 int SI
    arg 0 <ssa_name 0x2a959a6b70
        type <enumeral_type 0x2a95995ee0 t unsigned type_0 SI>>
       >>

In this case the NOP_EXPR is getting in the way, and with STRIP_NOPS
we see that the int and the enum are in the same mode, so it's safe
to ignore the NOP_EXPR, and we can identify the call to f as a tail
call opportunity.

Bootstrapped and tested on x86-64-unknown-linux-gnu.  OK?

Gr.
Steven

	PR opt/14472
 	* tree-tailcall.c (process_assignment): Use STRIP_NOPS to
	ignore type conversions that do not inhibit tail calling.
 	(find_tail_calls): Likewise.

Index: tree-tailcall.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-tailcall.c,v
retrieving revision 2.1
diff -c -3 -p -r2.1 tree-tailcall.c
*** tree-tailcall.c	13 May 2004 06:39:50 -0000	2.1
--- tree-tailcall.c	14 May 2004 15:06:36 -0000
*************** process_assignment (tree ass, tree stmt,
*** 260,269 ****
    tree dest = TREE_OPERAND (ass, 0);
    tree src = TREE_OPERAND (ass, 1);
    enum tree_code code = TREE_CODE (src);
  
!   if (code == SSA_NAME)
      {
!       if (src != *ass_var)
  	return false;
  
        *ass_var = dest;
--- 260,275 ----
    tree dest = TREE_OPERAND (ass, 0);
    tree src = TREE_OPERAND (ass, 1);
    enum tree_code code = TREE_CODE (src);
+   tree src_var = src;
  
!   /* See if this is a simple copy operation of an SSA name to the function
!      result.  In that case we may have a simple tail call.  Ignore type
!      conversions that can never produce extra code between the function
!      call and the function return.  */
!   STRIP_NOPS (src_var);
!   if (TREE_CODE (src_var) == SSA_NAME)
      {
!       if (src_var != *ass_var)
  	return false;
  
        *ass_var = dest;
*************** process_assignment (tree ass, tree stmt,
*** 295,301 ****
    else
      return false;
  
!   switch (TREE_CODE (src))
      {
      case PLUS_EXPR:
        /* There should be no previous addition.  TODO -- it should be fairly
--- 301,307 ----
    else
      return false;
  
!   switch (code)
      {
      case PLUS_EXPR:
        /* There should be no previous addition.  TODO -- it should be fairly
*************** find_tail_calls (basic_block bb, struct 
*** 463,474 ****
  	return;
      }
  
    ret_var = TREE_OPERAND (stmt, 0);
    if (ret_var
        && TREE_CODE (ret_var) == MODIFY_EXPR)
      {
        if (!tail_recursion
! 	  && TREE_CODE (TREE_OPERAND (ret_var, 1)) != SSA_NAME)
  	return;
  
        if (!process_assignment (ret_var, stmt, bsi, &m, &a, &ass_var))
--- 469,483 ----
  	return;
      }
  
+   /* See if this is a tail call we can handle.  */
    ret_var = TREE_OPERAND (stmt, 0);
    if (ret_var
        && TREE_CODE (ret_var) == MODIFY_EXPR)
      {
+       tree ret_op = TREE_OPERAND (ret_var, 1);
+       STRIP_NOPS (ret_op);
        if (!tail_recursion
! 	  && TREE_CODE (ret_op) != SSA_NAME)
  	return;
  
        if (!process_assignment (ret_var, stmt, bsi, &m, &a, &ass_var))



More information about the Gcc-patches mailing list