File fpreserve-function-arguments4.patch of Package gcc41
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c.orig 2007-08-27 16:39:56.000000000 +0200
--- gcc/gimplify.c 2007-09-28 19:40:59.000000000 +0200
*************** gimplify_body (tree *body_p, tree fndecl
*** 4976,4981 ****
--- 4976,5031 ----
BIND_EXPR_BODY (body) = parm_stmts;
}
+ /* If we want to forcibly preserve function argument values, do so here. */
+ if (flag_preserve_function_arguments)
+ {
+ char s[1024] = "# ";
+ tree asmt, parm, inputs = NULL_TREE, stmts = NULL_TREE;
+ bool mem_p = false;
+ int i = 0;
+
+ sprintf (s + strlen(s), "%s ", IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+
+ for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = TREE_CHAIN (parm))
+ {
+ tree pt = parm;
+ tree type = TREE_TYPE (parm);
+ /* Maybe build a fancy memory operand here. For now just use
+ a pointer input and let the operand scanner deal with the rest. */
+ if (TYPE_MODE (type) == BLKmode)
+ {
+ pt = build_fold_addr_expr (parm);
+ type = TREE_TYPE (pt);
+ }
+ if (POINTER_TYPE_P (type))
+ mem_p = true;
+ sprintf (s + strlen(s), "%%%i ", i++);
+ inputs = tree_cons (tree_cons (NULL_TREE, build_string (1, "g"),
+ NULL_TREE), pt, inputs);
+ }
+
+ if (i != 0)
+ {
+ /* While on the tree level we can do w/o explicit "memory"
+ clobbering because we tweak the operand scanner, on RTL level
+ we need it. */
+ tree clobbers = NULL_TREE;
+ if (mem_p)
+ clobbers = tree_cons (NULL_TREE, build_string (6, "memory"),
+ NULL_TREE);
+ asmt = build4 (ASM_EXPR, void_type_node,
+ build_string (strlen (s), s),
+ NULL_TREE, /* no outputs */
+ inputs, clobbers);
+ ASM_VOLATILE_P (asmt) = 1;
+ TREE_READONLY (asmt) = 1;
+ gimplify_and_add (asmt, &stmts);
+
+ append_to_statement_list_force (BIND_EXPR_BODY (body), &stmts);
+ BIND_EXPR_BODY (body) = stmts;
+ }
+ }
+
/* Unshare again, in case gimplification was sloppy. */
unshare_all_trees (body);
Index: gcc/common.opt
===================================================================
*** gcc/common.opt.orig 2007-02-05 13:59:11.000000000 +0100
--- gcc/common.opt 2007-09-28 15:29:26.000000000 +0200
*************** fmudflapir
*** 590,595 ****
--- 590,599 ----
Common RejectNegative Report Var(flag_mudflap_ignore_reads)
Ignore read operations when inserting mudflap instrumentation
+ fpreserve-function-arguments
+ Common Report Var(flag_preserve_function_arguments)
+ Preserve function argument values for debugging
+
freschedule-modulo-scheduled-loops
Common Report Var(flag_resched_modulo_sched)
Enable/Disable the traditional scheduling in loops that already passed modulo scheduling
Index: gcc/tree-ssa-operands.c
===================================================================
*** gcc/tree-ssa-operands.c.orig 2007-06-06 16:58:54.000000000 +0200
--- gcc/tree-ssa-operands.c 2007-09-28 16:02:12.000000000 +0200
*************** Boston, MA 02110-1301, USA. */
*** 103,108 ****
--- 103,110 ----
to distinguish "reset the world" events from explicit MODIFY_EXPRs. */
#define opf_non_specific (1 << 3)
+ /* Hack to mark all SSA_NAME uses in asms as abnormal. */
+ #define opf_mark_abnormal (1 << 4)
/* Array for building all the def operands. */
static VEC(tree,heap) *build_defs;
*************** get_asm_expr_operands (tree stmt)
*** 1343,1349 ****
int i;
tree link;
const char *constraint;
! bool allows_mem, allows_reg, is_inout;
for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
{
--- 1345,1351 ----
int i;
tree link;
const char *constraint;
! bool allows_mem, allows_reg, is_inout, memory_p;
for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
{
*************** get_asm_expr_operands (tree stmt)
*** 1367,1392 ****
get_expr_operands (stmt, &TREE_VALUE (link), opf_is_def);
}
! for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
! {
! constraint
! = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
! parse_input_constraint (&constraint, 0, 0, noutputs, 0,
! oconstraints, &allows_mem, &allows_reg);
!
! /* Memory operands are addressable. Note that STMT needs the
! address of this operand. */
! if (!allows_reg && allows_mem)
! {
! tree t = get_base_address (TREE_VALUE (link));
! if (t && DECL_P (t) && s_ann)
! add_to_addressable_set (t, &s_ann->addresses_taken);
! }
!
! get_expr_operands (stmt, &TREE_VALUE (link), 0);
! }
!
!
/* Clobber memory for asm ("" : : : "memory"); */
for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
if (strcmp (TREE_STRING_POINTER (TREE_VALUE (link)), "memory") == 0)
--- 1369,1375 ----
get_expr_operands (stmt, &TREE_VALUE (link), opf_is_def);
}
! memory_p = false;
/* Clobber memory for asm ("" : : : "memory"); */
for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
if (strcmp (TREE_STRING_POINTER (TREE_VALUE (link)), "memory") == 0)
*************** get_asm_expr_operands (tree stmt)
*** 1394,1399 ****
--- 1377,1388 ----
unsigned i;
bitmap_iterator bi;
+ if (TREE_READONLY (stmt))
+ {
+ memory_p = true;
+ break;
+ }
+
/* Clobber all call-clobbered variables (or .GLOBAL_VAR if we
decided to group them). */
if (global_var)
*************** get_asm_expr_operands (tree stmt)
*** 1425,1430 ****
--- 1414,1470 ----
break;
}
+
+ for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
+ {
+ constraint
+ = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+ oconstraints, &allows_mem, &allows_reg);
+
+ /* Memory operands are addressable. Note that STMT needs the
+ address of this operand. */
+ if (!allows_reg && allows_mem)
+ {
+ tree t = get_base_address (TREE_VALUE (link));
+ if (t && DECL_P (t) && s_ann)
+ add_to_addressable_set (t, &s_ann->addresses_taken);
+ }
+
+ get_expr_operands (stmt, &TREE_VALUE (link), opf_mark_abnormal);
+
+ /* Read-only memory. Copied from get_indirect_ref_operands. */
+ if (memory_p
+ && POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (link)))
+ && SSA_VAR_P (TREE_VALUE (link)))
+ {
+ tree ptr = TREE_VALUE (link);
+ int flags = 0;
+ struct ptr_info_def *pi = NULL;
+
+ /* If PTR has flow-sensitive points-to information, use it. */
+ if (TREE_CODE (ptr) == SSA_NAME
+ && (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
+ && pi->name_mem_tag)
+ {
+ /* PTR has its own memory tag. Use it. */
+ add_stmt_operand (&pi->name_mem_tag, s_ann, flags);
+ }
+ else
+ {
+ /* If PTR is not an SSA_NAME or it doesn't have a name
+ tag, use its type memory tag. */
+ var_ann_t v_ann;
+
+ if (TREE_CODE (ptr) == SSA_NAME)
+ ptr = SSA_NAME_VAR (ptr);
+ v_ann = var_ann (ptr);
+ if (v_ann->type_mem_tag)
+ add_stmt_operand (&v_ann->type_mem_tag, s_ann, flags);
+ }
+ }
+ }
+
}
/* A subroutine of get_expr_operands to handle INDIRECT_REF,
*************** add_stmt_operand (tree *var_p, stmt_ann_
*** 1681,1686 ****
--- 1721,1730 ----
append_def (var_p);
else
append_use (var_p);
+
+ if (flags & opf_mark_abnormal
+ && TREE_CODE (*var_p) == SSA_NAME)
+ SSA_NAME_OCCURS_IN_ABNORMAL_PHI (*var_p) = true;
}
else
{
Index: gcc/combine.c
===================================================================
*** gcc/combine.c.orig 2007-05-19 19:09:46.000000000 +0200
--- gcc/combine.c 2007-09-28 18:14:51.000000000 +0200
*************** can_combine_p (rtx insn, rtx i3, rtx pre
*** 1265,1271 ****
and it is a pain to update that information.
Exception: if source is a constant, moving it later can't hurt.
Accept that special case, because it helps -fforce-addr a lot. */
! || (INSN_CUID (insn) < last_call_cuid && ! CONSTANT_P (src)))
return 0;
/* DEST must either be a REG or CC0. */
--- 1265,1278 ----
and it is a pain to update that information.
Exception: if source is a constant, moving it later can't hurt.
Accept that special case, because it helps -fforce-addr a lot. */
! || (INSN_CUID (insn) < last_call_cuid && ! CONSTANT_P (src))
! || (flag_preserve_function_arguments
! && REG_P (dest)
! && REG_P (src)
! && GET_CODE (PATTERN (i3)) == PARALLEL
! && GET_CODE (XVECEXP (PATTERN (i3), 0, 0)) == ASM_OPERANDS
! && REG_USERVAR_P (dest)
! && REG_EXPR (dest) != REG_EXPR (src)))
return 0;
/* DEST must either be a REG or CC0. */
Index: gcc/var-tracking.c
===================================================================
*** gcc/var-tracking.c.orig 2007-02-20 11:27:19.000000000 +0100
--- gcc/var-tracking.c 2007-09-28 19:27:29.000000000 +0200
*************** dump_variable (void **slot, void *data A
*** 1750,1757 ****
int i;
location_chain node;
! fprintf (dump_file, " name: %s\n",
! IDENTIFIER_POINTER (DECL_NAME (var->decl)));
for (i = 0; i < var->n_var_parts; i++)
{
fprintf (dump_file, " offset %ld\n",
--- 1750,1758 ----
int i;
location_chain node;
! fprintf (dump_file, " name: %sD.%u\n",
! IDENTIFIER_POINTER (DECL_NAME (var->decl)),
! DECL_UID (var->decl));
for (i = 0; i < var->n_var_parts; i++)
{
fprintf (dump_file, " offset %ld\n",
Index: gcc/recog.c
===================================================================
*** gcc/recog.c.orig 2005-12-22 13:49:10.000000000 +0100
--- gcc/recog.c 2007-10-05 14:52:54.000000000 +0200
*************** num_changes_pending (void)
*** 336,341 ****
--- 336,369 ----
return num_changes;
}
+ /* If we want to preserve arguments to inlined functions we need
+ to preserve some asm operands. We know we changed OLD into NEW
+ in an asm instruction. Return 1 if this wasn't okay, 0 otherwise. */
+ static int
+ invalid_asm_change (rtx old, rtx new)
+ {
+ tree e1, e2;
+ /* It is invalid to change a REG which had an associated decl expression,
+ with something which has a different expression. It's okay, though,
+ to change a REG with no expression to some other. */
+ if (GET_CODE (old) == SUBREG)
+ old = SUBREG_REG (old);
+ if (GET_CODE (new) == SUBREG)
+ new = SUBREG_REG (new);
+ /* If we replaced something else than a REG or MEM, it's okay. */
+ if (!REG_P (old) && !MEM_P (old))
+ return 0;
+ /* If we replaced a REG or MEM with something else, we are going
+ to loose that information. */
+ if (!REG_P (new) && !MEM_P (new))
+ return 1;
+ e1 = REG_P (old) ? REG_EXPR (old) : MEM_EXPR (old);
+ if (!e1)
+ return 0;
+ e2 = REG_P (new) ? REG_EXPR (new) : MEM_EXPR (new);
+ return e1 != e2;
+ }
+
/* Tentatively apply the changes numbered NUM and up.
Return 1 if all changes are valid, zero otherwise. */
*************** verify_changes (int num)
*** 368,373 ****
--- 396,405 ----
if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
break;
}
+ else if (flag_preserve_function_arguments
+ && asm_noperands (PATTERN (object)) >= 0
+ && invalid_asm_change (changes[i].old, *changes[i].loc))
+ break;
else if (insn_invalid_p (object))
{
rtx pat = PATTERN (object);