This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Improve ECF_NOTHROW flags for direct internal functions


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]