diff mbox

replace fold_convert (..., integer_zero_node) with build_zero_cst

Message ID 20101102133508.GA26083@nightcrawler
State New
Headers show

Commit Message

Nathan Froyd Nov. 2, 2010, 1:35 p.m. UTC
http://gcc.gnu.org/wiki/Partial_Transitions indicates that it'd be a
good idea to replace fold_converts of integer_zero_node with
build_int_cst.  The patch below takes the lazy route of not carefully
examining every such instance for dealing with integer types only, but
instead relying on build_zero_cst for dealing with real vs. integer
vs. fixed, etc.

In order to avoid making us do:

  build_zero_cst -> fold_convert -> ... -> build_int_cst

where we were once doing:

  fold_convert -> ... -> build_int_cst

the patch also adds shortcut cases for numerical types, similar to what
is already done in build_one_cst.

Tested on x86_64-unknown-linux-gnu.  I think the patch qualifies as
obvious (replacing bits of code with a call that implements said bits),
but the changes to build_zero_cst need approval.  OK to commit?

-Nathan

gcc/
	* builtins.c (fold_builtin_signbit): Use build_zero_cst instead of
	fold_convert.
	* c-typeck.c (build_function_call_vec): Likewise.
	* cfgexpand.c (expand_debug_expr): Likewise.
	* cgraphunit.c (assemble_thunk): Likewise.
	* config/sparc/sparc.c (sparc_fold_builtin): Likewise.
	* fold-const.c (fold_unary_loc, fold_mult_zconjz): Likewise.
	(fold_binary_loc, fold_ternary_loc): Likewise.
	* gimple-fold.c (get_symbol_constant_value): Likewise.
	* gimple-low.c (lower_builtin_setjmp): Likewise.
	* gimple.c (gimple_cond_get_ops_from_tree): Likewise.
	* gimplify.c (gimplify_init_constructor): Likewise.
	* lambda.h (build_linear_expr): Likewise.
	* omp-low.c (omp_reduction_init): Likewise.
	* tree-inline.c (remap_ssa_name): Likewise.
	* tree-object-size.c (compute_object_sizes): Likewise.
	* tree-sra.c (init_subtree_with_zero): Likewise.
	(sra_ipa_modify_assign): Likewise.
	* tree-ssa-copy.c (propagate_tree_value_into_stmt): Likewise.
	* tree-ssa-reassoc.c (eliminate_duplicate_pair): Likewise.
	(eliminate_plus_minus_pair, eliminate_not_pairs): Likewise.
	(undistribute_ops_list): Likewise.
	* tree-ssa-sccvn.c (vn_reference_lookup_3): Likewise.
	* tree-vect-stmts.c (vectorizable_call): Likewise.
	* tree.c (build_vector_from_ctor, build_one_cst): Likewise.
	(build_zero_cst): Handle more cases directly.  Update comment.

gcc/cp/
	* class.c (build_base_path, add_vcall_offset): Use build_zero_cst
	instead of fold_convert.
	* init.c (build_zero_init): Likewise.
	* typeck.c (cp_build_binary_op): Likewise.

gcc/fortran/
	* trans-decl.c (add_argument_checking): Use build_zero_cst instead of
	fold_convert.
	* trans-expr.c (gfc_conv_missing_dummy, fill_with_spaces): Likewise.
	* trans-stmt.c (gfc_trans_do): Likewise.

Comments

Steve Kargl Nov. 2, 2010, 2:10 p.m. UTC | #1
On Tue, Nov 02, 2010 at 09:35:10AM -0400, Nathan Froyd wrote:
> 
> gcc/fortran/
> 	* trans-decl.c (add_argument_checking): Use build_zero_cst instead of
> 	fold_convert.
> 	* trans-expr.c (gfc_conv_missing_dummy, fill_with_spaces): Likewise.
> 	* trans-stmt.c (gfc_trans_do): Likewise.

