gcc/fortran/
* trans-array.c (gfc_grow_array): Calculate old array size and pass it
to gfc_call_realloc.
* trans.c (gfc_call_realloc): Accept new arg old_size. All callers
changed. If it is not NULL_TREE, use the realloc_known_size builtin.
* trans.h (gfc_call_realloc): Adjust declaration.
* f95-lang.c (gfc_init_builtin_functions): Define realloc_known_size
builtin.
gcc/
* builtins.c (expand_builtin): Handle BUILT_IN_REALLOC_KNOWN_SIZE.
* builtins.def (BUILT_IN_REALLOC_KNOWN_SIZE): New.
* builtin-types.def (BT_FN_PTR_PTR_SIZE_SIZE): New.
* target.def (avoid_realloc): New data hook.
* tm.texi.in (TARGET_AVOID_REALLOC): Add.
* tm.texi: Regenerate.
* config/nvptx/nvptx.c (TARGET_AVOID_REALLOC): Define to true.
libgcc/
* config/nvptx/t-nvptx (LIB2ADD): New.
* reallo_known_size.c: New file.
===================================================================
@@ -1233,7 +1233,7 @@ gfc_get_iteration_count (tree start, tre
static void
gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
{
- tree arg0, arg1;
+ tree arg0, arg1, arg2;
tree tmp;
tree size;
tree ubound;
@@ -1242,6 +1242,14 @@ gfc_grow_array (stmtblock_t * pblock, tr
return;
ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
+ size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
+
+ /* Calculate the old array size. */
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
+ ubound, gfc_index_one_node);
+ arg2 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
+ fold_convert (size_type_node, tmp),
+ fold_convert (size_type_node, size));
/* Add EXTRA to the upper bound. */
tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
@@ -1252,7 +1260,6 @@ gfc_grow_array (stmtblock_t * pblock, tr
arg0 = gfc_conv_descriptor_data_get (desc);
/* Calculate the new array size. */
- size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
ubound, gfc_index_one_node);
arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
@@ -1260,7 +1267,7 @@ gfc_grow_array (stmtblock_t * pblock, tr
fold_convert (size_type_node, size));
/* Call the realloc() function. */
- tmp = gfc_call_realloc (pblock, arg0, arg1);
+ tmp = gfc_call_realloc (pblock, arg0, arg1, arg2);
gfc_conv_descriptor_data_set (pblock, desc, tmp);
}
===================================================================
@@ -761,7 +761,7 @@ gfc_omp_clause_assign_op (tree clause, t
gfc_init_block (&inner_block);
gfc_add_modify (&inner_block, ptr,
- gfc_call_realloc (&inner_block, ptr, size));
+ gfc_call_realloc (&inner_block, ptr, size, NULL_TREE));
else_b = gfc_finish_block (&inner_block);
gfc_add_expr_to_block (&cond_block2,
===================================================================
@@ -1459,7 +1459,7 @@ internal_realloc (void *mem, size_t size
return res;
} */
tree
-gfc_call_realloc (stmtblock_t * block, tree mem, tree size)
+gfc_call_realloc (stmtblock_t * block, tree mem, tree size, tree old_size)
{
tree msg, res, nonzero, null_result, tmp;
tree type = TREE_TYPE (mem);
@@ -1473,9 +1473,19 @@ gfc_call_realloc (stmtblock_t * block, t
res = gfc_create_var (type, NULL);
/* Call realloc and check the result. */
- tmp = build_call_expr_loc (input_location,
- builtin_decl_explicit (BUILT_IN_REALLOC), 2,
- fold_convert (pvoid_type_node, mem), size);
+ if (old_size == NULL_TREE)
+ tmp = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_REALLOC), 2,
+ fold_convert (pvoid_type_node, mem), size);
+ else
+ {
+ if (TREE_TYPE (old_size) != TREE_TYPE (size_type_node))
+ old_size = fold_convert (size_type_node, old_size);
+ tree decl = builtin_decl_explicit (BUILT_IN_REALLOC_KNOWN_SIZE);
+ tmp = build_call_expr_loc (input_location, decl, 3,
+ fold_convert (pvoid_type_node, mem), size,
+ old_size);
+ }
gfc_add_modify (block, res, fold_convert (type, tmp));
null_result = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
res, build_int_cst (pvoid_type_node, 0));
===================================================================
@@ -643,8 +643,8 @@ tree gfc_deallocate_with_status (tree, t
gfc_expr *, bool);
tree gfc_deallocate_scalar_with_status (tree, tree, bool, gfc_expr*, gfc_typespec);
-/* Generate code to call realloc(). */
-tree gfc_call_realloc (stmtblock_t *, tree, tree);
+/* Generate code to call realloc or __realloc_known_size. */
+tree gfc_call_realloc (stmtblock_t *, tree, tree, tree);
/* Generate code for an assignment, includes scalarization. */
tree gfc_trans_assignment (gfc_expr *, gfc_expr *, bool, bool);
===================================================================
@@ -6168,6 +6168,16 @@ expand_builtin (tree exp, rtx target, rt
return target;
break;
+ case BUILT_IN_REALLOC_KNOWN_SIZE:
+ if (!targetm.avoid_realloc)
+ {
+ tree fn = builtin_decl_implicit (BUILT_IN_REALLOC);
+ exp = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 2,
+ CALL_EXPR_ARG (exp, 0),
+ CALL_EXPR_ARG (exp, 1));
+ }
+ break;
+
case BUILT_IN_SETJMP:
/* This should have been lowered to the builtins below. */
gcc_unreachable ();
===================================================================
@@ -766,6 +766,7 @@ DEF_GCC_BUILTIN (BUILT_IN_POPCOUN
DEF_EXT_LIB_BUILTIN (BUILT_IN_POSIX_MEMALIGN, "posix_memalign", BT_FN_INT_PTRPTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_GCC_BUILTIN (BUILT_IN_PREFETCH, "prefetch", BT_FN_VOID_CONST_PTR_VAR, ATTR_NOVOPS_LEAF_LIST)
DEF_LIB_BUILTIN (BUILT_IN_REALLOC, "realloc", BT_FN_PTR_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_REALLOC_KNOWN_SIZE, "__realloc_known_size", BT_FN_PTR_PTR_SIZE_SIZE, ATTR_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UINT, ATTR_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL)
===================================================================
@@ -356,6 +356,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_INT_S
BT_PTR, BT_PTR, BT_INT, BT_SIZE)
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_SIZE,
BT_VOID, BT_PTR, BT_INT, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_SIZE_SIZE,
+ BT_PTR, BT_PTR, BT_SIZE, BT_SIZE)
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_INT,
BT_VOID, BT_PTR, BT_INT, BT_INT)
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_CONST_PTR_PTR_SIZE,
===================================================================
@@ -2019,6 +2019,9 @@ nvptx_file_end (void)
#undef TARGET_VECTOR_ALIGNMENT
#define TARGET_VECTOR_ALIGNMENT nvptx_vector_alignment
+#undef TARGET_AVOID_REALLOC
+#define TARGET_AVOID_REALLOC true
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-nvptx.h"
===================================================================
@@ -5154,6 +5154,12 @@ is set to true, the @file{tm.h} file mus
@code{#define LIBGCC2_GNU_PREFIX}.
@end deftypevr
+@deftypevr {Target Hook} bool TARGET_AVOID_REALLOC
+If true, the compiler tries to avoid replace calls to @code{realloc}
+with an internal library function implemented with @code{malloc},
+@code{free} and @code{memcpy}. The default is false.
+@end deftypevr
+
@defmac FLOAT_LIB_COMPARE_RETURNS_BOOL (@var{mode}, @var{comparison})
This macro should return @code{true} if the library routine that
implements the floating point comparison operator @var{comparison} in
===================================================================
@@ -3974,6 +3974,8 @@ are ABI-mandated names that the compiler
@hook TARGET_LIBFUNC_GNU_PREFIX
+@hook TARGET_AVOID_REALLOC
+
@defmac FLOAT_LIB_COMPARE_RETURNS_BOOL (@var{mode}, @var{comparison})
This macro should return @code{true} if the library routine that
implements the floating point comparison operator @var{comparison} in
===================================================================
@@ -2246,6 +2246,14 @@ is set to true, the @file{tm.h} file mus
@code{#define LIBGCC2_GNU_PREFIX}.",
bool, false)
+/* Add a __gnu_ prefix to library functions rather than just __. */
+DEFHOOKPOD
+(avoid_realloc,
+ "If true, the compiler tries to avoid replace calls to @code{realloc}\n\
+with an internal library function implemented with @code{malloc},\n\
+@code{free} and @code{memcpy}. The default is false.",
+ bool, false)
+
/* Given a decl, a section name, and whether the decl initializer
has relocs, choose attributes for the section. */
/* ??? Should be merged with SELECT_SECTION and UNIQUE_SECTION. */
===================================================================
@@ -1,5 +1,6 @@
LIB2ADDEH=
LIB2FUNCS_EXCLUDE=__main
+LIB2ADD = $(srcdir)/realloc_known_size.c
crt0.o: $(srcdir)/config/nvptx/crt0.s
cp $< $@
===================================================================
@@ -0,0 +1,38 @@
+/* Avoid calls to realloc if the size is known. */
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <string.h>
+
+void *
+__realloc_known_size (void *ptr, size_t newsize, size_t oldsize)
+{
+ void *newp = malloc (newsize);
+ if (ptr != 0)
+ {
+ memcpy (newp, ptr, oldsize);
+ free (ptr);
+ }
+ return newp;
+}
===================================================================
@@ -985,6 +985,13 @@
gfc_define_builtin ("__builtin_realloc", ftype, BUILT_IN_REALLOC,
"realloc", ATTR_NOTHROW_LEAF_LIST);
+ ftype = build_function_type_list (pvoid_type_node,
+ pvoid_type_node, size_type_node,
+ size_type_node, NULL_TREE);
+ gfc_define_builtin ("__builtin_realloc_known_size", ftype,
+ BUILT_IN_REALLOC_KNOWN_SIZE,
+ "__realloc_known_size", ATTR_NOTHROW_LEAF_LIST);
+
ftype = build_function_type_list (integer_type_node,
void_type_node, NULL_TREE);
gfc_define_builtin ("__builtin_isnan", ftype, BUILT_IN_ISNAN,