Allow gimple_build with internal functions

Message ID 87603mofpj.fsf@linaro.org
State New
Headers show
Series
  • Allow gimple_build with internal functions
Related show

Commit Message

Richard Sandiford May 17, 2018, 8:21 a.m.
This patch makes the function versions of gimple_build and
gimple_simplify take combined_fns rather than built_in_codes,
so that they work with internal functions too.  The old
gimple_builds were unused, so no existing callers need
to be updated.

Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
and x86_64-linux-gnu.  OK to install?

Richard


2018-05-17  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* gimple-fold.h (gimple_build): Make the function forms take
	combined_fn rather than built_in_function.
	(gimple_simplify): Likewise.
	* gimple-match-head.c (gimple_simplify): Likewise.
	* gimple-fold.c (gimple_build): Likewise.
	* tree-vect-loop.c (get_initial_def_for_reduction): Use gimple_build
	rather than gimple_build_call_internal.
	(get_initial_defs_for_reduction): Likewise.
	(vect_create_epilog_for_reduction): Likewise.
	(vectorizable_live_operation): Likewise.

Comments

Richard Biener May 17, 2018, 10:38 a.m. | #1
On Thu, May 17, 2018 at 10:21 AM Richard Sandiford <
richard.sandiford@linaro.org> wrote:

> This patch makes the function versions of gimple_build and

> gimple_simplify take combined_fns rather than built_in_codes,

> so that they work with internal functions too.  The old

> gimple_builds were unused, so no existing callers need

> to be updated.


> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf

> and x86_64-linux-gnu.  OK to install?


Ok.

Thanks,
Richard.

> Richard



> 2018-05-17  Richard Sandiford  <richard.sandiford@linaro.org>


> gcc/

>          * gimple-fold.h (gimple_build): Make the function forms take

>          combined_fn rather than built_in_function.

>          (gimple_simplify): Likewise.

>          * gimple-match-head.c (gimple_simplify): Likewise.

>          * gimple-fold.c (gimple_build): Likewise.

>          * tree-vect-loop.c (get_initial_def_for_reduction): Use

gimple_build
>          rather than gimple_build_call_internal.

>          (get_initial_defs_for_reduction): Likewise.

>          (vect_create_epilog_for_reduction): Likewise.

>          (vectorizable_live_operation): Likewise.


> Index: gcc/gimple-fold.h

> ===================================================================

> --- gcc/gimple-fold.h   2018-05-16 20:17:39.114152860 +0100

> +++ gcc/gimple-fold.h   2018-05-17 09:17:32.876478942 +0100

