Hi all, I admit that, the title looks a little bit confusing.
The situation is like this, To make insn_1 strict, lra generates a new insn_1_reload insn. In insn_1_reload, there is a scratch operand with this form clobber (match_scratch:MODE x "=&r") When lra tries to reload insn_1_reload in later iteration, a new pseudo register (let say RXX) is created to replace this scratch operand in-place. Additionally, a new insn will be generated and inserted after insn_1_reload to finish the reload. It's in this form: (set scratch, RXX) And this instruction is illegal. no target implements this kind of pattern. LRA will ICE because of this. "internal compiler error: in lra_set_insn_recog_data, at lra.c:964" And indeed, this pattern has no side-effect. The scratch operand should stay inside the pattern. Normally, at the very beginning of LRA reload, all scratch operands will be replaced by newly created pseudo register. However, this is a problem when generated reload insn has output scratch operand. I have checked, x86, arm, aarch64, mips, arc all have such patterns. But it's not triggered. In my case, it's triggered by compiling glibc with local change. So a simple change is made in this patch. The output operand is reloaded only when it's not a scratch operand and it's not unused since then. aarch64-none-linux-gnu bootstrap and regression test OK. x86_64-linux bootstrap and regression test OK. OK for trunk? Regards, Renlin Li gcc/ChangeLog: 2016-02-26 Renlin Li<renlin...@arm.com> * lra-constraints.c (curr_insn_transform): Don't generate reload for output scratch operand.
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 08cf0aa6c4208bb60ba5071bad1255d587f1cb4a..ef5809ff226cca69bb711bfc5dab55e24caba01a 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -3882,6 +3882,8 @@ curr_insn_transform (bool check_only_p) } *loc = new_reg; if (type != OP_IN + /* Don't generate reload for output scratch operand. */ + && GET_CODE (old) != SCRATCH && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX) { start_sequence ();