The Fortran part is OK.
Richard Henderson Nov. 2, 2010, 8:47 p.m. UTC | #2
On 11/02/2010 06:35 AM, Nathan Froyd wrote:
> http://gcc.gnu.org/wiki/Partial_Transitions indicates that it'd be a
> good idea to replace fold_converts of integer_zero_node with
> build_int_cst.  The patch below takes the lazy route of not carefully
> examining every such instance for dealing with integer types only, but
> instead relying on build_zero_cst for dealing with real vs. integer
> vs. fixed, etc.
> 
> In order to avoid making us do:
> 
>   build_zero_cst -> fold_convert -> ... -> build_int_cst
> 
> where we were once doing:
> 
>   fold_convert -> ... -> build_int_cst
> 
> the patch also adds shortcut cases for numerical types, similar to what
> is already done in build_one_cst.


Ok.


r~
diff mbox

Patch

diff --git a/gcc/builtins.c b/gcc/builtins.c
index ced2fa7..4ff0546 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -9101,8 +9101,6 @@  fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
 static tree
 fold_builtin_signbit (location_t loc, tree arg, tree type)
 {
-  tree temp;
-
   if (!validate_arg (arg, REAL_TYPE))
     return NULL_TREE;
 
@@ -9113,8 +9111,9 @@  fold_builtin_signbit (location_t loc, tree arg, tree type)
       REAL_VALUE_TYPE c;
 
       c = TREE_REAL_CST (arg);
-      temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
-      return fold_convert_loc (loc, type, temp);
+      return (REAL_VALUE_NEGATIVE (c)
+	      ? build_one_cst (type)
+	      : build_zero_cst (type));
     }
 
   /* If ARG is non-negative, the result is always zero.  */
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 4c53ef0..7f448dd 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -2821,7 +2821,7 @@  build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
 					  build_constructor (return_type, 0),
 					  false);
 	  else
-	    rhs = fold_convert_loc (loc, return_type, integer_zero_node);
+	    rhs = build_zero_cst (return_type);
 
 	  return require_complete_type (build2 (COMPOUND_EXPR, return_type,
 						trap, rhs));
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 1ef1fa0..f02a8cd 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3073,7 +3073,7 @@  expand_debug_expr (tree exp)
 	  if (i < TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp)))
 	    {
 	      op1 = expand_debug_expr
-		(fold_convert (TREE_TYPE (TREE_TYPE (exp)), integer_zero_node));
+		(build_zero_cst (TREE_TYPE (TREE_TYPE (exp))));
 
 	      if (!op1)
 		return NULL;
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 2abcb67..ed86a02 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1411,8 +1411,7 @@  assemble_thunk (struct cgraph_node *node)
 	      remove_edge (single_succ_edge (bb));
 	      true_label = gimple_block_label (then_bb);
 	      stmt = gimple_build_cond (NE_EXPR, restmp,
-	      				fold_convert (TREE_TYPE (restmp),
-						      integer_zero_node),
+	      				build_zero_cst (TREE_TYPE (restmp)),
 	      			        NULL_TREE, NULL_TREE);
 	      gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
 	      make_edge (bb, then_bb, EDGE_TRUE_VALUE);
@@ -1429,8 +1428,8 @@  assemble_thunk (struct cgraph_node *node)
 	    {
 	      gimple stmt;
 	      bsi = gsi_last_bb (else_bb);
-	      stmt = gimple_build_assign (restmp, fold_convert (TREE_TYPE (restmp),
-								integer_zero_node));
+	      stmt = gimple_build_assign (restmp,
+					  build_zero_cst (TREE_TYPE (restmp)));
 	      gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
 	      bsi = gsi_last_bb (return_bb);
 	    }
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index e23ede0..4793e77 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -8748,7 +8748,7 @@  sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
   if (ignore
       && icode != CODE_FOR_alignaddrsi_vis
       && icode != CODE_FOR_alignaddrdi_vis)
-    return fold_convert (rtype, integer_zero_node);
+    return build_zero_cst (rtype);
 
   switch (icode)
     {
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 217450c..ed551c3 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -431,8 +431,7 @@  build_base_path (enum tree_code code,
  out:
   if (null_test)
     expr = fold_build3_loc (input_location, COND_EXPR, target_type, null_test, expr,
-			fold_build1_loc (input_location, NOP_EXPR, target_type,
-				     integer_zero_node));
+			    build_zero_cst (target_type));
 
   return expr;
 }
@@ -8267,8 +8266,7 @@  add_vcall_offset (tree orig_fn, tree binfo, vtbl_init_data *vid)
       /* Find the overriding function.  */
       fn = find_final_overrider (vid->rtti_binfo, binfo, orig_fn);
       if (fn == error_mark_node)
-	vcall_offset = build1 (NOP_EXPR, vtable_entry_type,
-			       integer_zero_node);
+	vcall_offset = build_zero_cst (vtable_entry_type);
       else
 	{
 	  base = TREE_VALUE (fn);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index d632816..1f73d14 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -254,7 +254,7 @@  build_zero_init (tree type, tree nelts, bool static_storage_p)
       init = build_constructor (type, v);
     }
   else if (TREE_CODE (type) == VECTOR_TYPE)
-    init = fold_convert (type, integer_zero_node);
+    init = build_zero_cst (type);
   else
     gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0da3278..25a65b6 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4141,8 +4141,7 @@  cp_build_binary_op (location_t location,
 	      tree e1 = cp_build_binary_op (location,
 					    EQ_EXPR,
 	  			            pfn0,	
-				      	    fold_convert (TREE_TYPE (pfn0),
-							  integer_zero_node),
+				      	    build_zero_cst (TREE_TYPE (pfn0)),
 					    complain);
 	      tree e2 = cp_build_binary_op (location,
 					    BIT_AND_EXPR, 
@@ -4232,8 +4231,7 @@  cp_build_binary_op (location_t location,
 				       complain);
 	      e2 = cp_build_binary_op (location, EQ_EXPR,
 				       pfn0,
-				       fold_convert (TREE_TYPE (pfn0),
-						     integer_zero_node),
+				       build_zero_cst (TREE_TYPE (pfn0)),
 				       complain);
 	      e2 = cp_build_binary_op (location,
 				       TRUTH_ANDIF_EXPR, e2, e1, complain);
@@ -4258,8 +4256,7 @@  cp_build_binary_op (location_t location,
 	      e2 = cp_build_binary_op (location,
 				       EQ_EXPR,
 		      		       pfn0,
-			   	       fold_convert (TREE_TYPE (pfn0),
-						     integer_zero_node),
+			   	       build_zero_cst (TREE_TYPE (pfn0)),
 				       complain);
 	      e1 = cp_build_binary_op (location,
 				       TRUTH_ORIF_EXPR, e1, e2, complain);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 67268ad..da890f1 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8228,7 +8228,7 @@  fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
 
     case IMAGPART_EXPR:
       if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-	return fold_convert_loc (loc, type, integer_zero_node);
+	return build_zero_cst (type);
       if (TREE_CODE (arg0) == COMPLEX_EXPR)
 	return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 1),
 				 TREE_OPERAND (arg0, 0));
@@ -9283,7 +9283,7 @@  fold_mult_zconjz (location_t loc, tree type, tree expr)
 		     fold_build2_loc (loc, MULT_EXPR, itype, rpart, rpart),
 		     fold_build2_loc (loc, MULT_EXPR, itype, ipart, ipart));
   return fold_build2_loc (loc, COMPLEX_EXPR, type, tem,
-		      fold_convert_loc (loc, itype, integer_zero_node));
+			  build_zero_cst (itype));
 }
 
 
@@ -10275,7 +10275,7 @@  fold_binary_loc (location_t loc,
 
       if ((!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type)))
 	  && operand_equal_p (arg0, arg1, 0))
