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);