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

Kewen Lin <linkw at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bergner at gcc dot gnu.org,
                   |                            |segher at gcc dot gnu.org,
                   |                            |vmakarov at gcc dot gnu.org

--- Comment #3 from Kewen Lin <linkw at gcc dot gnu.org> ---
The culprit commit offers more chances on float constant copying, but it leads
LRA to generate one insn which is an unrecognizable insn:

(insn 181 0 0 (set (const_vector:V1TI [
                (const_int 0 [0])
            ])
        (reg:V1TI 179)) -1
     (nil))

Initially at function curr_insn_transform curr_insn is

(insn 106 102 160 12 (set (mem:V1TI (and:DI (plus:DI (plus:DI (reg/f:DI 110
sfp)
                        (reg:DI 162))
                    (const_int 144 [0x90]))
                (const_int -16 [0xfffffffffffffff0])) [2  S16 A128])
        (subreg:V1TI (reg:KF 133) 0)) "test.i":9:5 discrim 2 1178
{*vsx_le_perm_store_v1ti}
     (expr_list:REG_DEAD (reg:DI 162)
        (expr_list:REG_DEAD (reg:KF 133)
            (nil))))

with equiv substition, it becomes to

(insn 106 102 160 12 (set (mem:V1TI (and:DI (plus:DI (plus:DI (reg/f:DI 110
sfp)
                        (reg:DI 162))
                    (const_int 144 [0x90]))
                (const_int -16 [0xfffffffffffffff0])) [2  S16 A128])
        (const_vector:V1TI [
                (const_int 0 [0])
            ])) "test.i":9:5 discrim 2 1178 {*vsx_le_perm_store_v1ti}
     (expr_list:REG_DEAD (reg:DI 162)
        (expr_list:REG_DEAD (reg:KF 133)
            (nil))))

the corresponding pattern is:

(define_insn "*vsx_le_perm_store_<mode>"
  [(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z,Q")
        (match_operand:VSX_LE_128 1 "vsx_register_operand" "+wa,r"))]
  "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR
   && !altivec_indexed_or_indirect_operand (operands[0], <MODE>mode)"
  "@
   #
   #"
  [(set_attr "type" "vecstore,store")
   (set_attr "length" "12,8")
   (set_attr "isa" "<VSisa>,*")])

, alt 0 is selected, LRA fixes it up with:

Creating newreg=179, assigning class VSX_REGS to r179

(insn 180 179 0 (set (reg:V1TI 179)
        (const_vector:V1TI [
                (const_int 0 [0])
            ])) 1193 {vsx_movv1ti_64bit}
     (nil))

which is sensible, but the unexpected thing is that is also generates 

(insn 181 0 0 (set (const_vector:V1TI [
                (const_int 0 [0])
            ])
        (reg:V1TI 179)) -1
     (nil))

...
via the code:

          *loc = new_reg;
          if (type != OP_IN
              && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX)
            {
              start_sequence ();
              lra_emit_move (type == OP_INOUT ? copy_rtx (old) : old, new_reg);
              emit_insn (after);
              after = get_insns ();
              end_sequence ();
              *loc = new_reg;
            }
...

the reason here is the type isn't OP_IN so it wants to assign back to the OUT
OP, but the old here is a const_vector which is replaced with equiv, I think we
should stop move emission for this case.

The below patch makes it pass:

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 92b343fa99a..024c85c87d9 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -4742,7 +4742,8 @@ curr_insn_transform (bool check_only_p)
             }
           *loc = new_reg;
           if (type != OP_IN
-              && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX)
+              && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX
+              && nonimmediate_operand (old, GET_MODE (old)))
             {
               start_sequence ();
               lra_emit_move (type == OP_INOUT ? copy_rtx (old) : old,
new_reg);

Reply via email to