-	return fold_convert_loc (loc, type, integer_zero_node);
+	return build_zero_cst (type);
 
       /* A - B -> A + (-B) if B is easily negatable.  */
       if (negate_expr_p (arg1)
@@ -10662,7 +10662,7 @@  fold_binary_loc (location_t loc,
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
 	  && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
 	{
-	  t1 = fold_convert_loc (loc, type, integer_zero_node);
+	  t1 = build_zero_cst (type);
 	  t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
 	  return omit_one_operand_loc (loc, type, t1, arg1);
 	}
@@ -10671,7 +10671,7 @@  fold_binary_loc (location_t loc,
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
 	  && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
 	{
-	  t1 = fold_convert_loc (loc, type, integer_zero_node);
+	  t1 = build_zero_cst (type);
 	  t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
 	  return omit_one_operand_loc (loc, type, t1, arg0);
 	}
@@ -10801,7 +10801,7 @@  fold_binary_loc (location_t loc,
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
 	  && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
 	{
-	  t1 = fold_convert_loc (loc, type, integer_zero_node);
+	  t1 = build_zero_cst (type);
 	  t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
 	  return omit_one_operand_loc (loc, type, t1, arg1);
 	}
@@ -10810,7 +10810,7 @@  fold_binary_loc (location_t loc,
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
 	  && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
 	{
-	  t1 = fold_convert_loc (loc, type, integer_zero_node);
+	  t1 = build_zero_cst (type);
 	  t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
 	  return omit_one_operand_loc (loc, type, t1, arg0);
 	}
@@ -13598,7 +13598,7 @@  fold_ternary_loc (location_t loc, enum tree_code code, tree type,
 	      if (elements)
 		return TREE_VALUE (elements);
 	      else
-		return fold_convert_loc (loc, type, integer_zero_node);
+		return build_zero_cst (type);
 	    }
 	}
 
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 2c4ebbb..70cad69 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -4214,8 +4214,7 @@  add_argument_checking (stmtblock_t *block, gfc_symbol *sym)
 	    not_0length = fold_build2_loc (input_location, NE_EXPR,
 					   boolean_type_node,
 					   cl->passed_length,
-					   fold_convert (gfc_charlen_type_node,
-							 integer_zero_node));
+					   build_zero_cst (gfc_charlen_type_node));
 	    /* The symbol needs to be referenced for gfc_get_symbol_decl.  */
 	    fsym->attr.referenced = 1;
 	    not_absent = gfc_conv_expr_present (fsym);
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index c1588f8..8da6cf0 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -187,7 +187,7 @@  gfc_conv_missing_dummy (gfc_se * se, gfc_expr * arg, gfc_typespec ts, int kind)
     {
       tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
 			present, se->expr,
-			fold_convert (TREE_TYPE (se->expr), integer_zero_node));
+			build_zero_cst (TREE_TYPE (se->expr)));
       tmp = gfc_evaluate_now (tmp, &se->pre);
       se->expr = tmp;
     }
@@ -3634,7 +3634,7 @@  fill_with_spaces (tree start, tree type, tree size)
 
   /* Exit condition.  */
   cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, i,
-			  fold_convert (sizetype, integer_zero_node));
+			  build_zero_cst (sizetype));
   tmp = build1_v (GOTO_EXPR, exit_label);
   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
 			 build_empty_stmt (input_location));
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index da790d8..f065adb 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -1126,7 +1126,7 @@  gfc_trans_do (gfc_code * code, tree exit_cond)
   if (gfc_option.rtcheck & GFC_RTCHECK_DO)
     {
       tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
-			     fold_convert (type, integer_zero_node));
+			     build_zero_cst (type));
       gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
 			       "DO step value is zero");
     }
@@ -1138,7 +1138,7 @@  gfc_trans_do (gfc_code * code, tree exit_cond)
     return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
 
   pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
