On Tue, Dec 8, 2020 at 10:36 AM Jakub Jelinek <ja...@redhat.com> wrote:
>
> Hi!
>
> The documentation says
>      For a named pattern, the condition may not depend on the data in
>      the insn being matched, but only the target-machine-type flags.
> The i386 backend violates that by using flag_excess_precision and
> flag_unsafe_math_optimizations in the conditions too, which is bad
> when optimize attribute or pragmas are used.  The problem is that the
> middle-end caches the enabled conditions for the optabs for a particular
> switchable target, but multiple functions can share the same
> TARGET_OPTION_NODE, but have different TREE_OPTIMIZATION_NODE with different
> flag_excess_precision or flag_unsafe_math_optimizations, so the enabled
> conditions then match only one of those.
>
> I think best would be to just have a single options node for both the
> generic and target options, then such problems wouldn't exist, but that
> would be very risky at this point and quite large change.
>
> So, instead the following patch just shadows flag_excess_precision and
> flag_unsafe_math_optimizations values for uses in the instruction conditions
> in TargetVariable and during set_cfun artificially creates new
> TARGET_OPTION_NODE if flag_excess_precision and/or
> flag_unsafe_math_optimizations change from what is recorded in their
> TARGET_OPTION_NODE.  The target nodes are hashed, so worst case we can get 4
> times as many target option nodes if one would for each unique target option
> try all the flag_excess_precision and flag_unsafe_math_optimizations values.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2020-12-08  Jakub Jelinek  <ja...@redhat.com>
>
>         PR target/94440
>         * config/i386/i386.opt (ix86_excess_precision,
>         ix86_unsafe_math_optimizations): New TargetVariables.
>         * config/i386/i386.h (X87_ENABLE_ARITH, X87_ENABLE_FLOAT): Use
>         ix86_unsafe_math_optimizations instead of
>         flag_unsafe_math_optimizations and ix86_excess_precision instead of
>         flag_excess_precision.
>         * config/i386/i386.c (ix86_excess_precision): Rename to ...
>         (ix86_get_excess_precision): ... this.
>         (TARGET_C_EXCESS_PRECISION): Define to ix86_get_excess_precision.
>         * config/i386/i386-options.c (ix86_valid_target_attribute_tree,
>         ix86_option_override_internal): Update ix86_unsafe_math_optimization
>         from flag_unsafe_math_optimizations and ix86_excess_precision
>         from flag_excess_precision when constructing target option nodes.
>         (ix86_set_current_function): If flag_unsafe_math_optimizations
>         or flag_excess_precision is different from the one recorded
>         in TARGET_OPTION_NODE, create a new target option node for the
>         current function and switch to that.

LGTM, but I'm not really experienced in option processing functionality.

Thanks,
Uros.

