extern void link_error (const char *); extern int ones; void foo(int); void kernel () { struct { unsigned int a : 7; } s; s.a = ones; if (s.a >> 8) link_error ("foo"); if (s.a >> 9) link_error ("foo"); } mainline optimizes this to an empty function with -O2, dataflow branch retains the s.a >> 9 check.
Confirmed, same problem on alphaev56-unknown-linux-gnu.
Problem here is combine.
This unrelated patch fixes a very similar case for powerpc unpatched: < or r0,r3,r28 < rlwinm r0,r0,0,0xff < cmpwi cr7,r0,0 < beq- cr7,L4929 patched: (r3 and r28 are both extended from QImode) > or. r0,r3,r28 > beq- cr0,L4929 With some luck, it does the same for this testcase too? It would be nice to examine why though. :-) Sorry for the lack of professionality exhibited in this comment... Index: combine.c =================================================================== --- combine.c (revision 122195) +++ combine.c (working copy) @@ -1016,6 +1016,7 @@ combine_instructions (rtx f, unsigned in #endif rtx links, nextlinks; rtx first; + basic_block prev_basic_block; int new_direct_jump_p = 0; @@ -1057,15 +1058,20 @@ combine_instructions (rtx f, unsigned in for what bits are known to be set. */ label_tick = label_tick_ebb_start = 1; + prev_basic_block = NULL; setup_incoming_promotions (first); - create_log_links (); + FOR_EACH_BB (this_basic_block) { last_call_luid = 0; mem_last_set = -1; label_tick++; + if (!single_pred_p (this_basic_block) + || single_pred (this_basic_block) != prev_basic_block) + label_tick_ebb_start = label_tick; + FOR_BB_INSNS (this_basic_block, insn) if (INSN_P (insn) && BLOCK_FOR_INSN (insn)) { @@ -1090,8 +1096,8 @@ combine_instructions (rtx f, unsigned in fprintf(dump_file, "insn_cost %d: %d\n", INSN_UID (insn), INSN_COST (insn)); } - else if (LABEL_P (insn)) - label_tick_ebb_start = label_tick; + + prev_basic_block = this_basic_block; } nonzero_sign_valid = 1; @@ -1099,6 +1105,8 @@ combine_instructions (rtx f, unsigned in /* Now scan all the insns in forward order. */ label_tick = label_tick_ebb_start = 1; + prev_basic_block = NULL; + init_reg_last (); setup_incoming_promotions (first); @@ -1107,6 +1115,10 @@ combine_instructions (rtx f, unsigned in last_call_luid = 0; mem_last_set = -1; label_tick++; + if (!single_pred_p (this_basic_block) + || single_pred (this_basic_block) != prev_basic_block) + label_tick_ebb_start = label_tick; + for (insn = BB_HEAD (this_basic_block); insn != NEXT_INSN (BB_END (this_basic_block)); insn = next ? next : NEXT_INSN (insn)) @@ -1253,9 +1265,9 @@ combine_instructions (rtx f, unsigned in retry: ; } - else if (LABEL_P (insn)) - label_tick_ebb_start = label_tick; } + + prev_basic_block = this_basic_block; } clear_log_links ();
It doesn't, but I confirm that the bug is target independent. A way to fix it would be to do the transform in VRP, but I'll look at combine if time permits.
The first one is in the same EBB as the assignment. The second one isn't and combine screws up. This is because of the way combine treats regs with one def that dominates all uses, I talked to zadeck yesterday about that on IRC.
Created attachment 13083 [details] patch to fix the bug The logic in trunk's combine with respect to uninitialized variables is correct. We have to look at DF_LR_IN for the entry basic block to find variables that are not used uninitialized. In fact, the name of DF_UR_IN is misleading, as it computes *initialized* registers.
Now that the patch has been applied to dataflow branch, this remains as a missed optimization on the tree level.
Subject: Bug 30904 Author: bonzini Date: Sat Feb 24 16:07:41 2007 New Revision: 122290 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=122290 Log: 2007-02-23 Paolo Bonzini <bonzini@gnu.org> PR tree-optimization/30904 * gcc.dg/pr30904.c: New test. Added: trunk/gcc/testsuite/gcc.dg/pr30904.c Modified: trunk/gcc/testsuite/ChangeLog
Subject: Bug 30904 Author: rguenth Date: Fri Mar 9 12:29:09 2007 New Revision: 122748 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=122748 Log: 2007-03-09 Richard Guenther <rguenther@suse.de> PR tree-optimization/30904 PR middle-end/31058 * tree-vrp.c (extract_range_from_binary_expr): Handle RSHIFT_EXPR the same way as *_DIV_EXPR. * gcc.dg/pr30904.c: Remove xfail. Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gcc.dg/pr30904.c trunk/gcc/tree-vrp.c
Fixed.