-			      fold_convert (type, integer_zero_node));
+			      build_zero_cst (type));
 
   if (TREE_CODE (type) == INTEGER_TYPE)
     utype = unsigned_type_for (type);
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 6862c12..f2db1db 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -159,7 +159,7 @@  get_symbol_constant_value (tree sym)
       if (!val
           && (INTEGRAL_TYPE_P (TREE_TYPE (sym))
 	       || SCALAR_FLOAT_TYPE_P (TREE_TYPE (sym))))
-	return fold_convert (TREE_TYPE (sym), integer_zero_node);
+	return build_zero_cst (TREE_TYPE (sym));
     }
 
   return NULL_TREE;
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 1f7ae2f..dcbb560 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -844,8 +844,7 @@  lower_builtin_setjmp (gimple_stmt_iterator *gsi)
   /* Build 'DEST = 0' and insert.  */
   if (dest)
     {
-      g = gimple_build_assign (dest, fold_convert_loc (loc, TREE_TYPE (dest),
-						       integer_zero_node));
+      g = gimple_build_assign (dest, build_zero_cst (TREE_TYPE (dest)));
       gimple_set_location (g, loc);
       gimple_set_block (g, gimple_block (stmt));
       gsi_insert_before (gsi, g, GSI_SAME_STMT);
diff --git a/gcc/gimple.c b/gcc/gimple.c
index dea0b83..1bb241a 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -449,7 +449,6 @@  void
 gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
                                tree *lhs_p, tree *rhs_p)
 {
-  location_t loc = EXPR_LOCATION (cond);
   gcc_assert (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison
 	      || TREE_CODE (cond) == TRUTH_NOT_EXPR
 	      || is_gimple_min_invariant (cond)
@@ -462,14 +461,14 @@  gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
     {
       *code_p = EQ_EXPR;
       gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
-      *rhs_p = fold_convert_loc (loc, TREE_TYPE (*lhs_p), integer_zero_node);
+      *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
     }
   /* Canonicalize conditionals of the form 'if (VAL)'  */
   else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
     {
       *code_p = NE_EXPR;
       gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
-      *rhs_p = fold_convert_loc (loc, TREE_TYPE (*lhs_p), integer_zero_node);
+      *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
     }
 }
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 885f013..94a6689 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -3885,7 +3885,7 @@  gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	i = VEC_index (constructor_elt, elts, 1)->value;
 	if (r == NULL || i == NULL)
 	  {
-	    tree zero = fold_convert (TREE_TYPE (type), integer_zero_node);
+	    tree zero = build_zero_cst (TREE_TYPE (type));
 	    if (r == NULL)
 	      r = zero;
 	    if (i == NULL)
diff --git a/gcc/lambda.h b/gcc/lambda.h
index 8ef11b9..d54ed27 100644
--- a/gcc/lambda.h
+++ b/gcc/lambda.h
@@ -486,7 +486,7 @@  build_linear_expr (tree type, lambda_vector coefs, VEC (tree, heap) *ivs)
 {
   unsigned i;
   tree iv;
-  tree expr = fold_convert (type, integer_zero_node);
+  tree expr = build_zero_cst (type);
 
   for (i = 0; VEC_iterate (tree, ivs, i, iv); i++)
     {
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 3fe94c9..54c243c 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -2167,7 +2167,7 @@  omp_reduction_init (tree clause, tree type)
     case TRUTH_ORIF_EXPR:
     case TRUTH_XOR_EXPR:
     case NE_EXPR:
-      return fold_convert_loc (loc, type, integer_zero_node);
+      return build_zero_cst (type);
 
     case MULT_EXPR:
     case TRUTH_AND_EXPR:
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 133d916..cf8a68e 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -242,10 +242,9 @@  remap_ssa_name (tree name, copy_body_data *id)
 	    {
 	      gimple_stmt_iterator gsi = gsi_last_bb (id->entry_bb);
 	      gimple init_stmt;
+	      tree zero = build_zero_cst (TREE_TYPE (new_tree));
 
-	      init_stmt = gimple_build_assign (new_tree,
-		                               fold_convert (TREE_TYPE (new_tree),
-					       		    integer_zero_node));
+	      init_stmt = gimple_build_assign (new_tree, zero);
 	      gsi_insert_after (&gsi, init_stmt, GSI_NEW_STMT);
 	      SSA_NAME_IS_DEFAULT_DEF (new_tree) = 0;
 	    }
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 2e8ba26..092348b 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -1231,8 +1231,7 @@  compute_object_sizes (void)
 			result = fold_convert (size_type_node,
 					       integer_minus_one_node);
 		      else if (object_size_type < 4)
-			result = fold_convert (size_type_node,
-					       integer_zero_node);
+			result = build_zero_cst (size_type_node);
 		    }
 		}
 
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 3328261..4f0d2e5 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -2324,8 +2324,7 @@  init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
       gimple stmt;
 
       stmt = gimple_build_assign (get_access_replacement (access),
-				  fold_convert (access->type,
-						integer_zero_node));
+				  build_zero_cst (access->type));
       if (insert_after)
 	gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
       else
@@ -4098,7 +4097,7 @@  sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi,
 	    {
 	      /* V_C_Es of constructors can cause trouble (PR 42714).  */
 	      if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
-		*rhs_p = fold_convert (TREE_TYPE (*lhs_p), integer_zero_node);
+		*rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
 	      else
 		*rhs_p = build_constructor (TREE_TYPE (*lhs_p), 0);
 	    }
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index a92b63b..6837033 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -246,7 +246,7 @@  propagate_tree_value_into_stmt (gimple_stmt_iterator *gsi, tree val)
   else if (gimple_code (stmt) == GIMPLE_COND)
     {
       tree lhs = NULL_TREE;
-      tree rhs = fold_convert (TREE_TYPE (val), integer_zero_node);
+      tree rhs = build_zero_cst (TREE_TYPE (val));
       propagate_tree_value (&lhs, val);
       gimple_cond_set_code (stmt, NE_EXPR);
       gimple_cond_set_lhs (stmt, lhs);
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index b4cadfe..790635c 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -467,8 +467,7 @@  eliminate_duplicate_pair (enum tree_code opcode,
 	    {
 	      VEC_free (operand_entry_t, heap, *ops);
 	      *ops = NULL;
-	      add_to_ops_vec (ops, fold_convert (TREE_TYPE (last->op),
-						 integer_zero_node));
+	      add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (last->op)));
 	      *all_done = true;
 	    }
 	  else
@@ -535,8 +534,7 @@  eliminate_plus_minus_pair (enum tree_code opcode,
 	    }
 
 	  VEC_ordered_remove (operand_entry_t, *ops, i);
-	  add_to_ops_vec (ops, fold_convert(TREE_TYPE (oe->op),
-					    integer_zero_node));
+	  add_to_ops_vec (ops, build_zero_cst (TREE_TYPE (oe->op)));
 	  VEC_ordered_remove (operand_entry_t, *ops, currindex);
 	  reassociate_stats.ops_eliminated ++;
 
@@ -623,7 +621,7 @@  eliminate_not_pairs (enum tree_code opcode,
 	    }
 
 	  if (opcode == BIT_AND_EXPR)
-	    oe->op = fold_convert (TREE_TYPE (oe->op), integer_zero_node);
+	    oe->op = build_zero_cst (TREE_TYPE (oe->op));
 	  else if (opcode == BIT_IOR_EXPR)
 	    oe->op = build_low_bits_mask (TREE_TYPE (oe->op),
 					  TYPE_PRECISION (TREE_TYPE (oe->op)));
@@ -1177,7 +1175,7 @@  undistribute_ops_list (enum tree_code opcode,
 		}
 	      zero_one_operation (&oe2->op, c->oecode, c->op);
 	      sum = build_and_add_sum (tmpvar, oe1->op, oe2->op, opcode);
-	      oe2->op = fold_convert (TREE_TYPE (oe2->op), integer_zero_node);
+	      oe2->op = build_zero_cst (TREE_TYPE (oe2->op));
 	      oe2->rank = 0;
 	      oe1->op = gimple_get_lhs (sum);
 	    }
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 557c393..02613aa 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1338,7 +1338,7 @@  vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
 	  && offset2 <= offset
 	  && offset2 + size2 >= offset + maxsize)
 	{
-	  tree val = fold_convert (vr->type, integer_zero_node);
+	  tree val = build_zero_cst (vr->type);
 	  unsigned int value_id = get_or_alloc_constant_value_id (val);
 	  return vn_reference_insert_pieces (vuse, vr->set, vr->type,
 					     VEC_copy (vn_reference_op_s,
@@ -1361,7 +1361,7 @@  vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
 	  && offset2 <= offset
 	  && offset2 + size2 >= offset + maxsize)
 	{
-	  tree val = fold_convert (vr->type, integer_zero_node);
+	  tree val = build_zero_cst (vr->type);
 	  unsigned int value_id = get_or_alloc_constant_value_id (val);
 	  return vn_reference_insert_pieces (vuse, vr->set, vr->type,
 					     VEC_copy (vn_reference_op_s,
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 183bb11..4961ccb 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1580,7 +1580,7 @@  vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
 
   type = TREE_TYPE (scalar_dest);
   new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
-				  fold_convert (type, integer_zero_node));
+				  build_zero_cst (type));
   set_vinfo_for_stmt (new_stmt, stmt_info);
   set_vinfo_for_stmt (stmt, NULL);
   STMT_VINFO_STMT (stmt_info) = new_stmt;
diff --git a/gcc/tree.c b/gcc/tree.c
index a746031..85c4146 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1362,7 +1362,7 @@  build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v)
     list = tree_cons (NULL_TREE, value, list);
   for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx)
     list = tree_cons (NULL_TREE,
-		      fold_convert (TREE_TYPE (type), integer_zero_node), list);
+		      build_zero_cst (TREE_TYPE (type)), list);
   return build_vector (type, nreverse (list));
 }
 
