diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c58d419556b..ac283a63a9e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2018-02-13 Segher Boessenkool + + PR rtl-optimization/84169 + * combine.c (try_combine): New variable split_i2i3. Set it to true if + we generated a parallel as new i3 and we split that to new i2 and i3 + instructions. Handle split_i2i3 similar to swap_i2i3: scan the + LOG_LINKs of i3 to see which of those need to link to i2 now. Link + those to i2, not i1. Partially rewrite this scan code. + 2018-02-13 Jakub Jelinek PR c/82210 diff --git a/gcc/combine.c b/gcc/combine.c index a9929f2a3e2..c4d55eb85a4 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -2665,6 +2665,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, /* Notes that I1, I2 or I3 is a MULT operation. */ int have_mult = 0; int swap_i2i3 = 0; + int split_i2i3 = 0; int changed_i3_dest = 0; int maxreg; @@ -4091,6 +4092,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, } insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); + + if (insn_code_number >= 0) + split_i2i3 = 1; } } @@ -4258,44 +4262,45 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, if (swap_i2i3) { - rtx_insn *insn; - struct insn_link *link; - rtx ni2dest; - /* I3 now uses what used to be its destination and which is now I2's destination. This requires us to do a few adjustments. */ PATTERN (i3) = newpat; adjust_for_new_dest (i3); + } - /* We need a LOG_LINK from I3 to I2. But we used to have one, - so we still will. + if (swap_i2i3 || split_i2i3) + { + /* We might need a LOG_LINK from I3 to I2. But then we used to + have one, so we still will. However, some later insn might be using I2's dest and have - a LOG_LINK pointing at I3. We must remove this link. - The simplest way to remove the link is to point it at I1, - which we know will be a NOTE. */ + a LOG_LINK pointing at I3. We should change it to point at + I2 instead. */ /* newi2pat is usually a SET here; however, recog_for_combine might have added some clobbers. */ - if (GET_CODE (newi2pat) == PARALLEL) - ni2dest = SET_DEST (XVECEXP (newi2pat, 0, 0)); - else - ni2dest = SET_DEST (newi2pat); + rtx x = newi2pat; + if (GET_CODE (x) == PARALLEL) + x = XVECEXP (newi2pat, 0, 0); - for (insn = NEXT_INSN (i3); - insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun) - || insn != BB_HEAD (this_basic_block->next_bb)); + unsigned int regno = REGNO (SET_DEST (x)); + + bool done = false; + for (rtx_insn *insn = NEXT_INSN (i3); + !done + && insn + && NONDEBUG_INSN_P (insn) + && BLOCK_FOR_INSN (insn) == this_basic_block; insn = NEXT_INSN (insn)) { - if (NONDEBUG_INSN_P (insn) - && reg_referenced_p (ni2dest, PATTERN (insn))) - { - FOR_EACH_LOG_LINK (link, insn) - if (link->insn == i3) - link->insn = i1; - - break; - } + struct insn_link *link; + FOR_EACH_LOG_LINK (link, insn) + if (link->insn == i3 && link->regno == regno) + { + link->insn = i2; + done = true; + break; + } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e14dd7d7a17..034931bad9b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-02-13 Segher Boessenkool + + PR rtl-optimization/84169 + * gcc.c-torture/execute/pr84169.c: New. + 2018-02-13 Peter Bergner PR target/84370 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr84169.c b/gcc/testsuite/gcc.c-torture/execute/pr84169.c new file mode 100644 index 00000000000..ba8f8fc4c05 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr84169.c @@ -0,0 +1,25 @@ +/* PR rtl-optimization/84169 */ + +#ifdef __SIZEOF_INT128__ +typedef unsigned __int128 T; +#else +typedef unsigned long long T; +#endif + +T b; + +static __attribute__ ((noipa)) T +foo (T c, T d, T e, T f, T g, T h) +{ + __builtin_mul_overflow ((unsigned char) h, -16, &h); + return b + h; +} + +int +main () +{ + T x = foo (0, 0, 0, 0, 0, 4); + if (x != -64) + __builtin_abort (); + return 0; +}