]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[RFA] Minor improvement to coremark, avoid unconditional jump to return
authorJeff Law <jeffreyalaw@gmail.com>
Sun, 25 Sep 2022 16:23:59 +0000 (12:23 -0400)
committerJeff Law <jeffreyalaw@gmail.com>
Mon, 26 Sep 2022 13:40:41 +0000 (09:40 -0400)
gcc/
* cfgcleanup.cc (bb_is_just_return): No longer static.
* cfgcleanup.h (bb_is_just_return): Add prototype.
* cfgrtl.cc (fixup_reorder_chain): Do not create an
unconditional jump to a return block.  Conditionally
remove unreachable blocks.

gcc/testsuite/

* gcc.target/riscv/ret-1.c: New test.

gcc/cfgcleanup.cc
gcc/cfgcleanup.h
gcc/cfgrtl.cc
gcc/testsuite/gcc.target/riscv/ret-1.c [new file with mode: 0644]

index a8b0139bb4dcfcfbc0ac7fb11e2020af8a9de45f..a363e0b4da3cc1bda23efd3d3ddd5f47da0e050d 100644 (file)
@@ -2599,7 +2599,7 @@ trivially_empty_bb_p (basic_block bb)
    return value.  Fill in *RET and *USE with the return and use insns
    if any found, otherwise NULL.  All CLOBBERs are ignored.  */
 
-static bool
+bool
 bb_is_just_return (basic_block bb, rtx_insn **ret, rtx_insn **use)
 {
   *ret = *use = NULL;
index a6d882f98a44abb958ab0fbbf9f5eca4835ba281..f1021ca835fff8e023b79ae9f1a18d7ac5de8922 100644 (file)
@@ -30,5 +30,6 @@ extern int flow_find_head_matching_sequence (basic_block, basic_block,
 extern bool delete_unreachable_blocks (void);
 extern void delete_dead_jumptables (void);
 extern bool cleanup_cfg (int);
+extern bool bb_is_just_return (basic_block, rtx_insn **, rtx_insn **);
 
 #endif /* GCC_CFGCLEANUP_H */
index a05c338a4c81f40403352b8f85597e41a87fa91d..90cd6ee56a7bdda2d6b06b7580e5ec6f3db32db3 100644 (file)
@@ -3901,6 +3901,7 @@ fixup_reorder_chain (void)
   /* Now add jumps and labels as needed to match the blocks new
      outgoing edges.  */
 
+  bool remove_unreachable_blocks = false;
   for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb ; bb = (basic_block)
        bb->aux)
     {
@@ -4043,10 +4044,30 @@ fixup_reorder_chain (void)
            continue;
        }
 
+      /* If E_FALL->dest is just a return block, then we can emit a
+        return rather than a jump to the return block.  */
+      rtx_insn *ret, *use;
+      basic_block dest;
+      if (bb_is_just_return (e_fall->dest, &ret, &use)
+         && (PATTERN (ret) == simple_return_rtx || PATTERN (ret) == ret_rtx))
+       {
+         ret_label = PATTERN (ret);
+         dest = EXIT_BLOCK_PTR_FOR_FN (cfun);
+
+         /* E_FALL->dest might become unreachable as a result of
+            replacing the jump with a return.  So arrange to remove
+            unreachable blocks.  */
+         remove_unreachable_blocks = true;
+       }
+      else
+       {
+         dest = e_fall->dest;
+       }
+
       /* We got here if we need to add a new jump insn. 
         Note force_nonfallthru can delete E_FALL and thus we have to
         save E_FALL->src prior to the call to force_nonfallthru.  */
-      nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
+      nb = force_nonfallthru_and_redirect (e_fall, dest, ret_label);
       if (nb)
        {
          nb->aux = bb->aux;
@@ -4134,6 +4155,12 @@ fixup_reorder_chain (void)
                  ei_next (&ei2);
            }
       }
+
+  /* Replacing a jump with a return may have exposed an unreachable
+     block.  Conditionally remove them if such transformations were
+     made.  */
+  if (remove_unreachable_blocks)
+    delete_unreachable_blocks ();
 }
 \f
 /* Perform sanity checks on the insn chain.
diff --git a/gcc/testsuite/gcc.target/riscv/ret-1.c b/gcc/testsuite/gcc.target/riscv/ret-1.c
new file mode 100644 (file)
index 0000000..28133aa
--- /dev/null
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -dp" } */
+/* This was extracted from coremark.  */
+
+
+typedef signed short ee_s16;
+typedef struct list_data_s
+{
+    ee_s16 data16;
+    ee_s16 idx;
+} list_data;
+
+typedef struct list_head_s
+{
+    struct list_head_s *next;
+    struct list_data_s *info;
+} list_head;
+
+
+list_head *
+core_list_find(list_head *list, list_data *info)
+{
+    if (info->idx >= 0)
+    {
+        while (list && (list->info->idx != info->idx))
+            list = list->next;
+        return list;
+    }
+    else
+    {
+        while (list && ((list->info->data16 & 0xff) != info->data16))
+            list = list->next;
+        return list;
+    }
+}
+
+/* There is only one legitimate unconditional jump, so test for that,
+   which will catch the case where bb-reorder leaves a jump to a ret
+   in the IL.  */
+/* { dg-final { scan-assembler-times "jump" 1 } } */
+