https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78516

--- Comment #4 from Peter Bergner <bergner at gcc dot gnu.org> ---
Created attachment 40317
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40317&action=edit
Potential fix to spe.md

(In reply to Peter Bergner from comment #2)
> So we're hitting this code in lra-assigns.c:lra_assign():1612:
> 
>   if (flag_checking && !flag_ipa_ra)
>     for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
>       if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
>           && lra_reg_info[i].call_p
>           && overlaps_hard_reg_set_p (call_used_reg_set,
>                                       PSEUDO_REGNO_MODE (i),
> reg_renumber[i]))
>         gcc_unreachable ();
> 
> Our pseudo (i == 184) had been assigned to r9 (a call clobbered reg) and yet
> lra_reg_info[184].call_p is true, leading to the assert.
> 
> Looking through the rtl dumps, pseudo 184 is live only over two consecutive
> insns, so clearly call_p should not be true here.  I'm tracking down where
> that is getting set.

This ends up being a bug in the spe.md:*mov_sidf_e500_subreg0_2_be pattern's
constraints (ditto from some other patterns).

The problem RTL is below.  We have a call followed later in the same basic
block, by a set of pseudo 184 and then its only use closely thereafter:

(call_insn 13 10 14 2 (parallel [
            (call (mem:SI (symbol_ref:SI ("bar") [flags 0x41] <function_decl
0x3fff821b4600 bar>) [0 barD.1674 S4 A32])
                (const_int 0 [0]))
            (use (const_int 0 [0]))
            (clobber (reg:SI 65 lr))
        ]) "pr78516.i":5 654 {*call_nonlocal_sysvsi}
     (nil)
    (nil))
...
(insn 16 15 17 2 (set (reg:SI 184)
        (subreg:SI (reg:DF 155 [ neg0.0_1 ]) 0)) "pr78516.i":7 1975
{*mov_sidf_e500_subreg0_2_be}
     (expr_list:REG_DEAD (reg:DF 155 [ neg0.0_1 ])
        (nil)))
...
(insn 19 18 20 2 (set (reg:CC 167)
        (compare:CC (reg:SI 184)
            (const_int 0 [0]))) "pr78516.i":7 678 {*cmpsi_signed}
     (expr_list:REG_DEAD (reg:SI 184)
        (nil)))

So pseudo 184 (assigned to a call clobber reg) is not live across the call, but
lra-lives.c:process_bb_lives() thinks it is, so it triggers the above assert. 
It seems IRA uses the gcc df infrastructure to determine liveness and this
tells IRA is can assign a call clobbered register to pseudo 184 and it does
(r9).  lra-lives.c has its own liveness analysis code which does not make use
of df (should it?) and its analysis finds the pseudo 184's live range extends
up to the call and beyond.  This is due to lra-lives.c uses an insn's recog
data to see what operands are defined and used in an insn and computes liveness
from that.  The "bug" is that the *mov_sidf_e500_subreg0_2_be pattern has
incorrect constraints and the defined pseudo is marked as a OP_INOUT operand,
so it what makes pseudo 184 live range extend up to the top of the block and
across the call leading to the ICE.  The pattern is:

(define_insn "*mov_si<mode>_e500_subreg0_2_be"
  [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
        (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,&r") 0))]
  "WORDS_BIG_ENDIAN
   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
  "@
   evmergehi %0,%0,%1
   evmergelohi %1,%1,%1\;stw%U0%X0 %1,%0"
  [(set_attr "length" "4,8")])

There are multiple problems with the first alternative.  First, op1 is marked
as an input/output operand, but it clearly only an input.

Secondly, op0 is also marked as a input/output operand (and this is what leads
to our ICE) since it is used as an input to the evmergehi instruction. 
However, the purpose of the pattern is to simply copy the high word of op1 and
place it into the low word of op0.  In that case, that case, the source operand
%0 here could be any register, since it's value will be unused (since we're
writing a SImode reg).  That means op0 really should only be an output operand.
 To simplify things, so changed the instruction for the first alternative to be
the same as the second alternative, since they're performing the same function,
except that alternative 1 also stores the value to memory.

For the second alternative, I moved the earlyclobber constraint modifier to the
output operand to quiet the following message I was getting after my changes:

/home/bergner/gcc/gcc-fsf-mainline-pr78516/gcc/config/rs6000/spe.md:2561:1:
earlyclobber operands may not be read-only in alternative 1

Therefore, the "fixed" pattern which eliminates the ICE, looks like:

 (define_insn "*mov_si<mode>_e500_subreg0_2_be"
-  [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
-       (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,&r") 0))]
+  [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,&m")
+       (subreg:SI (match_operand:SPE64TF 1 "register_operand" "r,r") 0))]
   "WORDS_BIG_ENDIAN
    && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
        || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
   "@
-   evmergehi %0,%0,%1
+   evmergelohi %0,%1,%1
    evmergelohi %1,%1,%1\;stw%U0%X0 %1,%0"
   [(set_attr "length" "4,8")])


Looking through the spe.md file, I see similar issues with constraints on other
patterns, so I fixed them similarly as here.

Joseph, can you try the attached patch to see if it works for you, and if so,
whether it bootstraps and regtests?

Reply via email to