diff options
Diffstat (limited to 'meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0395-PR-c-49264.patch')
-rw-r--r-- | meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0395-PR-c-49264.patch | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0395-PR-c-49264.patch b/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0395-PR-c-49264.patch new file mode 100644 index 0000000000..eab6abedb3 --- /dev/null +++ b/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0395-PR-c-49264.patch | |||
@@ -0,0 +1,134 @@ | |||
1 | From 90eb3072e3353e49d60c903664b2e9e2efc5d1de Mon Sep 17 00:00:00 2001 | ||
2 | From: jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | ||
3 | Date: Mon, 6 Jun 2011 17:16:35 +0000 | ||
4 | Subject: [PATCH] PR c++/49264 | ||
5 | * gimple-fold.c (fold_stmt_1): Don't try to fold *& on the lhs | ||
6 | if stmt folded into nothing. | ||
7 | * tree-inline.c (fold_marked_statements): If a builtin at the | ||
8 | end of a bb folded into nothing, just update cgraph edges | ||
9 | and move to next bb. | ||
10 | * cgraph.c (cgraph_update_edges_for_call_stmt_node): Allow new_stmt | ||
11 | to be NULL. Don't compute count and frequency if new_call is NULL. | ||
12 | |||
13 | * g++.dg/opt/pr49264.C: New test. | ||
14 | |||
15 | |||
16 | git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@174713 138bc75d-0d04-0410-961f-82ee72b054a4 | ||
17 | |||
18 | index 64d278f..41265f8 100644 | ||
19 | --- a/gcc/cgraph.c | ||
20 | +++ b/gcc/cgraph.c | ||
21 | @@ -1241,13 +1241,17 @@ cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee, | ||
22 | |||
23 | /* Update or remove the corresponding cgraph edge if a GIMPLE_CALL | ||
24 | OLD_STMT changed into NEW_STMT. OLD_CALL is gimple_call_fndecl | ||
25 | - of OLD_STMT if it was previously call statement. */ | ||
26 | + of OLD_STMT if it was previously call statement. | ||
27 | + If NEW_STMT is NULL, the call has been dropped without any | ||
28 | + replacement. */ | ||
29 | |||
30 | static void | ||
31 | cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node, | ||
32 | - gimple old_stmt, tree old_call, gimple new_stmt) | ||
33 | + gimple old_stmt, tree old_call, | ||
34 | + gimple new_stmt) | ||
35 | { | ||
36 | - tree new_call = (is_gimple_call (new_stmt)) ? gimple_call_fndecl (new_stmt) : 0; | ||
37 | + tree new_call = (new_stmt && is_gimple_call (new_stmt)) | ||
38 | + ? gimple_call_fndecl (new_stmt) : 0; | ||
39 | |||
40 | /* We are seeing indirect calls, then there is nothing to update. */ | ||
41 | if (!new_call && !old_call) | ||
42 | @@ -1287,7 +1291,7 @@ cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node, | ||
43 | loop_nest = e->loop_nest; | ||
44 | cgraph_remove_edge (e); | ||
45 | } | ||
46 | - else | ||
47 | + else if (new_call) | ||
48 | { | ||
49 | /* We are seeing new direct call; compute profile info based on BB. */ | ||
50 | basic_block bb = gimple_bb (new_stmt); | ||
51 | diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c | ||
52 | index 910e3b0..cd8f409 100644 | ||
53 | --- a/gcc/gimple-fold.c | ||
54 | +++ b/gcc/gimple-fold.c | ||
55 | @@ -1484,6 +1484,11 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) | ||
56 | bool changed = false; | ||
57 | gimple stmt = gsi_stmt (*gsi); | ||
58 | unsigned i; | ||
59 | + gimple_stmt_iterator gsinext = *gsi; | ||
60 | + gimple next_stmt; | ||
61 | + | ||
62 | + gsi_next (&gsinext); | ||
63 | + next_stmt = gsi_end_p (gsinext) ? NULL : gsi_stmt (gsinext); | ||
64 | |||
65 | /* Fold the main computation performed by the statement. */ | ||
66 | switch (gimple_code (stmt)) | ||
67 | @@ -1572,10 +1577,19 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) | ||
68 | default:; | ||
69 | } | ||
70 | |||
71 | + /* If stmt folds into nothing and it was the last stmt in a bb, | ||
72 | + don't call gsi_stmt. */ | ||
73 | + if (gsi_end_p (*gsi)) | ||
74 | + { | ||
75 | + gcc_assert (next_stmt == NULL); | ||
76 | + return changed; | ||
77 | + } | ||
78 | + | ||
79 | stmt = gsi_stmt (*gsi); | ||
80 | |||
81 | - /* Fold *& on the lhs. */ | ||
82 | - if (gimple_has_lhs (stmt)) | ||
83 | + /* Fold *& on the lhs. Don't do this if stmt folded into nothing, | ||
84 | + as we'd changing the next stmt. */ | ||
85 | + if (gimple_has_lhs (stmt) && stmt != next_stmt) | ||
86 | { | ||
87 | tree lhs = gimple_get_lhs (stmt); | ||
88 | if (lhs && REFERENCE_CLASS_P (lhs)) | ||
89 | new file mode 100644 | ||
90 | index 0000000..dc23740 | ||
91 | --- /dev/null | ||
92 | +++ b/gcc/testsuite/g++.dg/opt/pr49264.C | ||
93 | @@ -0,0 +1,19 @@ | ||
94 | +// PR c++/49264 | ||
95 | +// { dg-do compile } | ||
96 | +// { dg-options "-O2" } | ||
97 | + | ||
98 | +struct B { }; | ||
99 | +struct A { char a[sizeof (B) + 1]; } a; | ||
100 | + | ||
101 | +static inline void | ||
102 | +foo (const B &b) | ||
103 | +{ | ||
104 | + __builtin_memcpy (&a, &b, sizeof (b)); | ||
105 | +} | ||
106 | + | ||
107 | +void | ||
108 | +bar () | ||
109 | +{ | ||
110 | + B c; | ||
111 | + foo (c); | ||
112 | +} | ||
113 | diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c | ||
114 | index ef3f1a3..a0162de 100644 | ||
115 | --- a/gcc/tree-inline.c | ||
116 | +++ b/gcc/tree-inline.c | ||
117 | @@ -4117,6 +4117,14 @@ fold_marked_statements (int first, struct pointer_set_t *statements) | ||
118 | if (fold_stmt (&gsi)) | ||
119 | { | ||
120 | gimple new_stmt; | ||
121 | + /* If a builtin at the end of a bb folded into nothing, | ||
122 | + the following loop won't work. */ | ||
123 | + if (gsi_end_p (gsi)) | ||
124 | + { | ||
125 | + cgraph_update_edges_for_call_stmt (old_stmt, | ||
126 | + old_decl, NULL); | ||
127 | + break; | ||
128 | + } | ||
129 | if (gsi_end_p (i2)) | ||
130 | i2 = gsi_start_bb (BASIC_BLOCK (first)); | ||
131 | else | ||
132 | -- | ||
133 | 1.7.0.4 | ||
134 | |||