This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Repost: RFA [4.1]: improvement to if-conversion and cross-jumping (PR20070)


I wrote:

> block A:
>    ...
>    (set (reg 2 [71]) (symbol_ref X))
>    (set (mem (reg 2 [71])) (reg 1 [74])) 
>    (set (pc) (label_ref L))
> 
> block B:
>    ...
>    (set (reg 1 [84]) (symbol_ref X))
>    (set (mem (reg 1 [84])) (reg 2 [87]))
>    (set (pc) (label_ref L))
> 
> and after .ce3 I see
> 
> block A:
>    ...
>    (set (reg 1 [84]) (reg 2 [71]))    (***)
>    (set (reg 2 [87]) (reg 1 [74]))
>    (set (pc) (label_ref N))
> 
> block B:
>    ...
> new block (label_ref N):
>    (set (reg 1 [84]) (symbol_ref X))
>    (set (mem (reg 1 [84])) (reg 2 [87]))
> 
> It would appear the insn marked (***) is the incorrect one ...

Some more data: the insn (***) is generated here

#0  make_insn_raw (pattern=0x77e720c0) at ../../gcc-head/gcc/emit-rtl.c:3314
#1  0x005a9912 in emit_insn (x=0x77e7b780) at ../../gcc-head/gcc/emit-rtl.c:4461
#2  0x0063ee1e in gen_movsi (operand0=0x77e720c0, operand1=0x77e67d50) at s390.md:1151
#3  0x005d2bec in emit_move_insn_1 (x=0x77e720c0, y=0x77e67d50) at ../../gcc-head/gcc/expr.c:3021
#4  0x006772ba in gen_move_insn (x=0x77e720c0, y=0x77e67d50) at ../../gcc-head/gcc/optabs.c:4233
#5  0x0053c566 in try_crossjump_to_edge (mode=19, e1=0x77e7b780, e2=0x77e614e0) at ../../gcc-head/gcc/cfgcleanup.c:1301
#6  0x0053d5b0 in try_crossjump_bb (mode=19, bb=0x77e5f2d8) at ../../gcc-head/gcc/cfgcleanup.c:1568
#7  0x0053e2c8 in cleanup_cfg (mode=19) at ../../gcc-head/gcc/cfgcleanup.c:1757
#8  0x00809fe2 in rest_of_handle_stack_adjustments () at ../../gcc-head/gcc/regmove.c:2512
#9  0x0071a128 in execute_one_pass (pass=0x92f878) at ../../gcc-head/gcc/passes.c:845
#10 0x0071a2ac in execute_pass_list (pass=0x92f878) at ../../gcc-head/gcc/passes.c:877
#11 0x0071a2bc in execute_pass_list (pass=0x92ea44) at ../../gcc-head/gcc/passes.c:878
#12 0x0071a2bc in execute_pass_list (pass=0x92ea78) at ../../gcc-head/gcc/passes.c:878
#13 0x0048de1a in tree_rest_of_compilation (fndecl=0x77e55100) at ../../gcc-head/gcc/tree-optimize.c:419
#14 0x00415646 in c_expand_body (fndecl=0x77e55100) at ../../gcc-head/gcc/c-decl.c:6648
#15 0x00763fb6 in cgraph_expand_function (node=0x77dba3f0) at ../../gcc-head/gcc/cgraphunit.c:1055
#16 0x00764fb8 in cgraph_optimize () at ../../gcc-head/gcc/cgraphunit.c:1121
#17 0x00417ed8 in c_write_global_declarations () at ../../gcc-head/gcc/c-decl.c:7754
#18 0x006e68c0 in toplev_main (argc=9819952, argv=0x586a2c) at ../../gcc-head/gcc/toplev.c:1003
#19 0x0046c5f8 in main (argc=2011674496, argv=0x77e34c00) at ../../gcc-head/gcc/main.c:35

in try_crossjump_to_edge:

1299      for (i = 0; i < info.cur.local_count; i++)
1300        if (info.local_rvalue[i])
1301          emit_insn_before (gen_move_insn (info.x_local[i], info.y_local[i]),
1302                            y_active);

where

(gdb) print info.cur.local_count
$2 = 2
(gdb) call debug_rtx (info.x_local[0])
(reg/f:SI 1 %r1 [83])
(gdb) call debug_rtx (info.y_local[0])
(reg/f:SI 2 %r2 [70])
(gdb) call debug_rtx (info.x_local[1])
(reg:SI 2 %r2 [86])
(gdb) call debug_rtx (info.y_local[1])
(reg:SI 1 %r1 [73])

which doesn't seem right.  In fact, there's code in resolve_input_conflict
that's supposed to prevent just this problem, but this function is never
even called in my test case, because info->check_input_conflict is never
set.  This in turn happens because this piece of code in struct_equiv_block_eq,
which is supposed to set that flag as far as I can tell:

          if (!input_conflict
              && info->dying_inputs > 1
              && bitmap_intersect_p (info->x_local_live, info->y_local_live))
            {
              regset_head clobbered_regs;

              INIT_REG_SET (&clobbered_regs);
              for (i = 0; i < info->cur.local_count; i++)
                {
                  if (assign_reg_reg_set (&clobbered_regs, info->y_local[i], 0))
                    {
                      input_conflict = true;
                      break;
                    }
                  assign_reg_reg_set (&clobbered_regs, info->x_local[i], 1);
                }
              CLEAR_REG_SET (&clobbered_regs);
            }
          if (input_conflict && !info->check_input_conflict)
            info->need_rerun = true;
          info->check_input_conflict = input_conflict;
        }

is never entered because the bitmap_intersect_p call fails:

(gdb) call debug_bitmap (info->x_local_live)

first = 0x9afd38 current = 0x9afd38 indx = 0
        0x9afd38 next = (nil) prev = (nil) indx = 0
                bits = { 2 }
(gdb) call debug_bitmap (info->y_local_live)

first = 0x9afdac current = 0x9afdac indx = 0
        0x9afdac next = (nil) prev = (nil) indx = 0
                bits = { 1 }

If I comment out the bitmap_intersect_p call, the cross-jump opportunity
is rejected and I get valid code.  (However, this doesn't seem ideal either
since we *can* do a cross-jump in this particular case ...)

Any suggestions?

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  Linux on zSeries Development
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]