https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95267
--- Comment #4 from otcmaf <xuemaosheng at huawei dot com> --- (In reply to Andrew Pinski from comment #3) > The internals documentation documents this even, read: > https://gcc.gnu.org/onlinedocs/gccint/RTL-Template.html#index-match_005fdup > > From that: > Note that match_dup should not be used to tell the compiler that a > particular register is being used for two operands (example: add that adds > one register to another; the second register is both an input operand and > the output operand). Use a matching constraint (see Simple Constraints) for > those. However, in gcc/config/aarch64/aarch64-simd.md also has the similar usage。 For example: 1227 (define_insn "aarch64_simd_move_hi_quad_<mode>" 1228 [(set (match_operand:VQ 0 "register_operand" "+w,w") 1229 (vec_concat:VQ 1230 (vec_select:<VHALF> 1231 (match_dup 0) 1232 (match_operand:VQ 2 "vect_par_cnst_lo_half" "")) 1233 (match_operand:<VHALF> 1 "register_operand" "w,r")))] 1234 "TARGET_SIMD && !BYTES_BIG_ENDIAN" 1235 "@ 1236 ins\\t%0.d[1], %1.d[0] 1237 ins\\t%0.d[1], %1" 1238 [(set_attr "type" "neon_ins")] 1239 ) the operands[0] is a inout reg, and the pattern also use (match_dup 0). Another case in gcc/config/c6x/c6x.md 440 (define_insn "*movstricthi_high" 441 [(set (match_operand:SI 0 "register_operand" "+ab") 442 (ior:SI (and:SI (match_dup 0) (const_int 65535)) 443 (ashift:SI (match_operand:SI 1 "const_int_operand" "IuB") 444 (const_int 16))))] 445 "reload_completed" 446 "%|%.\\tmvklh\\t%$\\t%1, %0" 447 [(set_attr "units" "s")]) 2930 (define_insn "setup_dsbt" 2931 [(set (match_operand:SI 0 "pic_register_operand" "+Z") 2932 (unspec:SI [(match_dup 0) 2933 (match_operand:SI 1 "symbolic_operand" "")] 2934 UNSPEC_SETUP_DSBT))] 2935 "TARGET_DSBT" 2936 "%|%.\\tldw\\t%$\\t*+%0($DSBT_index%1), %0" 2937 [(set_attr "type" "load") 2938 (set_attr "units" "d_addr") 2939 (set_attr "dest_regfile" "b") 2940 (set_attr "addr_regfile" "b")]) Do you mean that those pattern above are also wrong pattern ? As you say that, that match_dup should not be used to tell the compiler that a particular register is being used for two operands. But I still think that the function can_assign_to_reg_without_clobbers_p can do bettter, use max_reg_num to replace FIRST_PSEUDO_REGISTER * 2 and update TEST_INSN when calling this function.