On 3/30/20 12:18 AM, luoxhu via Gcc-patches wrote:


On 2020/3/28 00:04, Segher Boessenkool wrote:
Hi!

On Fri, Mar 27, 2020 at 09:34:00AM +0800, luoxhu wrote:
On 2020/3/27 07:59, Segher Boessenkool wrote:
On Wed, Mar 25, 2020 at 11:15:22PM -0500, luo...@linux.ibm.com wrote:
frame_pointer_needed is set to true in reload pass setup_can_eliminate, but regs_ever_live[31] is false, so pro_and_epilogue doesn't save/restore r31 even it is used actually, causing CPU2006 465.tonto segment fault of
loading from invalid addresses.

If df_regs_ever_live_p(31) is false there is no hard frame pointer
anywhere in the program.  How can it be used then?

There is a piece of code emit move instruction to r31 even df_regs_ever_live_p(31) is false
in pro_and_epilogue.

Can you point out where (in rs6000-logue.c ot similar)?  We should fix
*that*.

As frame_point_needed is true and frame_pointer_needed is widely
used in this function, so I propose to save r31 in save_reg_p instead of check (frame_pointer_needed && df_regs_ever_live_p(31), I haven't verify whether this works yet).
Is this reasonable?  Thanks.

frame_pointer_needed is often true when the backend can figure out we do
not actually need it.

rs6000-logue.c
void
rs6000_emit_prologue (void)
{
...
bbd21807fdf6 (geoffk         2000-03-16 03:16:41 +0000 26840)   /* Set frame pointer, if needed.  */ bbd21807fdf6 (geoffk         2000-03-16 03:16:41 +0000 26841)   if (frame_pointer_needed)
bbd21807fdf6 (geoffk         2000-03-16 03:16:41 +0000 26842)     {
0d6c02bf24e4 (jakub          2005-06-30 14:26:32 +0000 26843)       insn = emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM), bbd21807fdf6 (geoffk         2000-03-16 03:16:41 +0000 26844)                        sp_reg_rtx); bbd21807fdf6 (geoffk         2000-03-16 03:16:41 +0000 26845)       RTX_FRAME_RELATED_P (insn) = 1;
6b02f2a5c61e (meissner       1995-11-30 20:02:16 +0000 26846)     }
d1bd513ed578 (kenner         1992-02-09 19:26:21 +0000 26847)
...
}

Ah, so this you mean.  I see.  It looks like if you change this to

   if (frame_pointer_needed && df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM))
     {
       insn = emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
                 sp_reg_rtx);
       RTX_FRAME_RELATED_P (insn) = 1;
     }

(so just that "if" clause changes), it'll all be fine.  Could you test
that please?

Tried with below patch, it still fails at same place, I guess this is not enough. The instruction in 100dc034 change r31 from 0x105fdd70 to 0x7fffffffbbf0 and didn't
restore it before return.
00000000100dc020 <__atomvec_module_MOD_atom_index_from_pos>:
   100dc020:   51 10 40 3c     lis     r2,4177
   100dc024:   00 7f 42 38     addi    r2,r2,32512
   100dc028:   28 00 e3 e8     ld      r7,40(r3)
   100dc02c:   e1 ff 21 f8     stdu    r1,-32(r1)
   100dc030:   00 00 27 2c     cmpdi   r7,0
   100dc034:   78 0b 3f 7c     mr      r31,r1
   100dc038:   08 00 82 40     bne     100dc040 <__atomvec_module_MOD_atom_index_from_pos+0x20>
   100dc03c:   01 00 e0 38     li      r7,1
   100dc040:   38 00 43 e9     ld      r10,56(r3)
   100dc044:   30 00 23 e9     ld      r9,48(r3)
   100dc048:   00 00 03 e9     ld      r8,0(r3)


Diff:

diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c
index 4cbf228eb79..28fda1866d8 100644
--- a/gcc/config/rs6000/rs6000-logue.c
+++ b/gcc/config/rs6000/rs6000-logue.c
@@ -3658,7 +3658,7 @@ rs6000_emit_prologue (void)
    }

  /* Set frame pointer, if needed.  */
-  if (frame_pointer_needed)
+  if (frame_pointer_needed && df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM))
    {
      insn = emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
                            sp_reg_rtx);
@@ -4534,7 +4534,8 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type)
    }
  /* If we have a frame pointer, we can restore the old stack pointer
     from it.  */
-  else if (frame_pointer_needed)
+  else if (frame_pointer_needed
+          && df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM))
    {
      frame_reg_rtx = sp_reg_rtx;
      if (DEFAULT_ABI == ABI_V4)
@@ -4873,7 +4874,8 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type)
        a REG_CFA_DEF_CFA note, but that's OK;  A duplicate is
        discarded by dwarf2cfi.c/dwarf2out.c, and in any case would
        be harmless if emitted.  */
-      if (frame_pointer_needed)
+      if (frame_pointer_needed
+         && df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM))
       {
         insn = get_last_insn ();
         add_reg_note (insn, REG_CFA_DEF_CFA,



Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x2000000a2243 in ???
#1  0x2000000a0abb in ???
#2  0x2000000604d7 in ???
#3  0x1027418c in __mol_module_MOD_make_image_of_shell
       at /home/luoxhu/workspace/cpu2006/benchspec/CPU2006/465.tonto/build/build_peak_none.0000/mol.fppized.f90:9376
#4  0x10281adf in __mol_module_MOD_symmetrise_r
       at /home/luoxhu/workspace/cpu2006/benchspec/CPU2006/465.tonto/build/build_peak_none.0000/mol.fppized.f90:9276
#5  0x10322d3b in __mol_module_MOD_symmetrise.constprop.0
       at /home/luoxhu/workspace/cpu2006/benchspec/CPU2006/465.tonto/build/build_peak_none.0000/mol.fppized.f90:9239
#6  0x1023d1ff in __mol_module_MOD_make_atom_density
       at /home/luoxhu/workspace/cpu2006/benchspec/CPU2006/465.tonto/build/build_peak_none.0000/mol.fppized.f90:12477
#7  0x1023d9a3 in __mol_module_MOD_get_atom_density
       at /home/luoxhu/workspace/cpu2006/benchspec/CPU2006/465.tonto/build/build_peak_none.0000/mol.fppized.f90:12434
#8  0x1023e87b in __mol_module_MOD_make_atom_guess
       at /home/luoxhu/workspace/cpu2006/benchspec/CPU2006/465.tonto/build/build_peak_none.0000/mol.fppized.f90:12406
#9  0x1023e87b in __mol_module_MOD_get_initial_density


Thanks,
Xionghu

Xionghu,

I'm don't have access to SPEC to test this but on line 4534 in rs6000_emit_prologue in that if block:
 insn = emit_insn (gen_add3_insn (frame_reg_rtx, hard_frame_pointer_rtx,
                                 GEN_INT (info->total_size)));
seems this should be an emit_move_insn and therefore probably just:
insn = emit_move_insn (frame_reg_rtx, hard_frame_pointer_rtx);

Seems to be what may be missing as the other callers all do emit_move_insn in your patch. Unless
there is a edge case I'm missing.

Cheers,
Nick


Thanks,


Segher


Reply via email to