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

--- Comment #19 from Peter Bergner <bergner at gcc dot gnu.org> ---
(In reply to Peter Bergner from comment #18)
> With the patch Vlad attached minus the one unwanted line/typo, I'm getting
> an ICE on a powerpc64le-linux bootstrap.  Looking into it.

Here's a minimal test case:

bergner@genoa:~/gcc/BUGS/PR78516$ cat libgcc2.i
float
fn1 (__int128 a)
{
  if ((unsigned)a == a)
    return a;
}
bergner@genoa:~/gcc/BUGS/PR78516$
/home/bergner/gcc/build/gcc-fsf-mainline-pr78516/./gcc/xgcc
-B/home/bergner/gcc/build/gcc-fsf-mainline-pr78516/./gcc/ -O2 -S libgcc2.i 
libgcc2.i: In function ‘fn1’:
libgcc2.i:6:1: internal compiler error: in lra_set_insn_recog_data, at
lra.c:965
 }
 ^
0x10a8eaaf lra_set_insn_recog_data(rtx_insn*)
        /home/bergner/gcc/gcc-fsf-mainline-pr78516/gcc/lra.c:963

We have the following insn after IRA:

(insn 13 12 31 4 (set (reg:SF 157 [ <retval> ])
        (float:SF (subreg:DI (reg/v:TI 158 [ aD.2516 ]) 0))) "libgcc2.i":5 407
{floatdisf2_fcfids}
     (expr_list:REG_DEAD (reg/v:TI 158 [ aD.2516 ])
        (nil)))

With pseudo 157 being assigned to fp reg fr1 and pseudo 158 being assigned to
r3.  The floatdisf2_fcfids pattern looks like:

(define_insn "floatdisf2_fcfids"
  [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy")
        (float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))]
  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
   && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
  "@
   fcfids %0,%1
   xscvsxdsp %x0,%x1"
  [(set_attr "type" "fp")])

...so pseudo 158 does not match the pattern's constraints. 
check_and_process_move() doesn't handle this type of insn, so it returns false
and eventually, we generate the following two insns (haven't tracked down where
they come from yet):

(insn 38 12 13 4 (set (reg:DI 165)
        (subreg:DI (reg/v:TI 158 [ a ]) 0)) "libgcc2.i":5 582
{*movdi_internal64}
     (nil))

(insn 13 38 31 4 (set (reg:SF 157 [ <retval> ])
        (float:SF (reg:DI 165))) "libgcc2.i":5 407 {floatdisf2_fcfids}
     (expr_list:REG_DEAD (reg/v:TI 158 [ a ])
        (nil)))

This maybe looks ok (?), except for the REG_DEAD on insn 13 should have been
removed and added to the new insn 38.

Later, check_and_process_move() is called again, this time for the new insn 38
and this is where we end up ICEing.  We end up seeing:

(gdb) pr dest
(reg:DI 165)
(gdb) pr dreg
(reg:DI 165)
(gdb) p dclass
$54 = FLOAT_REGS
(gdb) p dregno
$55 = 165

(gdb) pr src
(subreg:DI (reg/v:TI 158 [ a ]) 0)
(gdb) pr sreg
(reg/v:TI 158 [ a ])
(gdb) p sregno
$56 = -1
(gdb) p sclass
$57 = BASE_REGS

(gdb) p secondary_class 
$58 = NO_REGS

Due to the above, new_reg == NULL_RTX and sri.icode ==
CODE_FOR_reload_vsx_from_gprti.  This pushes us down the else clause of the
following if:

  if (sri.icode == CODE_FOR_nothing)
    lra_emit_move (new_reg, sreg);
  else
    {
      enum reg_class scratch_class;

      scratch_class = (reg_class_from_constraints
                       (insn_data[sri.icode].operand[2].constraint));
      scratch_reg = (lra_create_new_reg_with_unique_value
                     (insn_data[sri.icode].operand[2].mode, NULL_RTX,
                      scratch_class, "scratch"));
      emit_insn (GEN_FCN (sri.icode) (new_reg != NULL_RTX ? new_reg : dest,
                                      new_reg != NULL_RTX ? sreg : src,
                                      scratch_reg));
    }

We then up calling gen_reload_vsx_from_gprti() via the emit_insn() with:
op0, op1 and op2 as:

(gdb) pr operand0
(reg:DI 165)
(gdb) pr operand1
(subreg:DI (reg/v:TI 158 [ a ]) 0)
(gdb) pr operand2
(reg:IF 166)

That subreg for operand1 does not look correct to me.

Reply via email to