https://gcc.gnu.org/g:333445364ba7829dde7a9e8548a26c26eb979c21

commit 333445364ba7829dde7a9e8548a26c26eb979c21
Author: David Faust <david.fa...@oracle.com>
Date:   Thu Mar 7 09:29:32 2024 -0800

    bpf: add size threshold for inlining mem builtins
    
    BPF cannot fall back on library calls to implement memmove, memcpy and
    memset, so we attempt to expand these inline always if possible.
    However, this inline expansion was being attempted even for excessively
    large operations, which could result in gcc consuming huge amounts of
    memory and hanging.
    
    Add a size threshold in the BPF backend below which to always expand
    these operations inline, and introduce an option
    -minline-memops-threshold= to control the threshold. Defaults to
    1024 bytes.
    
    gcc/
    
            * config/bpf/bpf.cc (bpf_expand_cpymem, bpf_expand_setmem): Do
            not attempt inline expansion if size is above threshold.
            * config/bpf/bpf.opt (-minline-memops-threshold): New option.
            * doc/invoke.texi (eBPF Options) <-minline-memops-threshold>:
            Document.
    
    gcc/testsuite/
    
            * gcc.target/bpf/inline-memops-threshold-1.c: New test.
            * gcc.target/bpf/inline-memops-threshold-2.c: New test.
    
    (cherry picked from commit 0e850eff58539fb79483664962fac6c46d65c79d)

Diff:
---
 gcc/config/bpf/bpf.cc                              | 26 +++++++++++++++++++++-
 gcc/config/bpf/bpf.opt                             |  4 ++++
 gcc/doc/invoke.texi                                | 11 ++++++++-
 .../gcc.target/bpf/inline-memops-threshold-1.c     | 15 +++++++++++++
 .../gcc.target/bpf/inline-memops-threshold-2.c     | 11 +++++++++
 5 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index c008a961e51..83843574029 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -1244,9 +1244,9 @@ bool
 bpf_expand_cpymem (rtx *operands, bool is_move)
 {
   /* Size must be constant for this expansion to work.  */
+  const char *name = is_move ? "memmove" : "memcpy";
   if (!CONST_INT_P (operands[2]))
     {
-      const char *name = is_move ? "memmove" : "memcpy";
       if (flag_building_libgcc)
        warning (0, "could not inline call to %<__builtin_%s%>: "
                 "size must be constant", name);
@@ -1275,6 +1275,18 @@ bpf_expand_cpymem (rtx *operands, bool is_move)
       gcc_unreachable ();
     }
 
+  /* For sizes above threshold, always use a libcall.  */
+  if (size_bytes > (unsigned HOST_WIDE_INT) bpf_inline_memops_threshold)
+    {
+      if (flag_building_libgcc)
+       warning (0, "could not inline call to %<__builtin_%s%>: "
+                "too many bytes, use %<-minline-memops-threshold%>", name);
+      else
+       error ("could not inline call to %<__builtin_%s%>: "
+              "too many bytes, use %<-minline-memops-threshold%>", name);
+      return false;
+    }
+
   unsigned iters = size_bytes >> ceil_log2 (align);
   unsigned remainder = size_bytes & (align - 1);
 
@@ -1347,6 +1359,18 @@ bpf_expand_setmem (rtx *operands)
       gcc_unreachable ();
     }
 
+  /* For sizes above threshold, always use a libcall.  */
+  if (size_bytes > (unsigned HOST_WIDE_INT) bpf_inline_memops_threshold)
+    {
+      if (flag_building_libgcc)
+       warning (0, "could not inline call to %<__builtin_memset%>: "
+                "too many bytes, use %<-minline-memops-threshold%>");
+      else
+       error ("could not inline call to %<__builtin_memset%>: "
+              "too many bytes, use %<-minline-memops-threshold%>");
+      return false;
+    }
+
   unsigned iters = size_bytes >> ceil_log2 (align);
   unsigned remainder = size_bytes & (align - 1);
   unsigned inc = GET_MODE_SIZE (mode);
diff --git a/gcc/config/bpf/bpf.opt b/gcc/config/bpf/bpf.opt
index efa0380ee3f..ab166bfd865 100644
--- a/gcc/config/bpf/bpf.opt
+++ b/gcc/config/bpf/bpf.opt
@@ -106,3 +106,7 @@ Enum(asm_dialect) String(normal) Value(ASM_NORMAL)
 
 EnumValue
 Enum(asm_dialect) String(pseudoc) Value(ASM_PSEUDOC)
+
+minline-memops-threshold=
+Target RejectNegative Joined UInteger Var(bpf_inline_memops_threshold) 
Init(1024)
+-minline-memops-threshold=<number> Maximum size of memset/memmove/memcpy to 
inline, larger sizes will use a library call.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 999867e9d6d..746ce282f39 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -946,7 +946,7 @@ Objective-C and Objective-C++ Dialects}.
 @gccoptlist{-mbig-endian -mlittle-endian
 -mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re -mjmpext
 -mjmp32 -malu32 -mv3-atomics -mbswap -msdiv -msmov -mcpu=@var{version}
--masm=@var{dialect}}
+-masm=@var{dialect} -minline-memops-threshold=@var{bytes}}
 
 @emph{FR30 Options}
 @gccoptlist{-msmall-model  -mno-lsim}
@@ -24620,6 +24620,15 @@ Outputs pseudo-c assembly dialect.
 
 @end table
 
+@opindex -minline-memops-threshold
+@item -minline-memops-threshold=@var{bytes}
+Specifies a size threshold in bytes at or below which memmove, memcpy
+and memset shall always be expanded inline.  Operations dealing with
+sizes larger than this threshold would have to be be implemented using
+a library call instead of being expanded inline, but since BPF doesn't
+allow libcalls, exceeding this threshold results in a compile-time
+error.  The default is @samp{1024} bytes.
+
 @end table
 
 @node FR30 Options
diff --git a/gcc/testsuite/gcc.target/bpf/inline-memops-threshold-1.c 
b/gcc/testsuite/gcc.target/bpf/inline-memops-threshold-1.c
new file mode 100644
index 00000000000..c2ba4db5b7b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/inline-memops-threshold-1.c
@@ -0,0 +1,15 @@
+
+/* { dg-do compile } */
+/* { dg-options "-O2" "-minline-memops-threshold=256"} */
+
+char buf[512];
+
+void
+mov_small (void)
+{
+  __builtin_memmove (buf, buf + 2, 255);
+}
+
+/* { dg-final { scan-assembler-not "call" } } */
+/* { dg-final { scan-assembler "ldxb" } } */
+/* { dg-final { scan-assembler "stxb" } } */
diff --git a/gcc/testsuite/gcc.target/bpf/inline-memops-threshold-2.c 
b/gcc/testsuite/gcc.target/bpf/inline-memops-threshold-2.c
new file mode 100644
index 00000000000..50910483890
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/inline-memops-threshold-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -minline-memops-threshold=256" } */
+
+char buf[512];
+
+void
+mov_big (void)
+{
+  __builtin_memmove (buf, buf + 12, 354); /* { dg-error "too many bytes" } */
+}
+

Reply via email to