https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124079
--- Comment #1 from Stefan Schulze Frielinghaus <stefansf at gcc dot gnu.org>
---
A slightly smaller reproducer is
int foo (const char *a, const char *b)
{
return __builtin_strcmp (a, b);
}
(insn 17 10 18 2 (parallel [
(set (reg/i:DI 2 %r2)
(sign_extend:DI (unspec:SI [
(reg:CCU 33 %cc)
] UNSPEC_STRCMPCC_TO_INT)))
(clobber (reg:CC 33 %cc))
]) "t.c":4:1 2022 {*cmpint_sign}
(expr_list:REG_DEAD (reg:CCU 33 %cc)
(expr_list:REG_UNUSED (reg:CC 33 %cc)
(nil))))
(define_insn_and_split "*cmpint_sign"
[(set (match_operand:DI 0 "register_operand" "=d")
(sign_extend:DI (unspec:SI [(match_operand:CCU 1 "register_operand"
"0")]
UNSPEC_STRCMPCC_TO_INT)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ZARCH"
"#"
"&& reload_completed"
[(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 34)))
(parallel
[(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 62)))
(clobber (reg:CC CC_REGNUM))])])
Insn 17 leads to a reload because operand 1 matches operand 0 and the hard regs
differ. So we end up in match_reload() where in_rtx equals (reg:CCU 33 %cc)
and out_rtx equals (reg/i:DI 2 %r2) which means the modes differ and we end up
in the else branch:
else
{
reg = new_out_reg
= lra_create_new_reg_with_unique_value (outmode, out_rtx,
goal_class,
exclude_start_hard_regs,
"");
new_in_reg = get_matching_reload_reg_subreg (inmode, reg);
and try to create a subreg with inner mode DI and outer mode CCU (mode size ==
4 bytes). Partially reverting r16-7464 by using gen_lowpart_SUBREG (mode, reg)
instead of gen_rtx_SUBREG (mode, reg, 0) in get_matching_reload_reg_subreg()
solves this and we end up with new_in_reg == (subreg:CCU (reg:DI 71) 4) which
looks good to me. However, I haven't looked into PR121191 and how this
interferes with that so far.