RISC-V: Do not grow complete unrolling at -O2

Message ID 20260717074838.25214-1-juewang@linux.alibaba.com
State Committed
Delegated to: Jeff Law
Headers
Series RISC-V: Do not grow complete unrolling at -O2 |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed

Commit Message

wangjue July 17, 2026, 7:48 a.m. UTC
  From: "wangjue.wangjue" <wangjue.wangjue@alibaba-inc.com>

RISC-V enables -funroll-loops at -O2 for small-loop unrolling.  Keep
size-growing complete unrolling disabled unless unrolling is explicitly
requested.

gcc/ChangeLog:

	* config/riscv/riscv.cc (riscv_override_options_after_change): New
	function.
	(riscv_option_override): Call it.
	(TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE): Define.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/unroll-explicit-attr-cunroll.c: New test.
	* gcc.target/riscv/unroll-small-loop-cunroll.c: New test.
---
 gcc/config/riscv/riscv.cc                     | 31 +++++++++++++------
 .../riscv/unroll-explicit-attr-cunroll.c      | 22 +++++++++++++
 .../riscv/unroll-small-loop-cunroll.c         | 22 +++++++++++++
 3 files changed, 66 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/unroll-explicit-attr-cunroll.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/unroll-small-loop-cunroll.c
  

Comments

Jeffrey Law July 18, 2026, 7:40 p.m. UTC | #1
On 7/17/2026 1:48 AM, wangjue wrote:
> RISC-V enables -funroll-loops at -O2 for small-loop unrolling.  Keep
> size-growing complete unrolling disabled unless unrolling is explicitly
> requested.
>
> gcc/ChangeLog:
>
> 	* config/riscv/riscv.cc (riscv_override_options_after_change): New
> 	function.
> 	(riscv_option_override): Call it.
> 	(TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE): Define.
>
> gcc/testsuite/ChangeLog:
>
> 	* gcc.target/riscv/unroll-explicit-attr-cunroll.c: New test.
> 	* gcc.target/riscv/unroll-small-loop-cunroll.c: New test.
Thanks.  I pushed this to the trunk after a final riscv32-elf and 
riscv64-elf test run.

jeff
  

Patch

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 57e798556d0..a401c0c7c93 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -12142,6 +12142,24 @@  riscv_override_options_internal (struct gcc_options *opts)
     }
 }
 
+/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE.  */
+
+static void
+riscv_override_options_after_change (void)
+{
+  /* Explicit unrolling is not restricted to small loops.  */
+  if ((OPTION_SET_P (flag_unroll_loops) && flag_unroll_loops)
+      || (OPTION_SET_P (flag_unroll_all_loops) && flag_unroll_all_loops))
+    {
+      if (!OPTION_SET_P (riscv_unroll_only_small_loops))
+	riscv_unroll_only_small_loops = 0;
+      if (!OPTION_SET_P (flag_cunroll_grow_size))
+	flag_cunroll_grow_size = 1;
+    }
+  else if (!OPTION_SET_P (flag_cunroll_grow_size))
+    flag_cunroll_grow_size = flag_peel_loops || optimize >= 3;
+}
+
 /* Implement TARGET_OPTION_OVERRIDE.  */
 
 void
@@ -12153,15 +12171,7 @@  riscv_option_override (void)
 
   flag_pcc_struct_return = 0;
 
-  /* Explicit -funroll-loops or -funroll-all-loops turns
-     -munroll-only-small-loops off, allowing the unroller to handle
-     all loops without the conservative small-loop restriction.  */
-  if ((OPTION_SET_P (flag_unroll_loops) && flag_unroll_loops)
-      || (OPTION_SET_P (flag_unroll_all_loops) && flag_unroll_all_loops))
-    {
-      if (!OPTION_SET_P (riscv_unroll_only_small_loops))
-	riscv_unroll_only_small_loops = 0;
-    }
+  riscv_override_options_after_change ();
 
   if (flag_pic)
     g_switch_value = 0;
@@ -16523,6 +16533,9 @@  riscv_memtag_tag_bitsize ()
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE riscv_option_override
 
+#undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
+#define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE riscv_override_options_after_change
+
 #undef TARGET_OPTION_SAVE
 #define TARGET_OPTION_SAVE riscv_option_save
 
diff --git a/gcc/testsuite/gcc.target/riscv/unroll-explicit-attr-cunroll.c b/gcc/testsuite/gcc.target/riscv/unroll-explicit-attr-cunroll.c
new file mode 100644
index 00000000000..e9628cf8ffb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/unroll-explicit-attr-cunroll.c
@@ -0,0 +1,22 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-cunroll-details" } */
+
+unsigned short data;
+
+__attribute__ ((optimize ("unroll-loops")))
+void
+explicit_attr_cunroll (void)
+{
+  unsigned char x;
+
+  for (unsigned int i = 0; i < 8; ++i)
+    {
+      x = data & 1;
+      data >>= 1;
+      if (x == 1)
+	data ^= 0x4;
+      data >>= 1;
+    }
+}
+
+/* { dg-final { scan-tree-dump "loop with 7 iterations completely unrolled" "cunroll" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/unroll-small-loop-cunroll.c b/gcc/testsuite/gcc.target/riscv/unroll-small-loop-cunroll.c
new file mode 100644
index 00000000000..87aec5988fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/unroll-small-loop-cunroll.c
@@ -0,0 +1,22 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-cunroll-details" } */
+
+unsigned short data;
+
+void
+small_loop_cunroll (void)
+{
+  unsigned char x;
+
+  for (unsigned int i = 0; i < 8; ++i)
+    {
+      x = data & 1;
+      data >>= 1;
+      if (x == 1)
+	data ^= 0x4;
+      data >>= 1;
+    }
+}
+
+/* { dg-final { scan-tree-dump "Not unrolling loop \[0-9\]\+: size would grow" "cunroll" } } */
+/* { dg-final { scan-tree-dump-not "completely unrolled" "cunroll" } } */