Some users of is_parallel_of_n_reg_sets disregard the clobbers in a parallel after it has returned "yes, this is a parallel of N sets and maybe some clobbers". But combine uses a clobber of const0_rtx to indicate substitution failure, so this leads to disaster.
Fix this by checking for such special clobbers in is_parallel_of_n_reg_sets. Tested on powerpc64-linux. Also tested with Kyrill's testcase, manually inspected the generated asm and the combine dump file (with some extra instrumentation). This testcase needs -O1 btw. The "performance problem" in the PR (same testcase, but with -O3) is a missed jump optimization: a pseudo is set (to 0) in one BB (and nowhere else), and then tested against 0 in another BB. Nothing after combine seems to handle this. Applying this patch to trunk. Kyrill, could you handle the testcase? Together with whatever you decide should be done for the -O3 problem. Thank you for tracking down this nastiness! Segher 2015-11-24 Segher Boessenkool <seg...@kernel.crashing.org> PR rtl-optimization/68381 * combine.c (is_parallel_of_n_reg_sets): Return false if the pattern is poisoned. --- gcc/combine.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/combine.c b/gcc/combine.c index 2a66fd5..4958d3b 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -2512,7 +2512,8 @@ is_parallel_of_n_reg_sets (rtx pat, int n) || !REG_P (SET_DEST (XVECEXP (pat, 0, i)))) return false; for ( ; i < len; i++) - if (GET_CODE (XVECEXP (pat, 0, i)) != CLOBBER) + if (GET_CODE (XVECEXP (pat, 0, i)) != CLOBBER + || XEXP (XVECEXP (pat, 0, i), 0) == const0_rtx) return false; return true; -- 1.9.3