From 5d77cce2007b494c6e0bd094e7863b5b6e5a662b Mon Sep 17 00:00:00 2001 From: wilson Date: Sat, 13 May 2017 01:32:40 +0000 Subject: [PATCH] Patch for RTL expand bug affecting aarch64 vector code. gcc/ 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@248004 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 20 ++++++++++++++++++++ gcc/calls.c | 5 +++-- gcc/expmed.c | 14 +++++++++----- gcc/expmed.h | 2 +- gcc/expr.c | 25 ++++++++++++++----------- gcc/optabs.c | 1 + gcc/optabs.h | 5 ++++- 7 files changed, 52 insertions(+), 20 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1e14b0397d7..b58aacf9b53 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2017-05-12 Jim Wilson + + 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. + 2017-05-12 Uros Bizjak * compare-elim.c (try_eliminate_compare): Canonicalize diff --git a/gcc/calls.c b/gcc/calls.c index bd081ccf46c..91a4466b00b 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1164,7 +1164,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals) args[i].aligned_regs[j] = reg; word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX, - word_mode, word_mode, false); + word_mode, word_mode, false, NULL); /* There is no need to restrict this code to loading items in TYPE_ALIGN sized hunks. The bitfield instructions can @@ -2557,7 +2557,8 @@ load_register_parameters (struct arg_data *args, int num_actuals, unsigned int bitoff = (nregs - 1) * BITS_PER_WORD; unsigned int bitsize = size * BITS_PER_UNIT - bitoff; rtx x = extract_bit_field (mem, bitsize, bitoff, 1, dest, - word_mode, word_mode, false); + word_mode, word_mode, false, + NULL); if (BYTES_BIG_ENDIAN) x = expand_shift (LSHIFT_EXPR, word_mode, x, BITS_PER_WORD - bitsize, dest, 1); diff --git a/gcc/expmed.c b/gcc/expmed.c index c0260c53853..0c812806f9b 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1534,7 +1534,7 @@ static rtx extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target, machine_mode mode, machine_mode tmode, - bool reverse, bool fallback_p) + bool reverse, bool fallback_p, rtx *alt_rtl) { rtx op0 = str_rtx; machine_mode int_mode; @@ -1610,10 +1610,13 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT pos = bitnum / GET_MODE_BITSIZE (innermode); create_output_operand (&ops[0], target, innermode); + ops[0].target = 1; create_input_operand (&ops[1], op0, outermode); create_integer_operand (&ops[2], pos); if (maybe_expand_insn (icode, 3, ops)) { + if (alt_rtl && ops[0].target) + *alt_rtl = target; target = ops[0].value; if (GET_MODE (target) != mode) return gen_lowpart (tmode, target); @@ -1735,7 +1738,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, = extract_bit_field_1 (op0, MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD), bitnum + bit_offset, 1, target_part, - mode, word_mode, reverse, fallback_p); + mode, word_mode, reverse, fallback_p, NULL); gcc_assert (target_part); if (!result_part) @@ -1838,7 +1841,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, xop0 = copy_to_reg (xop0); rtx result = extract_bit_field_1 (xop0, bitsize, bitpos, unsignedp, target, - mode, tmode, reverse, false); + mode, tmode, reverse, false, NULL); if (result) return result; delete_insns_since (last); @@ -1894,7 +1897,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, rtx extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target, - machine_mode mode, machine_mode tmode, bool reverse) + machine_mode mode, machine_mode tmode, bool reverse, + rtx *alt_rtl) { machine_mode mode1; @@ -1929,7 +1933,7 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, } return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp, - target, mode, tmode, reverse, true); + target, mode, tmode, reverse, true, alt_rtl); } /* Use shifts and boolean operations to extract a field of BITSIZE bits diff --git a/gcc/expmed.h b/gcc/expmed.h index db1ce00c3f7..64476c3b4b2 100644 --- a/gcc/expmed.h +++ b/gcc/expmed.h @@ -725,7 +725,7 @@ extern void store_bit_field (rtx, unsigned HOST_WIDE_INT, machine_mode, rtx, bool); extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, int, rtx, - machine_mode, machine_mode, bool); + machine_mode, machine_mode, bool, rtx *); extern rtx extract_low_bits (machine_mode, machine_mode, rtx); extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int); extern rtx expand_mult_highpart_adjust (machine_mode, rtx, rtx, rtx, rtx, int); diff --git a/gcc/expr.c b/gcc/expr.c index 4749cc508b8..5febf07929d 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -2192,7 +2192,8 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize) && (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode))) tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT, subpos * BITS_PER_UNIT, - 1, NULL_RTX, mode, mode, false); + 1, NULL_RTX, mode, mode, false, + NULL); } else { @@ -2202,7 +2203,8 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize) mem = assign_stack_temp (GET_MODE (src), slen); emit_move_insn (mem, src); tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT, - 0, 1, NULL_RTX, mode, mode, false); + 0, 1, NULL_RTX, mode, mode, false, + NULL); } } /* FIXME: A SIMD parallel will eventually lead to a subreg of a @@ -2245,7 +2247,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize) else tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, 1, NULL_RTX, - mode, mode, false); + mode, mode, false, NULL); if (shift) tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i], @@ -2697,7 +2699,7 @@ copy_blkmode_from_reg (rtx target, rtx srcreg, tree type) extract_bit_field (src, bitsize, xbitpos % BITS_PER_WORD, 1, NULL_RTX, copy_mode, copy_mode, - false), + false, NULL), false); } } @@ -2776,7 +2778,7 @@ copy_blkmode_to_reg (machine_mode mode, tree src) extract_bit_field (src_word, bitsize, bitpos % BITS_PER_WORD, 1, NULL_RTX, word_mode, word_mode, - false), + false, NULL), false); } @@ -3225,7 +3227,7 @@ read_complex_part (rtx cplx, bool imag_p) } return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, - true, NULL_RTX, imode, imode, false); + true, NULL_RTX, imode, imode, false, NULL); } /* A subroutine of emit_move_insn_1. Yet another lowpart generator. @@ -6911,7 +6913,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, { machine_mode temp_mode = smallest_mode_for_size (bitsize, MODE_INT); temp = extract_bit_field (temp, bitsize, 0, 1, NULL_RTX, temp_mode, - temp_mode, false); + temp_mode, false, NULL); } /* Store the value in the bitfield. */ @@ -9780,7 +9782,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, case GIMPLE_SINGLE_RHS: { r = expand_expr_real (gimple_assign_rhs1 (g), target, - tmode, modifier, NULL, inner_reference_p); + tmode, modifier, alt_rtl, + inner_reference_p); break; } default: @@ -10210,7 +10213,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, 0, TYPE_UNSIGNED (TREE_TYPE (exp)), (modifier == EXPAND_STACK_PARM ? NULL_RTX : target), - mode, mode, false); + mode, mode, false, alt_rtl); } if (reverse && modifier != EXPAND_MEMORY @@ -10707,7 +10710,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp, (modifier == EXPAND_STACK_PARM ? NULL_RTX : target), - ext_mode, ext_mode, reversep); + ext_mode, ext_mode, reversep, alt_rtl); /* If the result has a record type and the mode of OP0 is an integral mode then, if BITSIZE is narrower than this mode @@ -10928,7 +10931,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, else if (reduce_bit_field) return extract_bit_field (op0, TYPE_PRECISION (type), 0, TYPE_UNSIGNED (type), NULL_RTX, - mode, mode, false); + mode, mode, false, NULL); /* As a last resort, spill op0 to memory, and reload it in a different mode. */ else if (!MEM_P (op0)) diff --git a/gcc/optabs.c b/gcc/optabs.c index 48e37f8bb40..b69e75943cc 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6962,6 +6962,7 @@ maybe_legitimize_operand (enum insn_code icode, unsigned int opno, return true; op->value = gen_reg_rtx (mode); + op->target = 0; break; case EXPAND_INPUT: diff --git a/gcc/optabs.h b/gcc/optabs.h index b2dd31acd06..728b866f08d 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -48,8 +48,11 @@ struct expand_operand { rather than signed. Only meaningful for certain types. */ unsigned int unsigned_p : 1; + /* Is the target operand. */ + unsigned int target : 1; + /* Unused; available for future use. */ - unsigned int unused : 7; + unsigned int unused : 6; /* The mode passed to the convert_*_operand function. It has a type-dependent meaning. */ -- 2.11.4.GIT