Hi All,

In PR116140 it was brought up that adding pragma GCC unroll in std::find makes
it so that you can't use a larger unroll factor if you wanted to.  This is
because the value can't be overriden by the other unrolling flags such as
-funroll-loops.

To know whether this should be possible to do or not this proposes an extension
to the pragma GCC unroll with an argument to indicate if we can override the
value or not.

The default is "requested" to match what it does today.

Bootstrapped Regtested on aarch64-none-linux-gnu,
arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
-m32, -m64 and no issues.

Ok for master?

Thanks,
Tamar

gcc/c/ChangeLog:

        PR libstdc++/116140
        * c-parser.cc (c_parser_pragma_unroll): Implement hint.

gcc/testsuite/ChangeLog:

        PR libstdc++/116140
        * gcc.dg/unroll-11.c: New test.
        * gcc.dg/unroll-12.c: New test.
        * gcc.dg/unroll-13.c: New test.

---
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 
8a63dc54c795157345c71177f8335d56f755c021..2538b2aecd21da7d4992862b97e7740a8bbe0fbc
 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -15602,6 +15602,25 @@ c_parser_pragma_unroll (c_parser *parser)
        unroll = 1;
     }
 
+  c_token *token = c_parser_peek_token (parser);
+  if (token->type != CPP_PRAGMA_EOL)
+    {
+      if (token->type != CPP_NAME)
+       c_parser_error (parser, "expected identifier");
+
+      tree name = token->value;
+      const char *token_name = IDENTIFIER_POINTER (name);
+      if (strcmp (token_name, "requested") != 0
+         && strcmp (token_name, "preferred") != 0)
+       error_at (token->location,
+                "unexpected token in %<#pragma GCC unroll%>, expected "
+                "'requested' or 'preferred'");
+      /* If preferred and -funroll-loops then ignore the unroll count.  */
+      if (flag_unroll_loops
+         && strcmp (token_name, "preferred") == 0)
+       unroll = 0;
+      c_parser_consume_token (parser);
+    }
   c_parser_skip_to_pragma_eol (parser);
   return unroll;
 }
diff --git a/gcc/testsuite/gcc.dg/unroll-11.c b/gcc/testsuite/gcc.dg/unroll-11.c
new file mode 100644
index 
0000000000000000000000000000000000000000..0714b24be147e23a81078b26932b596198e63125
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unroll-11.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O1 -fdump-rtl-loop2_unroll-details -funroll-loops 
-std=gnu99" } */
+
+void f1 (int *restrict a, int n)
+{
+#pragma GCC unroll 4 requested
+#pragma GCC novector
+  for (int i = 0; i < n; i++)
+    a[i] *= 2;
+}
+
+/* { dg-final { scan-rtl-dump "loop unrolled 3 times" "loop2_unroll" } } */
diff --git a/gcc/testsuite/gcc.dg/unroll-12.c b/gcc/testsuite/gcc.dg/unroll-12.c
new file mode 100644
index 
0000000000000000000000000000000000000000..4a4d9ec1451fe4babc264ef2b8b549b0b64fc98a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unroll-12.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O1 -fdump-rtl-loop2_unroll-details -funroll-loops 
-std=gnu99" } */
+
+void f2 (int *restrict a, int n)
+{
+#pragma GCC unroll 4
+#pragma GCC novector
+  for (int i = 0; i < n; i++)
+    a[i] *= 2;
+}
+
+/* { dg-final { scan-rtl-dump "loop unrolled 3 times" "loop2_unroll" } } */
diff --git a/gcc/testsuite/gcc.dg/unroll-13.c b/gcc/testsuite/gcc.dg/unroll-13.c
new file mode 100644
index 
0000000000000000000000000000000000000000..e5b92de2cd3292d2e23864aea3e83e4dc3368b12
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unroll-13.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O1 -fdump-rtl-loop2_unroll-details -funroll-loops 
-std=gnu99" } */
+
+void f3 (int *restrict a, int n)
+{
+#pragma GCC unroll 4 preferred
+#pragma GCC novector
+  for (int i = 0; i < n; i++)
+    a[i] *= 2;
+}
+
+/* { dg-final { scan-rtl-dump "loop unrolled 7 times" "loop2_unroll" } } */


-- 
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 8a63dc54c795157345c71177f8335d56f755c021..2538b2aecd21da7d4992862b97e7740a8bbe0fbc 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -15602,6 +15602,25 @@ c_parser_pragma_unroll (c_parser *parser)
 	unroll = 1;
     }
 
+  c_token *token = c_parser_peek_token (parser);
+  if (token->type != CPP_PRAGMA_EOL)
+    {
+      if (token->type != CPP_NAME)
+	c_parser_error (parser, "expected identifier");
+
+      tree name = token->value;
+      const char *token_name = IDENTIFIER_POINTER (name);
+      if (strcmp (token_name, "requested") != 0
+	  && strcmp (token_name, "preferred") != 0)
+	error_at (token->location,
+		 "unexpected token in %<#pragma GCC unroll%>, expected "
+		 "'requested' or 'preferred'");
+      /* If preferred and -funroll-loops then ignore the unroll count.  */
+      if (flag_unroll_loops
+	  && strcmp (token_name, "preferred") == 0)
+	unroll = 0;
+      c_parser_consume_token (parser);
+    }
   c_parser_skip_to_pragma_eol (parser);
   return unroll;
 }
diff --git a/gcc/testsuite/gcc.dg/unroll-11.c b/gcc/testsuite/gcc.dg/unroll-11.c
new file mode 100644
index 0000000000000000000000000000000000000000..0714b24be147e23a81078b26932b596198e63125
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unroll-11.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O1 -fdump-rtl-loop2_unroll-details -funroll-loops -std=gnu99" } */
+
+void f1 (int *restrict a, int n)
+{
+#pragma GCC unroll 4 requested
+#pragma GCC novector
+  for (int i = 0; i < n; i++)
+    a[i] *= 2;
+}
+
+/* { dg-final { scan-rtl-dump "loop unrolled 3 times" "loop2_unroll" } } */
diff --git a/gcc/testsuite/gcc.dg/unroll-12.c b/gcc/testsuite/gcc.dg/unroll-12.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a4d9ec1451fe4babc264ef2b8b549b0b64fc98a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unroll-12.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O1 -fdump-rtl-loop2_unroll-details -funroll-loops -std=gnu99" } */
+
+void f2 (int *restrict a, int n)
+{
+#pragma GCC unroll 4
+#pragma GCC novector
+  for (int i = 0; i < n; i++)
+    a[i] *= 2;
+}
+
+/* { dg-final { scan-rtl-dump "loop unrolled 3 times" "loop2_unroll" } } */
diff --git a/gcc/testsuite/gcc.dg/unroll-13.c b/gcc/testsuite/gcc.dg/unroll-13.c
new file mode 100644
index 0000000000000000000000000000000000000000..e5b92de2cd3292d2e23864aea3e83e4dc3368b12
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unroll-13.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O1 -fdump-rtl-loop2_unroll-details -funroll-loops -std=gnu99" } */
+
+void f3 (int *restrict a, int n)
+{
+#pragma GCC unroll 4 preferred
+#pragma GCC novector
+  for (int i = 0; i < n; i++)
+    a[i] *= 2;
+}
+
+/* { dg-final { scan-rtl-dump "loop unrolled 7 times" "loop2_unroll" } } */

Reply via email to