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

            Bug ID: 83691
           Summary: Invalid gpr_reg_operand handling in powerpcspe port
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rsandifo at gcc dot gnu.org
  Target Milestone: ---
            Target: powerpc-eabispe

The powerpcspe adddi3 pattern takes gpr_reg_operands:

(define_expand "add<mode>3"
  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
        (plus:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
                  (match_operand:SDI 2 "reg_or_add_cint_operand" "")))]

and splits the addition into two 32-bit instructions:

      rtx lo0 = gen_lowpart (SImode, operands[0]);
      rtx lo1 = gen_lowpart (SImode, operands[1]);
      rtx lo2 = gen_lowpart (SImode, operands[2]);
      rtx hi0 = gen_highpart (SImode, operands[0]);
      rtx hi1 = gen_highpart (SImode, operands[1]);
      rtx hi2 = gen_highpart_mode (SImode, DImode, operands[2]);

      if (!reg_or_short_operand (lo2, SImode))
        lo2 = force_reg (SImode, lo2);
      if (!adde_operand (hi2, SImode))
        hi2 = force_reg (SImode, hi2);

      emit_insn (gen_addsi3_carry (lo0, lo1, lo2));
      emit_insn (gen_addsi3_carry_in (hi0, hi1, hi2));

However, gpr_reg_operand rejects subregs that satisfy invalid_e500_subreg:

  if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode))
    return 0;

and invalid_e500_subreg rejects subregs of vectors for SImode but not
for DImode:

  if (TARGET_SPE
      && GET_CODE (op) == SUBREG
      && mode == SImode
      && REG_P (SUBREG_REG (op))
      && SPE_VECTOR_MODE (GET_MODE (SUBREG_REG (op))))
    return true;

This means that gpr_reg_operand accepts things for DImode that
are invalid when split to SImode.  An example of this is
gcc.dg/vect/vect-singleton_1.c when compiled at -O3, where we get:

error: unrecognizable insn:
 TEST (long long, int64x1_t, s64)
 ^~~~
(insn 10 9 11 2 (parallel [
            (set (subreg:SI (reg:DI 163) 4)
                (plus:SI (subreg:SI (reg/v:V1DI 159 [ a ]) 4)
                    (reg:SI 164)))
            (set (reg:SI 76 ca)
                (ltu:SI (plus:SI (subreg:SI (reg/v:V1DI 159 [ a ]) 4)
                        (reg:SI 164))
                    (subreg:SI (reg/v:V1DI 159 [ a ]) 4)))
        ]) "../../../testsuite/gcc.dg/./vect/vect-singleton_1.c":28 -1
     (nil))
during RTL pass: vregs

This particular testcase started failing with r256209, but that
really just exposed an existing problem.

Reply via email to