This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] PATCH to gimplify_asm_expr for optimization/12525
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 07 Oct 2003 17:59:25 -0400
- Subject: [tree-ssa] PATCH to gimplify_asm_expr for optimization/12525
PR 12525 is a bug whereby the optimizers treat in/out operands as
output-only, so we discard earlier defs.
Fixed for register operands by splitting them into separate input and
output operands.
I intended to fix this for memory operands by calling mark_addressable so
they don't get renamed, but the must-alias pass decides that we don't really
need the address after all. Diego, any thoughts on how to prevent that?
Test in gcc.dg/tree-ssa/asm-1.c.
2003-10-07 Jason Merrill <jason@redhat.com>
PR optimization/12525
* gimplify.c (gimplify_asm_expr): If the constraint doesn't allow
a register, call mark_addressable. Split an in/out operand that
does allow a register into separate input and output operands.
*** gimplify.c.~1~ 2003-09-24 17:10:37.000000000 -0400
--- gimplify.c 2003-10-07 17:25:24.000000000 -0400
*************** gimplify_addr_expr (tree *expr_p, tree *
*** 2156,2182 ****
static void
gimplify_asm_expr (tree expr, tree *pre_p, tree *post_p)
{
tree link;
ASM_STRING (expr)
= resolve_asm_operand_names (ASM_STRING (expr), ASM_OUTPUTS (expr),
ASM_INPUTS (expr));
! for (link = ASM_OUTPUTS (expr); link; link = TREE_CHAIN (link))
! gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
! is_gimple_lvalue, fb_lvalue);
for (link = ASM_INPUTS (expr); link; link = TREE_CHAIN (link))
{
/* If the operand is a memory input, it should be an lvalue. */
if (asm_op_is_mem_input (link, expr))
! gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
! is_gimple_lvalue, fb_lvalue);
else
gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
is_gimple_val, fb_rvalue);
}
-
}
/* If EXPR is a boolean expression, make sure it has BOOLEAN_TYPE. */
--- 2163,2225 ----
static void
gimplify_asm_expr (tree expr, tree *pre_p, tree *post_p)
{
+ int i;
tree link;
ASM_STRING (expr)
= resolve_asm_operand_names (ASM_STRING (expr), ASM_OUTPUTS (expr),
ASM_INPUTS (expr));
! for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = TREE_CHAIN (link))
! {
! bool allows_reg, allows_mem, is_inout;
! const char *constraint
! = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
!
! parse_output_constraint (&constraint, i, 0, 0,
! &allows_mem, &allows_reg, &is_inout);
!
! if (!allows_reg)
! (*lang_hooks.mark_addressable) (TREE_VALUE (link));
!
! gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
! is_gimple_lvalue, fb_lvalue);
!
! if (is_inout && allows_reg)
! {
! /* An input/output operand that allows a register. To give the
! optimizers more flexibility, split it into separate input and
! output operands. */
! tree input;
! char buf[10];
!
! /* Turn the in/out constraint into an output constraint. */
! char *p = xstrdup (constraint);
! p[0] = '=';
! TREE_VALUE (TREE_PURPOSE (link)) = build_string (strlen (p), p);
!
! /* And add a matching input constraint. */
! sprintf (buf, "%d", i);
! input = build_string (strlen (buf), buf);
! input = build_tree_list (build_tree_list (NULL_TREE, input),
! unshare_expr (TREE_VALUE (link)));
! ASM_INPUTS (expr) = chainon (input, ASM_INPUTS (expr));
! }
! }
for (link = ASM_INPUTS (expr); link; link = TREE_CHAIN (link))
{
/* If the operand is a memory input, it should be an lvalue. */
if (asm_op_is_mem_input (link, expr))
! {
! (*lang_hooks.mark_addressable) (TREE_VALUE (link));
! gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
! is_gimple_lvalue, fb_lvalue);
! }
else
gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
is_gimple_val, fb_rvalue);
}
}
/* If EXPR is a boolean expression, make sure it has BOOLEAN_TYPE. */