Hi Faust.
OK.  Thanks!

> [Changes from v1:
>  - Error if threshold is exceeded instead of silently emitting libcall
>  - Update test accordingly
>  - Expand documentation to explain this behavior  ]
>
> 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.
> ---
>  gcc/config/bpf/bpf.cc                         | 26 ++++++++++++++++++-
>  gcc/config/bpf/bpf.opt                        |  4 +++
>  gcc/doc/invoke.texi                           | 11 +++++++-
>  .../bpf/inline-memops-threshold-1.c           | 15 +++++++++++
>  .../bpf/inline-memops-threshold-2.c           | 11 ++++++++
>  5 files changed, 65 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/bpf/inline-memops-threshold-1.c
>  create mode 100644 gcc/testsuite/gcc.target/bpf/inline-memops-threshold-2.c
>
> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
> index 0e33f4347ba..8365cd9fcb1 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 acfddebdad7..541ebe4dfc4 100644
> --- a/gcc/config/bpf/bpf.opt
> +++ b/gcc/config/bpf/bpf.opt
> @@ -108,3 +108,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 c0d604a2c5c..85c938d4a14 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -971,7 +971,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}
> @@ -25701,6 +25701,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