> --- gcc/config/i386/i386.opt.jj 2020-12-02 14:42:52.195054633 +0100
> +++ gcc/config/i386/i386.opt    2020-12-07 16:05:16.898814331 +0100
> @@ -49,6 +49,16 @@ int recip_mask_explicit
>  TargetSave
>  int x_recip_mask_explicit
>
> +;; A copy of flag_excess_precision as a target variable that should
> +;; force a different DECL_FUNCTION_SPECIFIC_TARGET upon
> +;; flag_excess_precision changes.
> +TargetVariable
> +enum excess_precision ix86_excess_precision = EXCESS_PRECISION_DEFAULT
> +
> +;; Similarly for flag_unsafe_math_optimizations.
> +TargetVariable
> +bool ix86_unsafe_math_optimizations = false
> +
>  ;; Definitions to add to the cl_target_option structure
>  ;; -march= processor
>  TargetSave
> --- gcc/config/i386/i386.h.jj   2020-12-05 11:37:19.817423434 +0100
> +++ gcc/config/i386/i386.h      2020-12-07 16:17:13.051866670 +0100
> @@ -829,15 +829,15 @@ extern const char *host_detect_local_cpu
>     SFmode, DFmode and XFmode) in the current excess precision
>     configuration.  */
>  #define X87_ENABLE_ARITH(MODE)                         \
> -  (flag_unsafe_math_optimizations                      \
> -   || flag_excess_precision == EXCESS_PRECISION_FAST   \
> +  (ix86_unsafe_math_optimizations                      \
> +   || ix86_excess_precision == EXCESS_PRECISION_FAST   \
>     || (MODE) == XFmode)
>
>  /* Likewise, whether to allow direct conversions from integer mode
>     IMODE (HImode, SImode or DImode) to MODE.  */
>  #define X87_ENABLE_FLOAT(MODE, IMODE)                  \
> -  (flag_unsafe_math_optimizations                      \
> -   || flag_excess_precision == EXCESS_PRECISION_FAST   \
> +  (ix86_unsafe_math_optimizations                      \
> +   || ix86_excess_precision == EXCESS_PRECISION_FAST   \
>     || (MODE) == XFmode                                 \
>     || ((MODE) == DFmode && (IMODE) == SImode)          \
>     || (IMODE) == HImode)
> --- gcc/config/i386/i386.c.jj   2020-12-05 11:37:19.000000000 +0100
> +++ gcc/config/i386/i386.c      2020-12-07 16:34:39.460252324 +0100
> @@ -23001,7 +23001,7 @@ ix86_init_libfuncs (void)
>     apparently at random.  */
>
>  static enum flt_eval_method
> -ix86_excess_precision (enum excess_precision_type type)
> +ix86_get_excess_precision (enum excess_precision_type type)
>  {
>    switch (type)
>      {
> @@ -23527,7 +23527,7 @@ ix86_run_selftests (void)
>  #define TARGET_MD_ASM_ADJUST ix86_md_asm_adjust
>
>  #undef TARGET_C_EXCESS_PRECISION
> -#define TARGET_C_EXCESS_PRECISION ix86_excess_precision
> +#define TARGET_C_EXCESS_PRECISION ix86_get_excess_precision
>  #undef TARGET_PROMOTE_PROTOTYPES
>  #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
>  #undef TARGET_SETUP_INCOMING_VARARGS
> --- gcc/config/i386/i386-options.c.jj   2020-12-05 11:37:19.806423559 +0100
> +++ gcc/config/i386/i386-options.c      2020-12-07 16:30:15.719179795 +0100
> @@ -1374,6 +1374,14 @@ ix86_valid_target_attribute_tree (tree f
>        /* Add any builtin functions with the new isa if any.  */
>        ix86_add_new_builtins (opts->x_ix86_isa_flags, 
> opts->x_ix86_isa_flags2);
>
> +      enum excess_precision orig_ix86_excess_precision
> +       = opts->x_ix86_excess_precision;
> +      bool orig_ix86_unsafe_math_optimizations
> +       = opts->x_ix86_unsafe_math_optimizations;
> +      opts->x_ix86_excess_precision = opts->x_flag_excess_precision;
> +      opts->x_ix86_unsafe_math_optimizations
> +       = opts->x_flag_unsafe_math_optimizations;
> +
>        /* Save the current options unless we are validating options for
>          #pragma.  */
>        t = build_target_option_node (opts, opts_set);
> @@ -1382,6 +1390,9 @@ ix86_valid_target_attribute_tree (tree f
>        opts->x_ix86_tune_string = orig_tune_string;
>        opts_set->x_ix86_fpmath = orig_fpmath_set;
>        opts_set->x_prefer_vector_width_type = orig_pvw_set;
> +      opts->x_ix86_excess_precision = orig_ix86_excess_precision;
> +      opts->x_ix86_unsafe_math_optimizations
> +       = orig_ix86_unsafe_math_optimizations;
>
>        release_options_strings (option_strings);
>      }
> @@ -3019,8 +3030,14 @@ ix86_option_override_internal (bool main
>    /* Save the initial options in case the user does function specific
>       options.  */
>    if (main_args_p)
> -    target_option_default_node = target_option_current_node
> -      = build_target_option_node (opts, opts_set);
> +    {
> +      opts->x_ix86_excess_precision
> +       = opts->x_flag_excess_precision;
> +      opts->x_ix86_unsafe_math_optimizations
> +       = opts->x_flag_unsafe_math_optimizations;
> +      target_option_default_node = target_option_current_node
> +        = build_target_option_node (opts, opts_set);
> +    }
>
>    if (opts->x_flag_cf_protection != CF_NONE)
>      opts->x_flag_cf_protection
> @@ -3322,6 +3339,24 @@ ix86_set_current_function (tree fndecl)
>        if (TREE_TARGET_GLOBALS (new_tree))
>         restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
>        else if (new_tree == target_option_default_node)
> +       restore_target_globals (&default_target_globals);
> +      else
> +       TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
> +    }
> +  else if (flag_unsafe_math_optimizations
> +          != TREE_TARGET_OPTION (new_tree)->x_ix86_unsafe_math_optimizations
> +          || (flag_excess_precision
> +              != TREE_TARGET_OPTION (new_tree)->x_ix86_excess_precision))
> +    {
> +      cl_target_option_restore (&global_options, &global_options_set,
> +                               TREE_TARGET_OPTION (new_tree));
> +      ix86_excess_precision = flag_excess_precision;
> +      ix86_unsafe_math_optimizations = flag_unsafe_math_optimizations;
> +      DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_tree
> +       = build_target_option_node (&global_options, &global_options_set);
> +      if (TREE_TARGET_GLOBALS (new_tree))
> +       restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
> +      else if (new_tree == target_option_default_node)
>         restore_target_globals (&default_target_globals);
>        else
>         TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
> --- gcc/testsuite/gcc.target/i386/pr94440-1.c.jj        2020-12-07 
> 16:37:48.216157159 +0100
> +++ gcc/testsuite/gcc.target/i386/pr94440-1.c   2020-12-07 16:37:15.586519343 
> +0100
> @@ -0,0 +1,23 @@
> +/* PR target/94440 */
> +/* { dg-do compile { target ia32 } } */
> +/* { dg-options "-mfpmath=sse,387 -msse2 -Ofast -fexcess-precision=standard 
> -fno-graphite --param=scev-max-expr-size=0" } */
> +
> +int b;
> +double c, d;
> +
> +void
> +foo (void)
> +{
> +  int i;
> +  for (i = 0; i < b; i++)
> +    c += i;
> +}
> +
> +int __attribute__((optimize(1)))
> +main ()
> +{
> +  double a[9];
> +  int i;
> +  for (i = 0; i < 9; i++)
> +    d += a[i];
> +}
> --- gcc/testsuite/gcc.target/i386/pr94440-2.c.jj        2020-12-07 
> 16:45:14.920196739 +0100
> +++ gcc/testsuite/gcc.target/i386/pr94440-2.c   2020-12-07 16:45:10.877241650 
> +0100
> @@ -0,0 +1,19 @@
> +/* PR target/94440 */
> +/* { dg-do compile } */
> +/* { dg-options "-O0 -msse2 -ffast-math" } */
> +
> +double a;
> +int b;
> +long double c;
> +
> +void
> +foo (void)
> +{
> +  float d = (double)(long double)b;
> +}
> +
> +__attribute__((optimize("O0"))) void
> +bar (void)
> +{
> +  a = c;
> +}
>
>         Jakub
>

Reply via email to