Hello,
I've looked into RTL after register allocation. Insn which
lead to assert is:
(insn 77 180 79 4 (set (reg/v:TF 44 loc12 [orig:359 T8 ] [359])
        (mem:TF (post_modify:DI (reg/f:DI 14 r14 [435])
                (plus:DI (reg/f:DI 14 r14 [435])
                    (reg:DI 45 loc13 [orig:342 D.3347 ] [342]))) [2 *R1_102+0 
S16 A128])) 1.i:2370 131 {*movtf_intern\
al}

When trying to split it into two DI loads here:
     ia64_split_tmode_move

We check if source and destination RTX are register overlapped,
and if so, set flag that says that load adress is dead after insns:
  if (GET_CODE (operands[1]) == MEM
      && reg_overlap_mentioned_p (operands[0], operands[1]))
    ...
    dead = true;

This flags is asserted (to be unset) later in splitting of memory operand in 
ia64_split_tmode:
          case POST_MODIFY:
            gcc_assert (!reversed && !dead);

I think that the insn (although op[0] and op1[1] are overlapped by regs)
is still safe to split. And we might end up with something like this:
  (insn 272 0 0 (set (reg:DI 44 loc12)
          (mem:DI (post_inc:DI (reg/f:DI 14 r14 [435])) [2 *R1_102+0 S8 A128]))
  (insn 273 272 0 (set (reg:DI 45 loc13)
          (mem:DI (post_modify:DI (reg/f:DI 14 r14 [435])
                  (plus:DI (reg/f:DI 14 r14 [435])
                      (reg:DI 45 loc13 [orig:342 D.3347 ] [342]))) [2 *R1_102+8 
S8 A64]))
  (set (reg/f:DI 14 r14 [435])
      (plus:DI (reg/f:DI 14 r14 [435])
          (const_int -8 [0xfffffffffffffff8])))

As far as I understand, second insn will update loc13 *after* ld is executed,
so value of location in r14 will be correct.

Patch in the bottom.

ChangeLog entry:
          * config/ia64/ia64.c (ia64_split_tmode_move): Relax `dead' flag 
setting.

Testcase builds w/o ICE with the patch.
Bootstrapped.

Could you pls take a look?

--
Thanks, K
---
 gcc/config/ia64/ia64.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index a128b19..446ee59 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -1527,12 +1527,19 @@ ia64_split_tmode_move (rtx operands[])
       && reg_overlap_mentioned_p (operands[0], operands[1]))
     {
       rtx base = XEXP (operands[1], 0);
+      rtx first_write = gen_rtx_REG (DImode, REGNO (operands[0]));
       while (GET_CODE (base) != REG)
        base = XEXP (base, 0);

       if (REGNO (base) == REGNO (operands[0]))
-       reversed = true;
-      dead = true;
+       {
+         reversed = true;
+         first_write = gen_rtx_REG (DImode, REGNO (operands[0]) + 1);
+       }
+
+      if (GET_CODE (operands[0]) == REG
+         && reg_overlap_mentioned_p (first_write, operands[1]))
+       dead = true;
     }
   /* Another reason to do the moves in reversed order is if the first
      element of the target register pair is also the second element of

Reply via email to