Hi!
5 further backports to 7 branch, bootstrapped/regtested on x86_64-linux and
i686-linux, committed to branch.
Jakub
2017-12-22 Jakub Jelinek <[email protected]>
Backported from mainline
2017-12-19 Jakub Jelinek <[email protected]>
PR ipa/82801
PR ipa/83346
* ipa-inline.c (flatten_remove_node_hook): New function.
(ipa_inline): Keep only nodes with flatten attribute at the end of
the array in the order from ipa_reverse_postorder, only walk that
portion of array for flattening, if there is more than one such
node, temporarily register a removal hook and ignore removed nodes.
* g++.dg/ipa/pr82801.C: New test.
--- gcc/ipa-inline.c (revision 255804)
+++ gcc/ipa-inline.c (revision 255805)
@@ -2338,6 +2338,19 @@ dump_inline_stats (void)
(int) reason[i][1], reason_freq[i].to_double (), reason[i][0]);
}
+/* Called when node is removed. */
+
+static void
+flatten_remove_node_hook (struct cgraph_node *node, void *data)
+{
+ if (lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) == NULL)
+ return;
+
+ hash_set<struct cgraph_node *> *removed
+ = (hash_set<struct cgraph_node *> *) data;
+ removed->add (node);
+}
+
/* Decide on the inlining. We do so in the topological order to avoid
expenses on updating data structures. */
@@ -2347,7 +2360,7 @@ ipa_inline (void)
struct cgraph_node *node;
int nnodes;
struct cgraph_node **order;
- int i;
+ int i, j;
int cold;
bool remove_functions = false;
@@ -2380,26 +2393,56 @@ ipa_inline (void)
if (dump_file)
fprintf (dump_file, "\nFlattening functions:\n");
+ /* First shrink order array, so that it only contains nodes with
+ flatten attribute. */
+ for (i = nnodes - 1, j = i; i >= 0; i--)
+ {
+ node = order[i];
+ if (lookup_attribute ("flatten",
+ DECL_ATTRIBUTES (node->decl)) != NULL)
+ order[j--] = order[i];
+ }
+
+ /* After the above loop, order[j + 1] ... order[nnodes - 1] contain
+ nodes with flatten attribute. If there is more than one such
+ node, we need to register a node removal hook, as flatten_function
+ could remove other nodes with flatten attribute. See PR82801. */
+ struct cgraph_node_hook_list *node_removal_hook_holder = NULL;
+ hash_set<struct cgraph_node *> *flatten_removed_nodes = NULL;
+ if (j < nnodes - 2)
+ {
+ flatten_removed_nodes = new hash_set<struct cgraph_node *>;
+ node_removal_hook_holder
+ = symtab->add_cgraph_removal_hook (&flatten_remove_node_hook,
+ flatten_removed_nodes);
+ }
+
/* In the first pass handle functions to be flattened. Do this with
a priority so none of our later choices will make this impossible. */
- for (i = nnodes - 1; i >= 0; i--)
+ for (i = nnodes - 1; i > j; i--)
{
node = order[i];
+ if (flatten_removed_nodes
+ && flatten_removed_nodes->contains (node))
+ continue;
/* Handle nodes to be flattened.
Ideally when processing callees we stop inlining at the
entry of cycles, possibly cloning that entry point and
try to flatten itself turning it into a self-recursive
function. */
- if (lookup_attribute ("flatten",
- DECL_ATTRIBUTES (node->decl)) != NULL)
- {
- if (dump_file)
- fprintf (dump_file,
- "Flattening %s\n", node->name ());
- flatten_function (node, false);
- }
+ if (dump_file)
+ fprintf (dump_file, "Flattening %s\n", node->name ());
+ flatten_function (node, false);
}
+
+ if (j < nnodes - 2)
+ {
+ symtab->remove_cgraph_removal_hook (node_removal_hook_holder);
+ delete flatten_removed_nodes;
+ }
+ free (order);
+
if (dump_file)
dump_overall_stats ();
@@ -2411,7 +2454,6 @@ ipa_inline (void)
inline functions and virtual functions so we really know what is called
once. */
symtab->remove_unreachable_nodes (dump_file);
- free (order);
/* Inline functions with a property that after inlining into all callers the
code size will shrink because the out-of-line copy is eliminated.
--- gcc/testsuite/g++.dg/ipa/pr82801.C (nonexistent)
+++ gcc/testsuite/g++.dg/ipa/pr82801.C (revision 255805)
@@ -0,0 +1,20 @@
+// PR ipa/82801
+// { dg-do compile }
+// { dg-options "-O2 -Wno-attributes" }
+
+template<int>
+struct A { A () {} };
+struct B { double foo () const; };
+
+__attribute__((always_inline, flatten))
+double B::foo () const
+{
+ A<1> v;
+ return 0.0;
+}
+
+int
+main ()
+{
+ return 0;
+}
2017-12-22 Jakub Jelinek <[email protected]>
Backported from mainline
2017-12-21 Jakub Jelinek <[email protected]>
PR tree-optimization/83521
* tree-ssa-phiopt.c (factor_out_conditional_conversion): Use
gimple_build_assign without code on result of
fold_build1 (VIEW_CONVERT_EXPR, ...), as it might not create
a VIEW_CONVERT_EXPR.
* gcc.dg/pr83521.c: New test.
--- gcc/tree-ssa-phiopt.c (revision 255951)
+++ gcc/tree-ssa-phiopt.c (revision 255952)
@@ -548,8 +548,12 @@ factor_out_conditional_conversion (edge
/* Create the conversion stmt and insert it. */
if (convert_code == VIEW_CONVERT_EXPR)
- temp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (result), temp);
- new_stmt = gimple_build_assign (result, convert_code, temp);
+ {
+ temp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (result), temp);
+ new_stmt = gimple_build_assign (result, temp);
+ }
+ else
+ new_stmt = gimple_build_assign (result, convert_code, temp);
gsi = gsi_after_labels (gimple_bb (phi));
gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
--- gcc/testsuite/gcc.dg/pr83521.c (nonexistent)
+++ gcc/testsuite/gcc.dg/pr83521.c (revision 255952)
@@ -0,0 +1,10 @@
+/* PR tree-optimization/83521 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-tree-forwprop" } */
+
+int
+foo (unsigned int x, int y)
+{
+ int *z = (int *)&x;
+ return (y == 0) ? y : *z;
+}
2017-12-22 Jakub Jelinek <[email protected]>
Backported from mainline
2017-12-21 Jakub Jelinek <[email protected]>
PR tree-optimization/83523
* tree-ssa-math-opts.c (is_widening_mult_p): Return false if
for INTEGER_TYPE TYPE_OVERFLOW_TRAPS.
(convert_mult_to_fma): Likewise.
* g++.dg/tree-ssa/pr83523.C: New test.
--- gcc/tree-ssa-math-opts.c (revision 255952)
+++ gcc/tree-ssa-math-opts.c (revision 255953)
@@ -3074,8 +3074,12 @@ is_widening_mult_p (gimple *stmt,
{
tree type = TREE_TYPE (gimple_assign_lhs (stmt));
- if (TREE_CODE (type) != INTEGER_TYPE
- && TREE_CODE (type) != FIXED_POINT_TYPE)
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ {
+ if (TYPE_OVERFLOW_TRAPS (type))
+ return false;
+ }
+ else if (TREE_CODE (type) != FIXED_POINT_TYPE)
return false;
if (!is_widening_mult_rhs_p (type, gimple_assign_rhs1 (stmt), type1_out,
@@ -3443,7 +3447,8 @@ convert_mult_to_fma (gimple *mul_stmt, t
/* We don't want to do bitfield reduction ops. */
if (INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type)
- != GET_MODE_PRECISION (TYPE_MODE (type))))
+ != GET_MODE_PRECISION (TYPE_MODE (type))
+ || TYPE_OVERFLOW_TRAPS (type)))
return false;
/* If the target doesn't support it, don't generate it. We assume that
--- gcc/testsuite/g++.dg/tree-ssa/pr83523.C (nonexistent)
+++ gcc/testsuite/g++.dg/tree-ssa/pr83523.C (revision 255953)
@@ -0,0 +1,25 @@
+// PR tree-optimization/83523
+// { dg-do compile }
+// { dg-options "-O2 -fexceptions -fnon-call-exceptions -ftrapv" }
+
+#ifdef __SIZEOF_INT128__
+typedef __int128 T;
+typedef long long int U;
+#else
+typedef long long int T;
+typedef int U;
+#endif
+
+struct S { S (); ~S (); };
+void bar ();
+
+T
+foo (U x, U y)
+{
+ T z = x;
+ S s;
+ bar ();
+ z *= y;
+ bar ();
+ return z;
+}
2017-12-22 Jakub Jelinek <[email protected]>
Backported from mainline
2017-12-21 Jakub Jelinek <[email protected]>
PR rtl-optimization/80747
PR rtl-optimization/83512
* cfgrtl.c (force_nonfallthru_and_redirect): When splitting
succ edge from ENTRY, copy partition from e->dest to the newly
created bb.
* bb-reorder.c (reorder_basic_blocks_simple): If last_tail is
ENTRY, use BB_PARTITION of its successor block as current_partition.
Don't copy partition when splitting succ edge from ENTRY.
* gcc.dg/pr80747.c: New test.
* gcc.dg/pr83512.c: New test.
--- gcc/bb-reorder.c (revision 255953)
+++ gcc/bb-reorder.c (revision 255954)
@@ -2405,7 +2405,10 @@ reorder_basic_blocks_simple (void)
basic_block last_tail = (basic_block) ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux;
- int current_partition = BB_PARTITION (last_tail);
+ int current_partition
+ = BB_PARTITION (last_tail == ENTRY_BLOCK_PTR_FOR_FN (cfun)
+ ? EDGE_SUCC (ENTRY_BLOCK_PTR_FOR_FN (cfun), 0)->dest
+ : last_tail);
bool need_another_pass = true;
for (int pass = 0; pass < 2 && need_another_pass; pass++)
@@ -2446,7 +2449,6 @@ reorder_basic_blocks_simple (void)
{
force_nonfallthru (e);
e->src->aux = ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux;
- BB_COPY_PARTITION (e->src, e->dest);
}
}
--- gcc/cfgrtl.c (revision 255953)
+++ gcc/cfgrtl.c (revision 255954)
@@ -1542,6 +1542,9 @@ force_nonfallthru_and_redirect (edge e,
basic_block bb = create_basic_block (BB_HEAD (e->dest), NULL,
ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ /* Make sure new block ends up in correct hot/cold section. */
+ BB_COPY_PARTITION (bb, e->dest);
+
/* Change the existing edge's source to be the new block, and add
a new edge from the entry block to the new block. */
e->src = bb;
--- gcc/testsuite/gcc.dg/pr83512.c (nonexistent)
+++ gcc/testsuite/gcc.dg/pr83512.c (revision 255954)
@@ -0,0 +1,16 @@
+/* PR rtl-optimization/83512 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -freorder-blocks-algorithm=simple" } */
+
+int a;
+
+void
+foo (int *x)
+{
+ for (;;)
+ {
+ for (*x = 0; *x < 1; *x++)
+ ;
+ ++a;
+ }
+}
--- gcc/testsuite/gcc.dg/pr80747.c (nonexistent)
+++ gcc/testsuite/gcc.dg/pr80747.c (revision 255954)
@@ -0,0 +1,18 @@
+/* PR rtl-optimization/80747 */
+/* { dg-do compile } */
+/* { dg-options "-fprofile-use -freorder-blocks-and-partition -O1
-foptimize-sibling-calls" } */
+
+int
+foo (int a)
+{
+ int r;
+ if (a & 1)
+ r = foo (a - 1);
+ else if (a)
+ r = foo (a - 2);
+ else
+ return 0;
+ if (r)
+ r = r;
+ return r;
+}
2017-12-22 Jakub Jelinek <[email protected]>
Backported from mainline
2017-12-21 Jakub Jelinek <[email protected]>
PR c/83448
* gimple-ssa-sprintf.c (maybe_warn): Don't call set_caret_index
if navail is >= dir.len.
* gcc.c-torture/compile/pr83448.c: New test.
* gcc.dg/tree-ssa/builtin-snprintf-warn-4.c: New test.
--- gcc/gimple-ssa-sprintf.c (revision 255959)
+++ gcc/gimple-ssa-sprintf.c (revision 255960)
@@ -2466,7 +2466,8 @@ maybe_warn (substring_loc &dirloc, locat
/* For plain character directives (i.e., the format string itself)
but not others, point the caret at the first character that's
past the end of the destination. */
- dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
+ if (navail < dir.len)
+ dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
}
if (*dir.beg == '\0')
@@ -2594,7 +2595,8 @@ maybe_warn (substring_loc &dirloc, locat
/* For plain character directives (i.e., the format string itself)
but not others, point the caret at the first character that's
past the end of the destination. */
- dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
+ if (navail < dir.len)
+ dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
}
if (*dir.beg == '\0')
--- gcc/testsuite/gcc.c-torture/compile/pr83448.c (nonexistent)
+++ gcc/testsuite/gcc.c-torture/compile/pr83448.c (revision 255960)
@@ -0,0 +1,15 @@
+/* PR c/83448 */
+
+char *a;
+int b;
+
+void
+foo (void)
+{
+ for (;;)
+ {
+ if (b < 0)
+ foo ();
+ __builtin_snprintf (a, b, "%*s", b, "");
+ }
+}
--- gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-4.c (nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-4.c (revision
255960)
@@ -0,0 +1,46 @@
+/* PR c/83448 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wformat-truncation -fdiagnostics-show-caret" } */
+
+extern int snprintf (char *, __SIZE_TYPE__, const char *, ...);
+
+void
+foo (char *a, char *b, char *c, int d, int e)
+{
+ snprintf (a, 7, "abc\\\123 efg");
+ /* { dg-warning "directive output truncated writing 9 bytes into a region of
size 7" "" { target *-*-* } .-1 }
+ { dg-message ".snprintf. output 10 bytes into a destination of size 7"
"note" { target *-*-* } .-2 }
+ { dg-begin-multiline-output "" }
+ snprintf (a, 7, "abc\\\123 efg");
+ ~~~~~~~~~~~^~
+ { dg-end-multiline-output "" }
+ { dg-begin-multiline-output "note" }
+ snprintf (a, 7, "abc\\\123 efg");
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+ d &= 63;
+ d += 10;
+ snprintf (b, 7, "a%dbcdefg", d);
+ /* { dg-warning "'bcdefg' directive output truncated writing 6 bytes into a
region of size 4" "" { target *-*-* } .-1 }
+ { dg-message ".snprintf. output 10 bytes into a destination of size 7"
"note" { target *-*-* } .-2 }
+ { dg-begin-multiline-output "" }
+ snprintf (b, 7, "a%dbcdefg", d);
+ ~~~~^~
+ { dg-end-multiline-output "" }
+ { dg-begin-multiline-output "note" }
+ snprintf (b, 7, "a%dbcdefg", d);
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+ e &= 127;
+ snprintf (c, 7, "a%dbcdefgh", e);
+ /* { dg-warning "'bcdefgh' directive output truncated writing 7 bytes into a
region of size between 3 and 5" "" { target *-*-* } .-1 }
+ { dg-message ".snprintf. output between 10 and 12 bytes into a
destination of size 7" "note" { target *-*-* } .-2 }
+ { dg-begin-multiline-output "" }
+ snprintf (c, 7, "a%dbcdefgh", e);
+ ~~~~~^~
+ { dg-end-multiline-output "" }
+ { dg-begin-multiline-output "note" }
+ snprintf (c, 7, "a%dbcdefgh", e);
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+}