reduced test case: typedef union { long all; struct { int low; int high; } s; } udwords; int a, b, c, d; void __udivmoddi4() { udwords r; d = __builtin_clz(0); r.s.low = 0; for (; d; --d) { r.s.high = r.s.high << 1 | r.s.low >> a; r.s.low = r.s.low << b >> 1; int s = -r.all; c = s; r.all--; } } % g++ -O2 -c test.ii test.ii: In function ‘void __udivmoddi4()’: test.ii:20:1: internal compiler error: Segmentation fault } ^ 0xb4f8df crash_signal ../../gcc/gcc/toplev.c:337 0xb056c9 reg_used_between_p(rtx_def const*, rtx_def const*, rtx_def const*) ../../gcc/gcc/rtlanal.c:753 0x103e6eb combine_reaching_defs ../../gcc/gcc/ree.c:734 0x103e6eb find_and_remove_re ../../gcc/gcc/ree.c:973 0x103e6eb rest_of_handle_ree ../../gcc/gcc/ree.c:1035 0x103e6eb execute ../../gcc/gcc/ree.c:1074 Please submit a full bug report,
Started with r206418.
The ICE is because cand->insn is earlier in the bb than def_insn. But too tired to look why.
No worries Jakub. I'll take it as it's clearly mine.
I see what's going on. Basically the code exhibits undefined behaviour (r.s.high is not defined before its first use in the loop). Thus the first and only reaching def is appearing after the first use. Obviously we shouldn't be faulting here. Markus -- You might want to go back to your original test and ensure it's not exhibiting undefined behaviour. The original code may be exhibiting undefined behaviour.
I think we can just check DF_INSN_LUIDs here to catch this case. My systems are busy right now, but I should be able to nail this down as soon as one frees up.
Created attachment 31791 [details] original testcase Here's the unreduced original.
(In reply to Jeffrey A. Law from comment #5) > I think we can just check DF_INSN_LUIDs here to catch this case. My systems > are busy right now, but I should be able to nail this down as soon as one > frees up. But is DF_INSN_LUID always computed? I mean, for -O2 it probably is, but what about -O -free ? For -O I think the live problem isn't on and thus I think DF_INSN_LUID isn't computed. The DF documentation is unfortunately non-existent :(.
/* The logical uid of the insn in the basic block. This is valid after any call to df_analyze but may rot after insns are added, deleted or moved. */ int luid;
And note that ree does not make the LUID data stale until after analyzing *all* the potential transformations. So the limitations of LUIDs shouldn't be a problem. Anyway, patch is in testing.
Ah, there is: /* If the df_live problem is not defined, such as at -O0 and -O1, we still need to keep the luids up to date. This is normally done in the df_live problem since this problem has a forwards scan. */ if (!df_live) df_recompute_luids (bb); in df_lr_bb_local_compute, so I think luids are fine even at -O0/-O1.
Thanks. I'm still working through the RTL/source on the full testcase to see if there are any uninitialized uses. Regardless the patch I have here works for both the reduced and original testcase. I'll be posting it for review momentarily.
Author: law Date: Fri Jan 10 22:13:18 2014 New Revision: 206545 URL: http://gcc.gnu.org/viewcvs?rev=206545&root=gcc&view=rev Log: PR middle-end/59743 * ree.c (combine_reaching_defs): Ensure the defining statement occurs before the extension when optimizing extensions with different source and destination hard registers. PR middle-end/59743 * gcc.c-torture/compile/pr59743.c: New test. Added: trunk/gcc/testsuite/gcc.c-torture/compile/pr59743.c Modified: trunk/gcc/ChangeLog trunk/gcc/ree.c trunk/gcc/testsuite/ChangeLog
Should be fixed on the trunk now.