From 2ac3f65eeeac88cf2a9a8b339eab1fee3c94e42a Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 7 Nov 2011 16:24:10 +0100 Subject: erts: Rename macros used by float instructions without FPE No semantic change, just code clarification. Use unique macro names instead of redefining the original ones. --- erts/emulator/beam/beam_emu.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 9c5450bd48..028a532b4c 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -4747,7 +4747,12 @@ void process_main(void) OpCase(fclearerror): OpCase(i_fcheckerror): erl_exit(1, "fclearerror/i_fcheckerror without fpe signals (beam_emu)"); +# define ERTS_NO_FPE_CHECK_INIT ERTS_FP_CHECK_INIT +# define ERTS_NO_FPE_ERROR ERTS_FP_ERROR #else +# define ERTS_NO_FPE_CHECK_INIT(p) +# define ERTS_NO_FPE_ERROR(p, a, b) + OpCase(fclearerror): { BeamInstr *next; @@ -4763,10 +4768,6 @@ void process_main(void) ERTS_FP_ERROR(c_p, freg[0].fd, goto fbadarith); NextPF(0, next); } -# undef ERTS_FP_CHECK_INIT -# undef ERTS_FP_ERROR -# define ERTS_FP_CHECK_INIT(p) -# define ERTS_FP_ERROR(p, a, b) #endif @@ -4774,45 +4775,45 @@ void process_main(void) BeamInstr *next; PreFetch(3, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(2)) = fb(Arg(0)) + fb(Arg(1)); - ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith); NextPF(3, next); } OpCase(i_fsub_lll): { BeamInstr *next; PreFetch(3, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(2)) = fb(Arg(0)) - fb(Arg(1)); - ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith); NextPF(3, next); } OpCase(i_fmul_lll): { BeamInstr *next; PreFetch(3, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(2)) = fb(Arg(0)) * fb(Arg(1)); - ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith); NextPF(3, next); } OpCase(i_fdiv_lll): { BeamInstr *next; PreFetch(3, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(2)) = fb(Arg(0)) / fb(Arg(1)); - ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith); NextPF(3, next); } OpCase(i_fnegate_ll): { BeamInstr *next; PreFetch(2, next); - ERTS_FP_CHECK_INIT(c_p); + ERTS_NO_FPE_CHECK_INIT(c_p); fb(Arg(1)) = -fb(Arg(0)); - ERTS_FP_ERROR(c_p, fb(Arg(1)), goto fbadarith); + ERTS_NO_FPE_ERROR(c_p, fb(Arg(1)), goto fbadarith); NextPF(2, next); fbadarith: -- cgit v1.2.3 From 30f85a8d2f81665626e5a94d10ff9b0ea507caac Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 7 Nov 2011 16:39:41 +0100 Subject: hipe: Fix bug in hipe_rtl_lcm:calc_killed_expr_bb Bug causing hipe to crash. Only provoked when changing the RTL generation for floating point operations. hipe_rtl:defines() was called with a expression ID instead of an expression. Use expr_id_map_get_expr() to get expression from ID. Need to pass along IdMap in order to do that. --- lib/hipe/rtl/hipe_rtl_lcm.erl | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/hipe/rtl/hipe_rtl_lcm.erl b/lib/hipe/rtl/hipe_rtl_lcm.erl index 9224623c8b..262aedb409 100644 --- a/lib/hipe/rtl/hipe_rtl_lcm.erl +++ b/lib/hipe/rtl/hipe_rtl_lcm.erl @@ -486,7 +486,7 @@ lcm_precalc(CFG, Options) -> ?option_time(NodeInfo2 = calc_down_exp(CFG, ExprMap, NodeInfo1, Labels), "RTL LCM calc_down_exp", Options), ?option_time(NodeInfo3 = calc_killed_expr(CFG, NodeInfo2, UseMap, AllExpr, - Labels), + IdMap, Labels), "RTL LCM calc_killed_exp", Options), ?option_time(NodeInfo4 = calc_avail(CFG, NodeInfo3), "RTL LCM calc_avail", Options), @@ -815,19 +815,19 @@ exp_kill_expr(Instr, [CheckedExpr|Exprs]) -> %%============================================================================= %% Calculates the killed expression sets for all given labels. -calc_killed_expr(_, NodeInfo, _, _, []) -> +calc_killed_expr(_, NodeInfo, _, _, _, []) -> NodeInfo; -calc_killed_expr(CFG, NodeInfo, UseMap, AllExpr, [Label|Labels]) -> +calc_killed_expr(CFG, NodeInfo, UseMap, AllExpr, IdMap, [Label|Labels]) -> Code = hipe_bb:code(hipe_rtl_cfg:bb(CFG, Label)), - KilledExprs = calc_killed_expr_bb(Code, UseMap, AllExpr, ?SETS:new()), + KilledExprs = calc_killed_expr_bb(Code, UseMap, AllExpr, IdMap, ?SETS:new()), NewNodeInfo = set_killed_expr(NodeInfo, Label, KilledExprs), - calc_killed_expr(CFG, NewNodeInfo, UseMap, AllExpr, Labels). + calc_killed_expr(CFG, NewNodeInfo, UseMap, AllExpr, IdMap, Labels). %%============================================================================= %% Calculates the killed expressions set for one basic block. -calc_killed_expr_bb([], _UseMap, _AllExpr, KilledExprs) -> +calc_killed_expr_bb([], _UseMap, _AllExpr, _IdMap, KilledExprs) -> KilledExprs; -calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, KilledExprs) -> +calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, IdMap, KilledExprs) -> %% Calls, gctests and stores potentially clobber everything case Instr of #call{} -> AllExpr; @@ -837,7 +837,8 @@ calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, KilledExprs) -> %% Kill all float expressions %% FIXME: Make separate function is_fp_expr ?SETS:from_list - (lists:foldl(fun(Expr, Fexprs) -> + (lists:foldl(fun(ExprId, Fexprs) -> + Expr = expr_id_map_get_expr(IdMap, ExprId), [Define|_] = hipe_rtl:defines(Expr), case hipe_rtl:is_fpreg(Define) of true -> @@ -849,10 +850,10 @@ calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, KilledExprs) -> _ -> case hipe_rtl:defines(Instr) of [] -> - calc_killed_expr_bb(Instrs, UseMap, AllExpr, KilledExprs); + calc_killed_expr_bb(Instrs, UseMap, AllExpr, IdMap, KilledExprs); [Define|_] -> NewKilledExprs = use_map_get_expr_uses(UseMap, Define), - calc_killed_expr_bb(Instrs, UseMap, AllExpr, + calc_killed_expr_bb(Instrs, UseMap, AllExpr, IdMap, ?SETS:union(NewKilledExprs, KilledExprs)) end end. -- cgit v1.2.3 From c0b6c30a98c154a1ea190dd930b53dc4f155e67b Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 15 Nov 2011 12:27:29 +0100 Subject: hipe,erts: Allow hipe without floating point exceptions --- erts/configure.in | 2 -- erts/emulator/beam/erl_process.c | 4 ++-- erts/emulator/beam/erl_process.h | 2 +- erts/emulator/hipe/hipe_amd64_bifs.m4 | 2 ++ erts/emulator/hipe/hipe_amd64_primops.h | 2 ++ erts/emulator/hipe/hipe_bif0.c | 20 ++++++++++++++++++++ erts/emulator/hipe/hipe_bif0.tab | 2 ++ erts/emulator/hipe/hipe_bif_list.m4 | 4 ++++ erts/emulator/hipe/hipe_mkliterals.c | 16 +++++++++++++++- erts/emulator/hipe/hipe_native_bif.c | 2 ++ erts/emulator/hipe/hipe_native_bif.h | 5 +++++ erts/emulator/hipe/hipe_primops.h | 4 ++++ erts/emulator/hipe/hipe_process.h | 3 +++ erts/emulator/hipe/hipe_x86.h | 2 ++ erts/emulator/hipe/hipe_x86_bifs.m4 | 2 ++ erts/emulator/hipe/hipe_x86_primops.h | 3 +++ lib/hipe/rtl/hipe_rtl.erl | 5 ++++- lib/hipe/rtl/hipe_rtl_arch.erl | 27 ++++++++++++++++++++++++++- 18 files changed, 99 insertions(+), 8 deletions(-) diff --git a/erts/configure.in b/erts/configure.in index fafa1c7e92..e44e38e7cc 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -3063,8 +3063,6 @@ dnl done up where floating point is checked, need to descide there already... if test X${enable_hipe} = Xyes; then if test X$ac_cv_sizeof_void_p != X4 -a X$ARCH != Xamd64 -a X$ARCH != Xppc64; then AC_MSG_WARN([HiPE is not supported in 64-bit builds]) - elif test X$FPE != Xreliable -a X$ARCH != Xarm; then - AC_MSG_WARN([HiPE is not supported on $ARCH without reliable floating-point exceptions]) else HIPE_ENABLED=yes AC_DEFINE(HIPE,[1],[Define to enable HiPE]) diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index a3c1c9577b..cd80eb849e 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -7136,7 +7136,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->pending_exit.bp = NULL; #endif -#if !defined(NO_FPE_SIGNALS) +#if !defined(NO_FPE_SIGNALS) || defined(HIPE) p->fp_exception = 0; #endif @@ -7310,7 +7310,7 @@ void erts_init_empty_process(Process *p) p->run_queue = ERTS_RUNQ_IX(0); #endif -#if !defined(NO_FPE_SIGNALS) +#if !defined(NO_FPE_SIGNALS) || defined(HIPE) p->fp_exception = 0; #endif diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 4027fade35..6ec1720b94 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -617,7 +617,7 @@ struct process { Uint min_heap_size; /* Minimum size of heap (in words). */ Uint min_vheap_size; /* Minimum size of virtual heap (in words). */ -#if !defined(NO_FPE_SIGNALS) +#if !defined(NO_FPE_SIGNALS) || defined(HIPE) volatile unsigned long fp_exception; #endif diff --git a/erts/emulator/hipe/hipe_amd64_bifs.m4 b/erts/emulator/hipe/hipe_amd64_bifs.m4 index 97a8267647..ec25c0b9b7 100644 --- a/erts/emulator/hipe/hipe_amd64_bifs.m4 +++ b/erts/emulator/hipe/hipe_amd64_bifs.m4 @@ -549,7 +549,9 @@ ASYM($1): /* * AMD64-specific primops. */ +#ifndef NO_FPE_SIGNALS noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu) +#endif /* NO_FPE_SIGNALS */ /* * Implement gc_bif_interface_0 as nofail_primop_interface_0. diff --git a/erts/emulator/hipe/hipe_amd64_primops.h b/erts/emulator/hipe/hipe_amd64_primops.h index e3c7111997..55cb0eadb8 100644 --- a/erts/emulator/hipe/hipe_amd64_primops.h +++ b/erts/emulator/hipe/hipe_amd64_primops.h @@ -19,5 +19,7 @@ PRIMOP_LIST(am_inc_stack_0, &nbif_inc_stack_0) +#ifndef NO_FPE_SIGNALS PRIMOP_LIST(am_handle_fp_exception, &nbif_handle_fp_exception) +#endif PRIMOP_LIST(am_sse2_fnegate_mask, &sse2_fnegate_mask) diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c index e7fb850530..cec22b3836 100644 --- a/erts/emulator/hipe/hipe_bif0.c +++ b/erts/emulator/hipe/hipe_bif0.c @@ -985,6 +985,26 @@ BIF_RETTYPE hipe_conv_big_to_float(BIF_ALIST_1) BIF_RET(res); } +#ifdef NO_FPE_SIGNALS + +/* + This is the current solution to make hipe run without FPE. + The native code is the same except that a call to this primop + is made after _every_ float operation to check the result. + The native fcheckerror still done later will detect if an + "emulated" FPE has occured. + We use p->hipe.float_result to avoid passing a 'double' argument, + which has its own calling convention (on amd64 at least). + Simple and slow... +*/ +void hipe_emulate_fpe(Process* p) +{ + if (!finite(p->hipe.float_result)) { + p->fp_exception = 1; + } +} +#endif + #if 0 /* XXX: unused */ /* * At least parts of this should be inlined in native code. diff --git a/erts/emulator/hipe/hipe_bif0.tab b/erts/emulator/hipe/hipe_bif0.tab index b6c6bede23..ce641365e9 100644 --- a/erts/emulator/hipe/hipe_bif0.tab +++ b/erts/emulator/hipe/hipe_bif0.tab @@ -140,3 +140,5 @@ atom bs_put_utf16le atom bs_get_utf16 atom bs_validate_unicode atom bs_validate_unicode_retract +atom emulate_fpe + diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4 index 48c7c1bc9b..942fa0c5cb 100644 --- a/erts/emulator/hipe/hipe_bif_list.m4 +++ b/erts/emulator/hipe/hipe_bif_list.m4 @@ -245,6 +245,10 @@ noproc_primop_interface_5(nbif_bs_put_big_integer, hipe_bs_put_big_integer) gc_bif_interface_0(nbif_check_get_msg, hipe_check_get_msg) +#ifdef NO_FPE_SIGNALS +nocons_nofail_primop_interface_0(nbif_emulate_fpe, hipe_emulate_fpe) +#endif + /* * SMP-specific stuff */ diff --git a/erts/emulator/hipe/hipe_mkliterals.c b/erts/emulator/hipe/hipe_mkliterals.c index 61e15f1d58..d07d14028c 100644 --- a/erts/emulator/hipe/hipe_mkliterals.c +++ b/erts/emulator/hipe/hipe_mkliterals.c @@ -293,6 +293,11 @@ static const struct literal { { "P_NRA", offsetof(struct process, hipe.nra) }, #endif { "P_NARITY", offsetof(struct process, hipe.narity) }, + { "P_FLOAT_RESULT", +# ifdef NO_FPE_SIGNALS + offsetof(struct process, hipe.float_result) +# endif + }, # if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP) { "P_BIF_CALLEE", offsetof(struct process, hipe.bif_callee) }, # endif @@ -491,7 +496,7 @@ static const struct rts_param { #endif }, { 14, "P_FP_EXCEPTION", -#if !defined(NO_FPE_SIGNALS) +#if !defined(NO_FPE_SIGNALS) || defined(HIPE) 1, offsetof(struct process, fp_exception) #endif }, @@ -502,6 +507,15 @@ static const struct rts_param { 1 #else 0 +#endif + }, + /* This flag is always defined, but its value is configuration-dependent. */ + { 16, "ERTS_NO_FPE_SIGNALS", + 1, +#if defined(NO_FPE_SIGNALS) + 1 +#else + 0 #endif }, /* This parameter is always defined, but its value depends on ERTS_SMP. */ diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c index 77dee6f9e9..3be821f8f7 100644 --- a/erts/emulator/hipe/hipe_native_bif.c +++ b/erts/emulator/hipe/hipe_native_bif.c @@ -189,6 +189,8 @@ void hipe_fclearerror_error(Process *p) { #if !defined(NO_FPE_SIGNALS) erts_fp_check_init_error(&p->fp_exception); +#else + erl_exit(ERTS_ABORT_EXIT, "Emulated FPE not cleared by HiPE"); #endif } diff --git a/erts/emulator/hipe/hipe_native_bif.h b/erts/emulator/hipe/hipe_native_bif.h index 8c9dec180e..9e3a156fbc 100644 --- a/erts/emulator/hipe/hipe_native_bif.h +++ b/erts/emulator/hipe/hipe_native_bif.h @@ -93,6 +93,11 @@ BIF_RETTYPE hipe_bs_validate_unicode(BIF_ALIST_1); struct erl_bin_match_buffer; int hipe_bs_validate_unicode_retract(struct erl_bin_match_buffer*, Eterm); +#ifdef NO_FPE_SIGNALS +AEXTERN(void,nbif_emulate_fpe,(Process*)); +void hipe_emulate_fpe(Process*); +#endif + /* * Stuff that is different in SMP and non-SMP. */ diff --git a/erts/emulator/hipe/hipe_primops.h b/erts/emulator/hipe/hipe_primops.h index 94113ffcd8..38509c105b 100644 --- a/erts/emulator/hipe/hipe_primops.h +++ b/erts/emulator/hipe/hipe_primops.h @@ -77,6 +77,10 @@ PRIMOP_LIST(am_nonclosure_address, &nbif_nonclosure_address) PRIMOP_LIST(am_conv_big_to_float, &nbif_conv_big_to_float) PRIMOP_LIST(am_fclearerror_error, &nbif_fclearerror_error) +#ifdef NO_FPE_SIGNALS +PRIMOP_LIST(am_emulate_fpe, &nbif_emulate_fpe) +#endif + #if defined(__sparc__) #include "hipe_sparc_primops.h" #endif diff --git a/erts/emulator/hipe/hipe_process.h b/erts/emulator/hipe/hipe_process.h index 43f47d1a28..4ee99d78a2 100644 --- a/erts/emulator/hipe/hipe_process.h +++ b/erts/emulator/hipe/hipe_process.h @@ -42,6 +42,9 @@ struct hipe_process_state { void (*nra)(void); /* Native code return address. */ #endif unsigned int narity; /* Arity of BIF call, for stack walks. */ +#ifdef NO_FPE_SIGNALS + double float_result; /* to be checked for inf/NaN by hipe_emulate_fpe */ +#endif #if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP) void (*bif_callee)(void); /* When calling BIF's via debug wrapper */ #endif diff --git a/erts/emulator/hipe/hipe_x86.h b/erts/emulator/hipe/hipe_x86.h index f0f3c158af..97f09e38cd 100644 --- a/erts/emulator/hipe/hipe_x86.h +++ b/erts/emulator/hipe/hipe_x86.h @@ -49,7 +49,9 @@ static __inline__ int hipe_word32_address_ok(void *address) #define hipe_arch_name am_x86 extern void nbif_inc_stack_0(void); +#ifndef NO_FPE_SIGNALS extern void nbif_handle_fp_exception(void); +#endif /* for hipe_bifs_enter_code_2 */ extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p); diff --git a/erts/emulator/hipe/hipe_x86_bifs.m4 b/erts/emulator/hipe/hipe_x86_bifs.m4 index 2ea69bde3c..3cb7d67be0 100644 --- a/erts/emulator/hipe/hipe_x86_bifs.m4 +++ b/erts/emulator/hipe/hipe_x86_bifs.m4 @@ -621,7 +621,9 @@ ASYM($1): /* * x86-specific primops. */ +#ifndef NO_FPE_SIGNALS noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu) +#endif /* NO_FPE_SIGNALS */ /* * Implement gc_bif_interface_0 as nofail_primop_interface_0. diff --git a/erts/emulator/hipe/hipe_x86_primops.h b/erts/emulator/hipe/hipe_x86_primops.h index 96d2336bc5..111b1fa8bd 100644 --- a/erts/emulator/hipe/hipe_x86_primops.h +++ b/erts/emulator/hipe/hipe_x86_primops.h @@ -19,4 +19,7 @@ PRIMOP_LIST(am_inc_stack_0, &nbif_inc_stack_0) +#ifndef NO_FPE_SIGNALS PRIMOP_LIST(am_handle_fp_exception, &nbif_handle_fp_exception) +#endif + diff --git a/lib/hipe/rtl/hipe_rtl.erl b/lib/hipe/rtl/hipe_rtl.erl index 29e9c8c8fe..4bf4eb6bd7 100644 --- a/lib/hipe/rtl/hipe_rtl.erl +++ b/lib/hipe/rtl/hipe_rtl.erl @@ -781,8 +781,11 @@ fstore_src_update(F, NewSrc) -> F#fstore{src=NewSrc}. %% fp %% + mk_fp(Dst, Src1, Op, Src2) -> - #fp{dst=Dst, src1=Src1, op=Op, src2=Src2}. + [#fp{dst=Dst, src1=Src1, op=Op, src2=Src2} + | hipe_rtl_arch:mk_fp_check_result(Dst)]. + fp_dst(#fp{dst=Dst}) -> Dst. fp_dst_update(Fp, NewDst) -> Fp#fp{dst=NewDst}. fp_src1(#fp{src1=Src1}) -> Src1. diff --git a/lib/hipe/rtl/hipe_rtl_arch.erl b/lib/hipe/rtl/hipe_rtl_arch.erl index 22cda57a3a..99eb80f3d1 100644 --- a/lib/hipe/rtl/hipe_rtl_arch.erl +++ b/lib/hipe/rtl/hipe_rtl_arch.erl @@ -65,7 +65,8 @@ %% alignment/0, nr_of_return_regs/0, log2_word_size/0, - word_size/0 + word_size/0, + mk_fp_check_result/1 ]). -include("hipe_literals.hrl"). @@ -558,6 +559,12 @@ eval_cond_bits(Cond, N, Z, V, C) -> %%---------------------------------------------------------------------- fwait() -> + case ?ERTS_NO_FPE_SIGNALS of + 1 -> []; + 0 -> fwait_real() + end. + +fwait_real() -> case get(hipe_target_arch) of x86 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)]; amd64 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)]; @@ -573,6 +580,12 @@ fwait() -> %% Returns RTL code to restore the FPU after a floating-point exception. %% @end handle_fp_exception() -> + case ?ERTS_NO_FPE_SIGNALS of + 1 -> []; + 0 -> handle_real_fp_exception() + end. + +handle_real_fp_exception() -> case get(hipe_target_arch) of x86 -> ContLbl = hipe_rtl:mk_new_label(), @@ -655,3 +668,15 @@ nr_of_return_regs() -> 1 %% hipe_amd64_registers:nr_rets(); end. + + +mk_fp_check_result(Result) -> + case ?ERTS_NO_FPE_SIGNALS of + 0 -> + []; + 1 -> + [hipe_rtl:mk_fstore(proc_pointer(), + hipe_rtl:mk_imm(?P_FLOAT_RESULT), + Result), + hipe_rtl:mk_call([], emulate_fpe, [], [], [], not_remote)] + end. -- cgit v1.2.3 From 1870ee5b2532f3b1c4a30eaf9658875326d8dc9f Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 15 Nov 2011 12:29:11 +0100 Subject: erts: Add test for inf/NaN intermediate float results Make sure that badarith is thrown even if end result is not inf/NaN --- erts/emulator/test/float_SUITE.erl | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl index 46466427c5..8e6923ce9f 100644 --- a/erts/emulator/test/float_SUITE.erl +++ b/erts/emulator/test/float_SUITE.erl @@ -27,6 +27,7 @@ fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1, bad_float_unpack/1,cmp_zero/1, cmp_integer/1, cmp_bignum/1]). -export([otp_7178/1]). +-export([hidden_inf/1]). init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> @@ -41,7 +42,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [fpe, fp_drv, fp_drv_thread, otp_7178, denormalized, - match, bad_float_unpack, {group, comparison}]. + match, bad_float_unpack, {group, comparison} + ,hidden_inf + ]. groups() -> [{comparison, [parallel], [cmp_zero, cmp_integer, cmp_bignum]}]. @@ -300,3 +303,25 @@ start_node(Config) when is_list(Config) -> stop_node(Node) -> ?t:stop_node(Node). + + +%% Test that operations that might hide infinite intermediate results +%% do not supress the badarith. +hidden_inf(Config) when is_list(Config) -> + ZeroP = 0.0, + ZeroN = id(ZeroP) * (-1), + [hidden_inf_1(A, B, Z, 9.23e307) + || A <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN], + B <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN], + Z <- [ZeroP, ZeroN]], + ok. + +hidden_inf_1(A, B, Zero, Huge) -> + {'EXIT',{badarith,_}} = (catch (B / (A / Zero))), + {'EXIT',{badarith,_}} = (catch (B * (A / Zero))), + {'EXIT',{badarith,_}} = (catch (B / (Huge * Huge))), + {'EXIT',{badarith,_}} = (catch (B * (Huge * Huge))), + {'EXIT',{badarith,_}} = (catch (B / (Huge + Huge))), + {'EXIT',{badarith,_}} = (catch (B * (Huge + Huge))), + {'EXIT',{badarith,_}} = (catch (B / (-Huge - Huge))), + {'EXIT',{badarith,_}} = (catch (B * (-Huge - Huge))). -- cgit v1.2.3 From 11892310e0a681aff0ce1fb8f5411b2098f5c9ba Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 11 Nov 2011 18:28:22 +0100 Subject: stdlib: Make sure qlc_SUITE:otp_6964 restores backtrace_depth --- lib/stdlib/test/qlc_SUITE.erl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl index 8a9d8f7883..9be547c690 100644 --- a/lib/stdlib/test/qlc_SUITE.erl +++ b/lib/stdlib/test/qlc_SUITE.erl @@ -6118,6 +6118,7 @@ otp_6964(Config) when is_list(Config) -> qlc:e(Q, [{max_list_size,64*1024},{tmpdir_usage,Use}]) end, D = erlang:system_flag(backtrace_depth, 0), + try 20000 = length(F(allowed)), ErrReply = F(not_allowed), {error, qlc, {tmpdir_usage,joining}} = ErrReply, @@ -6129,8 +6130,10 @@ otp_6964(Config) when is_list(Config) -> 20000 = length(F(info_msg)), {info, joining} = qlc_SUITE:read_error_logger(), 20000 = length(F(error_msg)), - {error, joining} = qlc_SUITE:read_error_logger(), - _ = erlang:system_flag(backtrace_depth, D), + {error, joining} = qlc_SUITE:read_error_logger() + after + _ = erlang:system_flag(backtrace_depth, D) + end, qlc_SUITE:uninstall_error_logger()">>], ?line run(Config, T1), -- cgit v1.2.3 From 327c072661840f671fc0041bc5e88bc69691d5aa Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 17 Nov 2011 14:13:42 +0100 Subject: otp_build: Disable FPE by default on Linux FPE = floating point exceptions --- otp_build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/otp_build b/otp_build index 44bbab22b5..ac5f523303 100755 --- a/otp_build +++ b/otp_build @@ -174,9 +174,9 @@ set_config_flags () # the cross configuration have been moved here). if target_contains linux; then - XX=`echo $* | grep -v able-hipe` + XX=`echo $* | grep -v able-fp-exceptions` if [ "$*" = "$XX" ]; then - CONFIG_FLAGS="$CONFIG_FLAGS --disable-hipe" + CONFIG_FLAGS="$CONFIG_FLAGS --disable-fp-exceptions" fi fi if target_contains "univel-sysv4"; then -- cgit v1.2.3