rs6000.c (rs6000_atomic_assign_expand_fenv): New function.
2014-10-19 Adhemerval Zanella <azanella@linux.vnet.ibm.com> David Edelsohn <dje.gcc@gmail.com> * config/rs6000/rs6000.c (rs6000_atomic_assign_expand_fenv): New function. (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New define. * gcc.dg/atomic/c11-atomic-exec-5.c (test_main_long_double_add_overflow): Define and run only for LDBL_MANT_DIG != 106. (test_main_complex_long_double_add_overflow): Likewise. (test_main_long_double_sub_overflow): Likewise. (test_main_complex_long_double_sub_overflow): Likewise. Co-Authored-By: David Edelsohn <dje.gcc@gmail.com> From-SVN: r216437
This commit is contained in:
parent
fad0fe1eda
commit
f4b0b1e3bb
@ -1,3 +1,10 @@
|
||||
2014-10-19 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
|
||||
David Edelsohn <dje.gcc@gmail.com>
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_atomic_assign_expand_fenv): New
|
||||
function.
|
||||
(TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New define.
|
||||
|
||||
2014-10-18 Manuel López-Ibáñez <manu@gcc.gnu.org>
|
||||
|
||||
* doc/invoke.texi (Options to Request or Suppress Warnings):
|
||||
|
@ -1647,6 +1647,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
|
||||
|
||||
#undef TARGET_CAN_USE_DOLOOP_P
|
||||
#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
|
||||
|
||||
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
|
||||
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV rs6000_atomic_assign_expand_fenv
|
||||
|
||||
|
||||
/* Processor table. */
|
||||
@ -34575,6 +34578,117 @@ make_pass_analyze_swaps (gcc::context *ctxt)
|
||||
{
|
||||
return new pass_analyze_swaps (ctxt);
|
||||
}
|
||||
|
||||
/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV hook. */
|
||||
|
||||
static void
|
||||
rs6000_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
|
||||
{
|
||||
if (!TARGET_HARD_FLOAT || !TARGET_FPRS)
|
||||
return;
|
||||
|
||||
tree mffs = rs6000_builtin_decls[RS6000_BUILTIN_MFFS];
|
||||
tree mtfsf = rs6000_builtin_decls[RS6000_BUILTIN_MTFSF];
|
||||
tree call_mffs = build_call_expr (mffs, 0);
|
||||
|
||||
/* Generates the equivalent of feholdexcept (&fenv_var)
|
||||
|
||||
*fenv_var = __builtin_mffs ();
|
||||
double fenv_hold;
|
||||
*(uint64_t*)&fenv_hold = *(uint64_t*)fenv_var & 0xffffffff00000007LL;
|
||||
__builtin_mtfsf (0xff, fenv_hold); */
|
||||
|
||||
/* Mask to clear everything except for the rounding modes and non-IEEE
|
||||
arithmetic flag. */
|
||||
const unsigned HOST_WIDE_INT hold_exception_mask =
|
||||
HOST_WIDE_INT_C (0xffffffff00000007);
|
||||
|
||||
tree fenv_var = create_tmp_var (double_type_node, NULL);
|
||||
|
||||
tree hold_mffs = build2 (MODIFY_EXPR, void_type_node, fenv_var, call_mffs);
|
||||
|
||||
tree fenv_llu = build1 (VIEW_CONVERT_EXPR, uint64_type_node, fenv_var);
|
||||
tree fenv_llu_and = build2 (BIT_AND_EXPR, uint64_type_node, fenv_llu,
|
||||
build_int_cst (uint64_type_node,
|
||||
hold_exception_mask));
|
||||
|
||||
tree fenv_hold_mtfsf = build1 (VIEW_CONVERT_EXPR, double_type_node,
|
||||
fenv_llu_and);
|
||||
|
||||
tree hold_mtfsf = build_call_expr (mtfsf, 2,
|
||||
build_int_cst (unsigned_type_node, 0xff),
|
||||
fenv_hold_mtfsf);
|
||||
|
||||
*hold = build2 (COMPOUND_EXPR, void_type_node, hold_mffs, hold_mtfsf);
|
||||
|
||||
/* Generates the equivalent of feclearexcept (FE_ALL_EXCEPT):
|
||||
|
||||
double fenv_clear = __builtin_mffs ();
|
||||
*(uint64_t)&fenv_clear &= 0xffffffff00000000LL;
|
||||
__builtin_mtfsf (0xff, fenv_clear); */
|
||||
|
||||
/* Mask to clear everything except for the rounding modes and non-IEEE
|
||||
arithmetic flag. */
|
||||
const unsigned HOST_WIDE_INT clear_exception_mask =
|
||||
HOST_WIDE_INT_C (0xffffffff00000000);
|
||||
|
||||
tree fenv_clear = create_tmp_var (double_type_node, NULL);
|
||||
|
||||
tree clear_mffs = build2 (MODIFY_EXPR, void_type_node, fenv_clear, call_mffs);
|
||||
|
||||
tree fenv_clean_llu = build1 (VIEW_CONVERT_EXPR, uint64_type_node, fenv_clear);
|
||||
tree fenv_clear_llu_and = build2 (BIT_AND_EXPR, uint64_type_node,
|
||||
fenv_clean_llu,
|
||||
build_int_cst (uint64_type_node,
|
||||
clear_exception_mask));
|
||||
|
||||
tree fenv_clear_mtfsf = build1 (VIEW_CONVERT_EXPR, double_type_node,
|
||||
fenv_clear_llu_and);
|
||||
|
||||
tree clear_mtfsf = build_call_expr (mtfsf, 2,
|
||||
build_int_cst (unsigned_type_node, 0xff),
|
||||
fenv_clear_mtfsf);
|
||||
|
||||
*clear = build2 (COMPOUND_EXPR, void_type_node, clear_mffs, clear_mtfsf);
|
||||
|
||||
/* Generates the equivalent of feupdateenv (&fenv_var)
|
||||
|
||||
double old_fenv = __builtin_mffs ();
|
||||
double fenv_update;
|
||||
*(uint64_t*)&fenv_update = (*(uint64_t*)&old & 0xffffffff1fffff00LL) |
|
||||
(*(uint64_t*)fenv_var 0x1ff80fff);
|
||||
__builtin_mtfsf (0xff, fenv_update); */
|
||||
|
||||
const unsigned HOST_WIDE_INT update_exception_mask =
|
||||
HOST_WIDE_INT_C (0xffffffff1fffff00);
|
||||
const unsigned HOST_WIDE_INT new_exception_mask =
|
||||
HOST_WIDE_INT_C (0x1ff80fff);
|
||||
|
||||
tree old_fenv = create_tmp_var (double_type_node, NULL);
|
||||
tree update_mffs = build2 (MODIFY_EXPR, void_type_node, old_fenv, call_mffs);
|
||||
|
||||
tree old_llu = build1 (VIEW_CONVERT_EXPR, uint64_type_node, old_fenv);
|
||||
tree old_llu_and = build2 (BIT_AND_EXPR, uint64_type_node, old_llu,
|
||||
build_int_cst (uint64_type_node,
|
||||
update_exception_mask));
|
||||
|
||||
tree new_llu_and = build2 (BIT_AND_EXPR, uint64_type_node, fenv_llu,
|
||||
build_int_cst (uint64_type_node,
|
||||
new_exception_mask));
|
||||
|
||||
tree new_llu_mask = build2 (BIT_IOR_EXPR, uint64_type_node,
|
||||
old_llu_and, new_llu_and);
|
||||
|
||||
tree fenv_update_mtfsf = build1 (VIEW_CONVERT_EXPR, double_type_node,
|
||||
new_llu_mask);
|
||||
|
||||
tree update_mtfsf = build_call_expr (mtfsf, 2,
|
||||
build_int_cst (unsigned_type_node, 0xff),
|
||||
fenv_update_mtfsf);
|
||||
|
||||
*update = build2 (COMPOUND_EXPR, void_type_node, update_mffs, update_mtfsf);
|
||||
}
|
||||
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
2014-10-19 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
|
||||
|
||||
* gcc.dg/atomic/c11-atomic-exec-5.c
|
||||
(test_main_long_double_add_overflow): Define and run only for
|
||||
LDBL_MANT_DIG != 106.
|
||||
(test_main_complex_long_double_add_overflow): Likewise.
|
||||
(test_main_long_double_sub_overflow): Likewise.
|
||||
(test_main_complex_long_double_sub_overflow): Likewise.
|
||||
|
||||
2014-10-18 Paul Thomas <pault@gcc.gnu.org>
|
||||
|
||||
PR fortran/63553
|
||||
|
@ -507,23 +507,23 @@ main (void)
|
||||
ret |= test_main_int_div_double_inexact ();
|
||||
ret |= test_main_complex_double_div_overflow ();
|
||||
ret |= test_main_long_double_add_invalid ();
|
||||
ret |= test_main_long_double_add_overflow ();
|
||||
#if LDBL_MANT_DIG != 106
|
||||
ret |= test_main_long_double_add_overflow ();
|
||||
ret |= test_main_long_double_add_inexact ();
|
||||
ret |= test_main_long_double_add_inexact_int ();
|
||||
ret |= test_main_long_double_preinc_inexact ();
|
||||
ret |= test_main_long_double_postinc_inexact ();
|
||||
#endif
|
||||
ret |= test_main_complex_long_double_add_overflow ();
|
||||
#endif
|
||||
ret |= test_main_long_double_sub_invalid ();
|
||||
ret |= test_main_long_double_sub_overflow ();
|
||||
#if LDBL_MANT_DIG != 106
|
||||
ret |= test_main_long_double_sub_overflow ();
|
||||
ret |= test_main_long_double_sub_inexact ();
|
||||
ret |= test_main_long_double_sub_inexact_int ();
|
||||
ret |= test_main_long_double_predec_inexact ();
|
||||
ret |= test_main_long_double_postdec_inexact ();
|
||||
#endif
|
||||
ret |= test_main_complex_long_double_sub_overflow ();
|
||||
#endif
|
||||
ret |= test_main_long_double_mul_invalid ();
|
||||
ret |= test_main_long_double_mul_overflow ();
|
||||
ret |= test_main_long_double_mul_overflow_float ();
|
||||
|
Loading…
Reference in New Issue
Block a user