OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index a22b5d3..8c2c5ac 100644 (file)
@@ -1109,12 +1109,12 @@ build_stack_save_restore (gimple *save, gimple *restore)
 {
   tree tmp_var;
 
-  *save = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_SAVE], 0);
+  *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
   tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
   gimple_call_set_lhs (*save, tmp_var);
 
   *restore
-    = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_RESTORE],
+    = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
                         1, tmp_var);
 }
 
@@ -1329,8 +1329,9 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
   SET_DECL_VALUE_EXPR (decl, t);
   DECL_HAS_VALUE_EXPR_P (decl) = 1;
 
-  t = built_in_decls[BUILT_IN_ALLOCA];
-  t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
+  t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+  t = build_call_expr (t, 2, DECL_SIZE_UNIT (decl),
+                      size_int (DECL_ALIGN (decl)));
   /* The call has been built for a variable-sized object.  */
   CALL_ALLOCA_FOR_VAR_P (t) = 1;
   t = fold_convert (ptr_type, t);
@@ -1799,7 +1800,6 @@ canonicalize_addr_expr (tree *expr_p)
 static enum gimplify_status
 gimplify_conversion (tree *expr_p)
 {
-  tree tem;
   location_t loc = EXPR_LOCATION (*expr_p);
   gcc_assert (CONVERT_EXPR_P (*expr_p));
 
@@ -1810,17 +1810,6 @@ gimplify_conversion (tree *expr_p)
   if (tree_ssa_useless_type_conversion (*expr_p))
     *expr_p = TREE_OPERAND (*expr_p, 0);
 
-  /* Attempt to avoid NOP_EXPR by producing reference to a subtype.
-     For example this fold (subclass *)&A into &A->subclass avoiding
-     a need for statement.  */
-  if (CONVERT_EXPR_P (*expr_p)
-      && POINTER_TYPE_P (TREE_TYPE (*expr_p))
-      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))
-      && (tem = maybe_fold_offset_to_address
-         (EXPR_LOCATION (*expr_p), TREE_OPERAND (*expr_p, 0),
-          integer_zero_node, TREE_TYPE (*expr_p))) != NULL_TREE)
-    *expr_p = tem;
-
   /* If we still have a conversion at the toplevel,
      then canonicalize some constructs.  */
   if (CONVERT_EXPR_P (*expr_p))
@@ -3222,7 +3211,7 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
   to_ptr = build_fold_addr_expr_loc (loc, to);
   gimplify_arg (&to_ptr, seq_p, loc);
 
-  t = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  t = builtin_decl_implicit (BUILT_IN_MEMCPY);
 
   gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
 
@@ -3269,7 +3258,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
 
   to_ptr = build_fold_addr_expr_loc (loc, to);
   gimplify_arg (&to_ptr, seq_p, loc);
-  t = implicit_built_in_decls[BUILT_IN_MEMSET];
+  t = builtin_decl_implicit (BUILT_IN_MEMSET);
 
   gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
 
@@ -4692,7 +4681,7 @@ gimplify_variable_sized_compare (tree *expr_p)
   arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
   src = build_fold_addr_expr_loc (loc, op1);
   dest = build_fold_addr_expr_loc (loc, op0);
-  t = implicit_built_in_decls[BUILT_IN_MEMCMP];
+  t = builtin_decl_implicit (BUILT_IN_MEMCMP);
   t = build_call_expr_loc (loc, t, 3, dest, src, arg);
 
   expr
