Message ID | 87k222frr1.fsf@linaro.org |
---|---|
State | New |
Headers | show |
On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford <richard.sandiford@linaro.org> wrote: > Internal functions that map directly to an optab can only throw an > exception for -fnon-call-exceptions. This patch handles that in > internal_fn_flags, in a similar way to ATTR_*NOTHROW in builtins.def. > > (Functions that don't throw even for flag_non_call_exceptions should be > explicitly marked ECF_NOTHROW in internal-fn.def.) > > Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? Hmm. Note the outcome of flag_non_call_exceptions depends on the current function and thus IPA passes querying flags would need to push an appropriate function context. This means the function should get a struct function * argument and opt_for_fn (fn, flag_non_call_exceptions) should be used. It doesn't help very much that all callers don't have any such context either which means this "optimization" looks like in the wrong place :/ (the global value of flag_non_call_exceptions in the IPA case isn't necessarily conservative). So if you insist then add a comment and add a && cfun check so we're sure we are in non-IPA context (or in properly setup context). Richard. > Richard > > > 2017-08-17 Richard Sandiford <richard.sandiford@linaro.org> > > gcc/ > * internal-fn.h (internal_fn_flags): Just declare and move > the actual implementation out-of-line to... > * internal-fn.c (internal_fn_flags): ...here. Set ECF_NOTHROW for > directly-mapped internal functions if !flag_non_call_exceptions. > > Index: gcc/internal-fn.h > =================================================================== > --- gcc/internal-fn.h 2017-02-23 19:54:03.000000000 +0000 > +++ gcc/internal-fn.h 2017-08-17 09:05:37.459968561 +0100 > @@ -107,15 +107,7 @@ internal_fn_name (enum internal_fn fn) > return internal_fn_name_array[(int) fn]; > } > > -/* Return the ECF_* flags for function FN. */ > - > -extern const int internal_fn_flags_array[]; > - > -static inline int > -internal_fn_flags (enum internal_fn fn) > -{ > - return internal_fn_flags_array[(int) fn]; > -} > +extern int internal_fn_flags (enum internal_fn fn); > > /* Return fnspec for function FN. */ > > Index: gcc/internal-fn.c > =================================================================== > --- gcc/internal-fn.c 2017-08-10 14:36:07.453493083 +0100 > +++ gcc/internal-fn.c 2017-08-17 09:05:37.459968561 +0100 > @@ -2814,3 +2814,18 @@ expand_PHI (internal_fn, gcall *) > { > gcc_unreachable (); > } > + > +/* Return the ECF_* flags for function FN. */ > + > +int > +internal_fn_flags (enum internal_fn fn) > +{ > + int flags = internal_fn_flags_array[(int) fn]; > + /* Functions that map to optabs can only throw a catchable exception > + when non-call exceptions are enabled. The non-call exceptions in > + these cases will typically come from things like IEEE exceptions, > + divide by zero errors and SEGVs. */ > + if (direct_internal_fn_p (fn) && !flag_non_call_exceptions) > + flags |= ECF_NOTHROW; > + return flags; > +}
Richard Biener <richard.guenther@gmail.com> writes: > On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford > <richard.sandiford@linaro.org> wrote: >> Internal functions that map directly to an optab can only throw an >> exception for -fnon-call-exceptions. This patch handles that in >> internal_fn_flags, in a similar way to ATTR_*NOTHROW in builtins.def. >> >> (Functions that don't throw even for flag_non_call_exceptions should be >> explicitly marked ECF_NOTHROW in internal-fn.def.) >> >> Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? > > Hmm. Note the outcome of flag_non_call_exceptions depends on the > current function and thus IPA passes querying flags would need to > push an appropriate function context. This means the function should > get a struct function * argument and opt_for_fn (fn, flag_non_call_exceptions) > should be used. It doesn't help very much that all callers don't have > any such context either which means this "optimization" looks like > in the wrong place :/ (the global value of flag_non_call_exceptions in > the IPA case isn't necessarily conservative). > > So if you insist then add a comment and add a && cfun check so > we're sure we are in non-IPA context (or in properly setup context). Bah. In that case, what should happen if a -fno-non-call-exceptions function is inlined into an -fnon-call-exceptions one? Should the call keep the NOTHROWness of the original function, or should it lose NOTHROWness (and thus gain an exception edge)? I guess the path of least resistance would be to add an extra check for this case in the places that need it, rather than relying solely on gimple_call_flags. Thanks, Richard > > Richard. > >> Richard >> >> >> 2017-08-17 Richard Sandiford <richard.sandiford@linaro.org> >> >> gcc/ >> * internal-fn.h (internal_fn_flags): Just declare and move >> the actual implementation out-of-line to... >> * internal-fn.c (internal_fn_flags): ...here. Set ECF_NOTHROW for >> directly-mapped internal functions if !flag_non_call_exceptions. >> >> Index: gcc/internal-fn.h >> =================================================================== >> --- gcc/internal-fn.h 2017-02-23 19:54:03.000000000 +0000 >> +++ gcc/internal-fn.h 2017-08-17 09:05:37.459968561 +0100 >> @@ -107,15 +107,7 @@ internal_fn_name (enum internal_fn fn) >> return internal_fn_name_array[(int) fn]; >> } >> >> -/* Return the ECF_* flags for function FN. */ >> - >> -extern const int internal_fn_flags_array[]; >> - >> -static inline int >> -internal_fn_flags (enum internal_fn fn) >> -{ >> - return internal_fn_flags_array[(int) fn]; >> -} >> +extern int internal_fn_flags (enum internal_fn fn); >> >> /* Return fnspec for function FN. */ >> >> Index: gcc/internal-fn.c >> =================================================================== >> --- gcc/internal-fn.c 2017-08-10 14:36:07.453493083 +0100 >> +++ gcc/internal-fn.c 2017-08-17 09:05:37.459968561 +0100 >> @@ -2814,3 +2814,18 @@ expand_PHI (internal_fn, gcall *) >> { >> gcc_unreachable (); >> } >> + >> +/* Return the ECF_* flags for function FN. */ >> + >> +int >> +internal_fn_flags (enum internal_fn fn) >> +{ >> + int flags = internal_fn_flags_array[(int) fn]; >> + /* Functions that map to optabs can only throw a catchable exception >> + when non-call exceptions are enabled. The non-call exceptions in >> + these cases will typically come from things like IEEE exceptions, >> + divide by zero errors and SEGVs. */ >> + if (direct_internal_fn_p (fn) && !flag_non_call_exceptions) >> + flags |= ECF_NOTHROW; >> + return flags; >> +}
On Thu, Aug 17, 2017 at 1:06 PM, Richard Sandiford <richard.sandiford@linaro.org> wrote > Richard Biener <richard.guenther@gmail.com> writes: >> On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford >> <richard.sandiford@linaro.org> wrote: >>> Internal functions that map directly to an optab can only throw an >>> exception for -fnon-call-exceptions. This patch handles that in >>> internal_fn_flags, in a similar way to ATTR_*NOTHROW in builtins.def. >>> >>> (Functions that don't throw even for flag_non_call_exceptions should be >>> explicitly marked ECF_NOTHROW in internal-fn.def.) >>> >>> Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? >> >> Hmm. Note the outcome of flag_non_call_exceptions depends on the >> current function and thus IPA passes querying flags would need to >> push an appropriate function context. This means the function should >> get a struct function * argument and opt_for_fn (fn, flag_non_call_exceptions) >> should be used. It doesn't help very much that all callers don't have >> any such context either which means this "optimization" looks like >> in the wrong place :/ (the global value of flag_non_call_exceptions in >> the IPA case isn't necessarily conservative). >> >> So if you insist then add a comment and add a && cfun check so >> we're sure we are in non-IPA context (or in properly setup context). > > Bah. In that case, what should happen if a -fno-non-call-exceptions > function is inlined into an -fnon-call-exceptions one? Should the call > keep the NOTHROWness of the original function, or should it lose > NOTHROWness (and thus gain an exception edge)? nothrow-ness is tracked on the GIMPLE stmt via gimple_call_[set_]nothrow_p, GIMPLE shouldn't look at flag_non_call_exceptions, it is basically part of the IL. > I guess the path of least resistance would be to add an extra check > for this case in the places that need it, rather than relying solely > on gimple_call_flags. Well, gimple_call_flags works fine already (looking at the above in addition to internal_fn_flags). call_expr_flags looks like it might not. Richard. > > Thanks, > Richard > > >> >> Richard. >> >>> Richard >>> >>> >>> 2017-08-17 Richard Sandiford <richard.sandiford@linaro.org> >>> >>> gcc/ >>> * internal-fn.h (internal_fn_flags): Just declare and move >>> the actual implementation out-of-line to... >>> * internal-fn.c (internal_fn_flags): ...here. Set ECF_NOTHROW for >>> directly-mapped internal functions if !flag_non_call_exceptions. >>> >>> Index: gcc/internal-fn.h >>> =================================================================== >>> --- gcc/internal-fn.h 2017-02-23 19:54:03.000000000 +0000 >>> +++ gcc/internal-fn.h 2017-08-17 09:05:37.459968561 +0100 >>> @@ -107,15 +107,7 @@ internal_fn_name (enum internal_fn fn) >>> return internal_fn_name_array[(int) fn]; >>> } >>> >>> -/* Return the ECF_* flags for function FN. */ >>> - >>> -extern const int internal_fn_flags_array[]; >>> - >>> -static inline int >>> -internal_fn_flags (enum internal_fn fn) >>> -{ >>> - return internal_fn_flags_array[(int) fn]; >>> -} >>> +extern int internal_fn_flags (enum internal_fn fn); >>> >>> /* Return fnspec for function FN. */ >>> >>> Index: gcc/internal-fn.c >>> =================================================================== >>> --- gcc/internal-fn.c 2017-08-10 14:36:07.453493083 +0100 >>> +++ gcc/internal-fn.c 2017-08-17 09:05:37.459968561 +0100 >>> @@ -2814,3 +2814,18 @@ expand_PHI (internal_fn, gcall *) >>> { >>> gcc_unreachable (); >>> } >>> + >>> +/* Return the ECF_* flags for function FN. */ >>> + >>> +int >>> +internal_fn_flags (enum internal_fn fn) >>> +{ >>> + int flags = internal_fn_flags_array[(int) fn]; >>> + /* Functions that map to optabs can only throw a catchable exception >>> + when non-call exceptions are enabled. The non-call exceptions in >>> + these cases will typically come from things like IEEE exceptions, >>> + divide by zero errors and SEGVs. */ >>> + if (direct_internal_fn_p (fn) && !flag_non_call_exceptions) >>> + flags |= ECF_NOTHROW; >>> + return flags; >>> +}
Richard Biener <richard.guenther@gmail.com> writes: > On Thu, Aug 17, 2017 at 1:06 PM, Richard Sandiford > <richard.sandiford@linaro.org> wrote >> Richard Biener <richard.guenther@gmail.com> writes: >>> On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford >>> <richard.sandiford@linaro.org> wrote: >>>> Internal functions that map directly to an optab can only throw an >>>> exception for -fnon-call-exceptions. This patch handles that in >>>> internal_fn_flags, in a similar way to ATTR_*NOTHROW in builtins.def. >>>> >>>> (Functions that don't throw even for flag_non_call_exceptions should be >>>> explicitly marked ECF_NOTHROW in internal-fn.def.) >>>> >>>> Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? >>> >>> Hmm. Note the outcome of flag_non_call_exceptions depends on the >>> current function and thus IPA passes querying flags would need to >>> push an appropriate function context. This means the function should >>> get a struct function * argument and opt_for_fn (fn, >>> flag_non_call_exceptions) >>> should be used. It doesn't help very much that all callers don't have >>> any such context either which means this "optimization" looks like >>> in the wrong place :/ (the global value of flag_non_call_exceptions in >>> the IPA case isn't necessarily conservative). >>> >>> So if you insist then add a comment and add a && cfun check so >>> we're sure we are in non-IPA context (or in properly setup context). >> >> Bah. In that case, what should happen if a -fno-non-call-exceptions >> function is inlined into an -fnon-call-exceptions one? Should the call >> keep the NOTHROWness of the original function, or should it lose >> NOTHROWness (and thus gain an exception edge)? > > nothrow-ness is tracked on the GIMPLE stmt via gimple_call_[set_]nothrow_p, > GIMPLE shouldn't look at flag_non_call_exceptions, it is basically part > of the IL. > >> I guess the path of least resistance would be to add an extra check >> for this case in the places that need it, rather than relying solely >> on gimple_call_flags. > > Well, gimple_call_flags works fine already (looking at the above in > addition to internal_fn_flags). call_expr_flags looks like it might not. OK, how does this look? Only the gimple flags matter for the use case I've seen (which is covered by the SVE tests, but hard to test as-is). Tested on aarch64-linux-gnu and x86_64-linux-gnu. Thanks, Richard 2017-08-28 Richard Sandiford <richard.sandiford@linaro.org> gcc/ * gimplify.c (gimplify_call_expr): Copy the nothrow flag to calls to internal functions. (gimplify_modify_expr): Likewise. * tree-call-cdce.c (use_internal_fn): Likewise. * tree-ssa-math-opts.c (pass_cse_reciprocals::execute): Likewise. (convert_to_divmod): Set the nothrow flag. * tree-if-conv.c (predicate_mem_writes): Likewise. * tree-vect-stmts.c (vectorizable_mask_load_store): Likewise. (vectorizable_call): Likewise. (vectorizable_store): Likewise. (vectorizable_load): Likewise. * tree-vect-patterns.c (vect_recog_pow_pattern): Likewise. (vect_recog_mask_conversion_pattern): Likewise. Index: gcc/gimplify.c =================================================================== *** gcc/gimplify.c 2017-08-17 13:17:21.266412322 +0100 --- gcc/gimplify.c 2017-08-28 09:10:13.246297839 +0100 *************** gimplify_call_expr (tree *expr_p, gimple *** 3150,3156 **** if (EXPR_CILK_SPAWN (*expr_p)) gimplify_cilk_detach (pre_p); ! gimple *call = gimple_build_call_internal_vec (ifn, vargs); gimplify_seq_add_stmt (pre_p, call); return GS_ALL_DONE; } --- 3150,3157 ---- if (EXPR_CILK_SPAWN (*expr_p)) gimplify_cilk_detach (pre_p); ! gcall *call = gimple_build_call_internal_vec (ifn, vargs); ! gimple_call_set_nothrow (call, TREE_NOTHROW (*expr_p)); gimplify_seq_add_stmt (pre_p, call); return GS_ALL_DONE; } *************** gimplify_modify_expr (tree *expr_p, gimp *** 5636,5641 **** --- 5637,5643 ---- vargs.quick_push (CALL_EXPR_ARG (*from_p, i)); } call_stmt = gimple_build_call_internal_vec (ifn, vargs); + gimple_call_set_nothrow (call_stmt, TREE_NOTHROW (*from_p)); gimple_set_location (call_stmt, EXPR_LOCATION (*expr_p)); } else Index: gcc/tree-call-cdce.c =================================================================== *** gcc/tree-call-cdce.c 2017-06-30 12:50:38.243662675 +0100 --- gcc/tree-call-cdce.c 2017-08-28 09:10:13.246297839 +0100 *************** use_internal_fn (gcall *call) *** 1019,1024 **** --- 1019,1025 ---- args.safe_push (gimple_call_arg (call, i)); gcall *new_call = gimple_build_call_internal_vec (ifn, args); gimple_set_location (new_call, gimple_location (call)); + gimple_call_set_nothrow (new_call, gimple_call_nothrow_p (call)); /* Transfer the LHS to the new call. */ tree lhs = gimple_call_lhs (call); Index: gcc/tree-ssa-math-opts.c =================================================================== *** gcc/tree-ssa-math-opts.c 2017-08-24 08:46:02.098124751 +0100 --- gcc/tree-ssa-math-opts.c 2017-08-28 09:10:13.247297839 +0100 *************** pass_cse_reciprocals::execute (function *** 690,695 **** --- 690,697 ---- gimple_set_vdef (stmt2, gimple_vdef (call)); SSA_NAME_DEF_STMT (gimple_vdef (stmt2)) = stmt2; } + gimple_call_set_nothrow (stmt2, + gimple_call_nothrow_p (call)); gimple_set_vuse (stmt2, gimple_vuse (call)); gimple_stmt_iterator gsi2 = gsi_for_stmt (call); gsi_replace (&gsi2, stmt2, true); *************** convert_to_divmod (gassign *stmt) *** 4100,4105 **** --- 4102,4109 ---- tree res = make_temp_ssa_name (build_complex_type (TREE_TYPE (op1)), call_stmt, "divmod_tmp"); gimple_call_set_lhs (call_stmt, res); + /* We rejected throwing statements above. */ + gimple_call_set_nothrow (call_stmt, true); /* Insert the call before top_stmt. */ gimple_stmt_iterator top_stmt_gsi = gsi_for_stmt (top_stmt); Index: gcc/tree-if-conv.c =================================================================== *** gcc/tree-if-conv.c 2017-08-22 17:13:27.429500899 +0100 --- gcc/tree-if-conv.c 2017-08-28 09:10:13.246297839 +0100 *************** predicate_mem_writes (loop_p loop) *** 2219,2225 **** tree lhs = gimple_assign_lhs (stmt); tree rhs = gimple_assign_rhs1 (stmt); tree ref, addr, ptr, mask; ! gimple *new_stmt; gimple_seq stmts = NULL; int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs))); ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs; --- 2219,2225 ---- tree lhs = gimple_assign_lhs (stmt); tree rhs = gimple_assign_rhs1 (stmt); tree ref, addr, ptr, mask; ! gcall *new_stmt; gimple_seq stmts = NULL; int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs))); ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs; *************** predicate_mem_writes (loop_p loop) *** 2281,2286 **** --- 2281,2287 ---- gimple_set_vdef (new_stmt, gimple_vdef (stmt)); SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; } + gimple_call_set_nothrow (new_stmt, true); gsi_replace (&gsi, new_stmt, true); } Index: gcc/tree-vect-stmts.c =================================================================== *** gcc/tree-vect-stmts.c 2017-08-22 17:13:27.429500899 +0100 --- gcc/tree-vect-stmts.c 2017-08-28 09:10:13.248297839 +0100 *************** vectorizable_mask_load_store (gimple *st *** 2364,2372 **** misalign); tree ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), misalign ? least_bit_hwi (misalign) : align); ! new_stmt = gimple_build_call_internal (IFN_MASK_STORE, 4, dataref_ptr, ptr, vec_mask, vec_rhs); vect_finish_stmt_generation (stmt, new_stmt, gsi); if (i == 0) STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt; --- 2364,2374 ---- misalign); tree ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), misalign ? least_bit_hwi (misalign) : align); ! gcall *call = gimple_build_call_internal (IFN_MASK_STORE, 4, dataref_ptr, ptr, vec_mask, vec_rhs); + gimple_call_set_nothrow (call, true); + new_stmt = call; vect_finish_stmt_generation (stmt, new_stmt, gsi); if (i == 0) STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt; *************** vectorizable_mask_load_store (gimple *st *** 2414,2429 **** misalign); tree ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), misalign ? least_bit_hwi (misalign) : align); ! new_stmt = gimple_build_call_internal (IFN_MASK_LOAD, 3, dataref_ptr, ptr, vec_mask); ! gimple_call_set_lhs (new_stmt, make_ssa_name (vec_dest)); ! vect_finish_stmt_generation (stmt, new_stmt, gsi); if (i == 0) ! STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt; else ! STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; ! prev_stmt_info = vinfo_for_stmt (new_stmt); } } --- 2416,2432 ---- misalign); tree ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), misalign ? least_bit_hwi (misalign) : align); ! gcall *call = gimple_build_call_internal (IFN_MASK_LOAD, 3, dataref_ptr, ptr, vec_mask); ! gimple_call_set_lhs (call, make_ssa_name (vec_dest)); ! gimple_call_set_nothrow (call, true); ! vect_finish_stmt_generation (stmt, call, gsi); if (i == 0) ! STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = call; else ! STMT_VINFO_RELATED_STMT (prev_stmt_info) = call; ! prev_stmt_info = vinfo_for_stmt (call); } } *************** vectorizable_call (gimple *gs, gimple_st *** 2867,2874 **** if (modifier == NARROW) { tree half_res = make_ssa_name (vectype_in); ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); ! gimple_call_set_lhs (new_stmt, half_res); vect_finish_stmt_generation (stmt, new_stmt, gsi); if ((i & 1) == 0) { --- 2870,2880 ---- if (modifier == NARROW) { tree half_res = make_ssa_name (vectype_in); ! gcall *call ! = gimple_build_call_internal_vec (ifn, vargs); ! gimple_call_set_lhs (call, half_res); ! gimple_call_set_nothrow (call, true); ! new_stmt = call; vect_finish_stmt_generation (stmt, new_stmt, gsi); if ((i & 1) == 0) { *************** vectorizable_call (gimple *gs, gimple_st *** 2881,2892 **** } else { if (ifn != IFN_LAST) ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); else ! new_stmt = gimple_build_call_vec (fndecl, vargs); ! new_temp = make_ssa_name (vec_dest, new_stmt); ! gimple_call_set_lhs (new_stmt, new_temp); } vect_finish_stmt_generation (stmt, new_stmt, gsi); SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt); --- 2887,2901 ---- } else { + gcall *call; if (ifn != IFN_LAST) ! call = gimple_build_call_internal_vec (ifn, vargs); else ! call = gimple_build_call_vec (fndecl, vargs); ! new_temp = make_ssa_name (vec_dest, call); ! gimple_call_set_lhs (call, new_temp); ! gimple_call_set_nothrow (call, true); ! new_stmt = call; } vect_finish_stmt_generation (stmt, new_stmt, gsi); SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt); *************** vectorizable_call (gimple *gs, gimple_st *** 2934,2941 **** else if (modifier == NARROW) { tree half_res = make_ssa_name (vectype_in); ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); ! gimple_call_set_lhs (new_stmt, half_res); vect_finish_stmt_generation (stmt, new_stmt, gsi); if ((j & 1) == 0) { --- 2943,2952 ---- else if (modifier == NARROW) { tree half_res = make_ssa_name (vectype_in); ! gcall *call = gimple_build_call_internal_vec (ifn, vargs); ! gimple_call_set_lhs (call, half_res); ! gimple_call_set_nothrow (call, true); ! new_stmt = call; vect_finish_stmt_generation (stmt, new_stmt, gsi); if ((j & 1) == 0) { *************** vectorizable_call (gimple *gs, gimple_st *** 2948,2959 **** } else { if (ifn != IFN_LAST) ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); else ! new_stmt = gimple_build_call_vec (fndecl, vargs); new_temp = make_ssa_name (vec_dest, new_stmt); ! gimple_call_set_lhs (new_stmt, new_temp); } vect_finish_stmt_generation (stmt, new_stmt, gsi); --- 2959,2973 ---- } else { + gcall *call; if (ifn != IFN_LAST) ! call = gimple_build_call_internal_vec (ifn, vargs); else ! call = gimple_build_call_vec (fndecl, vargs); new_temp = make_ssa_name (vec_dest, new_stmt); ! gimple_call_set_lhs (call, new_temp); ! gimple_call_set_nothrow (call, true); ! new_stmt = call; } vect_finish_stmt_generation (stmt, new_stmt, gsi); *************** vectorizable_call (gimple *gs, gimple_st *** 2996,3007 **** vargs.quick_push (vec_oprndsk[i]); vargs.quick_push (vec_oprndsk[i + 1]); } if (ifn != IFN_LAST) ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); else ! new_stmt = gimple_build_call_vec (fndecl, vargs); ! new_temp = make_ssa_name (vec_dest, new_stmt); ! gimple_call_set_lhs (new_stmt, new_temp); vect_finish_stmt_generation (stmt, new_stmt, gsi); SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt); } --- 3010,3024 ---- vargs.quick_push (vec_oprndsk[i]); vargs.quick_push (vec_oprndsk[i + 1]); } + gcall *call; if (ifn != IFN_LAST) ! call = gimple_build_call_internal_vec (ifn, vargs); else ! call = gimple_build_call_vec (fndecl, vargs); ! new_temp = make_ssa_name (vec_dest, call); ! gimple_call_set_lhs (call, new_temp); ! gimple_call_set_nothrow (call, true); ! new_stmt = call; vect_finish_stmt_generation (stmt, new_stmt, gsi); SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt); } *************** vectorizable_store (gimple *stmt, gimple *** 6356,6363 **** /* Emit: MEM_REF[...all elements...] = STORE_LANES (VEC_ARRAY). */ data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type); ! new_stmt = gimple_build_call_internal (IFN_STORE_LANES, 1, vec_array); ! gimple_call_set_lhs (new_stmt, data_ref); vect_finish_stmt_generation (stmt, new_stmt, gsi); } else --- 6373,6383 ---- /* Emit: MEM_REF[...all elements...] = STORE_LANES (VEC_ARRAY). */ data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type); ! gcall *call = gimple_build_call_internal (IFN_STORE_LANES, 1, ! vec_array); ! gimple_call_set_lhs (call, data_ref); ! gimple_call_set_nothrow (call, true); ! new_stmt = call; vect_finish_stmt_generation (stmt, new_stmt, gsi); } else *************** vectorizable_load (gimple *stmt, gimple_ *** 7448,7455 **** /* Emit: VEC_ARRAY = LOAD_LANES (MEM_REF[...all elements...]). */ data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type); ! new_stmt = gimple_build_call_internal (IFN_LOAD_LANES, 1, data_ref); ! gimple_call_set_lhs (new_stmt, vec_array); vect_finish_stmt_generation (stmt, new_stmt, gsi); /* Extract each vector into an SSA_NAME. */ --- 7468,7478 ---- /* Emit: VEC_ARRAY = LOAD_LANES (MEM_REF[...all elements...]). */ data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type); ! gcall *call = gimple_build_call_internal (IFN_LOAD_LANES, 1, ! data_ref); ! gimple_call_set_lhs (call, vec_array); ! gimple_call_set_nothrow (call, true); ! new_stmt = call; vect_finish_stmt_generation (stmt, new_stmt, gsi); /* Extract each vector into an SSA_NAME. */ Index: gcc/tree-vect-patterns.c =================================================================== *** gcc/tree-vect-patterns.c 2017-08-21 15:50:48.663709938 +0100 --- gcc/tree-vect-patterns.c 2017-08-28 09:10:13.247297839 +0100 *************** vect_recog_pow_pattern (vec<gimple *> *s *** 1085,1090 **** --- 1085,1091 ---- gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base); var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt); gimple_call_set_lhs (stmt, var); + gimple_call_set_nothrow (stmt, true); return stmt; } } *************** vect_recog_mask_conversion_pattern (vec< *** 3867,3873 **** stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); stmt_vec_info pattern_stmt_info; vec_info *vinfo = stmt_vinfo->vinfo; - gimple *pattern_stmt; /* Check for MASK_LOAD ans MASK_STORE calls requiring mask conversion. */ if (is_gimple_call (last_stmt) --- 3868,3873 ---- *************** vect_recog_mask_conversion_pattern (vec< *** 3875,3880 **** --- 3875,3881 ---- && (gimple_call_internal_fn (last_stmt) == IFN_MASK_STORE || gimple_call_internal_fn (last_stmt) == IFN_MASK_LOAD)) { + gcall *pattern_stmt; bool load = (gimple_call_internal_fn (last_stmt) == IFN_MASK_LOAD); if (load) *************** vect_recog_mask_conversion_pattern (vec< *** 3918,3923 **** --- 3919,3925 ---- tmp, gimple_call_arg (last_stmt, 3)); + gimple_call_set_nothrow (pattern_stmt, true); pattern_stmt_info = new_stmt_vec_info (pattern_stmt, vinfo); set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info); *************** vect_recog_mask_conversion_pattern (vec< *** 3940,3945 **** --- 3942,3948 ---- if (!is_gimple_assign (last_stmt)) return NULL; + gimple *pattern_stmt; lhs = gimple_assign_lhs (last_stmt); rhs1 = gimple_assign_rhs1 (last_stmt); rhs_code = gimple_assign_rhs_code (last_stmt);
On Mon, Aug 28, 2017 at 10:16 AM, Richard Sandiford <richard.sandiford@linaro.org> wrote: > Richard Biener <richard.guenther@gmail.com> writes: >> On Thu, Aug 17, 2017 at 1:06 PM, Richard Sandiford >> <richard.sandiford@linaro.org> wrote >>> Richard Biener <richard.guenther@gmail.com> writes: >>>> On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford >>>> <richard.sandiford@linaro.org> wrote: >>>>> Internal functions that map directly to an optab can only throw an >>>>> exception for -fnon-call-exceptions. This patch handles that in >>>>> internal_fn_flags, in a similar way to ATTR_*NOTHROW in builtins.def. >>>>> >>>>> (Functions that don't throw even for flag_non_call_exceptions should be >>>>> explicitly marked ECF_NOTHROW in internal-fn.def.) >>>>> >>>>> Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? >>>> >>>> Hmm. Note the outcome of flag_non_call_exceptions depends on the >>>> current function and thus IPA passes querying flags would need to >>>> push an appropriate function context. This means the function should >>>> get a struct function * argument and opt_for_fn (fn, >>>> flag_non_call_exceptions) >>>> should be used. It doesn't help very much that all callers don't have >>>> any such context either which means this "optimization" looks like >>>> in the wrong place :/ (the global value of flag_non_call_exceptions in >>>> the IPA case isn't necessarily conservative). >>>> >>>> So if you insist then add a comment and add a && cfun check so >>>> we're sure we are in non-IPA context (or in properly setup context). >>> >>> Bah. In that case, what should happen if a -fno-non-call-exceptions >>> function is inlined into an -fnon-call-exceptions one? Should the call >>> keep the NOTHROWness of the original function, or should it lose >>> NOTHROWness (and thus gain an exception edge)? >> >> nothrow-ness is tracked on the GIMPLE stmt via gimple_call_[set_]nothrow_p, >> GIMPLE shouldn't look at flag_non_call_exceptions, it is basically part >> of the IL. >> >>> I guess the path of least resistance would be to add an extra check >>> for this case in the places that need it, rather than relying solely >>> on gimple_call_flags. >> >> Well, gimple_call_flags works fine already (looking at the above in >> addition to internal_fn_flags). call_expr_flags looks like it might not. > > OK, how does this look? Only the gimple flags matter for the use > case I've seen (which is covered by the SVE tests, but hard to > test as-is). > > Tested on aarch64-linux-gnu and x86_64-linux-gnu. Ok. Thanks, Richard. > Thanks, > Richard > > > 2017-08-28 Richard Sandiford <richard.sandiford@linaro.org> > > gcc/ > * gimplify.c (gimplify_call_expr): Copy the nothrow flag to > calls to internal functions. > (gimplify_modify_expr): Likewise. > * tree-call-cdce.c (use_internal_fn): Likewise. > * tree-ssa-math-opts.c (pass_cse_reciprocals::execute): Likewise. > (convert_to_divmod): Set the nothrow flag. > * tree-if-conv.c (predicate_mem_writes): Likewise. > * tree-vect-stmts.c (vectorizable_mask_load_store): Likewise. > (vectorizable_call): Likewise. > (vectorizable_store): Likewise. > (vectorizable_load): Likewise. > * tree-vect-patterns.c (vect_recog_pow_pattern): Likewise. > (vect_recog_mask_conversion_pattern): Likewise. > > Index: gcc/gimplify.c > =================================================================== > *** gcc/gimplify.c 2017-08-17 13:17:21.266412322 +0100 > --- gcc/gimplify.c 2017-08-28 09:10:13.246297839 +0100 > *************** gimplify_call_expr (tree *expr_p, gimple > *** 3150,3156 **** > > if (EXPR_CILK_SPAWN (*expr_p)) > gimplify_cilk_detach (pre_p); > ! gimple *call = gimple_build_call_internal_vec (ifn, vargs); > gimplify_seq_add_stmt (pre_p, call); > return GS_ALL_DONE; > } > --- 3150,3157 ---- > > if (EXPR_CILK_SPAWN (*expr_p)) > gimplify_cilk_detach (pre_p); > ! gcall *call = gimple_build_call_internal_vec (ifn, vargs); > ! gimple_call_set_nothrow (call, TREE_NOTHROW (*expr_p)); > gimplify_seq_add_stmt (pre_p, call); > return GS_ALL_DONE; > } > *************** gimplify_modify_expr (tree *expr_p, gimp > *** 5636,5641 **** > --- 5637,5643 ---- > vargs.quick_push (CALL_EXPR_ARG (*from_p, i)); > } > call_stmt = gimple_build_call_internal_vec (ifn, vargs); > + gimple_call_set_nothrow (call_stmt, TREE_NOTHROW (*from_p)); > gimple_set_location (call_stmt, EXPR_LOCATION (*expr_p)); > } > else > Index: gcc/tree-call-cdce.c > =================================================================== > *** gcc/tree-call-cdce.c 2017-06-30 12:50:38.243662675 +0100 > --- gcc/tree-call-cdce.c 2017-08-28 09:10:13.246297839 +0100 > *************** use_internal_fn (gcall *call) > *** 1019,1024 **** > --- 1019,1025 ---- > args.safe_push (gimple_call_arg (call, i)); > gcall *new_call = gimple_build_call_internal_vec (ifn, args); > gimple_set_location (new_call, gimple_location (call)); > + gimple_call_set_nothrow (new_call, gimple_call_nothrow_p (call)); > > /* Transfer the LHS to the new call. */ > tree lhs = gimple_call_lhs (call); > Index: gcc/tree-ssa-math-opts.c > =================================================================== > *** gcc/tree-ssa-math-opts.c 2017-08-24 08:46:02.098124751 +0100 > --- gcc/tree-ssa-math-opts.c 2017-08-28 09:10:13.247297839 +0100 > *************** pass_cse_reciprocals::execute (function > *** 690,695 **** > --- 690,697 ---- > gimple_set_vdef (stmt2, gimple_vdef (call)); > SSA_NAME_DEF_STMT (gimple_vdef (stmt2)) = stmt2; > } > + gimple_call_set_nothrow (stmt2, > + gimple_call_nothrow_p (call)); > gimple_set_vuse (stmt2, gimple_vuse (call)); > gimple_stmt_iterator gsi2 = gsi_for_stmt (call); > gsi_replace (&gsi2, stmt2, true); > *************** convert_to_divmod (gassign *stmt) > *** 4100,4105 **** > --- 4102,4109 ---- > tree res = make_temp_ssa_name (build_complex_type (TREE_TYPE (op1)), > call_stmt, "divmod_tmp"); > gimple_call_set_lhs (call_stmt, res); > + /* We rejected throwing statements above. */ > + gimple_call_set_nothrow (call_stmt, true); > > /* Insert the call before top_stmt. */ > gimple_stmt_iterator top_stmt_gsi = gsi_for_stmt (top_stmt); > Index: gcc/tree-if-conv.c > =================================================================== > *** gcc/tree-if-conv.c 2017-08-22 17:13:27.429500899 +0100 > --- gcc/tree-if-conv.c 2017-08-28 09:10:13.246297839 +0100 > *************** predicate_mem_writes (loop_p loop) > *** 2219,2225 **** > tree lhs = gimple_assign_lhs (stmt); > tree rhs = gimple_assign_rhs1 (stmt); > tree ref, addr, ptr, mask; > ! gimple *new_stmt; > gimple_seq stmts = NULL; > int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs))); > ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs; > --- 2219,2225 ---- > tree lhs = gimple_assign_lhs (stmt); > tree rhs = gimple_assign_rhs1 (stmt); > tree ref, addr, ptr, mask; > ! gcall *new_stmt; > gimple_seq stmts = NULL; > int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs))); > ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs; > *************** predicate_mem_writes (loop_p loop) > *** 2281,2286 **** > --- 2281,2287 ---- > gimple_set_vdef (new_stmt, gimple_vdef (stmt)); > SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; > } > + gimple_call_set_nothrow (new_stmt, true); > > gsi_replace (&gsi, new_stmt, true); > } > Index: gcc/tree-vect-stmts.c > =================================================================== > *** gcc/tree-vect-stmts.c 2017-08-22 17:13:27.429500899 +0100 > --- gcc/tree-vect-stmts.c 2017-08-28 09:10:13.248297839 +0100 > *************** vectorizable_mask_load_store (gimple *st > *** 2364,2372 **** > misalign); > tree ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), > misalign ? least_bit_hwi (misalign) : align); > ! new_stmt > = gimple_build_call_internal (IFN_MASK_STORE, 4, dataref_ptr, > ptr, vec_mask, vec_rhs); > vect_finish_stmt_generation (stmt, new_stmt, gsi); > if (i == 0) > STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt; > --- 2364,2374 ---- > misalign); > tree ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), > misalign ? least_bit_hwi (misalign) : align); > ! gcall *call > = gimple_build_call_internal (IFN_MASK_STORE, 4, dataref_ptr, > ptr, vec_mask, vec_rhs); > + gimple_call_set_nothrow (call, true); > + new_stmt = call; > vect_finish_stmt_generation (stmt, new_stmt, gsi); > if (i == 0) > STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt; > *************** vectorizable_mask_load_store (gimple *st > *** 2414,2429 **** > misalign); > tree ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), > misalign ? least_bit_hwi (misalign) : align); > ! new_stmt > = gimple_build_call_internal (IFN_MASK_LOAD, 3, dataref_ptr, > ptr, vec_mask); > ! gimple_call_set_lhs (new_stmt, make_ssa_name (vec_dest)); > ! vect_finish_stmt_generation (stmt, new_stmt, gsi); > if (i == 0) > ! STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt; > else > ! STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; > ! prev_stmt_info = vinfo_for_stmt (new_stmt); > } > } > > --- 2416,2432 ---- > misalign); > tree ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), > misalign ? least_bit_hwi (misalign) : align); > ! gcall *call > = gimple_build_call_internal (IFN_MASK_LOAD, 3, dataref_ptr, > ptr, vec_mask); > ! gimple_call_set_lhs (call, make_ssa_name (vec_dest)); > ! gimple_call_set_nothrow (call, true); > ! vect_finish_stmt_generation (stmt, call, gsi); > if (i == 0) > ! STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = call; > else > ! STMT_VINFO_RELATED_STMT (prev_stmt_info) = call; > ! prev_stmt_info = vinfo_for_stmt (call); > } > } > > *************** vectorizable_call (gimple *gs, gimple_st > *** 2867,2874 **** > if (modifier == NARROW) > { > tree half_res = make_ssa_name (vectype_in); > ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); > ! gimple_call_set_lhs (new_stmt, half_res); > vect_finish_stmt_generation (stmt, new_stmt, gsi); > if ((i & 1) == 0) > { > --- 2870,2880 ---- > if (modifier == NARROW) > { > tree half_res = make_ssa_name (vectype_in); > ! gcall *call > ! = gimple_build_call_internal_vec (ifn, vargs); > ! gimple_call_set_lhs (call, half_res); > ! gimple_call_set_nothrow (call, true); > ! new_stmt = call; > vect_finish_stmt_generation (stmt, new_stmt, gsi); > if ((i & 1) == 0) > { > *************** vectorizable_call (gimple *gs, gimple_st > *** 2881,2892 **** > } > else > { > if (ifn != IFN_LAST) > ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); > else > ! new_stmt = gimple_build_call_vec (fndecl, vargs); > ! new_temp = make_ssa_name (vec_dest, new_stmt); > ! gimple_call_set_lhs (new_stmt, new_temp); > } > vect_finish_stmt_generation (stmt, new_stmt, gsi); > SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt); > --- 2887,2901 ---- > } > else > { > + gcall *call; > if (ifn != IFN_LAST) > ! call = gimple_build_call_internal_vec (ifn, vargs); > else > ! call = gimple_build_call_vec (fndecl, vargs); > ! new_temp = make_ssa_name (vec_dest, call); > ! gimple_call_set_lhs (call, new_temp); > ! gimple_call_set_nothrow (call, true); > ! new_stmt = call; > } > vect_finish_stmt_generation (stmt, new_stmt, gsi); > SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt); > *************** vectorizable_call (gimple *gs, gimple_st > *** 2934,2941 **** > else if (modifier == NARROW) > { > tree half_res = make_ssa_name (vectype_in); > ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); > ! gimple_call_set_lhs (new_stmt, half_res); > vect_finish_stmt_generation (stmt, new_stmt, gsi); > if ((j & 1) == 0) > { > --- 2943,2952 ---- > else if (modifier == NARROW) > { > tree half_res = make_ssa_name (vectype_in); > ! gcall *call = gimple_build_call_internal_vec (ifn, vargs); > ! gimple_call_set_lhs (call, half_res); > ! gimple_call_set_nothrow (call, true); > ! new_stmt = call; > vect_finish_stmt_generation (stmt, new_stmt, gsi); > if ((j & 1) == 0) > { > *************** vectorizable_call (gimple *gs, gimple_st > *** 2948,2959 **** > } > else > { > if (ifn != IFN_LAST) > ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); > else > ! new_stmt = gimple_build_call_vec (fndecl, vargs); > new_temp = make_ssa_name (vec_dest, new_stmt); > ! gimple_call_set_lhs (new_stmt, new_temp); > } > vect_finish_stmt_generation (stmt, new_stmt, gsi); > > --- 2959,2973 ---- > } > else > { > + gcall *call; > if (ifn != IFN_LAST) > ! call = gimple_build_call_internal_vec (ifn, vargs); > else > ! call = gimple_build_call_vec (fndecl, vargs); > new_temp = make_ssa_name (vec_dest, new_stmt); > ! gimple_call_set_lhs (call, new_temp); > ! gimple_call_set_nothrow (call, true); > ! new_stmt = call; > } > vect_finish_stmt_generation (stmt, new_stmt, gsi); > > *************** vectorizable_call (gimple *gs, gimple_st > *** 2996,3007 **** > vargs.quick_push (vec_oprndsk[i]); > vargs.quick_push (vec_oprndsk[i + 1]); > } > if (ifn != IFN_LAST) > ! new_stmt = gimple_build_call_internal_vec (ifn, vargs); > else > ! new_stmt = gimple_build_call_vec (fndecl, vargs); > ! new_temp = make_ssa_name (vec_dest, new_stmt); > ! gimple_call_set_lhs (new_stmt, new_temp); > vect_finish_stmt_generation (stmt, new_stmt, gsi); > SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt); > } > --- 3010,3024 ---- > vargs.quick_push (vec_oprndsk[i]); > vargs.quick_push (vec_oprndsk[i + 1]); > } > + gcall *call; > if (ifn != IFN_LAST) > ! call = gimple_build_call_internal_vec (ifn, vargs); > else > ! call = gimple_build_call_vec (fndecl, vargs); > ! new_temp = make_ssa_name (vec_dest, call); > ! gimple_call_set_lhs (call, new_temp); > ! gimple_call_set_nothrow (call, true); > ! new_stmt = call; > vect_finish_stmt_generation (stmt, new_stmt, gsi); > SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt); > } > *************** vectorizable_store (gimple *stmt, gimple > *** 6356,6363 **** > /* Emit: > MEM_REF[...all elements...] = STORE_LANES (VEC_ARRAY). */ > data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type); > ! new_stmt = gimple_build_call_internal (IFN_STORE_LANES, 1, vec_array); > ! gimple_call_set_lhs (new_stmt, data_ref); > vect_finish_stmt_generation (stmt, new_stmt, gsi); > } > else > --- 6373,6383 ---- > /* Emit: > MEM_REF[...all elements...] = STORE_LANES (VEC_ARRAY). */ > data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type); > ! gcall *call = gimple_build_call_internal (IFN_STORE_LANES, 1, > ! vec_array); > ! gimple_call_set_lhs (call, data_ref); > ! gimple_call_set_nothrow (call, true); > ! new_stmt = call; > vect_finish_stmt_generation (stmt, new_stmt, gsi); > } > else > *************** vectorizable_load (gimple *stmt, gimple_ > *** 7448,7455 **** > /* Emit: > VEC_ARRAY = LOAD_LANES (MEM_REF[...all elements...]). */ > data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type); > ! new_stmt = gimple_build_call_internal (IFN_LOAD_LANES, 1, data_ref); > ! gimple_call_set_lhs (new_stmt, vec_array); > vect_finish_stmt_generation (stmt, new_stmt, gsi); > > /* Extract each vector into an SSA_NAME. */ > --- 7468,7478 ---- > /* Emit: > VEC_ARRAY = LOAD_LANES (MEM_REF[...all elements...]). */ > data_ref = create_array_ref (aggr_type, dataref_ptr, ref_type); > ! gcall *call = gimple_build_call_internal (IFN_LOAD_LANES, 1, > ! data_ref); > ! gimple_call_set_lhs (call, vec_array); > ! gimple_call_set_nothrow (call, true); > ! new_stmt = call; > vect_finish_stmt_generation (stmt, new_stmt, gsi); > > /* Extract each vector into an SSA_NAME. */ > Index: gcc/tree-vect-patterns.c > =================================================================== > *** gcc/tree-vect-patterns.c 2017-08-21 15:50:48.663709938 +0100 > --- gcc/tree-vect-patterns.c 2017-08-28 09:10:13.247297839 +0100 > *************** vect_recog_pow_pattern (vec<gimple *> *s > *** 1085,1090 **** > --- 1085,1091 ---- > gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base); > var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt); > gimple_call_set_lhs (stmt, var); > + gimple_call_set_nothrow (stmt, true); > return stmt; > } > } > *************** vect_recog_mask_conversion_pattern (vec< > *** 3867,3873 **** > stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); > stmt_vec_info pattern_stmt_info; > vec_info *vinfo = stmt_vinfo->vinfo; > - gimple *pattern_stmt; > > /* Check for MASK_LOAD ans MASK_STORE calls requiring mask conversion. */ > if (is_gimple_call (last_stmt) > --- 3868,3873 ---- > *************** vect_recog_mask_conversion_pattern (vec< > *** 3875,3880 **** > --- 3875,3881 ---- > && (gimple_call_internal_fn (last_stmt) == IFN_MASK_STORE > || gimple_call_internal_fn (last_stmt) == IFN_MASK_LOAD)) > { > + gcall *pattern_stmt; > bool load = (gimple_call_internal_fn (last_stmt) == IFN_MASK_LOAD); > > if (load) > *************** vect_recog_mask_conversion_pattern (vec< > *** 3918,3923 **** > --- 3919,3925 ---- > tmp, > gimple_call_arg (last_stmt, 3)); > > + gimple_call_set_nothrow (pattern_stmt, true); > > pattern_stmt_info = new_stmt_vec_info (pattern_stmt, vinfo); > set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info); > *************** vect_recog_mask_conversion_pattern (vec< > *** 3940,3945 **** > --- 3942,3948 ---- > if (!is_gimple_assign (last_stmt)) > return NULL; > > + gimple *pattern_stmt; > lhs = gimple_assign_lhs (last_stmt); > rhs1 = gimple_assign_rhs1 (last_stmt); > rhs_code = gimple_assign_rhs_code (last_stmt);
Index: gcc/internal-fn.h =================================================================== --- gcc/internal-fn.h 2017-02-23 19:54:03.000000000 +0000 +++ gcc/internal-fn.h 2017-08-17 09:05:37.459968561 +0100 @@ -107,15 +107,7 @@ internal_fn_name (enum internal_fn fn) return internal_fn_name_array[(int) fn]; } -/* Return the ECF_* flags for function FN. */ - -extern const int internal_fn_flags_array[]; - -static inline int -internal_fn_flags (enum internal_fn fn) -{ - return internal_fn_flags_array[(int) fn]; -} +extern int internal_fn_flags (enum internal_fn fn); /* Return fnspec for function FN. */ Index: gcc/internal-fn.c =================================================================== --- gcc/internal-fn.c 2017-08-10 14:36:07.453493083 +0100 +++ gcc/internal-fn.c 2017-08-17 09:05:37.459968561 +0100 @@ -2814,3 +2814,18 @@ expand_PHI (internal_fn, gcall *) { gcc_unreachable (); } + +/* Return the ECF_* flags for function FN. */ + +int +internal_fn_flags (enum internal_fn fn) +{ + int flags = internal_fn_flags_array[(int) fn]; + /* Functions that map to optabs can only throw a catchable exception + when non-call exceptions are enabled. The non-call exceptions in + these cases will typically come from things like IEEE exceptions, + divide by zero errors and SEGVs. */ + if (direct_internal_fn_p (fn) && !flag_non_call_exceptions) + flags |= ECF_NOTHROW; + return flags; +}