Comments
Patch
===================================================================
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.
#include "tree-ssa-propagate.h"
#include "target.h"
#include "gimple-fold.h"
+#include "params.h"
/* Return true when DECL can be referenced from current unit.
We can get declarations that are not possible to reference for
@@ -1170,6 +1171,54 @@ get_maxval_strlen (tree arg, tree *lengt
}
}
+/* Detects a vla-related alloca with a constant argument. Declares fixed-size
+ array and return the address, if found, otherwise returns NULL_TREE. */
+
+static tree
+fold_builtin_alloca (gimple stmt)
+{
+ unsigned HOST_WIDE_INT size, threshold, n_elem;
+ tree lhs, arg, block, var, elem_type, array_type;
+ unsigned int align;
+
+ /* Get lhs. */
+ lhs = gimple_call_lhs (stmt);
+ if (lhs == NULL_TREE)
+ return NULL_TREE;
+
+ /* Only handle vla-related allocas for the moment. We do not yet detect when
+ a source-level alloca can be safely folded. */
+ if (!gimple_call_alloca_for_var_p (stmt))
+ return NULL_TREE;
+
+ /* Detect constant argument. */
+ arg = gimple_call_arg (stmt, 0);
+ if (TREE_CODE (arg) != INTEGER_CST || !host_integerp (arg, 1))
+ return NULL_TREE;
+ size = TREE_INT_CST_LOW (arg);
+
+ /* Heuristic: don't fold large vlas. */
+ threshold = (unsigned HOST_WIDE_INT)PARAM_VALUE (PARAM_LARGE_STACK_FRAME);
+ /* In case a vla is declared at function scope, it has the same lifetime as a
+ declared array, so we allow a larger size. */
+ block = gimple_block (stmt);
+ if (!(cfun->after_inlining
+ && TREE_CODE (BLOCK_SUPERCONTEXT (block)) == FUNCTION_DECL))
+ threshold /= 10;
+ if (size > threshold)
+ return NULL_TREE;
+
+ /* Declare array. */
+ elem_type = build_nonstandard_integer_type (BITS_PER_UNIT, 1);
+ n_elem = size * 8 / BITS_PER_UNIT;
+ align = MIN (size * 8, GET_MODE_PRECISION (word_mode));
+ array_type = build_aligned_type (build_array_type_nelts (elem_type, n_elem),
+ align);
+ var = create_tmp_var (array_type, NULL);
+
+ /* Fold alloca to the address of the array. */
+ return fold_convert (TREE_TYPE (lhs), build_fold_addr_expr (var));
+}
/* Fold builtin call in statement STMT. Returns a simplified tree.
We may return a non-constant expression, including another call
@@ -1246,6 +1295,8 @@ gimple_fold_builtin (gimple stmt)
arg_idx = 1;
type = 2;
break;
+ case BUILT_IN_ALLOCA:
+ return fold_builtin_alloca (stmt);
default:
return NULL_TREE;
}
===================================================================
@@ -1727,6 +1727,13 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi
if (gimple_call_internal_p (stmt))
return false;
+ /* The heuristic of fold_builtin_alloca differs before and after
+ inlining, so we don't require the arg to be changed into a constant
+ for folding, but just to be constant. */
+ if (gimple_call_alloca_for_var_p (stmt)
+ && get_constant_value (gimple_call_arg (stmt, 0)))
+ return true;
+
/* Propagate into the call arguments. Compared to replace_uses_in
this can use the argument slot types for type verification
instead of the current argument type. We also can safely
===================================================================
@@ -2672,7 +2672,7 @@ gimple-iterator.o : gimple-iterator.c $(
gimple-fold.o : gimple-fold.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
- $(TREE_DUMP_H) $(BASIC_BLOCK_H) $(TREE_PASS_H) langhooks.h \
+ $(TREE_DUMP_H) $(BASIC_BLOCK_H) $(TREE_PASS_H) langhooks.h $(PARAMS_H) \
tree-ssa-propagate.h value-prof.h $(FLAGS_H) $(TARGET_H) gimple-fold.h
gimple-low.o : gimple-low.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
$(DIAGNOSTIC_H) $(GIMPLE_H) $(TREE_INLINE_H) langhooks.h \