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);

Reply via email to