The function instantiate_virtual_regs_in_insn does not handle the case if an address with offset is taken. Then a virtual register may appear (e.g argptr) inside a PLUS.
This patch adds the handling for PLUS. Stefan --- a/gcc/function.c +++ b/gcc/function.c @@ -1,5 +1,5 @@ /* Expands front end tree to back end RTL for GCC. - Copyright (C) 1987-2019 Free Software Foundation, Inc. + Copyright (C) 1987-2020 Free Software Foundation, Inc. This file is part of GCC. @@ -1658,9 +1658,12 @@ instantiate_virtual_regs_in_insn (rtx_insn *insn) } /* In the general case, we expect virtual registers to appear only in - operands, and then only as either bare registers or inside memories. */ + operands, and then only as either bare registers or inside memories. + SBF: ... and sometimes - taking an address - inside a PLUS. */ for (i = 0; i < recog_data.n_operands; ++i) { + poly_int64 old_offset = 0; + x = recog_data.operand[i]; switch (GET_CODE (x)) { @@ -1694,10 +1697,19 @@ instantiate_virtual_regs_in_insn (rtx_insn *insn) } break; + case PLUS: + if (!REG_P (XEXP (x, 0)) || !CONST_INT_P (XEXP (x, 1))) + continue; + + old_offset = INTVAL (XEXP (x, 1)); + x = XEXP (x, 0); + /* no break */ case REG: new_rtx = instantiate_new_reg (x, &offset); if (new_rtx == NULL) continue; + + offset += old_offset; if (known_eq (offset, 0)) x = new_rtx; else