View | Details | Raw Unified | Return to bug 33136 | Differences between
and this patch

Collapse All | Expand All

(-)gcc/tree-ssa-alias.c.jj (-32 / +45 lines)
Lines 2800-2850 may_alias_p (tree ptr, alias_set_type me Link Here
2800
	 are contained within the compilation unit, and that there is
2800
	 are contained within the compilation unit, and that there is
2801
	 no fancy addressing arithmetic associated with any of the
2801
	 no fancy addressing arithmetic associated with any of the
2802
	 types involved.  */
2802
	 types involved.  */
2803
      if (mem_alias_set != 0 && var_alias_set != 0)
2803
      if (mem_alias_set != 0 && var_alias_set != 0 && !alias_set_only)
2804
	{
2804
	{
2805
	  tree ptr_type = TREE_TYPE (ptr);
2806
	  tree var_type = TREE_TYPE (var);
2805
	  tree var_type = TREE_TYPE (var);
2807
      
2806
2808
	  /* The star count is -1 if the type at the end of the
2807
	  if (TREE_CODE (var) == STRUCT_FIELD_TAG)
2809
	     pointer_to chain is not a record or union type. */ 
2810
	  if ((!alias_set_only) && 
2811
	      ipa_type_escape_star_count_of_interesting_type (var_type) >= 0)
2812
	    {
2808
	    {
2813
	      int ptr_star_count = 0;
2809
	      tree aggr_type = TREE_TYPE (SFT_PARENT_VAR (var));
2814
	  
2810
	      if (ipa_type_escape_star_count_of_interesting_type (aggr_type)
2815
	      /* ipa_type_escape_star_count_of_interesting_type is a
2811
		  == 0)
2816
		 little too restrictive for the pointer type, need to
2817
		 allow pointers to primitive types as long as those
2818
		 types cannot be pointers to everything.  */
2819
	      while (POINTER_TYPE_P (ptr_type))
2820
		{
2821
		  /* Strip the *s off.  */ 
2822
		  ptr_type = TREE_TYPE (ptr_type);
2823
		  ptr_star_count++;
2824
		}
2825
	  
2826
	      /* There does not appear to be a better test to see if
2827
		 the pointer type was one of the pointer to everything
2828
		 types.  */
2829
	      if (ptr_star_count > 0)
2830
		{
2812
		{
2831
		  alias_stats.structnoaddress_queries++;
2813
		  alias_stats.structnoaddress_queries++;
2832
		  if (ipa_type_escape_field_does_not_clobber_p (var_type, 
2814
		  if (ipa_type_escape_field_does_not_clobber_p (aggr_type,
2833
								TREE_TYPE (ptr)))
2815
								var_type))
2834
		    {
2816
		    {
2835
		      alias_stats.structnoaddress_resolved++;
2817
		      alias_stats.structnoaddress_resolved++;
2836
		      alias_stats.alias_noalias++;
2818
		      alias_stats.alias_noalias++;
2837
		      return false;
2819
		      return false;
2838
		    }
2820
		    }
2839
		}
2821
		}
2840
	      else if (ptr_star_count == 0)
2822
	    }
2823
	  /* The star count is -1 if the type at the end of the
2824
	     pointer_to chain is not a record or union type.
2825
	     If star count is bigger than 0, VAR is a pointer
2826
	     to a record or union or pointer to pointer, etc.
2827
	     For
2828
	       struct A *var;
2829
	       struct A **ptr;
2830
	     may_alias_p query it only matters if &var was seen or
2831
	     not, ipa type escape analysis of the fields doesn't
2832
	     give useful information - this is the same as if
2833
	     instead of struct A void or int was used.  */
2834
	  else if (ipa_type_escape_star_count_of_interesting_type (var_type)
2835
		   == 0)
2836
	    {
2837
	      tree pointed_type = TREE_TYPE (TREE_TYPE (ptr));
2838
2839
	      /* For
2840
		 struct A var;
2841
		 struct A *ptr;
2842
		 ipa type escape analysis isn't useful, presence
2843
		 of &var is enough to cause ptr to point to var.
2844
		 If ptr on the other side points to some type among
2845
		 struct A's fields (fields of fields etc.), then
2846
		 ipa_type_escape_field_does_not_clobber_p should
2847
		 be used.  E.g.
2848
		 struct A { int a; float f; } var;
2849
		 float *ptr;  */
2850
	      if (TYPE_MAIN_VARIANT (var_type)
2851
		  != TYPE_MAIN_VARIANT (pointed_type))
2841
		{
2852
		{
2842
		  /* If PTR_TYPE was not really a pointer to type, it cannot 
2843
		     alias.  */ 
2844
		  alias_stats.structnoaddress_queries++;
2853
		  alias_stats.structnoaddress_queries++;
2845
		  alias_stats.structnoaddress_resolved++;
2854
		  if (ipa_type_escape_field_does_not_clobber_p (var_type, 
2846
		  alias_stats.alias_noalias++;
2855
								pointed_type))
2847
		  return false;
2856
		    {
2857
		      alias_stats.structnoaddress_resolved++;
2858
		      alias_stats.alias_noalias++;
2859
		      return false;
2860
		    }
2848
		}
2861
		}
2849
	    }
2862
	    }
2850
	}
2863
	}
(-)gcc/ipa-type-escape.c.jj (+15 lines)
Lines 1704-1709 analyze_function (struct cgraph_node *fn Link Here
1704
    FOR_EACH_BB_FN (this_block, this_cfun)
1704
    FOR_EACH_BB_FN (this_block, this_cfun)
1705
      {
1705
      {
1706
	block_stmt_iterator bsi;
1706
	block_stmt_iterator bsi;
1707
	tree phi, op;
1708
	use_operand_p use;
1709
	ssa_op_iter iter;
1710
1711
	/* Find the addresses taken in phi node arguments.  */
1712
	for (phi = phi_nodes (this_block); phi; phi = PHI_CHAIN (phi))
1713
	  {
1714
	    FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
1715
	      {
1716
		op = USE_FROM_PTR (use);
1717
		if (TREE_CODE (op) == ADDR_EXPR)
1718
		  check_rhs_var (op);
1719
	      }
1720
	  }
1721
1707
	for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
1722
	for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
1708
	  walk_tree (bsi_stmt_ptr (bsi), scan_for_refs, 
1723
	  walk_tree (bsi_stmt_ptr (bsi), scan_for_refs, 
1709
		     fn, visited_nodes);
1724
		     fn, visited_nodes);
(-)gcc/testsuite/gcc.c-torture/execute/20070824-1.c.jj (+24 lines)
Line 0 Link Here
1
/* PR tree-optimization/33136 */
2
3
extern void abort (void);
4
5
struct S
6
{
7
  struct S *a;
8
  int b;
9
};
10
11
int
12
main (void)
13
{
14
  struct S *s = (struct S *) 0, **p, *n;
15
  for (p = &s; *p; p = &(*p)->a);
16
  n = (struct S *) __builtin_alloca (sizeof (*n));
17
  n->a = *p;
18
  n->b = 1;
19
  *p = n;
20
21
  if (!s)
22
    abort ();
23
  return 0;
24
}
(-)gcc/testsuite/gcc.dg/pr33136-1.c.jj (+54 lines)
Line 0 Link Here
1
/* PR tree-optimization/33136 */
2
/* { dg-do run } */
3
/* { dg-options "-O2" } */
4
5
extern void abort (void);
6
7
struct S
8
{
9
  struct S *a;
10
  int b;
11
  float f;
12
};
13
14
static struct S s;
15
16
static int *
17
__attribute__((noinline, const))
18
foo (void)
19
{
20
  return &s.b;
21
}
22
23
float
24
__attribute__((noinline))
25
bar (float *f)
26
{
27
  s.f = 1.0;
28
  *f = 4.0;
29
  return s.f;
30
}
31
32
int
33
__attribute__((noinline))
34
baz (int *x)
35
{
36
  s.b = 1;
37
  *x = 4;
38
  return s.b;
39
}
40
41
int
42
t (void)
43
{
44
  float f = 8.0;
45
  return bar (&f) + baz (foo ());
46
}
47
48
int
49
main (void)
50
{
51
  if (t () != 5)
52
    abort ();
53
  return 0;
54
}
(-)gcc/testsuite/gcc.dg/pr33136-2.c.jj (+53 lines)
Line 0 Link Here
1
/* PR tree-optimization/33136 */
2
/* { dg-do compile } */
3
/* { dg-options "-O2 -fdump-tree-optimized" } */
4
5
struct S
6
{
7
  void *a;
8
  int b;
9
  float f;
10
};
11
12
static struct S s;
13
14
static int *
15
__attribute__((noinline, const))
16
foo (void)
17
{
18
  return &s.b;
19
}
20
21
float
22
__attribute__((noinline))
23
bar (float *f)
24
{
25
  s.f = 1.0;
26
  *f = 4.0;
27
  /* As nothing ever takes the address of any float field in struct S,
28
     the write to *f can't alias with the s.f field.  */
29
  return s.f;
30
}
31
32
int
33
__attribute__((noinline))
34
baz (int *x)
35
{
36
  s.b = 1;
37
  *x = 4;
38
  /* Function foo takes address of an int field in struct S,
39
     so *x can alias with the s.b field (and it does in this testcase).  */
40
  return s.b;
41
}
42
43
int
44
t (void)
45
{
46
  float f = 8.0;
47
  return bar (&f) + baz (foo ());
48
}
49
50
/* { dg-final { scan-tree-dump "return 1.0e\\+0;" "optimized" } } */
51
/* { dg-final { scan-tree-dump "return s.b;" "optimized" } } */
52
/* { dg-final { scan-tree-dump-not "return 1;" "optimized" } } */
53
/* { dg-final { cleanup-tree-dump "optimized" } } */
(-)gcc/testsuite/gcc.dg/pr33136-3.c.jj (+60 lines)
Line 0 Link Here
1
/* PR tree-optimization/33136 */
2
/* { dg-do run } */
3
/* { dg-options "-O2" } */
4
5
extern void abort (void);
6
7
struct S
8
{
9
  void *a;
10
  int b;
11
  int *c;
12
};
13
static int d, e;
14
15
static struct S s;
16
17
static int *
18
__attribute__((noinline, const))
19
foo (void)
20
{
21
  return &s.b;
22
}
23
24
int *
25
__attribute__((noinline))
26
bar (int **f)
27
{
28
  s.c = &d;
29
  *f = &e;
30
  /* As nothing ever takes the address of any int * field in struct S,
31
     the write to *f can't alias with the s.c field.  */
32
  return s.c;
33
}
34
35
int
36
__attribute__((noinline))
37
baz (int *x)
38
{
39
  s.b = 1;
40
  *x = 4;
41
  /* Function foo takes address of an int field in struct S,
42
     so *x can alias with the s.b field (and it does in this testcase).  */
43
  return s.b;
44
}
45
46
int
47
__attribute__((noinline))
48
t (void)
49
{
50
  int *f = (int *) 0;
51
  return 10 * (bar (&f) != &d) + baz (foo ());
52
}
53
54
int
55
main (void)
56
{
57
  if (t () != 4)
58
    abort ();
59
  return 0;
60
}
(-)gcc/testsuite/gcc.dg/pr33136-4.c.jj (+55 lines)
Line 0 Link Here
1
/* PR tree-optimization/33136 */
2
/* { dg-do compile } */
3
/* { dg-options "-O2 -fdump-tree-optimized" } */
4
5
struct S
6
{
7
  void *a;
8
  int b;
9
  int *c;
10
};
11
static int d, e;
12
13
static struct S s;
14
15
static int *
16
__attribute__((noinline, const))
17
foo (void)
18
{
19
  return &s.b;
20
}
21
22
int *
23
__attribute__((noinline))
24
bar (int **f)
25
{
26
  s.c = &d;
27
  *f = &e;
28
  /* As nothing ever takes the address of any int * field in struct S,
29
     the write to *f can't alias with the s.c field.  */
30
  return s.c;
31
}
32
33
int
34
__attribute__((noinline))
35
baz (int *x)
36
{
37
  s.b = 1;
38
  *x = 4;
39
  /* Function foo takes address of an int field in struct S,
40
     so *x can alias with the s.b field (and it does in this testcase).  */
41
  return s.b;
42
}
43
44
int
45
t (void)
46
{
47
  int *f = (int *) 0;
48
  return (bar (&f) != &d) + baz (foo ());
49
}
50
51
/* { dg-final { scan-tree-dump "return &d;" "optimized" } } */
52
/* { dg-final { scan-tree-dump-not "return s.c;" "optimized" } } */
53
/* { dg-final { scan-tree-dump "return s.b;" "optimized" } } */
54
/* { dg-final { scan-tree-dump-not "return 1;" "optimized" } } */
55
/* { dg-final { cleanup-tree-dump "optimized" } } */
(-)gcc/testsuite/gcc.dg/pr33136-5.c.jj (+60 lines)
Line 0 Link Here
1
/* PR tree-optimization/33136 */
2
/* { dg-do run } */
3
/* { dg-options "-O2" } */
4
5
extern void abort (void);
6
7
struct S
8
{
9
  void *a;
10
  int b[3];
11
  double *c;
12
};
13
static double d, e;
14
15
static struct S s;
16
17
static int *
18
__attribute__((noinline, const))
19
foo (void)
20
{
21
  return (int *) &s.b;
22
}
23
24
double *
25
__attribute__((noinline))
26
bar (double **f)
27
{
28
  s.c = &d;
29
  *f = &e;
30
  /* As nothing ever takes the address of any double * field in struct S,
31
     the write to *f can't alias with the s.c field.  */
32
  return s.c;
33
}
34
35
int
36
__attribute__((noinline))
37
baz (int *x)
38
{
39
  s.b[0] = 1;
40
  *x = 4;
41
  /* Function foo takes address of an int array field in struct S,
42
     so *x can alias with the s.b field (and it does in this testcase).  */
43
  return s.b[0];
44
}
45
46
int
47
__attribute__((noinline))
48
t (void)
49
{
50
  double *f = (double *) 0;
51
  return 10 * (bar (&f) != &d) + baz (foo ());
52
}
53
54
int
55
main (void)
56
{
57
  if (t () != 4)
58
    abort ();
59
  return 0;
60
}
(-)gcc/testsuite/gcc.dg/pr33136-6.c.jj (+55 lines)
Line 0 Link Here
1
/* PR tree-optimization/33136 */
2
/* { dg-do compile } */
3
/* { dg-options "-O2 -fdump-tree-optimized" } */
4
5
struct S
6
{
7
  void *a;
8
  int b[3];
9
  double *c;
10
};
11
static double d, e;
12
13
static struct S s;
14
15
static int *
16
__attribute__((noinline, const))
17
foo (void)
18
{
19
  return (int *) &s.b;
20
}
21
22
double *
23
__attribute__((noinline))
24
bar (double **f)
25
{
26
  s.c = &d;
27
  *f = &e;
28
  /* As nothing ever takes the address of any double * field in struct S,
29
     the write to *f can't alias with the s.c field.  */
30
  return s.c;
31
}
32
33
int
34
__attribute__((noinline))
35
baz (int *x)
36
{
37
  s.b[0] = 1;
38
  *x = 4;
39
  /* Function foo takes address of an int field in struct S,
40
     so *x can alias with the s.b field (and it does in this testcase).  */
41
  return s.b[0];
42
}
43
44
int
45
t (void)
46
{
47
  double *f = (double *) 0;
48
  return (bar (&f) != &d) + baz (foo ());
49
}
50
51
/* { dg-final { scan-tree-dump "return &d;" "optimized" } } */
52
/* { dg-final { scan-tree-dump-not "return s.c;" "optimized" } } */
53
/* { dg-final { scan-tree-dump "return s.b;" "optimized" } } */
54
/* { dg-final { scan-tree-dump-not "return 1;" "optimized" } } */
55
/* { dg-final { cleanup-tree-dump "optimized" } } */

Return to bug 33136