This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Repost: RFA [4.1]: improvement to if-conversion and cross-jumping (PR20070)
- From: Ulrich Weigand <uweigand at de dot ibm dot com>
- To: uweigand at de dot ibm dot com (Ulrich Weigand)
- Cc: joern dot rennecke at st dot com (Joern RENNECKE), bernds_cb1 at t-online dot de (Bernd Schmidt), stevenb at suse dot de (Steven Bosscher), rth at redhat dot com (Richard Henderson), gcc-patches at gcc dot gnu dot org, jh at suse dot cz
- Date: Mon, 19 Dec 2005 21:46:50 +0100 (CET)
- Subject: 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