For balanced and max partitioning we can modify create_asm_partition
to also include all needed symbols (with must_remain_in_tu) into one
partition.

This has two remaining issues:
1) The partition may be too large with many must_remain_in_tu symbols.
2) It does not handle name conflict of static symbols.

1to1 partitioning is still preferred as guaranteed to work. But if some
other partitioning is preferred for other reasons, this quick solution
should be enough for small amount of toplevel assembly.

gcc/lto/ChangeLog:

        * lto-partition.cc (create_asm_partition): Add symbols with
        must_remain_in_tu to partition.
        (lto_max_map): Start with create_asm_partition.
        (lto_balanced_map): Likewise.

gcc/testsuite/ChangeLog:

        * gcc.dg/lto/toplevel-extended-asm-2_0.c: Test more
        partitionings.
---
 gcc/lto/lto-partition.cc                      | 53 +++++++++++++++----
 .../gcc.dg/lto/toplevel-extended-asm-2_0.c    |  6 +--
 .../gcc.dg/lto/toplevel-extended-asm-2_1.c    |  5 +-
 3 files changed, 47 insertions(+), 17 deletions(-)

diff --git a/gcc/lto/lto-partition.cc b/gcc/lto/lto-partition.cc
index 8c6ec6f8338..ec0344030eb 100644
--- a/gcc/lto/lto-partition.cc
+++ b/gcc/lto/lto-partition.cc
@@ -398,17 +398,34 @@ lto_1_to_1_map (void)
    Before toplevel asm could be partitioned, all toplevel asm was inserted
    into first partition.
    This function achieves similar behavior for partitionings that cannot
-   easily satisfy requirements of toplevel asm.  */
-static void
+   easily satisfy requirements of toplevel asm.
+
+   All symbols that must be partitioned with the assembly will be in this 
single
+   partition, if most symbols are needed, it is better to use 1to1 
partitioning.
+   */
+static ltrans_partition
 create_asm_partition (void)
 {
   struct asm_node *anode = symtab->first_asm_symbol ();
-  if (anode)
+  if (!anode)
+    return NULL;
+
+  ltrans_partition partition = new_partition ("asm_nodes");
+  for (; anode; anode = anode->next)
+    add_symbol_to_partition (partition, anode);
+
+  symtab_node* node;
+  FOR_EACH_SYMBOL (node)
     {
-      ltrans_partition partition = new_partition ("asm_nodes");
-      for (; anode; anode = anode->next)
-       add_symbol_to_partition (partition, anode);
+      if (node->get_partitioning_class () != SYMBOL_PARTITION
+         || symbol_partitioned_p (node))
+       continue;
+
+      /* Must be with some assembly.  */
+      if (node->must_remain_in_tu)
+       add_symbol_to_partition (partition, node);
     }
+  return partition;
 }
 
 /* Maximal partitioning.  Put every new symbol into new partition if possible. 
 */
@@ -419,6 +436,8 @@ lto_max_map (void)
   symtab_node *node;
   ltrans_partition partition;
 
+  create_asm_partition ();
+
   FOR_EACH_SYMBOL (node)
     {
       if (node->get_partitioning_class () != SYMBOL_PARTITION
@@ -428,7 +447,6 @@ lto_max_map (void)
       add_symbol_to_partition (partition, node);
     }
 
-  create_asm_partition ();
   create_partition_if_empty ();
 }
 
@@ -1174,6 +1192,22 @@ lto_balanced_map (int n_lto_partitions, int 
max_partition_size)
     fprintf (dump_file, "Total unit size: %" PRId64 ", partition size: %" 
PRId64 "\n",
             total_size, partition_size);
 
+  ltrans_partition asm_partition = create_asm_partition ();
+  if (asm_partition)
+    {
+      if (partition_size < asm_partition->insns)
+       warning (0, "Large ASM partition %d out of %ld with expected partition"
+                "size %ld.  Large single partition will make parallelism"
+                "worse.  1to1 partitioning is able to split toplevel ASM.",
+                asm_partition->insns, original_total_size, partition_size);
+
+      total_size -= asm_partition->insns;
+      partition_size = total_size / n_lto_partitions;
+      if (partition_size < param_min_partition_size)
+       partition_size = param_min_partition_size;
+    }
+
+
   auto_vec<symtab_node *> next_nodes;
 
   for (unsigned i = 0; i < order.length (); i++)
@@ -1434,11 +1468,10 @@ lto_balanced_map (int n_lto_partitions, int 
max_partition_size)
     next_nodes.safe_push (noreorder[noreorder_pos++]);
   /* For one partition the cost of boundary should be 0 unless we added final
      symbols here (these are not accounted) or we have accounting bug.  */
-  gcc_assert (next_nodes.length () || npartitions != 1 || !best_cost || 
best_cost == -1);
+  gcc_assert (next_nodes.length () || ltrans_partitions.length () != 1
+             || !best_cost || best_cost == -1);
   add_sorted_nodes (next_nodes, partition);
 
-  create_asm_partition ();
-
   if (dump_file)
     {
       fprintf (dump_file, "\nPartition sizes:\n");
diff --git a/gcc/testsuite/gcc.dg/lto/toplevel-extended-asm-2_0.c 
b/gcc/testsuite/gcc.dg/lto/toplevel-extended-asm-2_0.c
index 19ac7c21b2d..2d874181712 100644
--- a/gcc/testsuite/gcc.dg/lto/toplevel-extended-asm-2_0.c
+++ b/gcc/testsuite/gcc.dg/lto/toplevel-extended-asm-2_0.c
@@ -1,10 +1,10 @@
 /* { dg-lto-do link } */
-/* { dg-lto-options {{-O2 -flto -flto-partition=1to1} } } */
+/* { dg-lto-options {{-O2 -flto -flto-partition=1to1} {-O2 -flto 
-flto-partition=max} {-O2 -flto -flto-partition=cache}} } */
 
-extern int use_statics ();
+extern int use_static ();
 
 extern int asm_var;
 
 int main() {
-  return use_statics ();
+  return use_static ();
 }
diff --git a/gcc/testsuite/gcc.dg/lto/toplevel-extended-asm-2_1.c 
b/gcc/testsuite/gcc.dg/lto/toplevel-extended-asm-2_1.c
index a115f139eaa..3e49b52f107 100644
--- a/gcc/testsuite/gcc.dg/lto/toplevel-extended-asm-2_1.c
+++ b/gcc/testsuite/gcc.dg/lto/toplevel-extended-asm-2_1.c
@@ -1,12 +1,9 @@
-static void static_asm_fn ();
 static int static_asm_var;
-asm("%cc0:" :: ":" (&static_asm_fn));
 asm("%cc0:" :: ":" (&static_asm_var));
 
 extern int asm_var;
 asm("%cc0:" :: ":" (&asm_var));
 
-int use_statics () {
-  static_asm_fn ();
+int use_static () {
   return static_asm_var;
 }
-- 
2.51.1

Reply via email to