> @@ -86,28 +86,25 @@ gimple_build (gimple_seq *seq,

>   {

>     return gimple_build (seq, UNKNOWN_LOCATION, code, type, op0, op1, op2);

>   }

> -extern tree gimple_build (gimple_seq *, location_t,

> -                         enum built_in_function, tree, tree);

> +extern tree gimple_build (gimple_seq *, location_t, combined_fn, tree,

tree);
>   inline tree

> -gimple_build (gimple_seq *seq,

> -             enum built_in_function fn, tree type, tree arg0)

> +gimple_build (gimple_seq *seq, combined_fn fn, tree type, tree arg0)

>   {

>     return gimple_build (seq, UNKNOWN_LOCATION, fn, type, arg0);

>   }

> -extern tree gimple_build (gimple_seq *, location_t,

> -                         enum built_in_function, tree, tree, tree);

> +extern tree gimple_build (gimple_seq *, location_t, combined_fn,

> +                         tree, tree, tree);

>   inline tree

> -gimple_build (gimple_seq *seq,

> -             enum built_in_function fn, tree type, tree arg0, tree arg1)

> +gimple_build (gimple_seq *seq, combined_fn fn,

> +             tree type, tree arg0, tree arg1)

>   {

>     return gimple_build (seq, UNKNOWN_LOCATION, fn, type, arg0, arg1);

>   }

> -extern tree gimple_build (gimple_seq *, location_t,

> -                         enum built_in_function, tree, tree, tree, tree);

> +extern tree gimple_build (gimple_seq *, location_t, combined_fn,

> +                         tree, tree, tree, tree);

>   inline tree

> -gimple_build (gimple_seq *seq,

> -             enum built_in_function fn, tree type,

> -             tree arg0, tree arg1, tree arg2)

> +gimple_build (gimple_seq *seq, combined_fn fn,

> +             tree type, tree arg0, tree arg1, tree arg2)

>   {

>     return gimple_build (seq, UNKNOWN_LOCATION, fn, type, arg0, arg1,

arg2);
>   }

> @@ -153,11 +150,11 @@ extern tree gimple_simplify (enum tree_c

>                               gimple_seq *, tree (*)(tree));

>   extern tree gimple_simplify (enum tree_code, tree, tree, tree, tree,

>                               gimple_seq *, tree (*)(tree));

> -extern tree gimple_simplify (enum built_in_function, tree, tree,

> +extern tree gimple_simplify (combined_fn, tree, tree,

>                               gimple_seq *, tree (*)(tree));

> -extern tree gimple_simplify (enum built_in_function, tree, tree, tree,

> +extern tree gimple_simplify (combined_fn, tree, tree, tree,

>                               gimple_seq *, tree (*)(tree));

> -extern tree gimple_simplify (enum built_in_function, tree, tree, tree,

tree,
> +extern tree gimple_simplify (combined_fn, tree, tree, tree, tree,

>                               gimple_seq *, tree (*)(tree));


>   #endif  /* GCC_GIMPLE_FOLD_H */

> Index: gcc/gimple-match-head.c

> ===================================================================

> --- gcc/gimple-match-head.c     2018-03-30 12:28:37.301927949 +0100

> +++ gcc/gimple-match-head.c     2018-05-17 09:17:32.876478942 +0100

> @@ -478,55 +478,53 @@ gimple_simplify (enum tree_code code, tr

>     return maybe_push_res_to_seq (rcode, type, ops, seq);

>   }


> -/* Builtin function with one argument.  */

> +/* Builtin or internal function with one argument.  */


>   tree

> -gimple_simplify (enum built_in_function fn, tree type,

> +gimple_simplify (combined_fn fn, tree type,

>                   tree arg0,

>                   gimple_seq *seq, tree (*valueize)(tree))

>   {

>     if (constant_for_folding (arg0))

>       {

> -      tree res = fold_const_call (as_combined_fn (fn), type, arg0);

> +      tree res = fold_const_call (fn, type, arg0);

>         if (res && CONSTANT_CLASS_P (res))

>          return res;

>       }


>     code_helper rcode;

>     tree ops[3] = {};

> -  if (!gimple_simplify (&rcode, ops, seq, valueize,

> -                       as_combined_fn (fn), type, arg0))

> +  if (!gimple_simplify (&rcode, ops, seq, valueize, fn, type, arg0))

>       return NULL_TREE;

>     return maybe_push_res_to_seq (rcode, type, ops, seq);

>   }


> -/* Builtin function with two arguments.  */

> +/* Builtin or internal function with two arguments.  */


>   tree

> -gimple_simplify (enum built_in_function fn, tree type,

> +gimple_simplify (combined_fn fn, tree type,

>                   tree arg0, tree arg1,

>                   gimple_seq *seq, tree (*valueize)(tree))

>   {

>     if (constant_for_folding (arg0)

>         && constant_for_folding (arg1))

>       {

> -      tree res = fold_const_call (as_combined_fn (fn), type, arg0, arg1);

> +      tree res = fold_const_call (fn, type, arg0, arg1);

>         if (res && CONSTANT_CLASS_P (res))

>          return res;

>       }


>     code_helper rcode;

>     tree ops[3] = {};

> -  if (!gimple_simplify (&rcode, ops, seq, valueize,

> -                       as_combined_fn (fn), type, arg0, arg1))

> +  if (!gimple_simplify (&rcode, ops, seq, valueize, fn, type, arg0,

arg1))
>       return NULL_TREE;

>     return maybe_push_res_to_seq (rcode, type, ops, seq);

>   }


> -/* Builtin function with three arguments.  */

> +/* Builtin or internal function with three arguments.  */


>   tree

> -gimple_simplify (enum built_in_function fn, tree type,

> +gimple_simplify (combined_fn fn, tree type,

>                   tree arg0, tree arg1, tree arg2,

>                   gimple_seq *seq, tree (*valueize)(tree))

>   {

> @@ -534,7 +532,7 @@ gimple_simplify (enum built_in_function

>         && constant_for_folding (arg1)

>         && constant_for_folding (arg2))

>       {

> -      tree res = fold_const_call (as_combined_fn (fn), type, arg0, arg1,

arg2);
> +      tree res = fold_const_call (fn, type, arg0, arg1, arg2);

>         if (res && CONSTANT_CLASS_P (res))

>          return res;

>       }

> @@ -542,7 +540,7 @@ gimple_simplify (enum built_in_function

>     code_helper rcode;

>     tree ops[3] = {};

>     if (!gimple_simplify (&rcode, ops, seq, valueize,

> -                       as_combined_fn (fn), type, arg0, arg1, arg2))

> +                       fn, type, arg0, arg1, arg2))

>       return NULL_TREE;

>     return maybe_push_res_to_seq (rcode, type, ops, seq);

>   }

> Index: gcc/gimple-fold.c

> ===================================================================

> --- gcc/gimple-fold.c   2018-05-01 19:30:33.230500376 +0100

> +++ gcc/gimple-fold.c   2018-05-17 09:17:32.876478942 +0100

> @@ -7204,14 +7204,20 @@ gimple_build (gimple_seq *seq, location_

>      statements possibly defining it to SEQ.  */


>   tree

> -gimple_build (gimple_seq *seq, location_t loc,

> -             enum built_in_function fn, tree type, tree arg0)

> +gimple_build (gimple_seq *seq, location_t loc, combined_fn fn,

> +             tree type, tree arg0)

>   {

>     tree res = gimple_simplify (fn, type, arg0, seq,

gimple_build_valueize);
>     if (!res)

>       {

> -      tree decl = builtin_decl_implicit (fn);

> -      gimple *stmt = gimple_build_call (decl, 1, arg0);

> +      gcall *stmt;

> +      if (internal_fn_p (fn))

> +       stmt = gimple_build_call_internal (as_internal_fn (fn), 1, arg0);

> +      else

> +       {

> +         tree decl = builtin_decl_implicit (as_builtin_fn (fn));

> +         stmt = gimple_build_call (decl, 1, arg0);

> +       }

>         if (!VOID_TYPE_P (type))

>          {

>            res = create_tmp_reg_or_ssa_name (type);

> @@ -7230,14 +7236,20 @@ gimple_build (gimple_seq *seq, location_

>      statements possibly defining it to SEQ.  */


>   tree

> -gimple_build (gimple_seq *seq, location_t loc,

> -             enum built_in_function fn, tree type, tree arg0, tree arg1)

> +gimple_build (gimple_seq *seq, location_t loc, combined_fn fn,

> +             tree type, tree arg0, tree arg1)

>   {

>     tree res = gimple_simplify (fn, type, arg0, arg1, seq,

gimple_build_valueize);
>     if (!res)

>       {

> -      tree decl = builtin_decl_implicit (fn);

> -      gimple *stmt = gimple_build_call (decl, 2, arg0, arg1);

> +      gcall *stmt;

> +      if (internal_fn_p (fn))

> +       stmt = gimple_build_call_internal (as_internal_fn (fn), 2, arg0,

arg1);
> +      else

> +       {

> +         tree decl = builtin_decl_implicit (as_builtin_fn (fn));

> +         stmt = gimple_build_call (decl, 2, arg0, arg1);

> +       }

>         if (!VOID_TYPE_P (type))

>          {

>            res = create_tmp_reg_or_ssa_name (type);

> @@ -7256,16 +7268,22 @@ gimple_build (gimple_seq *seq, location_

>      statements possibly defining it to SEQ.  */


>   tree

> -gimple_build (gimple_seq *seq, location_t loc,

> -             enum built_in_function fn, tree type,

> -             tree arg0, tree arg1, tree arg2)

> +gimple_build (gimple_seq *seq, location_t loc, combined_fn fn,

> +             tree type, tree arg0, tree arg1, tree arg2)

>   {

>     tree res = gimple_simplify (fn, type, arg0, arg1, arg2,

>                                seq, gimple_build_valueize);

>     if (!res)

>       {

> -      tree decl = builtin_decl_implicit (fn);

> -      gimple *stmt = gimple_build_call (decl, 3, arg0, arg1, arg2);

> +      gcall *stmt;

> +      if (internal_fn_p (fn))

> +       stmt = gimple_build_call_internal (as_internal_fn (fn),

> +                                          3, arg0, arg1, arg2);

> +      else

> +       {

> +         tree decl = builtin_decl_implicit (as_builtin_fn (fn));

> +         stmt = gimple_build_call (decl, 3, arg0, arg1, arg2);

> +       }

>         if (!VOID_TYPE_P (type))

>          {

>            res = create_tmp_reg_or_ssa_name (type);

> Index: gcc/tree-vect-loop.c

> ===================================================================

> --- gcc/tree-vect-loop.c        2018-05-16 12:50:14.893361868 +0100

> +++ gcc/tree-vect-loop.c        2018-05-17 09:17:32.877478908 +0100

> @@ -4179,12 +4179,10 @@ get_initial_def_for_reduction (gimple *s

>          else if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant ())

>            {

>              /* Option2 (variable length): the first element is INIT_VAL.

  */
> -           init_def = build_vector_from_val (vectype, def_for_init);

> -           gcall *call = gimple_build_call_internal (IFN_VEC_SHL_INSERT,

> -                                                     2, init_def,

init_val);
> -           init_def = make_ssa_name (vectype);

> -           gimple_call_set_lhs (call, init_def);

> -           gimple_seq_add_stmt (&stmts, call);

> +           init_def = gimple_build_vector_from_val (&stmts, vectype,

> +                                                    def_for_init);

> +           init_def = gimple_build (&stmts, CFN_VEC_SHL_INSERT,

> +                                    vectype, init_def, init_val);

>            }

>          else

>            {

> @@ -4327,11 +4325,8 @@ get_initial_defs_for_reduction (slp_tree

>                    while (k > 0)

>                      {

>                        k -= 1;

> -                     gcall *call = gimple_build_call_internal

> -                       (IFN_VEC_SHL_INSERT, 2, init, elts[k]);

> -                     init = make_ssa_name (vector_type);

> -                     gimple_call_set_lhs (call, init);

> -                     gimple_seq_add_stmt (&ctor_seq, call);

> +                     init = gimple_build (&ctor_seq, CFN_VEC_SHL_INSERT,

> +                                          vector_type, init, elts[k]);

>                      }

>                  }

>                else

> @@ -5234,10 +5229,8 @@ vect_create_epilog_for_reduction (vec<tr

>                                     sel, new_phi_result, vector_identity);


>            /* Do the reduction and convert it to the appropriate type.  */

> -         gcall *call = gimple_build_call_internal (reduc_fn, 1, vec);

> -         tree scalar = make_ssa_name (TREE_TYPE (vectype));

> -         gimple_call_set_lhs (call, scalar);

> -         gimple_seq_add_stmt (&seq, call);

> +         tree scalar = gimple_build (&seq, as_combined_fn (reduc_fn),

> +                                     TREE_TYPE (vectype), vec);

>            scalar = gimple_convert (&seq, scalar_type, scalar);

>            scalar_results.safe_push (scalar);

>          }

> @@ -8048,13 +8041,10 @@ vectorizable_live_operation (gimple *stm

>           the loop mask for the final iteration.  */

>         gcc_assert (ncopies == 1 && !slp_node);

>         tree scalar_type = TREE_TYPE (STMT_VINFO_VECTYPE (stmt_info));

> -      tree scalar_res = make_ssa_name (scalar_type);

>         tree mask = vect_get_loop_mask (gsi, &LOOP_VINFO_MASKS

(loop_vinfo),
>                                        1, vectype, 0);

> -      gcall *new_stmt = gimple_build_call_internal (IFN_EXTRACT_LAST,

> -                                                   2, mask, vec_lhs);

> -      gimple_call_set_lhs (new_stmt, scalar_res);

> -      gimple_seq_add_stmt (&stmts, new_stmt);

> +      tree scalar_res = gimple_build (&stmts, CFN_EXTRACT_LAST,

> +                                     scalar_type, mask, vec_lhs);


>         /* Convert the extracted vector element to the required scalar

type.  */
>         new_tree = gimple_convert (&stmts, lhs_type, scalar_res);

Patch

Index: gcc/gimple-fold.h
===================================================================
--- gcc/gimple-fold.h	2018-05-16 20:17:39.114152860 +0100
+++ gcc/gimple-fold.h	2018-05-17 09:17:32.876478942 +0100
@@ -86,28 +86,25 @@  gimple_build (gimple_seq *seq,
 {
   return gimple_build (seq, UNKNOWN_LOCATION, code, type, op0, op1, op2);
 }
-extern tree gimple_build (gimple_seq *, location_t,
-			  enum built_in_function, tree, tree);
+extern tree gimple_build (gimple_seq *, location_t, combined_fn, tree, tree);
 inline tree
-gimple_build (gimple_seq *seq,
-	      enum built_in_function fn, tree type, tree arg0)
+gimple_build (gimple_seq *seq, combined_fn fn, tree type, tree arg0)
 {
   return gimple_build (seq, UNKNOWN_LOCATION, fn, type, arg0);
 }
-extern tree gimple_build (gimple_seq *, location_t,
-			  enum built_in_function, tree, tree, tree);
+extern tree gimple_build (gimple_seq *, location_t, combined_fn,
+			  tree, tree, tree);
 inline tree
-gimple_build (gimple_seq *seq,
-	      enum built_in_function fn, tree type, tree arg0, tree arg1)
+gimple_build (gimple_seq *seq, combined_fn fn,
+	      tree type, tree arg0, tree arg1)
 {
   return gimple_build (seq, UNKNOWN_LOCATION, fn, type, arg0, arg1);
 }
-extern tree gimple_build (gimple_seq *, location_t,
-			  enum built_in_function, tree, tree, tree, tree);
+extern tree gimple_build (gimple_seq *, location_t, combined_fn,
+			  tree, tree, tree, tree);
 inline tree
-gimple_build (gimple_seq *seq,
-	      enum built_in_function fn, tree type,
-	      tree arg0, tree arg1, tree arg2)
+gimple_build (gimple_seq *seq, combined_fn fn,
+	      tree type, tree arg0, tree arg1, tree arg2)
 {
   return gimple_build (seq, UNKNOWN_LOCATION, fn, type, arg0, arg1, arg2);
 }
@@ -153,11 +150,11 @@  extern tree gimple_simplify (enum tree_c
 			     gimple_seq *, tree (*)(tree));
 extern tree gimple_simplify (enum tree_code, tree, tree, tree, tree,
 			     gimple_seq *, tree (*)(tree));
-extern tree gimple_simplify (enum built_in_function, tree, tree,
+extern tree gimple_simplify (combined_fn, tree, tree,
 			     gimple_seq *, tree (*)(tree));
-extern tree gimple_simplify (enum built_in_function, tree, tree, tree,
+extern tree gimple_simplify (combined_fn, tree, tree, tree,
 			     gimple_seq *, tree (*)(tree));
-extern tree gimple_simplify (enum built_in_function, tree, tree, tree, tree,
+extern tree gimple_simplify (combined_fn, tree, tree, tree, tree,
 			     gimple_seq *, tree (*)(tree));
 
 #endif  /* GCC_GIMPLE_FOLD_H */
Index: gcc/gimple-match-head.c
===================================================================
--- gcc/gimple-match-head.c	2018-03-30 12:28:37.301927949 +0100
+++ gcc/gimple-match-head.c	2018-05-17 09:17:32.876478942 +0100
@@ -478,55 +478,53 @@  gimple_simplify (enum tree_code code, tr
   return maybe_push_res_to_seq (rcode, type, ops, seq);
 }
 
-/* Builtin function with one argument.  */
+/* Builtin or internal function with one argument.  */
 
 tree
-gimple_simplify (enum built_in_function fn, tree type,
+gimple_simplify (combined_fn fn, tree type,
 		 tree arg0,
 		 gimple_seq *seq, tree (*valueize)(tree))
 {
   if (constant_for_folding (arg0))
     {
-      tree res = fold_const_call (as_combined_fn (fn), type, arg0);
+      tree res = fold_const_call (fn, type, arg0);
       if (res && CONSTANT_CLASS_P (res))
 	return res;
     }
 
   code_helper rcode;
   tree ops[3] = {};
-  if (!gimple_simplify (&rcode, ops, seq, valueize,
-			as_combined_fn (fn), type, arg0))
+  if (!gimple_simplify (&rcode, ops, seq, valueize, fn, type, arg0))
     return NULL_TREE;
   return maybe_push_res_to_seq (rcode, type, ops, seq);
 }
 
-/* Builtin function with two arguments.  */
+/* Builtin or internal function with two arguments.  */
 
 tree
-gimple_simplify (enum built_in_function fn, tree type,
+gimple_simplify (combined_fn fn, tree type,
 		 tree arg0, tree arg1,
 		 gimple_seq *seq, tree (*valueize)(tree))
 {
   if (constant_for_folding (arg0)
       && constant_for_folding (arg1))
     {
-      tree res = fold_const_call (as_combined_fn (fn), type, arg0, arg1);
+      tree res = fold_const_call (fn, type, arg0, arg1);
       if (res && CONSTANT_CLASS_P (res))
 	return res;
     }
 
   code_helper rcode;
   tree ops[3] = {};
-  if (!gimple_simplify (&rcode, ops, seq, valueize,
-			as_combined_fn (fn), type, arg0, arg1))
+  if (!gimple_simplify (&rcode, ops, seq, valueize, fn, type, arg0, arg1))
     return NULL_TREE;
   return maybe_push_res_to_seq (rcode, type, ops, seq);
 }
 
-/* Builtin function with three arguments.  */
+/* Builtin or internal function with three arguments.  */
 
 tree
-gimple_simplify (enum built_in_function fn, tree type,
+gimple_simplify (combined_fn fn, tree type,
 		 tree arg0, tree arg1, tree arg2,
 		 gimple_seq *seq, tree (*valueize)(tree))
 {
@@ -534,7 +532,7 @@  gimple_simplify (enum built_in_function
       && constant_for_folding (arg1)
       && constant_for_folding (arg2))
     {
-      tree res = fold_const_call (as_combined_fn (fn), type, arg0, arg1, arg2);
+      tree res = fold_const_call (fn, type, arg0, arg1, arg2);
       if (res && CONSTANT_CLASS_P (res))
 	return res;
     }
@@ -542,7 +540,7 @@  gimple_simplify (enum built_in_function
   code_helper rcode;
   tree ops[3] = {};
   if (!gimple_simplify (&rcode, ops, seq, valueize,
-			as_combined_fn (fn), type, arg0, arg1, arg2))
+			fn, type, arg0, arg1, arg2))
     return NULL_TREE;
   return maybe_push_res_to_seq (rcode, type, ops, seq);
 }
Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c	2018-05-01 19:30:33.230500376 +0100
+++ gcc/gimple-fold.c	2018-05-17 09:17:32.876478942 +0100
@@ -7204,14 +7204,20 @@  gimple_build (gimple_seq *seq, location_
    statements possibly defining it to SEQ.  */
 
 tree
-gimple_build (gimple_seq *seq, location_t loc,
-	      enum built_in_function fn, tree type, tree arg0)
+gimple_build (gimple_seq *seq, location_t loc, combined_fn fn,
+	      tree type, tree arg0)
 {
   tree res = gimple_simplify (fn, type, arg0, seq, gimple_build_valueize);
   if (!res)
     {
-      tree decl = builtin_decl_implicit (fn);
-      gimple *stmt = gimple_build_call (decl, 1, arg0);
+      gcall *stmt;
+      if (internal_fn_p (fn))
+	stmt = gimple_build_call_internal (as_internal_fn (fn), 1, arg0);
+      else
+	{
+	  tree decl = builtin_decl_implicit (as_builtin_fn (fn));
+	  stmt = gimple_build_call (decl, 1, arg0);
+	}
       if (!VOID_TYPE_P (type))
 	{
 	  res = create_tmp_reg_or_ssa_name (type);
@@ -7230,14 +7236,20 @@  gimple_build (gimple_seq *seq, location_
    statements possibly defining it to SEQ.  */
 
 tree
-gimple_build (gimple_seq *seq, location_t loc,
-	      enum built_in_function fn, tree type, tree arg0, tree arg1)
+gimple_build (gimple_seq *seq, location_t loc, combined_fn fn,
+	      tree type, tree arg0, tree arg1)
 {
   tree res = gimple_simplify (fn, type, arg0, arg1, seq, gimple_build_valueize);
   if (!res)
     {
-      tree decl = builtin_decl_implicit (fn);
-      gimple *stmt = gimple_build_call (decl, 2, arg0, arg1);
+      gcall *stmt;
+      if (internal_fn_p (fn))
+	stmt = gimple_build_call_internal (as_internal_fn (fn), 2, arg0, arg1);
+      else
+	{
+	  tree decl = builtin_decl_implicit (as_builtin_fn (fn));
+	  stmt = gimple_build_call (decl, 2, arg0, arg1);
+	}
       if (!VOID_TYPE_P (type))
 	{
 	  res = create_tmp_reg_or_ssa_name (type);
@@ -7256,16 +7268,22 @@  gimple_build (gimple_seq *seq, location_
    statements possibly defining it to SEQ.  */
 
 tree
-gimple_build (gimple_seq *seq, location_t loc,
-	      enum built_in_function fn, tree type,
-	      tree arg0, tree arg1, tree arg2)
+gimple_build (gimple_seq *seq, location_t loc, combined_fn fn,
+	      tree type, tree arg0, tree arg1, tree arg2)
 {
   tree res = gimple_simplify (fn, type, arg0, arg1, arg2,
 			      seq, gimple_build_valueize);
   if (!res)
     {
-      tree decl = builtin_decl_implicit (fn);
-      gimple *stmt = gimple_build_call (decl, 3, arg0, arg1, arg2);
+      gcall *stmt;
+      if (internal_fn_p (fn))
+	stmt = gimple_build_call_internal (as_internal_fn (fn),
+					   3, arg0, arg1, arg2);
+      else
+	{
+	  tree decl = builtin_decl_implicit (as_builtin_fn (fn));
+	  stmt = gimple_build_call (decl, 3, arg0, arg1, arg2);
+	}
       if (!VOID_TYPE_P (type))
 	{
 	  res = create_tmp_reg_or_ssa_name (type);
Index: gcc/tree-vect-loop.c
===================================================================
--- gcc/tree-vect-loop.c	2018-05-16 12:50:14.893361868 +0100
+++ gcc/tree-vect-loop.c	2018-05-17 09:17:32.877478908 +0100
@@ -4179,12 +4179,10 @@  get_initial_def_for_reduction (gimple *s
 	else if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant ())
 	  {
 	    /* Option2 (variable length): the first element is INIT_VAL.  */
-	    init_def = build_vector_from_val (vectype, def_for_init);
-	    gcall *call = gimple_build_call_internal (IFN_VEC_SHL_INSERT,
-						      2, init_def, init_val);
-	    init_def = make_ssa_name (vectype);
-	    gimple_call_set_lhs (call, init_def);
-	    gimple_seq_add_stmt (&stmts, call);
+	    init_def = gimple_build_vector_from_val (&stmts, vectype,
+						     def_for_init);
+	    init_def = gimple_build (&stmts, CFN_VEC_SHL_INSERT,
+				     vectype, init_def, init_val);
 	  }
 	else
 	  {
@@ -4327,11 +4325,8 @@  get_initial_defs_for_reduction (slp_tree
 		  while (k > 0)
 		    {
 		      k -= 1;
-		      gcall *call = gimple_build_call_internal
-			(IFN_VEC_SHL_INSERT, 2, init, elts[k]);
-		      init = make_ssa_name (vector_type);
-		      gimple_call_set_lhs (call, init);
-		      gimple_seq_add_stmt (&ctor_seq, call);
+		      init = gimple_build (&ctor_seq, CFN_VEC_SHL_INSERT,
+					   vector_type, init, elts[k]);
 		    }
 		}
 	      else
@@ -5234,10 +5229,8 @@  vect_create_epilog_for_reduction (vec<tr
 				   sel, new_phi_result, vector_identity);
 
 	  /* Do the reduction and convert it to the appropriate type.  */
-	  gcall *call = gimple_build_call_internal (reduc_fn, 1, vec);
-	  tree scalar = make_ssa_name (TREE_TYPE (vectype));
-	  gimple_call_set_lhs (call, scalar);
-	  gimple_seq_add_stmt (&seq, call);
+	  tree scalar = gimple_build (&seq, as_combined_fn (reduc_fn),
+				      TREE_TYPE (vectype), vec);
 	  scalar = gimple_convert (&seq, scalar_type, scalar);
 	  scalar_results.safe_push (scalar);
 	}
@@ -8048,13 +8041,10 @@  vectorizable_live_operation (gimple *stm
 	 the loop mask for the final iteration.  */
       gcc_assert (ncopies == 1 && !slp_node);
       tree scalar_type = TREE_TYPE (STMT_VINFO_VECTYPE (stmt_info));
-      tree scalar_res = make_ssa_name (scalar_type);
       tree mask = vect_get_loop_mask (gsi, &LOOP_VINFO_MASKS (loop_vinfo),
 				      1, vectype, 0);
-      gcall *new_stmt = gimple_build_call_internal (IFN_EXTRACT_LAST,
-						    2, mask, vec_lhs);
-      gimple_call_set_lhs (new_stmt, scalar_res);
-      gimple_seq_add_stmt (&stmts, new_stmt);
+      tree scalar_res = gimple_build (&stmts, CFN_EXTRACT_LAST,
+				      scalar_type, mask, vec_lhs);
 
       /* Convert the extracted vector element to the required scalar type.  */
       new_tree = gimple_convert (&stmts, lhs_type, scalar_res);