This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Eliminate eliminable regs even in DEBUG_INSNs
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Alexandre Oliva <aoliva at redhat dot com>
- Date: Thu, 11 Feb 2010 00:54:41 +0100
- Subject: [PATCH] Eliminate eliminable regs even in DEBUG_INSNs
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
int bar (unsigned long *, unsigned long *);
int
foo (void)
{
unsigned long a = 0, b = 0, c = 0;
a = bar (&b, &c);
unsigned long vara = a;
unsigned long varb = b;
unsigned long varc = c;
__asm__ volatile ("" : : "g" (vara), "g" (varb), "g" (varc));
return a;
}
doesn't get location info for varb and varc, eventhough those clearly have
to be live at the start of the inline asm. On the trunk there is a problem
in SSA expansion that I'll file a bug about shortly, on the
redhat/gcc-4_4-branch the problem is that we don't eliminate eliminable regs
in DEBUG_INSNs. So in *.asmcons we have:
(debug_insn 14 13 15 2 Y.ii:7 (var_location:DI D.4294967295 (zero_extend:DI (reg:SI 58 [ D.1605 ]))) -1 (nil))
(debug_insn 15 14 16 2 Y.ii:7 (var_location:DI a (debug_expr:DI D#1)) -1 (nil))
(debug_insn 16 15 17 2 Y.ii:8 (var_location:DI vara (debug_expr:DI D#1)) -1 (nil))
(debug_insn 17 16 18 2 Y.ii:9 (var_location:DI D.4294967294 (mem/c/i:DI (plus:DI (reg/f:DI 20 frame) (const_int -8 [0xfffffffffffffff8])) [2 b+0 S8 A64])) -1 (nil))
(debug_insn 18 17 19 2 Y.ii:9 (var_location:DI varb (debug_expr:DI D#2)) -1 (nil))
(debug_insn 19 18 20 2 Y.ii:10 (var_location:DI D.4294967293 (mem/c/i:DI (plus:DI (reg/f:DI 20 frame) (const_int -16 [0xfffffffffffffff0])) [2 c+0 S8 A64])) -1 (nil))
(debug_insn 20 19 21 2 Y.ii:10 (var_location:DI varc (debug_expr:DI D#3)) -1 (nil))
which matches the inputs of the asm, but in *.ira dump the debug_insns
remain the same, but in asm inputs reg 20 is eliminated to sp + 16. Then
during DSE2 the debug insns get cleared.
The attached patch fixes this, and on the trunk fixes on i686-linux also
-FAIL: gcc.dg/guality/pr41353-1.c -O1 line 28 i1 == 2 * 37
-FAIL: gcc.dg/guality/pr41353-1.c -O1 line 28 i2 == 3 * 37
-FAIL: gcc.dg/guality/pr41353-1.c -O2 line 28 i1 == 2 * 37
-FAIL: gcc.dg/guality/pr41353-1.c -O2 line 28 i2 == 3 * 37
-FAIL: gcc.dg/guality/pr41353-1.c -O3 -fomit-frame-pointer line 28 i1 == 2 * 37
-FAIL: gcc.dg/guality/pr41353-1.c -O3 -fomit-frame-pointer line 28 i2 == 3 * 37
-FAIL: gcc.dg/guality/pr41353-1.c -O3 -g line 28 i1 == 2 * 37
-FAIL: gcc.dg/guality/pr41353-1.c -O3 -g line 28 i2 == 3 * 37
-FAIL: gcc.dg/guality/pr41353-1.c -Os line 28 i1 == 2 * 37
-FAIL: gcc.dg/guality/pr41353-1.c -Os line 28 i2 == 3 * 37
In i686-linux cc1 with the patch there are roughly 1500 (0.7%) more DIEs
with DW_AT_location attribute. In x86_64-linux cc1 it is roughtly 1000 more
such DIEs.
The eliminate_regs_1 changes are to avoid -fcompare-debug differences and
not to crash on (clobber (const_int 0)) that is used in DEBUG_INSNs when no
location is available.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2010-02-10 Jakub Jelinek <jakub@redhat.com>
* reload1.c (eliminate_regs_1): If insn is DEBUG_INSN, avoid any
modifications outside of the DEBUG_INSN. Accept CLOBBERs inside
of DEBUG_INSNs.
(eliminate_regs_in_insn): Eliminate regs even in DEBUG_INSNs.
--- gcc/reload1.c.jj 2010-01-18 17:14:18.000000000 +0100
+++ gcc/reload1.c 2010-02-10 20:48:24.000000000 +0100
@@ -2570,7 +2570,7 @@ eliminate_regs_1 (rtx x, enum machine_mo
else if (reg_renumber && reg_renumber[regno] < 0
&& reg_equiv_invariant && reg_equiv_invariant[regno])
{
- if (may_use_invariant)
+ if (may_use_invariant || (insn && DEBUG_INSN_P (insn)))
return eliminate_regs_1 (copy_rtx (reg_equiv_invariant[regno]),
mem_mode, insn, true);
/* There exists at least one use of REGNO that cannot be
@@ -2685,9 +2685,11 @@ eliminate_regs_1 (rtx x, enum machine_mo
if (ep->from_rtx == XEXP (x, 0) && ep->can_eliminate)
{
if (! mem_mode
- /* Refs inside notes don't count for this purpose. */
+ /* Refs inside notes or in DEBUG_INSNs don't count for
+ this purpose. */
&& ! (insn != 0 && (GET_CODE (insn) == EXPR_LIST
- || GET_CODE (insn) == INSN_LIST)))
+ || GET_CODE (insn) == INSN_LIST
+ || DEBUG_INSN_P (insn))))
ep->ref_outside_mem = 1;
return
@@ -2863,6 +2865,9 @@ eliminate_regs_1 (rtx x, enum machine_mo
return x;
case CLOBBER:
+ gcc_assert (insn && DEBUG_INSN_P (insn));
+ break;
+
case ASM_OPERANDS:
case SET:
gcc_unreachable ();
@@ -3199,6 +3204,9 @@ eliminate_regs_in_insn (rtx insn, int re
|| GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
|| GET_CODE (PATTERN (insn)) == ASM_INPUT
|| DEBUG_INSN_P (insn));
+ if (DEBUG_INSN_P (insn))
+ INSN_VAR_LOCATION_LOC (insn)
+ = eliminate_regs (INSN_VAR_LOCATION_LOC (insn), VOIDmode, insn);
return 0;
}
Jakub