On 03/01/2017 03:06 PM, Jim Wilson wrote:
This is a proposed patch for the bug 79794 which I just submitted.
This isn't a regression, so this can wait for after the gcc 7 branch
if necessary.
The problem here is that a reg+offset MEM target is passed to
extract_bit_field with a vector register source. On aarch64, we have
an instruction for this, but it accepts a reg address only, so the
address gets loaded into a reg inside extract_bit_field. We then
return to expand_expr which does
! rtx_equal_p (temp, target)
which fails because of the address mode change, so we end up copying
target into a reg and then back to itself.
expand_expr has a solution for this problem. There is an alt_rtl
variable that can be set when temp is logically the same as target.
This variable is currently not passed into extract_bit_field. This
patch does that.
There is an additional complication that the actual address load into
a reg occurs inside maybe_expand_insn, and it doesn't seem reasonable
to pass alt_reg into that. However, I can grab a bit from the
expand_operand structure to indicate when an operand is the target,
and then clear it if target is replaced with a reg.
The resulting patch works, but ends up a bit more invasive than I
hoped. The patch has passed a bootstrap and make check test on x86_64
and aarch64.
Jim
alt-rtl.patch
Proposed patch for RTL expand bug affecting aarch64 vector code.
PR middle-end/79794
* expmed.c (extract_bit_field_1): Add alt_rtl argument. Before
maybe_expand_insn call, set ops[0].target. If still set after call,
set alt_rtl. Add extra arg to recursive calls.
(extract_bit_field): Add alt_rtl argument. Pass to
extract_bit_field.
* expmed.h (extract_bit_field): Fix prototype.
* expr.c (emit_group_load_1, copy_blkmode_from_reg)
(copy_blkmode_to_reg, read_complex_part, store_field): Pass extra NULL
to extract_bit_field_calls.
(expand_expr_real_1): Pass alt_rtl to expand_expr_real instead of 0.
Pass alt_rtl to extract_bit_field calls.
* calls.c (store_unaligned_arguments_into_psuedos)
load_register_parameters): Pass extra NULL to extract_bit_field calls.
* optabs.c (maybe_legitimize_operand): Clear op->target when call
gen_reg_rtx.
* optabs.h (struct expand_operand): Add target bitfield.
The only part I found intrusive was the op->target stuff, but it wasn't
terrible.
The additional argument creates visual clutter in the diffs as the
callers get updated, but that's pretty easy to filter out.
This seems fine to me. A testcase to add to the gcc.target testsuite
would be useful, but I don't think it's strictly necessary.
jeff