From patchwork Mon Oct 23 17:08:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 116765 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp4874724qgn; Mon, 23 Oct 2017 10:09:10 -0700 (PDT) X-Received: by 10.84.169.36 with SMTP id g33mr9559652plb.216.1508778549903; Mon, 23 Oct 2017 10:09:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508778549; cv=none; d=google.com; s=arc-20160816; b=lCCRlYUuGUPeKAjdlxne2f2ri9FJEBZAVIi0ccrNG8dxdrAZIajIxLZ3pd1+P2hgl0 /7TBdqS8nqTwk2/GNd3+WWZ2aBBtx83DHpCLE79QXfbjhMQE36tLw4/zCbPs0qlTqIZM JOeXIPxL17wQ1D61P1EhT/NnmctqhB430c7Mls6IT/ej8Rtvfs4yUB5EFItZyoRX55PI 9LYV0us0/5Fn+oGpAUtWOG+82ZQcWZYzSWLhPyRlIuvm2PAMKC4Ql4P8GKgIT+Su6zLk gPmp3lZDm1XMkIcR/7G/Q0SFbsh/XuA+f8DQuQ0dxdKM/a9azpLm5s2sb5H/cQNvbI0F M7OA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:user-agent:message-id:in-reply-to:date:references :subject:mail-followup-to:to:from:delivered-to:sender:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence :mailing-list:dkim-signature:domainkey-signature :arc-authentication-results; bh=YwCR+crocMvLiFdHMmHgUQ+2oeO39QeJfPE0DkiSw48=; b=k7P6ZqKlXSb47PU1epDxMpZJ7rg6H8jgIG7I0cIIhYz2b21x1xXU17lJUaG8SrB9t3 8pPc+MZNepJhN0XOgrTaIrDpn6TGsY/S6joU+zXPaUU6HQwl7/1rXJfoNR+6cWIxnfdQ wXMRYjhQgLPyFvv4y3eu9+zbZB1vYtQRC+ehv0x37UOhgxVTnBkzXjhmufRuNkxeLg5H 0qmm1TvzdeOYKa9b5csIsMo5ZoMT87fYreqEuyjctHGc/XiNVHavvAqhMrbYEeQuzVN6 b3FXOtY2LF7b75K+h6RZMNWYv1+pQzietgou5J23IxZt7KfYrkuIVNwyjM94ccvtMDkO zf2A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=pYWoc+9M; spf=pass (google.com: domain of gcc-patches-return-464797-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-464797-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id x1si5106588pgp.479.2017.10.23.10.09.09 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 23 Oct 2017 10:09:09 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-464797-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=pYWoc+9M; spf=pass (google.com: domain of gcc-patches-return-464797-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-464797-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; q=dns; s=default; b=g3g4jkt+DSICP55Zp3yHuS7hMNFRt 7JyNf1eAcAa6d61DPNKQC7ttxJqoPuhy7lbRnE+tvCttl0R84ZOvqsGvJPwqqz7o a+Iqb2Uu0qHz+yLXTmeLzZV8tUGH6uEvg5YgTJT78BCJq0NBqwnEwPQEBpuzD7H0 CnZw1vEXA7nvkE= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; s=default; bh=EvUfO875tUpcvPcitQ1sc8YHj7Y=; b=pYW oc+9MUIEA9AmnmegScLbMGN0jvCdgfCOoQ7y56JIY+nVVLQ5NwXKPTQykHHPuGAv HjIAZBMhHggyzu0J1ElBopI+3oJ4XTvUvfvs6jJxrKKfhubKkP4vVSsdgt3o2PvV hEDlSC2A+T/sOlWUtvq+dqGygOqcTBUQO4y0RR5U= Received: (qmail 129726 invoked by alias); 23 Oct 2017 17:08:44 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 129697 invoked by uid 89); 23 Oct 2017 17:08:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=20449 X-HELO: mail-wm0-f66.google.com Received: from mail-wm0-f66.google.com (HELO mail-wm0-f66.google.com) (74.125.82.66) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 23 Oct 2017 17:08:41 +0000 Received: by mail-wm0-f66.google.com with SMTP id b189so10815415wmd.4 for ; Mon, 23 Oct 2017 10:08:41 -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=YwCR+crocMvLiFdHMmHgUQ+2oeO39QeJfPE0DkiSw48=; b=YWO0TPZS/p73YhsGMmZ2VHMd0XCUfzNEzLWogY/kHRQD3/XA3Ov9su/ufDTRiGF2rj LnIWsSjWOnccr/QVTjTDjQio4fXrpkf6aKGwMbt1cMZK0ZCSd5mblNBPL0ql5WMrLAkD Y8vkifRlCWhFnA83gWDb3peylbR2JUl0/zwU5vWgXObr/sm81whFMn21t0Z3Os9PHPxf iP3/m3i6YpkjvMq1/5/dBSTizGM2OuTB72nqS5ftV+u19RPfRGkG9WkIpt0cjNGljfkI xbZbhaj7WVP3C661/whY28J66dgTSHdmnPLwF3G9ReyahBZCFMdohSuw5iOHeq5PAUBN dBuw== X-Gm-Message-State: AMCzsaWTNrcT5fBLq9CG3wY0J+7IsWle97G1EwHEh6dGUkg20myxvFpU jmQKKn7rbU7MEnyUEI3tsKXq/ChyesA= X-Google-Smtp-Source: ABhQp+Rr+cvGj33785bd3keMzAj/oqU57KvNGXtFJYmkK6efFNgyXBkJ01xE1ijuGSQM63tzUHQWvw== X-Received: by 10.28.48.143 with SMTP id w137mr6271503wmw.3.1508778518884; Mon, 23 Oct 2017 10:08:38 -0700 (PDT) Received: from localhost ([2.26.27.199]) by smtp.gmail.com with ESMTPSA id o3sm6023094wmg.3.2017.10.23.10.08.37 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 23 Oct 2017 10:08:38 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@linaro.org Subject: [021/nnn] poly_int: extract_bit_field bitrange References: <871sltvm7r.fsf@linaro.org> Date: Mon, 23 Oct 2017 18:08:37 +0100 In-Reply-To: <871sltvm7r.fsf@linaro.org> (Richard Sandiford's message of "Mon, 23 Oct 2017 17:54:32 +0100") Message-ID: <87d15drduy.fsf@linaro.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 Similar to the previous store_bit_field patch, but for extractions rather than insertions. The patch splits out the extraction-as-subreg handling into a new function (extract_bit_field_as_subreg), both for ease of writing and because a later patch will add another caller. The simplify_gen_subreg overload is temporary; it goes away in a later patch. 2017-10-23 Richard Sandiford Alan Hayward David Sherwood gcc/ * rtl.h (simplify_gen_subreg): Add a temporary overload that accepts poly_uint64 offsets. * expmed.h (extract_bit_field): Take bitsize and bitnum as poly_uint64s rather than unsigned HOST_WIDE_INTs. * expmed.c (lowpart_bit_field_p): Likewise. (extract_bit_field_as_subreg): New function, split out from... (extract_bit_field_1): ...here. Take bitsize and bitnum as poly_uint64s rather than unsigned HOST_WIDE_INTs. For vector extractions, check that BITSIZE matches the size of the extracted value and that BITNUM is an exact multiple of that size. If all else fails, try forcing the value into memory if BITNUM is variable, and adjusting the address so that the offset is constant. Split the part that can only handle constant bitsize and bitnum out into... (extract_integral_bit_field): ...this new function. (extract_bit_field): Take bitsize and bitnum as poly_uint64s rather than unsigned HOST_WIDE_INTs. Index: gcc/rtl.h =================================================================== --- gcc/rtl.h 2017-10-23 17:11:43.774024962 +0100 +++ gcc/rtl.h 2017-10-23 17:11:50.109574423 +0100 @@ -3267,6 +3267,12 @@ extern rtx simplify_subreg (machine_mode unsigned int); extern rtx simplify_gen_subreg (machine_mode, rtx, machine_mode, unsigned int); +inline rtx +simplify_gen_subreg (machine_mode omode, rtx x, machine_mode imode, + poly_uint64 offset) +{ + return simplify_gen_subreg (omode, x, imode, offset.to_constant ()); +} extern rtx lowpart_subreg (machine_mode, rtx, machine_mode); extern rtx simplify_replace_fn_rtx (rtx, const_rtx, rtx (*fn) (rtx, const_rtx, void *), void *); Index: gcc/expmed.h =================================================================== --- gcc/expmed.h 2017-10-23 17:11:43.774024962 +0100 +++ gcc/expmed.h 2017-10-23 17:11:50.109574423 +0100 @@ -722,8 +722,7 @@ extern void store_bit_field (rtx, poly_u unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, machine_mode, rtx, bool); -extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, int, rtx, +extern rtx extract_bit_field (rtx, poly_uint64, poly_uint64, int, rtx, 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); Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-10-23 17:11:43.774024962 +0100 +++ gcc/expmed.c 2017-10-23 17:11:50.109574423 +0100 @@ -68,6 +68,10 @@ static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, rtx, scalar_int_mode, bool); +static rtx extract_integral_bit_field (rtx, opt_scalar_int_mode, + unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, int, rtx, + machine_mode, machine_mode, bool, bool); static rtx extract_fixed_bit_field (machine_mode, rtx, opt_scalar_int_mode, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, rtx, int, bool); @@ -509,17 +513,17 @@ adjust_bit_field_mem_for_reg (enum extra offset is then BITNUM / BITS_PER_UNIT. */ static bool -lowpart_bit_field_p (unsigned HOST_WIDE_INT bitnum, - unsigned HOST_WIDE_INT bitsize, +lowpart_bit_field_p (poly_uint64 bitnum, poly_uint64 bitsize, machine_mode struct_mode) { - unsigned HOST_WIDE_INT regsize = REGMODE_NATURAL_SIZE (struct_mode); + poly_uint64 regsize = REGMODE_NATURAL_SIZE (struct_mode); if (BYTES_BIG_ENDIAN) - return (bitnum % BITS_PER_UNIT == 0 - && (bitnum + bitsize == GET_MODE_BITSIZE (struct_mode) - || (bitnum + bitsize) % (regsize * BITS_PER_UNIT) == 0)); + return (multiple_p (bitnum, BITS_PER_UNIT) + && (must_eq (bitnum + bitsize, GET_MODE_BITSIZE (struct_mode)) + || multiple_p (bitnum + bitsize, + regsize * BITS_PER_UNIT))); else - return bitnum % (regsize * BITS_PER_UNIT) == 0; + return multiple_p (bitnum, regsize * BITS_PER_UNIT); } /* Return true if -fstrict-volatile-bitfields applies to an access of OP0 @@ -1574,16 +1578,33 @@ extract_bit_field_using_extv (const extr return NULL_RTX; } +/* See whether it would be valid to extract the part of OP0 described + by BITNUM and BITSIZE into a value of mode MODE using a subreg + operation. Return the subreg if so, otherwise return null. */ + +static rtx +extract_bit_field_as_subreg (machine_mode mode, rtx op0, + poly_uint64 bitsize, poly_uint64 bitnum) +{ + poly_uint64 bytenum; + if (multiple_p (bitnum, BITS_PER_UNIT, &bytenum) + && must_eq (bitsize, GET_MODE_BITSIZE (mode)) + && lowpart_bit_field_p (bitnum, bitsize, GET_MODE (op0)) + && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op0))) + return simplify_gen_subreg (mode, op0, GET_MODE (op0), bytenum); + return NULL_RTX; +} + /* A subroutine of extract_bit_field, with the same arguments. If FALLBACK_P is true, fall back to extract_fixed_bit_field if we can find no other means of implementing the operation. if FALLBACK_P is false, return NULL instead. */ 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, rtx *alt_rtl) +extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, + int unsignedp, rtx target, machine_mode mode, + machine_mode tmode, bool reverse, bool fallback_p, + rtx *alt_rtl) { rtx op0 = str_rtx; machine_mode mode1; @@ -1600,13 +1621,13 @@ extract_bit_field_1 (rtx str_rtx, unsign /* If we have an out-of-bounds access to a register, just return an uninitialized register of the required mode. 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 gen_reg_rtx (tmode); if (REG_P (op0) && mode == GET_MODE (op0) - && bitnum == 0 - && bitsize == GET_MODE_BITSIZE (GET_MODE (op0))) + && known_zero (bitnum) + && must_eq (bitsize, GET_MODE_BITSIZE (GET_MODE (op0)))) { if (reverse) op0 = flip_storage_order (mode, op0); @@ -1618,6 +1639,7 @@ extract_bit_field_1 (rtx str_rtx, unsign if (VECTOR_MODE_P (GET_MODE (op0)) && !MEM_P (op0) && VECTOR_MODE_P (tmode) + && must_eq (bitsize, GET_MODE_SIZE (tmode)) && GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (tmode)) { machine_mode new_mode = GET_MODE (op0); @@ -1633,18 +1655,17 @@ extract_bit_field_1 (rtx str_rtx, unsign || !targetm.vector_mode_supported_p (new_mode)) new_mode = VOIDmode; } + poly_uint64 pos; if (new_mode != VOIDmode && (convert_optab_handler (vec_extract_optab, new_mode, tmode) != CODE_FOR_nothing) - && ((bitnum + bitsize - 1) / GET_MODE_BITSIZE (tmode) - == bitnum / GET_MODE_BITSIZE (tmode))) + && multiple_p (bitnum, GET_MODE_BITSIZE (tmode), &pos)) { struct expand_operand ops[3]; machine_mode outermode = new_mode; machine_mode innermode = tmode; enum insn_code icode = convert_optab_handler (vec_extract_optab, outermode, innermode); - unsigned HOST_WIDE_INT pos = bitnum / GET_MODE_BITSIZE (innermode); if (new_mode != GET_MODE (op0)) op0 = gen_lowpart (new_mode, op0); @@ -1697,17 +1718,17 @@ extract_bit_field_1 (rtx str_rtx, unsign 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) && (convert_optab_handler (vec_extract_optab, outermode, innermode) != CODE_FOR_nothing) - && ((bitnum + bitsize - 1) / 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 = convert_optab_handler (vec_extract_optab, outermode, innermode); - unsigned HOST_WIDE_INT pos = bitnum / GET_MODE_BITSIZE (innermode); create_output_operand (&ops[0], target, innermode); ops[0].target = 1; @@ -1765,14 +1786,9 @@ extract_bit_field_1 (rtx str_rtx, unsign /* Extraction of a full MODE1 value can be done with a subreg as long as the least significant bit of the value is the least significant bit of either OP0 or a word of OP0. */ - if (!MEM_P (op0) - && !reverse - && lowpart_bit_field_p (bitnum, bitsize, op0_mode.require ()) - && bitsize == GET_MODE_BITSIZE (mode1) - && TRULY_NOOP_TRUNCATION_MODES_P (mode1, op0_mode.require ())) + if (!MEM_P (op0) && !reverse) { - rtx sub = simplify_gen_subreg (mode1, op0, op0_mode.require (), - bitnum / BITS_PER_UNIT); + rtx sub = extract_bit_field_as_subreg (mode1, op0, bitsize, bitnum); if (sub) return convert_extracted_bit_field (sub, mode, tmode, unsignedp); } @@ -1788,6 +1804,39 @@ extract_bit_field_1 (rtx str_rtx, unsign return convert_extracted_bit_field (op0, mode, tmode, unsignedp); } + /* If we have a memory source and a non-constant bit offset, restrict + the memory to the referenced bytes. This is a worst-case fallback + but is useful for things like vector booleans. */ + if (MEM_P (op0) && !bitnum.is_constant ()) + { + bytenum = bits_to_bytes_round_down (bitnum); + bitnum = num_trailing_bits (bitnum); + poly_uint64 bytesize = bits_to_bytes_round_up (bitnum + bitsize); + op0 = adjust_bitfield_address_size (op0, BLKmode, bytenum, bytesize); + op0_mode = opt_scalar_int_mode (); + } + + /* 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. */ + return extract_integral_bit_field (op0, op0_mode, bitsize.to_constant (), + bitnum.to_constant (), unsignedp, + target, mode, tmode, reverse, fallback_p); +} + +/* Subroutine of extract_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 rtx +extract_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, + 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) +{ /* Handle fields bigger than a word. */ if (bitsize > BITS_PER_WORD) @@ -1807,12 +1856,16 @@ extract_bit_field_1 (rtx str_rtx, unsign /* In case we're about to clobber a base register or something (see gcc.c-torture/execute/20040625-1.c). */ - if (reg_mentioned_p (target, str_rtx)) + if (reg_mentioned_p (target, op0)) target = gen_reg_rtx (mode); /* Indicate for flow that the entire target reg is being set. */ emit_clobber (target); + /* The mode must be fixed-size, since extract_bit_field_1 handles + extractions from variable-sized objects before calling this + function. */ + unsigned int target_size = GET_MODE_SIZE (GET_MODE (target)); last = get_last_insn (); for (i = 0; i < nwords; i++) { @@ -1820,9 +1873,7 @@ extract_bit_field_1 (rtx str_rtx, unsign if I is 1, use the next to lowest word; and so on. */ /* Word number in TARGET to use. */ unsigned int wordnum - = (backwards - ? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1 - : i); + = (backwards ? target_size / UNITS_PER_WORD - i - 1 : i); /* Offset from start of field in OP0. */ unsigned int bit_offset = (backwards ^ reverse ? MAX ((int) bitsize - ((int) i + 1) @@ -1851,11 +1902,11 @@ extract_bit_field_1 (rtx str_rtx, unsign { /* Unless we've filled TARGET, the upper regs in a multi-reg value need to be zero'd out. */ - if (GET_MODE_SIZE (GET_MODE (target)) > nwords * UNITS_PER_WORD) + if (target_size > nwords * UNITS_PER_WORD) { unsigned int i, total_words; - total_words = GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD; + total_words = target_size / UNITS_PER_WORD; for (i = nwords; i < total_words; i++) emit_move_insn (operand_subword (target, @@ -1993,10 +2044,9 @@ extract_bit_field_1 (rtx str_rtx, unsign if they are equally easy. */ 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, - rtx *alt_rtl) +extract_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, + int unsignedp, rtx target, machine_mode mode, + machine_mode tmode, bool reverse, rtx *alt_rtl) { machine_mode mode1; @@ -2008,28 +2058,34 @@ extract_bit_field (rtx str_rtx, unsigned else mode1 = tmode; + unsigned HOST_WIDE_INT ibitsize, ibitnum; scalar_int_mode int_mode; - if (is_a (mode1, &int_mode) - && strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, int_mode, 0, 0)) + if (bitsize.is_constant (&ibitsize) + && bitnum.is_constant (&ibitnum) + && is_a (mode1, &int_mode) + && strict_volatile_bitfield_p (str_rtx, ibitsize, ibitnum, + int_mode, 0, 0)) { /* Extraction of a full INT_MODE value can be done with a simple load. 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)) { rtx result = adjust_bitfield_address (str_rtx, int_mode, - bitnum / BITS_PER_UNIT); + ibitnum / BITS_PER_UNIT); if (reverse) result = flip_storage_order (int_mode, result); - gcc_assert (bitnum % BITS_PER_UNIT == 0); + gcc_assert (ibitnum % BITS_PER_UNIT == 0); return convert_extracted_bit_field (result, mode, tmode, unsignedp); } - 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)); str_rtx = copy_to_reg (str_rtx); + return extract_bit_field_1 (str_rtx, ibitsize, ibitnum, unsignedp, + target, mode, tmode, reverse, true, alt_rtl); } return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp,