On Mon, Aug 28, 2017 at 10:16 AM, Richard Sandiford <richard.sandif...@linaro.org> wrote: > Richard Biener <richard.guent...@gmail.com> writes: >> On Thu, Aug 17, 2017 at 1:06 PM, Richard Sandiford >> <richard.sandif...@linaro.org> wrote >>> Richard Biener <richard.guent...@gmail.com> writes: >>>> On Thu, Aug 17, 2017 at 11:49 AM, Richard Sandiford >>>> <richard.sandif...@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.sandif...@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);