@@ -1599,22 +1599,52 @@  build_one_cst (tree type)
     case COMPLEX_TYPE:
       return build_complex (type,
 			    build_one_cst (TREE_TYPE (type)),
-			    fold_convert (TREE_TYPE (type), integer_zero_node));
+			    build_zero_cst (TREE_TYPE (type)));
 
     default:
       gcc_unreachable ();
     }
 }
 
-/* Build 0 constant of type TYPE.  This is used by constructor folding and thus
-   the constant should correspond zero in memory representation.  */
+/* Build 0 constant of type TYPE.  This is used by constructor folding
+   and thus the constant should be represented in memory by
+   zero(es).  */
 
 tree
 build_zero_cst (tree type)
 {
-  if (!AGGREGATE_TYPE_P (type))
-    return fold_convert (type, integer_zero_node);
-  return build_constructor (type, NULL);
+  switch (TREE_CODE (type))
+    {
+    case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+    case POINTER_TYPE: case REFERENCE_TYPE:
+    case OFFSET_TYPE:
+      return build_int_cst (type, 0);
+
+    case REAL_TYPE:
+      return build_real (type, dconst0);
+
+    case FIXED_POINT_TYPE:
+      return build_fixed (type, FCONST0 (TYPE_MODE (type)));
+
+    case VECTOR_TYPE:
+      {
+	tree scalar = build_zero_cst (TREE_TYPE (type));
+
+	return build_vector_from_val (type, scalar);
+      }
+
+    case COMPLEX_TYPE:
+      {
+	tree zero = build_zero_cst (TREE_TYPE (type));
+
+	return build_complex (type, zero, zero);
+      }
+
+    default:
+      if (!AGGREGATE_TYPE_P (type))
+	return fold_convert (type, integer_zero_node);
+      return build_constructor (type, NULL);
+    }
 }