Re: Improve ECF_NOTHROW flags for direct internal functions
On Mon, Aug 28, 2017 at 10:16 AM, Richard Sandifordwrote: > Richard Biener writes: >> On Thu, Aug 17, 2017 at 1:06 PM, Richard Sandiford >> wrote >>> Richard Biener writes: On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford 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 > > 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.c2017-06-30 12:50:38.243662675 +0100 > --- gcc/tree-call-cdce.c2017-08-28 09:10:13.246297839 +0100 > *** use_internal_fn (gcall *call) > *** 1019,1024 > ---
Re: Improve ECF_NOTHROW flags for direct internal functions
Richard Bienerwrites: > On Thu, Aug 17, 2017 at 1:06 PM, Richard Sandiford > wrote >> Richard Biener writes: >>> On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford >>> 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 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.c2017-06-30 12:50:38.243662675 +0100 --- gcc/tree-call-cdce.c2017-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
Re: Improve ECF_NOTHROW flags for direct internal functions
On Thu, Aug 17, 2017 at 1:06 PM, Richard Sandifordwrote > Richard Biener writes: >> On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford >> 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 >>> >>> 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.0 + >>> +++ 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; >>> +}
Re: Improve ECF_NOTHROW flags for direct internal functions
Richard Bienerwrites: > On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford > 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 >> >> 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.0 + >> +++ 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; >> +}
Re: Improve ECF_NOTHROW flags for direct internal functions
On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandifordwrote: > 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 > > 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.0 + > +++ 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; > +}
Improve ECF_NOTHROW flags for direct internal functions
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? Richard 2017-08-17 Richard Sandifordgcc/ * 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.0 + +++ 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; +}