@@ -7267,8 +7256,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        case TRUTH_XOR_EXPR:
          {
            tree orig_type = TREE_TYPE (*expr_p);
+           tree new_type, xop0, xop1;
            *expr_p = gimple_boolify (*expr_p);
-           if (!useless_type_conversion_p (orig_type, TREE_TYPE (*expr_p)))
+           new_type = TREE_TYPE (*expr_p);
+           if (!useless_type_conversion_p (orig_type, new_type))
              {
                *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
                ret = GS_OK;
@@ -7292,46 +7283,55 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
              default:
                break;
              }
-
+           /* Now make sure that operands have compatible type to
+              expression's new_type.  */
+           xop0 = TREE_OPERAND (*expr_p, 0);
+           xop1 = TREE_OPERAND (*expr_p, 1);
+           if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
+             TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
+                                                           new_type,
+                                                           xop0);
+           if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
+             TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
+                                                           new_type,
+                                                           xop1);
            /* Continue classified as tcc_binary.  */
            goto expr_2;
          }
 
        case FMA_EXPR:
+       case VEC_PERM_EXPR:
          /* Classified as tcc_expression.  */
          goto expr_3;
 
        case POINTER_PLUS_EXPR:
-          /* Convert ((type *)A)+offset into &A->field_of_type_and_offset.
-            The second is gimple immediate saving a need for extra statement.
-          */
-         if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
-             && (tmp = maybe_fold_offset_to_address
-                 (EXPR_LOCATION (*expr_p),
-                  TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
-                  TREE_TYPE (*expr_p))))
-           {
-             *expr_p = tmp;
-             ret = GS_OK;
-             break;
-           }
-         /* Convert (void *)&a + 4 into (void *)&a[1].  */
-         if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == NOP_EXPR
-             && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
-             && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p,
-                                                                       0),0)))
-             && (tmp = maybe_fold_offset_to_address
-                 (EXPR_LOCATION (*expr_p),
-                  TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0),
-                  TREE_OPERAND (*expr_p, 1),
-                  TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0),
-                                           0)))))
-            {
-               *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp);
-              ret = GS_OK;
-              break;
-            }
-          /* FALLTHRU */
+         {
+           enum gimplify_status r0, r1;
+           r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+                               post_p, is_gimple_val, fb_rvalue);
+           r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+                               post_p, is_gimple_val, fb_rvalue);
+           recalculate_side_effects (*expr_p);
+           ret = MIN (r0, r1);
+           /* Convert &X + CST to invariant &MEM[&X, CST].  Do this
+              after gimplifying operands - this is similar to how
+              it would be folding all gimplified stmts on creation
+              to have them canonicalized, which is what we eventually
+              should do anyway.  */
+           if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
+               && is_gimple_min_invariant (TREE_OPERAND (*expr_p, 0)))
+             {
+               *expr_p = build_fold_addr_expr_with_type_loc
+                  (input_location,
+                   fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (*expr_p)),
+                                TREE_OPERAND (*expr_p, 0),
+                                fold_convert (ptr_type_node,
+                                              TREE_OPERAND (*expr_p, 1))),
+                   TREE_TYPE (*expr_p));
+               ret = MIN (ret, GS_OK);
+             }
+           break;
+         }
 
        default:
          switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
@@ -7993,24 +7993,24 @@ gimplify_function_tree (tree fndecl)
       tree tmp_var;
       gimple call;
 
-      x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+      x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
       call = gimple_build_call (x, 1, integer_zero_node);
       tmp_var = create_tmp_var (ptr_type_node, "return_addr");
       gimple_call_set_lhs (call, tmp_var);
       gimplify_seq_add_stmt (&cleanup, call);
-      x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT];
+      x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_EXIT);
       call = gimple_build_call (x, 2,
                                build_fold_addr_expr (current_function_decl),
                                tmp_var);
       gimplify_seq_add_stmt (&cleanup, call);
       tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
 
-      x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+      x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
       call = gimple_build_call (x, 1, integer_zero_node);
       tmp_var = create_tmp_var (ptr_type_node, "return_addr");
       gimple_call_set_lhs (call, tmp_var);
       gimplify_seq_add_stmt (&body, call);
-      x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
+      x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_ENTER);
       call = gimple_build_call (x, 2,
                                build_fold_addr_expr (current_function_decl),
                                tmp_var);