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]

[tree-ssa] Yet another VLA fix



gcc.dg/20011015-1.c shows another problem with our code which searches
for VLAs.

If you look at the .dce dump for function "baz" you'll find something
like this:

baz (x)
{
  {
    char * x;

    x_2 = x_1;
    {
      char retval.6;
      char T.2;
      int T.3;
      unsigned int T.4;
      unsigned int T.5;

      {
        char * x;
        int <UV1cb0>;

        x_3 = x_2;
        {
          char T.1;

          T.1_6 = (*x)_5;
          <UV1cb0>_7 = (int)T.1_6;
          goto <UL1d90>;
        };
        <UL1d90>:;;
        retval.6_8 = (char)<UV1cb0>_7
      };
      T.3_9 = (int)retval.6_8;
      (void)0;
      (void)0;
      {
        void * arr[T.5];

        (void)0
      }
    }
  }
}

Note carefully that T.5 is uninitialized.

This really had me confused for a while as tracing the VLA code showed
that we were marking T.5 as having a hidden use.  Hmm, that's odd.

Then I realized that we were marking the *wrong* T.5 -- we marked the
T.5 occurring in function "bar" as having a hidden use.  Thus the T.5
in function "baz" appeared unused and it's initialization was removed
by dead code elimination.

When I started looking at the code I was *very* confused as to why we
were looking at the size of the ARRAY_TYPE (which might involve a 
SAVE_EXPR referencing variables in another function's context) -- what
we really need to look at is the size of the VAR_DECL!

Changing the code to look at the VAR_DECL's size in the expected manner
resulted in something that looks a lot more sensible:

baz (x)
{
  {
    char * x;

    x_2 = x_1;
    {
      char retval.6;
      int T.3;
      unsigned int T.4;
      unsigned int T.5;

      {
        char * x;
        int <UV1c40>;

        x_3 = x_2;
        {
          char T.1;

          T.1_6 = (*x)_5;
          <UV1c40>_7 = (int)T.1_6;
          goto <UL1d20>;
        };
        <UL1d20>:;;
        retval.6_8 = (char)<UV1c40>_7
      };
      T.3_9 = (int)retval.6_8;
      T.4_10 = (unsigned int)T.3_9;
      T.5_11 = T.4_10 * 4;
      {
        void * arr[T.5];

        (void)0
      }
    }
  }
}

[ Like many of the DFA bugs I've fixed recently, this bug was exposed by
  my code which removes unused variables.  Damn it's good at finding
  broken stuff. ]

	* tree-dfa.c (find_hidden_use_vars): Look at the size of
	VAR_DECLs, not the size of ARRAY_TYPES.  Also make sure
	to reset *inside_vla to its original value when done
	processing any particular VAR_DECL.

Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.107
diff -c -3 -p -r1.1.4.107 tree-dfa.c
*** tree-dfa.c	7 May 2003 13:28:27 -0000	1.1.4.107
--- tree-dfa.c	8 May 2003 02:58:00 -0000
*************** find_hidden_use_vars (block)
*** 2571,2580 ****
    return 0;
  }
  
! /* Callback for walk_tree used by find_hidden_use_vars to analyze each array
!    in a lexical block.  For each array type, it walks its TYPE_SIZE and
!    TYPE_SIZE_UNIT trees looking for VAR_DECLs.  Those VAR_DECLs will be
!    marked as having a hidden use.  */
  
  static tree
  find_hidden_use_vars_r (tp, walk_subtrees, data)
--- 2571,2580 ----
    return 0;
  }
  
! /* Callback for walk_tree used by find_hidden_use_vars to analyze each 
!    variable in a lexical block.  If the variable's size has a variable
!    size, then mark all objects needed to compute the variable's size
!    as having hidden uses.  */
  
  static tree
  find_hidden_use_vars_r (tp, walk_subtrees, data)
*************** find_hidden_use_vars_r (tp, walk_subtree
*** 2584,2595 ****
  {
    int *inside_vla = (int *) data;
  
!   if (TREE_CODE (*tp) == ARRAY_TYPE)
      {
        *inside_vla = 1;
!       walk_tree (&TYPE_SIZE (*tp), find_hidden_use_vars_r, inside_vla, NULL);
!       walk_tree (&TYPE_SIZE_UNIT (*tp), find_hidden_use_vars_r,
  		 inside_vla, NULL);
      }
    else if (*inside_vla && SSA_DECL_P (*tp))
      set_has_hidden_use (*tp);
--- 2584,2607 ----
  {
    int *inside_vla = (int *) data;
  
!   /* We need to look for hidden uses due to VLAs in variable
!      definitions.  We originally used to look for these hidden
!      uses in the variable's type, but that's unreliable if the
!      type's size contains a SAVE_EXPR for a different function
!      context than the variable is used within.  */
!   if (SSA_DECL_P (*tp)
!       && ((DECL_SIZE (*tp)
! 	   && ! really_constant_p (DECL_SIZE (*tp)))
! 	  || (DECL_SIZE_UNIT (*tp)
! 	      && ! really_constant_p (DECL_SIZE_UNIT (*tp)))))
      {
+       int save = *inside_vla;
+ 
        *inside_vla = 1;
!       walk_tree (&DECL_SIZE (*tp), find_hidden_use_vars_r, inside_vla, NULL);
!       walk_tree (&DECL_SIZE_UNIT (*tp), find_hidden_use_vars_r,
  		 inside_vla, NULL);
+       *inside_vla = save;
      }
    else if (*inside_vla && SSA_DECL_P (*tp))
      set_has_hidden_use (*tp);







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