Index: config/alpha/alpha.c =================================================================== --- config/alpha/alpha.c (revision 212457) +++ config/alpha/alpha.c (working copy) @@ -9888,6 +9888,72 @@ alpha_canonicalize_comparison (int *code, rtx *op0 *op1 = GEN_INT (255); } } + +/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */ + +static void +alpha_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) +{ + const unsigned HOST_WIDE_INT SWCR_STATUS_MASK = (0x3fUL << 17); + + tree fenv_var, get_fpscr, set_fpscr, mask, ld_fenv, masked_fenv; + tree new_fenv_var, reload_fenv, restore_fnenv; + tree update_call, atomic_feraiseexcept, hold_fnclex; + + /* Assume OSF/1 compatible interfaces. */ + if (!TARGET_ABI_OSF) + return; + + /* Generate the equivalent of : + unsigned long fenv_var; + fenv_var = __ieee_get_fp_control (); + + unsigned long masked_fenv; + masked_fenv = fenv_var & mask; + + __ieee_set_fp_control (masked_fenv); */ + + fenv_var = create_tmp_var (long_unsigned_type_node, NULL); + get_fpscr + = build_fn_decl ("__ieee_get_fp_control", + build_function_type_list (long_unsigned_type_node, NULL)); + set_fpscr + = build_fn_decl ("__ieee_set_fp_control", + build_function_type_list (void_type_node, NULL)); + mask = build_int_cst (long_unsigned_type_node, ~SWCR_STATUS_MASK); + ld_fenv = build2 (MODIFY_EXPR, long_unsigned_type_node, + fenv_var, build_call_expr (get_fpscr, 0)); + masked_fenv = build2 (BIT_AND_EXPR, long_unsigned_type_node, fenv_var, mask); + hold_fnclex = build_call_expr (set_fpscr, 1, masked_fenv); + *hold = build2 (COMPOUND_EXPR, void_type_node, + build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv), + hold_fnclex); + + /* Store the value of masked_fenv to clear the exceptions: + __ieee_set_fp_control (masked_fenv); */ + + *clear = build_call_expr (set_fpscr, 1, masked_fenv); + + /* Generate the equivalent of : + unsigned long new_fenv_var; + new_fenv_var = __ieee_get_fp_control (); + + __ieee_set_fp_control (fenv_var); + + __atomic_feraiseexcept (new_fenv_var); */ + + new_fenv_var = create_tmp_var (long_unsigned_type_node, NULL); + reload_fenv = build2 (MODIFY_EXPR, long_unsigned_type_node, new_fenv_var, + build_call_expr (get_fpscr, 0)); + restore_fnenv = build_call_expr (set_fpscr, 1, fenv_var); + atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT); + update_call + = build_call_expr (atomic_feraiseexcept, 1, + fold_convert (integer_type_node, new_fenv_var)); + *update = build2 (COMPOUND_EXPR, void_type_node, + build2 (COMPOUND_EXPR, void_type_node, + reload_fenv, restore_fnenv), update_call); +} /* Initialize the GCC target structure. */ #if TARGET_ABI_OPEN_VMS @@ -10060,6 +10126,9 @@ alpha_canonicalize_comparison (int *code, rtx *op0 #undef TARGET_CANONICALIZE_COMPARISON #define TARGET_CANONICALIZE_COMPARISON alpha_canonicalize_comparison +#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV +#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV alpha_atomic_assign_expand_fenv + struct gcc_target targetm = TARGET_INITIALIZER; Index: testsuite/gcc.dg/atomic/c11-atomic-exec-4.c =================================================================== --- testsuite/gcc.dg/atomic/c11-atomic-exec-4.c (revision 212457) +++ testsuite/gcc.dg/atomic/c11-atomic-exec-4.c (working copy) @@ -3,7 +3,7 @@ out in two threads. */ /* { dg-do run } */ /* { dg-options "-std=c11 -pedantic-errors -pthread -D_POSIX_C_SOURCE=200809L" } */ -/* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2.1[0-9]* } } +/* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2.1[0-9]* } } */ /* { dg-require-effective-target pthread } */ #include Index: testsuite/gcc.dg/atomic/c11-atomic-exec-5.c =================================================================== --- testsuite/gcc.dg/atomic/c11-atomic-exec-5.c (revision 212457) +++ testsuite/gcc.dg/atomic/c11-atomic-exec-5.c (working copy) @@ -4,7 +4,9 @@ get properly cleared). */ /* { dg-do run } */ /* { dg-options "-std=c11 -pedantic-errors -pthread -D_POSIX_C_SOURCE=200809L" } */ -/* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2.1[0-9]* } } +/* { dg-add-options ieee } */ +/* { dg-additional-options "-mieee-with-inexact" { target alpha*-*-* } } */ +/* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2.1[0-9]* } } */ /* { dg-require-effective-target fenv_exceptions } */ /* { dg-require-effective-target pthread } */ @@ -21,7 +23,11 @@ | FE_OVERFLOW \ | FE_UNDERFLOW) -#define ITER_COUNT 10000 +#if defined __alpha__ + #define ITER_COUNT 100 +#else + #define ITER_COUNT 10000 +#endif static volatile _Atomic bool thread_ready, thread_stop; Index: testsuite/lib/target-supports.exp =================================================================== --- testsuite/lib/target-supports.exp (revision 212457) +++ testsuite/lib/target-supports.exp (working copy) @@ -5923,7 +5923,7 @@ proc check_effective_target_fenv_exceptions {} { else abort (); } - } "-std=gnu99"] + } [add_options_for_ieee "-std=gnu99"]] } # Return 1 if LOGICAL_OP_NON_SHORT_CIRCUIT is set to 0 for the current target.