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] |
The following testcase: void foo (int a, int b, int c, int d, int e, int *f) { if (a == 0) if (b == 0) if (c == 0) if (d == 0) { *f = e; return; } *f = e; return; } ICEs at -O2 on mips targets. This happens both on mainline and 3.4 branch, but not 3.3. As expected, crossjumping unifies the duplicate "*f = e" blocks, leaving rtl like: if d == 0 then goto LABEL ;; end of block B1 ;; start of block B2 ;; end of block B2 ;; start of block B3 LABEL: cleanup_cfg() (specifically try_simplify_condjump()) then deletes the "if d == 0" branch, giving us: ;; start of block B1 ;; end of block B1 ;; start of block B3 LABEL: Now it looks like cleanup_cfg() is supposed to iterate until all such jumps have been simplified, but it doesn't. This is because it uses a cache (the bb aux field) to detect forwarder blocks, and this cache is not updated after B1 has been simplified. Thus we only eliminate one such branch for each call to cleanup_cfg(). The first patch below fixes that, and cures the ICE. But to finish the story... the task of cleaning up the final "a == 0" branch is left to: cleanup_cfg (CLEANUP_CFGLAYOUT); called from cfg_layout_initialize(), itself called from reorder_basic_blocks(). Now this call doesn't update the liveness information, so "a" is still marked as live after all uses have been deleted. This causes the usual verify_local_live_at_start failure during scheduling. CLEANUP_CFGLAYOUT is clearly capable of deleting register uses, so I assume that we should use CLEANUP_UPDATE_LIFE when liveness information needs to be kept up to date. That's what the second patch does, and it also fixes the ICE (independently of the first). The second patch has to touch other users of cfglayout as well: 1) tracer: - called once before flow1, where CLEANUP_UPDATE_LIFE isn't needed - called once during bbro, where C_U_L is needed. 2) reorder_basic_blocks - called once during bbro, where C_U_L is needed. - called once during stack, where C_U_L isn't needed. 3) partition_hot_and_cold_blocks - called after flow1, but liveness info is recomputed immedately afterwards, so I don't think C_U_L is needed. 4) thread_prologue_and_epilogue_insns - called between reload and flow2, C_U_L isn't needed. 5) loop2: - before flow1, C_U_L isn't needed. Slightly different patches are needed for mainline and branch. The mainline versions have been bootstrapped & regression tested on i686-pc-linux-gnu. I'm testing the 3.4 patches on mips*-linux-gnu targets now. Assuming the 3.4 tests pass, are both patches OK for mainline and branch? Or would it be better to just apply the first patch to branch? Richard
Attachment:
16643-1-mainline.diff
Description: Text document
Attachment:
16643-1-branch.diff
Description: Text document
Attachment:
16643-2-mainline.diff
Description: Text document
Attachment:
16643-2-branch.diff
Description: Text document
/* PR rtl-optimization/16643 */ void foo (int a, int b, int c, int d, int e, int *f) { if (a == 0) if (b == 0) if (c == 0) if (d == 0) { *f = e; return; } *f = e; return; }
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |