From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 127949 invoked by alias); 23 Oct 2017 17:08:23 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 127923 invoked by uid 89); 23 Oct 2017 17:08:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.0 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_2,GIT_PATCH_3,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-wm0-f45.google.com Received: from mail-wm0-f45.google.com (HELO mail-wm0-f45.google.com) (74.125.82.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 23 Oct 2017 17:08:19 +0000 Received: by mail-wm0-f45.google.com with SMTP id u138so11212686wmu.4 for ; Mon, 23 Oct 2017 10:08:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:mail-followup-to:subject:references:date :in-reply-to:message-id:user-agent:mime-version; bh=sBGyIjM8w8MMrwRh8DErraYUtmK6y1CZcEKYk5qadTE=; b=Ei+Bp4VoyIMus5VZjRE2UMXNK9Gos5WNGqnxOJf+eteUGWcOU5PLF6r08mJkI4J9fB Jz8Xe3a4wVTsgJGJDSBursbAz1Xvb7xzoHDoa1QZ5r9AbXNBVjM6wVyvvoYYcGR5TMs/ hLfdnFLKqUBaxxR80LSQabqTxi/QAPBCtxvtFQvT6Ob18WQJSn189t0t16DeAlrmom9a JD1nrqfryLyinXWSLFJwSi1SQuazQ8dogR2CLwHe8fmQFDaXxxg7hQA4MhUOt1N16ZXE ciExgIHAUEq9HFP5Vo/kt7hpNyUFlIw6J9Ida36Fsq6IgeFmiKvv1Om2MpiAmpOjlgzt YCRg== X-Gm-Message-State: AMCzsaX5Uy5WfiDFQIGf0iaFoCKXzFE+zxyq0CzbtIT+rAzw/xZDKJQk sNzU5n0FD5mn2iFaDhGcFGUv9LToV+0= X-Google-Smtp-Source: ABhQp+SPl4ob1+keiMznYZvepoMFbR/2EjcrFWzI/CVWMwg9d2YjYQwMD6CvuSmN3wF0WimQ3K36tQ== X-Received: by 10.28.63.145 with SMTP id m139mr6688077wma.5.1508778497144; Mon, 23 Oct 2017 10:08:17 -0700 (PDT) Received: from localhost ([2.26.27.199]) by smtp.gmail.com with ESMTPSA id o3sm6022386wmg.3.2017.10.23.10.08.15 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 23 Oct 2017 10:08:16 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@linaro.org Subject: [020/nnn] poly_int: store_bit_field bitrange References: <871sltvm7r.fsf@linaro.org> Date: Mon, 23 Oct 2017 17:08:00 -0000 In-Reply-To: <871sltvm7r.fsf@linaro.org> (Richard Sandiford's message of "Mon, 23 Oct 2017 17:54:32 +0100") Message-ID: <87h8uprdvk.fsf@linaro.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2017-10/txt/msg01521.txt.bz2 This patch changes the bitnum and bitsize arguments to store_bit_field from unsigned HOST_WIDE_INTs to poly_uint64s. The later part of store_bit_field_1 still needs to operate on constant bit positions and sizes, so the patch splits it out into a subfunction (store_integral_bit_field). 2017-10-23 Richard Sandiford Alan Hayward David Sherwood gcc/ * expmed.h (store_bit_field): Take bitsize and bitnum as poly_uint64s rather than unsigned HOST_WIDE_INTs. * expmed.c (simple_mem_bitfield_p): Likewise. Add a parameter that returns the byte size. (store_bit_field_1): Take bitsize and bitnum as poly_uint64s rather than unsigned HOST_WIDE_INTs. Update call to simple_mem_bitfield_p. Split the part that can only handle constant bitsize and bitnum out into... (store_integral_bit_field): ...this new function. (store_bit_field): Take bitsize and bitnum as poly_uint64s rather than unsigned HOST_WIDE_INTs. (extract_bit_field_1): Update call to simple_mem_bitfield_p. Index: gcc/expmed.h =================================================================== --- gcc/expmed.h 2017-10-23 17:00:54.441003964 +0100 +++ gcc/expmed.h 2017-10-23 17:02:01.542011677 +0100 @@ -718,8 +718,7 @@ extern rtx expand_divmod (int, enum tree rtx, int); #endif -extern void store_bit_field (rtx, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, +extern void store_bit_field (rtx, poly_uint64, poly_uint64, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, machine_mode, rtx, bool); Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-10-23 17:00:57.771973825 +0100 +++ gcc/expmed.c 2017-10-23 17:02:01.542011677 +0100 @@ -46,6 +46,12 @@ struct target_expmed default_target_expm struct target_expmed *this_target_expmed = &default_target_expmed; #endif +static bool store_integral_bit_field (rtx, opt_scalar_int_mode, + unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, + machine_mode, rtx, bool, bool); static void store_fixed_bit_field (rtx, opt_scalar_int_mode, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, @@ -562,17 +568,18 @@ strict_volatile_bitfield_p (rtx op0, uns } /* Return true if OP is a memory and if a bitfield of size BITSIZE at - bit number BITNUM can be treated as a simple value of mode MODE. */ + bit number BITNUM can be treated as a simple value of mode MODE. + Store the byte offset in *BYTENUM if so. */ static bool -simple_mem_bitfield_p (rtx op0, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitnum, machine_mode mode) +simple_mem_bitfield_p (rtx op0, poly_uint64 bitsize, poly_uint64 bitnum, + machine_mode mode, poly_uint64 *bytenum) { return (MEM_P (op0) - && bitnum % BITS_PER_UNIT == 0 - && bitsize == GET_MODE_BITSIZE (mode) + && multiple_p (bitnum, BITS_PER_UNIT, bytenum) + && must_eq (bitsize, GET_MODE_BITSIZE (mode)) && (!targetm.slow_unaligned_access (mode, MEM_ALIGN (op0)) - || (bitnum % GET_MODE_ALIGNMENT (mode) == 0 + || (multiple_p (bitnum, GET_MODE_ALIGNMENT (mode)) && MEM_ALIGN (op0) >= GET_MODE_ALIGNMENT (mode)))); } @@ -717,15 +724,13 @@ store_bit_field_using_insv (const extrac return false instead. */ static bool -store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitnum, +store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, unsigned HOST_WIDE_INT bitregion_start, unsigned HOST_WIDE_INT bitregion_end, machine_mode fieldmode, rtx value, bool reverse, bool fallback_p) { rtx op0 = str_rtx; - rtx orig_value; while (GET_CODE (op0) == SUBREG) { @@ -736,23 +741,23 @@ store_bit_field_1 (rtx str_rtx, unsigned /* No action is needed if the target is a register and if the field lies completely outside that register. This can occur if the source code contains an out-of-bounds access to a small array. */ - if (REG_P (op0) && bitnum >= GET_MODE_BITSIZE (GET_MODE (op0))) + if (REG_P (op0) && must_ge (bitnum, GET_MODE_BITSIZE (GET_MODE (op0)))) return true; /* Use vec_set patterns for inserting parts of vectors whenever available. */ machine_mode outermode = GET_MODE (op0); scalar_mode innermode = GET_MODE_INNER (outermode); + poly_uint64 pos; if (VECTOR_MODE_P (outermode) && !MEM_P (op0) && optab_handler (vec_set_optab, outermode) != CODE_FOR_nothing && fieldmode == innermode - && bitsize == GET_MODE_BITSIZE (innermode) - && !(bitnum % GET_MODE_BITSIZE (innermode))) + && must_eq (bitsize, GET_MODE_BITSIZE (innermode)) + && multiple_p (bitnum, GET_MODE_BITSIZE (innermode), &pos)) { struct expand_operand ops[3]; enum insn_code icode = optab_handler (vec_set_optab, outermode); - int pos = bitnum / GET_MODE_BITSIZE (innermode); create_fixed_operand (&ops[0], op0); create_input_operand (&ops[1], value, innermode); @@ -764,16 +769,16 @@ store_bit_field_1 (rtx str_rtx, unsigned /* If the target is a register, overwriting the entire object, or storing a full-word or multi-word field can be done with just a SUBREG. */ if (!MEM_P (op0) - && bitsize == GET_MODE_BITSIZE (fieldmode) - && ((bitsize == GET_MODE_BITSIZE (GET_MODE (op0)) && bitnum == 0) - || (bitsize % BITS_PER_WORD == 0 && bitnum % BITS_PER_WORD == 0))) + && must_eq (bitsize, GET_MODE_BITSIZE (fieldmode))) { /* Use the subreg machinery either to narrow OP0 to the required words or to cope with mode punning between equal-sized modes. In the latter case, use subreg on the rhs side, not lhs. */ rtx sub; - - if (bitsize == GET_MODE_BITSIZE (GET_MODE (op0))) + HOST_WIDE_INT regnum; + HOST_WIDE_INT regsize = REGMODE_NATURAL_SIZE (GET_MODE (op0)); + if (known_zero (bitnum) + && must_eq (bitsize, GET_MODE_BITSIZE (GET_MODE (op0)))) { sub = simplify_gen_subreg (GET_MODE (op0), value, fieldmode, 0); if (sub) @@ -784,10 +789,11 @@ store_bit_field_1 (rtx str_rtx, unsigned return true; } } - else + else if (constant_multiple_p (bitnum, regsize * BITS_PER_UNIT, ®num) + && multiple_p (bitsize, regsize * BITS_PER_UNIT)) { sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), - bitnum / BITS_PER_UNIT); + regnum * regsize); if (sub) { if (reverse) @@ -801,15 +807,23 @@ store_bit_field_1 (rtx str_rtx, unsigned /* If the target is memory, storing any naturally aligned field can be done with a simple store. For targets that support fast unaligned memory, any naturally sized, unit aligned field can be done directly. */ - if (simple_mem_bitfield_p (op0, bitsize, bitnum, fieldmode)) + poly_uint64 bytenum; + if (simple_mem_bitfield_p (op0, bitsize, bitnum, fieldmode, &bytenum)) { - op0 = adjust_bitfield_address (op0, fieldmode, bitnum / BITS_PER_UNIT); + op0 = adjust_bitfield_address (op0, fieldmode, bytenum); if (reverse) value = flip_storage_order (fieldmode, value); emit_move_insn (op0, value); return true; } + /* It's possible we'll need to handle other cases here for + polynomial bitnum and bitsize. */ + + /* From here on we need to be looking at a fixed-size insertion. */ + unsigned HOST_WIDE_INT ibitsize = bitsize.to_constant (); + unsigned HOST_WIDE_INT ibitnum = bitnum.to_constant (); + /* Make sure we are playing with integral modes. Pun with subregs if we aren't. This must come after the entire register case above, since that case is valid for any mode. The following cases are only @@ -825,12 +839,31 @@ store_bit_field_1 (rtx str_rtx, unsigned op0 = gen_lowpart (op0_mode.require (), op0); } + return store_integral_bit_field (op0, op0_mode, ibitsize, ibitnum, + bitregion_start, bitregion_end, + fieldmode, value, reverse, fallback_p); +} + +/* Subroutine of store_bit_field_1, with the same arguments, except + that BITSIZE and BITNUM are constant. Handle cases specific to + integral modes. If OP0_MODE is defined, it is the mode of OP0, + otherwise OP0 is a BLKmode MEM. */ + +static bool +store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, + unsigned HOST_WIDE_INT bitsize, + unsigned HOST_WIDE_INT bitnum, + unsigned HOST_WIDE_INT bitregion_start, + unsigned HOST_WIDE_INT bitregion_end, + machine_mode fieldmode, + rtx value, bool reverse, bool fallback_p) +{ /* Storing an lsb-aligned field in a register can be done with a movstrict instruction. */ if (!MEM_P (op0) && !reverse - && lowpart_bit_field_p (bitnum, bitsize, GET_MODE (op0)) + && lowpart_bit_field_p (bitnum, bitsize, op0_mode.require ()) && bitsize == GET_MODE_BITSIZE (fieldmode) && optab_handler (movstrict_optab, fieldmode) != CODE_FOR_nothing) { @@ -882,10 +915,13 @@ store_bit_field_1 (rtx str_rtx, unsigned subwords to extract. Note that fieldmode will often (always?) be VOIDmode, because that is what store_field uses to indicate that this is a bit field, but passing VOIDmode to operand_subword_force - is not allowed. */ - fieldmode = GET_MODE (value); - if (fieldmode == VOIDmode) - fieldmode = smallest_int_mode_for_size (nwords * BITS_PER_WORD); + is not allowed. + + The mode must be fixed-size, since insertions into variable-sized + objects are meant to be handled before calling this function. */ + fixed_size_mode value_mode = as_a (GET_MODE (value)); + if (value_mode == VOIDmode) + value_mode = smallest_int_mode_for_size (nwords * BITS_PER_WORD); last = get_last_insn (); for (i = 0; i < nwords; i++) @@ -893,7 +929,7 @@ store_bit_field_1 (rtx str_rtx, unsigned /* If I is 0, use the low-order word in both field and target; if I is 1, use the next to lowest word; and so on. */ unsigned int wordnum = (backwards - ? GET_MODE_SIZE (fieldmode) / UNITS_PER_WORD + ? GET_MODE_SIZE (value_mode) / UNITS_PER_WORD - i - 1 : i); unsigned int bit_offset = (backwards ^ reverse @@ -901,7 +937,7 @@ store_bit_field_1 (rtx str_rtx, unsigned * BITS_PER_WORD, 0) : (int) i * BITS_PER_WORD); - rtx value_word = operand_subword_force (value, wordnum, fieldmode); + rtx value_word = operand_subword_force (value, wordnum, value_mode); unsigned HOST_WIDE_INT new_bitsize = MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD); @@ -935,7 +971,7 @@ store_bit_field_1 (rtx str_rtx, unsigned integer of the corresponding size. This can occur on a machine with 64 bit registers that uses SFmode for float. It can also occur for unaligned float or complex fields. */ - orig_value = value; + rtx orig_value = value; scalar_int_mode value_mode; if (GET_MODE (value) == VOIDmode) /* By this point we've dealt with values that are bigger than a word, @@ -1043,41 +1079,43 @@ store_bit_field_1 (rtx str_rtx, unsigned If REVERSE is true, the store is to be done in reverse order. */ void -store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitnum, +store_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, unsigned HOST_WIDE_INT bitregion_start, unsigned HOST_WIDE_INT bitregion_end, machine_mode fieldmode, rtx value, bool reverse) { /* Handle -fstrict-volatile-bitfields in the cases where it applies. */ + unsigned HOST_WIDE_INT ibitsize = 0, ibitnum = 0; scalar_int_mode int_mode; - if (is_a (fieldmode, &int_mode) - && strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, int_mode, + if (bitsize.is_constant (&ibitsize) + && bitnum.is_constant (&ibitnum) + && is_a (fieldmode, &int_mode) + && strict_volatile_bitfield_p (str_rtx, ibitsize, ibitnum, int_mode, bitregion_start, bitregion_end)) { /* Storing of a full word can be done with a simple store. We know here that the field can be accessed with one single instruction. For targets that support unaligned memory, an unaligned access may be necessary. */ - if (bitsize == GET_MODE_BITSIZE (int_mode)) + if (ibitsize == GET_MODE_BITSIZE (int_mode)) { str_rtx = adjust_bitfield_address (str_rtx, int_mode, - bitnum / BITS_PER_UNIT); + ibitnum / BITS_PER_UNIT); if (reverse) value = flip_storage_order (int_mode, value); - gcc_assert (bitnum % BITS_PER_UNIT == 0); + gcc_assert (ibitnum % BITS_PER_UNIT == 0); emit_move_insn (str_rtx, value); } else { rtx temp; - str_rtx = narrow_bit_field_mem (str_rtx, int_mode, bitsize, bitnum, - &bitnum); - gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (int_mode)); + str_rtx = narrow_bit_field_mem (str_rtx, int_mode, ibitsize, + ibitnum, &ibitnum); + gcc_assert (ibitnum + ibitsize <= GET_MODE_BITSIZE (int_mode)); temp = copy_to_reg (str_rtx); - if (!store_bit_field_1 (temp, bitsize, bitnum, 0, 0, + if (!store_bit_field_1 (temp, ibitsize, ibitnum, 0, 0, int_mode, value, reverse, true)) gcc_unreachable (); @@ -1094,19 +1132,21 @@ store_bit_field (rtx str_rtx, unsigned H { scalar_int_mode best_mode; machine_mode addr_mode = VOIDmode; - HOST_WIDE_INT offset, size; + HOST_WIDE_INT offset; gcc_assert ((bitregion_start % BITS_PER_UNIT) == 0); offset = bitregion_start / BITS_PER_UNIT; bitnum -= bitregion_start; - size = (bitnum + bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT; + poly_int64 size = bits_to_bytes_round_up (bitnum + bitsize); bitregion_end -= bitregion_start; bitregion_start = 0; - if (get_best_mode (bitsize, bitnum, - bitregion_start, bitregion_end, - MEM_ALIGN (str_rtx), INT_MAX, - MEM_VOLATILE_P (str_rtx), &best_mode)) + if (bitsize.is_constant (&ibitsize) + && bitnum.is_constant (&ibitnum) + && get_best_mode (ibitsize, ibitnum, + bitregion_start, bitregion_end, + MEM_ALIGN (str_rtx), INT_MAX, + MEM_VOLATILE_P (str_rtx), &best_mode)) addr_mode = best_mode; str_rtx = adjust_bitfield_address_size (str_rtx, addr_mode, offset, size); @@ -1738,9 +1778,10 @@ extract_bit_field_1 (rtx str_rtx, unsign /* Extraction of a full MODE1 value can be done with a load as long as the field is on a byte boundary and is sufficiently aligned. */ - if (simple_mem_bitfield_p (op0, bitsize, bitnum, mode1)) + poly_uint64 bytenum; + if (simple_mem_bitfield_p (op0, bitsize, bitnum, mode1, &bytenum)) { - op0 = adjust_bitfield_address (op0, mode1, bitnum / BITS_PER_UNIT); + op0 = adjust_bitfield_address (op0, mode1, bytenum); if (reverse) op0 = flip_storage_order (mode1, op0); return convert_extracted_bit_field (op0, mode, tmode, unsignedp);