The basic problem here is parameters are marked with REG_USERVAR_P and IRA creates conflicts for the parameters with the callee clobbered registers.

This results in the copy from the parameter registers into callee clobbered registers being removed. The move instructions happen to be associated with the first line of code in the function. So when a breakpoint is placed on the function, the breakpoint triggers a statement later than expected.

This patch restores IRA's behaviour WRT regs associated with PARM_DECLs that was inadvertently removed by Steven when he changed this code back in July to eliminate the inclusion of tree.h in ira-conflicts.c.

We could have used a bit in the base rtl structure to represent PARMs independently from user variables, but given we don't have any real separation of rtl from trees and the scarcity of flag bits in that structure, I just created a trivial function that lives in emit-rtl.c which has access to both tree and rtl headers.

Steven has a patch which takes the other approach (using a flag bit in the base rtl structure) if folks would prefer that approach.

Bootstrapped and regression tested x86_64-linux-gnu.

OK for trunk?

        PR debug/53948
        * emit-rtl.c (reg_is_parm_p): New function.
        * regs.h (reg_is_parm_p): New prototype.
        * ira-conflicts.c (ira_build_conflicts): Allow parameters in
        callee-clobbered registers.

        * gcc.dg/debug/dwarf2/pr53948.c: New test.

diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index f997e5d..2c70fb1 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -919,6 +919,18 @@ gen_reg_rtx (enum machine_mode mode)
   return val;
 }
 
+/* Return TRUE if REG is a PARM_DECL, FALSE otherwise.  */
+
+bool
+reg_is_parm_p (rtx reg)
+{
+  tree decl;
+
+  gcc_assert (REG_P (reg));
+  decl = REG_EXPR (reg);
+  return (decl && TREE_CODE (decl) == PARM_DECL);
+}
+
 /* Update NEW with the same attributes as REG, but with OFFSET added
    to the REG_OFFSET.  */
 
diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c
index 711db0f..710986b 100644
--- a/gcc/ira-conflicts.c
+++ b/gcc/ira-conflicts.c
@@ -895,8 +895,12 @@ ira_build_conflicts (void)
 
          if ((! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
              /* For debugging purposes don't put user defined variables in
-                callee-clobbered registers.  */
-             || (optimize == 0 && REG_USERVAR_P (allocno_reg)))
+                callee-clobbered registers.  However, do allow parameters
+                in callee-clobbered registers to improve debugging.  This
+                is a bit of a fragile hack.  */
+             || (optimize == 0
+                 && REG_USERVAR_P (allocno_reg)
+                 && ! reg_is_parm_p (allocno_reg)))
            {
              IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
                                call_used_reg_set);
diff --git a/gcc/regs.h b/gcc/regs.h
index 0532d08..090d6b6 100644
--- a/gcc/regs.h
+++ b/gcc/regs.h
@@ -89,6 +89,8 @@ REG_N_SETS (int regno)
 #define SET_REG_N_SETS(N,V) (regstat_n_sets_and_refs[N].sets = V)
 #define INC_REG_N_SETS(N,V) (regstat_n_sets_and_refs[N].sets += V)
 
+/* Given a REG, return TRUE if the reg is a PARM_DECL, FALSE otherwise.  */
+extern bool reg_is_parm_p (rtx);
 
 /* Functions defined in regstat.c.  */
 extern void regstat_init_n_sets_and_refs (void);
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr53948.c 
b/gcc/testsuite/gcc.dg/debug/dwarf2/pr53948.c
new file mode 100644
index 0000000..8bc8ed4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr53948.c
@@ -0,0 +1,10 @@
+/* Test that we emit a .line directive for the line
+   with local variable initializations.  */
+/* { dg-options "-O0 -g" } */
+/* { dg-final { scan-assembler ".loc 1 8 0" } } */
+
+
+int f (register int a, register int b) {
+  register int x = b, y = a;
+  return x + y; }
+

Reply via email to