From patchwork Thu May 2 17:52:46 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kenneth Zadeck X-Patchwork-Id: 241046 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id BC1122C00A0 for ; Fri, 3 May 2013 03:53:12 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=A41PrW5RkiP3AT4K0 bvPC2R8g6Z9uSgglnsZHLm20/BJS5RmSgD4225OF2pfxn4mAQZmu24kJR3zFtM5R Mrw/Vu0h6cB6tQsk9Cg1absguWB/fqtz4ZoPwOYCNGQmT3zNm8zhBQm+gI01/vIH CdrkU+zSvmubB90LoTVGkpSsyU= 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 :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=oO7QUOuOXgTRgqB0ZL1tnZW NThk=; b=J53uhwHd3Id3F/IzzfYrBAVgfYry2bqOZna6D2scx/mawSrqO5iHPSM CHT1pR/xYKEuyIhDvHvOI4mqczXnNNjGNrK7BJv1m8nMUCGuNZInKjFoKL1C91yC 4SqzB31iU+flej24qsSzWbc5kPhz9nYxDGdLOZuZpbzPkE4EYCeE= Received: (qmail 11464 invoked by alias); 2 May 2013 17:53:03 -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 11391 invoked by uid 89); 2 May 2013 17:52:56 -0000 X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=BAYES_50, KHOP_RCVD_UNTRUST, KHOP_THREADED, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, TW_CP, TW_FN autolearn=ham version=3.3.1 Received: from mail-oa0-f44.google.com (HELO mail-oa0-f44.google.com) (209.85.219.44) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Thu, 02 May 2013 17:52:50 +0000 Received: by mail-oa0-f44.google.com with SMTP id h1so824638oag.17 for ; Thu, 02 May 2013 10:52:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:message-id:date:from:user-agent:mime-version:to:cc :subject:references:in-reply-to:content-type:x-gm-message-state; bh=AgSD9Xy8KF22baGIdmEGiFxJuw38nqFPmhbX/yndC7c=; b=jgZYZZGaUFrXHDtad0Mk4wBOIEUSwmDHWb8HDa5O+eaatufpbsXCUGVwEYBtCgDRwS riMbJgCBB3g6xPtDet985oksde9wRSCYFsCfXePDzNyjZ+3ZTOjhBhF7nk6FriCePOHM CEmBZeSPPAjnsrmqMElqZ53Rh9pnBOWaC4tt2Ww7dk4KtPjGjvqKQrp9kVKSrs9EB3pm hHezA2rilLwBEszlcKcYVi9j7zcpwgQOg8qp1vkLOJ/c5L/PQv0lNXjrnNvh9lp48Fc0 Sde6tP50Xa8a1o7viVk2whuElZOWbHPlN8oulvXfrjqToF+gq4FcxeUf+MPMg2wg46lk BiFg== X-Received: by 10.60.125.161 with SMTP id mr1mr2006181oeb.24.1367517168526; Thu, 02 May 2013 10:52:48 -0700 (PDT) Received: from ?IPv6:2001:468:913:2044:880d:59b1:64e0:61ad? ([2001:468:913:2044:880d:59b1:64e0:61ad]) by mx.google.com with ESMTPSA id b2sm1471296oby.5.2013.05.02.10.52.47 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 02 May 2013 10:52:47 -0700 (PDT) Message-ID: <5182A7EE.90800@naturalbridge.com> Date: Thu, 02 May 2013 13:52:46 -0400 From: Kenneth Zadeck User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130329 Thunderbird/17.0.5 MIME-Version: 1.0 To: Richard Biener CC: Mike Stump , gcc-patches , Lawrence Crowl , rdsandiford@googlemail.com, Ian Lance Taylor Subject: Re: patch to fix constant math - builtins.c - the first of the tree level patches for wide-int References: <506C72C7.7090207@naturalbridge.com> <50891AAC.8090301@naturalbridge.com> <87y5im3orb.fsf@sandifor-thinkpad.stglab.manchester.uk.ibm.com> <87pq3y3kyk.fsf@sandifor-thinkpad.stglab.manchester.uk.ibm.com> <50912D85.1070002@naturalbridge.com> <5091331C.3030504@naturalbridge.com> <512D686B.90000@naturalbridge.com> <515EC4E7.7040907@naturalbridge.com> <516DAF9B.3050008@naturalbridge.com> <516DB380.6000505@naturalbridge.com> In-Reply-To: <516DB380.6000505@naturalbridge.com> X-Gm-Message-State: ALoCoQk2r6xzvyPRZtoonLRkHhSESWXolOkNAre9UxKHJRYtaHBPdyeU0zZJ3K870TmTWRmPVarB X-Virus-Found: No The only changes here were account for the changes to the wide-int api. On 04/16/2013 04:24 PM, Kenneth Zadeck wrote: > Richard, this is the first of the tree level patches so that you can > see how the wide-int changes will effect the tree level. This patch > converts builtins.c so that it does not in any way assume that > tree-cst holds two HWIs. The patch divides all math into two > categories: Things that are always so small that we can easily > assume that the math can be done using a single HWI and everything > else. The things that it assumes can easily be done with a HWI are > guarded with assertions. The everything else is done with wide-int. > Everything else in this patch is additional abi to support this. > > The idea is that each pass will be converted, 1 pass per patch in this > way. Once everything does not depend on the internals of tree-cst > as they do now, then tree-cst will be converted to have an array > inside of it rather than just two hwis. > > Kenny 2012-05-02 Kenneth Zadeck * builtins.c (get_object_alignment_2, get_pointer_alignment_1, c_strlen, c_getstr, target_char_cast, expand_builtin_mempcpy_args, expand_builtin_strncpy, expand_builtin_memset_args, expand_builtin_strncpy, expand_builtin_memset_args, expand_builtin_frame_address, expand_builtin_alloca, expand_builtin_atomic_compare_exchange, fold_builtin_powi, fold_builtin_memset, fold_builtin_memory_op, fold_builtin_memchr, fold_builtin_memcmp, fold_builtin_strncmp, fold_builtin_load_exponent, fold_builtin_snprintf, expand_builtin_object_size, expand_builtin_memory_chk, maybe_emit_chk_warning, maybe_emit_sprintf_chk_warning, fold_builtin_object_size, fold_builtin_memory_chk, fold_builtin_stxcpy_chk, fold_builtin_strcat_chk, fold_builtin_sprintf_chk_1, fold_builtin_snprintf_chk_1, do_mpfr_bessel_n): Convert to api that does not assume that tree_cst is two HWIs. (fold_builtin_int_roundingfn, fold_builtin_bitop, fold_builtin_bswap, fold_builtin_memory_op, expand_builtin_object_size): Use wide-int rather than double-int api. * dfp.c (decimal_real_to_integer): Add wide-int version. * real.c (real_to_integer): Ditto. * tree.h (tree_fits_uhwi_p, tree_fits_shwi_p, tree_fits_hwi_p, tree_to_shwi, tree_to_hwi, tree_to_uhwi): New functions. diff --git a/gcc/builtins.c b/gcc/builtins.c index 0c587d1..181784b 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -339,8 +339,8 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, if (TREE_CODE (addr) == BIT_AND_EXPR && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST) { - align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)) - & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))); + align = (tree_to_hwi (TREE_OPERAND (addr, 1)) + & -tree_to_hwi (TREE_OPERAND (addr, 1))); align *= BITS_PER_UNIT; addr = TREE_OPERAND (addr, 0); } @@ -357,7 +357,7 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, { unsigned HOST_WIDE_INT step = 1; if (TMR_STEP (exp)) - step = TREE_INT_CST_LOW (TMR_STEP (exp)); + step = tree_to_hwi (TMR_STEP (exp)); align = MIN (align, (step & -step) * BITS_PER_UNIT); } if (TMR_INDEX2 (exp)) @@ -379,7 +379,8 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, bitpos += ptr_bitpos; if (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF) - bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT; + bitpos += wide_int::from_tree (TREE_OPERAND (exp, 1)) + .to_shwi () * BITS_PER_UNIT; } } else if (TREE_CODE (exp) == STRING_CST) @@ -408,23 +409,23 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, } else next_offset = NULL; - if (host_integerp (offset, 1)) + if (tree_fits_uhwi_p (offset)) { /* Any overflow in calculating offset_bits won't change the alignment. */ unsigned offset_bits - = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT); + = ((unsigned) tree_to_hwi (offset) * BITS_PER_UNIT); if (offset_bits) inner = MIN (inner, (offset_bits & -offset_bits)); } else if (TREE_CODE (offset) == MULT_EXPR - && host_integerp (TREE_OPERAND (offset, 1), 1)) + && tree_fits_uhwi_p (TREE_OPERAND (offset, 1))) { /* Any overflow in calculating offset_factor won't change the alignment. */ unsigned offset_factor - = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1) + = ((unsigned) tree_to_hwi (TREE_OPERAND (offset, 1)) * BITS_PER_UNIT); if (offset_factor) @@ -515,7 +516,7 @@ get_pointer_alignment_1 (tree exp, unsigned int *alignp, else if (TREE_CODE (exp) == INTEGER_CST) { *alignp = BIGGEST_ALIGNMENT; - *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT) + *bitposp = ((tree_to_hwi (exp) * BITS_PER_UNIT) & (BIGGEST_ALIGNMENT - 1)); return true; } @@ -624,10 +625,10 @@ c_strlen (tree src, int only_value) a null character if we can represent it as a single HOST_WIDE_INT. */ if (offset_node == 0) offset = 0; - else if (! host_integerp (offset_node, 0)) + else if (!tree_fits_shwi_p (offset_node)) offset = -1; else - offset = tree_low_cst (offset_node, 0); + offset = tree_to_hwi (offset_node); /* If the offset is known to be out of bounds, warn, and call strlen at runtime. */ @@ -665,11 +666,11 @@ c_getstr (tree src) if (offset_node == 0) return TREE_STRING_POINTER (src); - else if (!host_integerp (offset_node, 1) + else if (!tree_fits_uhwi_p (offset_node) || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0) return 0; - return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1); + return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node); } /* Return a constant integer corresponding to target reading @@ -723,7 +724,9 @@ target_char_cast (tree cst, char *p) || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT) return 1; - val = TREE_INT_CST_LOW (cst); + /* Do not care if it fits or not right here. */ + val = tree_to_hwi (cst); + if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT) val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1; @@ -3168,7 +3171,7 @@ expand_builtin_mempcpy_args (tree dest, tree src, tree len, return NULL_RTX; /* If LEN is not constant, call the normal function. */ - if (! host_integerp (len, 1)) + if (! tree_fits_uhwi_p (len)) return NULL_RTX; len_rtx = expand_normal (len); @@ -3403,7 +3406,7 @@ expand_builtin_strncpy (tree exp, rtx target) tree slen = c_strlen (src, 1); /* We must be passed a constant len and src parameter. */ - if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1)) + if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen)) return NULL_RTX; slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1)); @@ -3417,15 +3420,15 @@ expand_builtin_strncpy (tree exp, rtx target) const char *p = c_getstr (src); rtx dest_mem; - if (!p || dest_align == 0 || !host_integerp (len, 1) - || !can_store_by_pieces (tree_low_cst (len, 1), + if (!p || dest_align == 0 || !tree_fits_uhwi_p (len) + || !can_store_by_pieces (tree_to_uhwi (len), builtin_strncpy_read_str, CONST_CAST (char *, p), dest_align, false)) return NULL_RTX; dest_mem = get_memory_rtx (dest, len); - store_by_pieces (dest_mem, tree_low_cst (len, 1), + store_by_pieces (dest_mem, tree_to_uhwi (len), builtin_strncpy_read_str, CONST_CAST (char *, p), dest_align, false, 0); dest_mem = force_operand (XEXP (dest_mem, 0), target); @@ -3558,13 +3561,13 @@ expand_builtin_memset_args (tree dest, tree val, tree len, * the coefficients by pieces (in the required modes). * We can't pass builtin_memset_gen_str as that emits RTL. */ c = 1; - if (host_integerp (len, 1) - && can_store_by_pieces (tree_low_cst (len, 1), + if (tree_fits_uhwi_p (len) + && can_store_by_pieces (tree_to_hwi (len), builtin_memset_read_str, &c, dest_align, true)) { val_rtx = force_reg (val_mode, val_rtx); - store_by_pieces (dest_mem, tree_low_cst (len, 1), + store_by_pieces (dest_mem, tree_to_hwi (len), builtin_memset_gen_str, val_rtx, dest_align, true, 0); } @@ -3583,11 +3586,11 @@ expand_builtin_memset_args (tree dest, tree val, tree len, if (c) { - if (host_integerp (len, 1) - && can_store_by_pieces (tree_low_cst (len, 1), + if (tree_fits_uhwi_p (len) + && can_store_by_pieces (tree_to_hwi (len), builtin_memset_read_str, &c, dest_align, true)) - store_by_pieces (dest_mem, tree_low_cst (len, 1), + store_by_pieces (dest_mem, tree_to_hwi (len), builtin_memset_read_str, &c, dest_align, true, 0); else if (!set_storage_via_setmem (dest_mem, len_rtx, gen_int_mode (c, val_mode), @@ -4492,7 +4495,7 @@ expand_builtin_frame_address (tree fndecl, tree exp) if (call_expr_nargs (exp) == 0) /* Warning about missing arg was already issued. */ return const0_rtx; - else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1)) + else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0))) { if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) error ("invalid argument to %<__builtin_frame_address%>"); @@ -4504,7 +4507,7 @@ expand_builtin_frame_address (tree fndecl, tree exp) { rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), - tree_low_cst (CALL_EXPR_ARG (exp, 0), 1)); + tree_to_uhwi (CALL_EXPR_ARG (exp, 0))); /* Some ports cannot access arbitrary stack frames. */ if (tem == NULL) @@ -4558,7 +4561,7 @@ expand_builtin_alloca (tree exp, bool cannot_accumulate) /* Compute the alignment. */ align = (alloca_with_align - ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)) + ? tree_to_uhwi (CALL_EXPR_ARG (exp, 1)) : BIGGEST_ALIGNMENT); /* Allocate the desired space. */ @@ -5390,7 +5393,7 @@ expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp, weak = CALL_EXPR_ARG (exp, 3); is_weak = false; - if (host_integerp (weak, 0) && tree_low_cst (weak, 0) != 0) + if (tree_fits_shwi_p (weak) && tree_to_hwi (weak) != 0) is_weak = true; oldval = expect; @@ -8026,8 +8029,9 @@ fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg) { tree itype = TREE_TYPE (TREE_TYPE (fndecl)); tree ftype = TREE_TYPE (arg); - double_int val; + wide_int val; REAL_VALUE_TYPE r; + bool fail = false; switch (DECL_FUNCTION_CODE (fndecl)) { @@ -8053,9 +8057,10 @@ fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg) gcc_unreachable (); } - real_to_integer2 ((HOST_WIDE_INT *)&val.low, &val.high, &r); - if (double_int_fits_to_tree_p (itype, val)) - return double_int_to_tree (itype, val); + val = real_to_integer (&r, &fail, + TYPE_PRECISION (itype)); + if (!fail) + return wide_int_to_tree (itype, val); } } @@ -8088,100 +8093,40 @@ fold_builtin_bitop (tree fndecl, tree arg) /* Optimize for constant argument. */ if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg)) { - HOST_WIDE_INT hi, width, result; - unsigned HOST_WIDE_INT lo; - tree type; - - type = TREE_TYPE (arg); - width = TYPE_PRECISION (type); - lo = TREE_INT_CST_LOW (arg); - - /* Clear all the bits that are beyond the type's precision. */ - if (width > HOST_BITS_PER_WIDE_INT) - { - hi = TREE_INT_CST_HIGH (arg); - if (width < HOST_BITS_PER_DOUBLE_INT) - hi &= ~((unsigned HOST_WIDE_INT) (-1) - << (width - HOST_BITS_PER_WIDE_INT)); - } - else - { - hi = 0; - if (width < HOST_BITS_PER_WIDE_INT) - lo &= ~((unsigned HOST_WIDE_INT) (-1) << width); - } + wide_int warg = wide_int::from_tree (arg); + wide_int result; switch (DECL_FUNCTION_CODE (fndecl)) { CASE_INT_FN (BUILT_IN_FFS): - if (lo != 0) - result = ffs_hwi (lo); - else if (hi != 0) - result = HOST_BITS_PER_WIDE_INT + ffs_hwi (hi); - else - result = 0; + result = warg.ffs (); break; CASE_INT_FN (BUILT_IN_CLZ): - if (hi != 0) - result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT; - else if (lo != 0) - result = width - floor_log2 (lo) - 1; - else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result)) - result = width; + result = warg.clz (); break; CASE_INT_FN (BUILT_IN_CTZ): - if (lo != 0) - result = ctz_hwi (lo); - else if (hi != 0) - result = HOST_BITS_PER_WIDE_INT + ctz_hwi (hi); - else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result)) - result = width; + result = warg.ctz (); break; CASE_INT_FN (BUILT_IN_CLRSB): - if (width > HOST_BITS_PER_WIDE_INT - && (hi & ((unsigned HOST_WIDE_INT) 1 - << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0) - { - hi = ~hi & ~((unsigned HOST_WIDE_INT) (-1) - << (width - HOST_BITS_PER_WIDE_INT - 1)); - lo = ~lo; - } - else if (width <= HOST_BITS_PER_WIDE_INT - && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0) - lo = ~lo & ~((unsigned HOST_WIDE_INT) (-1) << (width - 1)); - if (hi != 0) - result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT; - else if (lo != 0) - result = width - floor_log2 (lo) - 2; - else - result = width - 1; + result = warg.clrsb (); break; CASE_INT_FN (BUILT_IN_POPCOUNT): - result = 0; - while (lo) - result++, lo &= lo - 1; - while (hi) - result++, hi &= (unsigned HOST_WIDE_INT) hi - 1; + result = warg.popcount (); break; CASE_INT_FN (BUILT_IN_PARITY): - result = 0; - while (lo) - result++, lo &= lo - 1; - while (hi) - result++, hi &= (unsigned HOST_WIDE_INT) hi - 1; - result &= 1; + result = warg.parity (); break; default: gcc_unreachable (); } - return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result); + return wide_int_to_tree (TREE_TYPE (TREE_TYPE (fndecl)), result); } return NULL_TREE; @@ -8198,49 +8143,25 @@ fold_builtin_bswap (tree fndecl, tree arg) /* Optimize constant value. */ if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg)) { - HOST_WIDE_INT hi, width, r_hi = 0; - unsigned HOST_WIDE_INT lo, r_lo = 0; tree type = TREE_TYPE (TREE_TYPE (fndecl)); - width = TYPE_PRECISION (type); - lo = TREE_INT_CST_LOW (arg); - hi = TREE_INT_CST_HIGH (arg); - switch (DECL_FUNCTION_CODE (fndecl)) { case BUILT_IN_BSWAP16: case BUILT_IN_BSWAP32: case BUILT_IN_BSWAP64: { - int s; - - for (s = 0; s < width; s += 8) - { - int d = width - s - 8; - unsigned HOST_WIDE_INT byte; - - if (s < HOST_BITS_PER_WIDE_INT) - byte = (lo >> s) & 0xff; - else - byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff; - - if (d < HOST_BITS_PER_WIDE_INT) - r_lo |= byte << d; - else - r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT); - } + wide_int::SignOp sgn = TYPE_UNSIGNED (type) + ? wide_int::UNSIGNED : wide_int::SIGNED; + tree result = + wide_int_to_tree (type, + wide_int::from_tree (arg) + .force_to_size (TYPE_PRECISION (type), sgn).bswap ()); + return result; } - - break; - default: gcc_unreachable (); } - - if (width < HOST_BITS_PER_WIDE_INT) - return build_int_cst (type, r_lo); - else - return build_int_cst_wide (type, r_lo, r_hi); } return NULL_TREE; @@ -8553,9 +8474,9 @@ fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED, if (real_onep (arg0)) return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1); - if (host_integerp (arg1, 0)) + if (tree_fits_shwi_p (arg1)) { - HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1); + HOST_WIDE_INT c = tree_to_hwi (arg1); /* Evaluate powi at compile-time. */ if (TREE_CODE (arg0) == REAL_CST @@ -8652,7 +8573,7 @@ fold_builtin_memset (location_t loc, tree dest, tree c, tree len, || ! validate_arg (len, INTEGER_TYPE)) return NULL_TREE; - if (! host_integerp (len, 1)) + if (! tree_fits_uhwi_p (len)) return NULL_TREE; /* If the LEN parameter is zero, return DEST. */ @@ -8682,7 +8603,7 @@ fold_builtin_memset (location_t loc, tree dest, tree c, tree len, if (! var_decl_component_p (var)) return NULL_TREE; - length = tree_low_cst (len, 1); + length = tree_to_uhwi (len); if (GET_MODE_SIZE (TYPE_MODE (etype)) != length || get_pointer_alignment (dest) / BITS_PER_UNIT < length) return NULL_TREE; @@ -8697,7 +8618,7 @@ fold_builtin_memset (location_t loc, tree dest, tree c, tree len, if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64) return NULL_TREE; - cval = TREE_INT_CST_LOW (c); + cval = tree_to_hwi (c); cval &= 0xff; cval |= cval << 8; cval |= cval << 16; @@ -8785,9 +8706,9 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, if (!dest_align || !src_align) return NULL_TREE; if (readonly_data_expr (src) - || (host_integerp (len, 1) + || (tree_fits_uhwi_p (len) && (MIN (src_align, dest_align) / BITS_PER_UNIT - >= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1)))) + >= (unsigned HOST_WIDE_INT) tree_to_uhwi (len)))) { tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY); if (!fn) @@ -8810,8 +8731,8 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, destvar = TREE_OPERAND (dest, 0); dest_base = get_ref_base_and_extent (destvar, &dest_offset, &size, &maxsize); - if (host_integerp (len, 1)) - maxsize = tree_low_cst (len, 1); + if (tree_fits_uhwi_p (len)) + maxsize = tree_to_hwi (len); else maxsize = -1; src_offset /= BITS_PER_UNIT; @@ -8827,20 +8748,19 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, else if (TREE_CODE (src_base) == MEM_REF && TREE_CODE (dest_base) == MEM_REF) { - double_int off; + wide_int off; if (! operand_equal_p (TREE_OPERAND (src_base, 0), TREE_OPERAND (dest_base, 0), 0)) return NULL_TREE; - off = mem_ref_offset (src_base) + - double_int::from_shwi (src_offset); - if (!off.fits_shwi ()) + off = wide_int::from_tree (TREE_OPERAND (src_base, 1)) + src_offset; + if (!off.fits_shwi_p ()) return NULL_TREE; - src_offset = off.low; - off = mem_ref_offset (dest_base) + - double_int::from_shwi (dest_offset); - if (!off.fits_shwi ()) + src_offset = off.to_shwi (); + + off = wide_int::from_tree (TREE_OPERAND (dest_base, 1)) + dest_offset; + if (!off.fits_shwi_p ()) return NULL_TREE; - dest_offset = off.low; + dest_offset = off.to_shwi (); if (ranges_overlap_p (src_offset, maxsize, dest_offset, maxsize)) return NULL_TREE; @@ -8877,7 +8797,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, return NULL_TREE; } - if (!host_integerp (len, 0)) + if (!tree_fits_shwi_p (len)) return NULL_TREE; /* FIXME: This logic lose for arguments like (type *)malloc (sizeof (type)), @@ -9165,7 +9085,7 @@ fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type) const char *p1; if (TREE_CODE (arg2) != INTEGER_CST - || !host_integerp (len, 1)) + || !tree_fits_uhwi_p (len)) return NULL_TREE; p1 = c_getstr (arg1); @@ -9178,7 +9098,7 @@ fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type) if (target_char_cast (arg2, &c)) return NULL_TREE; - r = (const char *) memchr (p1, c, tree_low_cst (len, 1)); + r = (const char *) memchr (p1, c, tree_to_uhwi (len)); if (r == NULL) return build_int_cst (TREE_TYPE (arg1), 0); @@ -9217,11 +9137,11 @@ fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len) /* If all arguments are constant, and the value of len is not greater than the lengths of arg1 and arg2, evaluate at compile-time. */ - if (host_integerp (len, 1) && p1 && p2 + if (tree_fits_uhwi_p (len) && p1 && p2 && compare_tree_int (len, strlen (p1) + 1) <= 0 && compare_tree_int (len, strlen (p2) + 1) <= 0) { - const int r = memcmp (p1, p2, tree_low_cst (len, 1)); + const int r = memcmp (p1, p2, tree_to_uhwi (len)); if (r > 0) return integer_one_node; @@ -9233,7 +9153,7 @@ fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len) /* If len parameter is one, return an expression corresponding to (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */ - if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1) + if (tree_fits_uhwi_p (len) && tree_to_hwi (len) == 1) { tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); tree cst_uchar_ptr_node @@ -9345,9 +9265,9 @@ fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len) p1 = c_getstr (arg1); p2 = c_getstr (arg2); - if (host_integerp (len, 1) && p1 && p2) + if (tree_fits_uhwi_p (len) && p1 && p2) { - const int i = strncmp (p1, p2, tree_low_cst (len, 1)); + const int i = strncmp (p1, p2, tree_to_hwi (len)); if (i > 0) return integer_one_node; else if (i < 0) @@ -9393,7 +9313,7 @@ fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len) /* If len parameter is one, return an expression corresponding to (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */ - if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1) + if (tree_fits_uhwi_p (len) && tree_to_hwi (len) == 1) { tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); tree cst_uchar_ptr_node @@ -9851,7 +9771,7 @@ fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1, /* If both arguments are constant, then try to evaluate it. */ if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2) && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0) - && host_integerp (arg1, 0)) + && tree_fits_shwi_p (arg1)) { /* Bound the maximum adjustment to twice the range of the mode's valid exponents. Use abs to ensure the range is @@ -9861,7 +9781,7 @@ fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1, - REAL_MODE_FORMAT (TYPE_MODE (type))->emin); /* Get the user-requested adjustment. */ - const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0); + const HOST_WIDE_INT req_exp_adj = tree_to_shwi (arg1); /* The requested adjustment must be inside this range. This is a preliminary cap to avoid things like overflow, we @@ -12331,7 +12251,7 @@ fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt, if (orig && !validate_arg (orig, POINTER_TYPE)) return NULL_TREE; - if (!host_integerp (destsize, 1)) + if (!tree_fits_uhwi_p (destsize)) return NULL_TREE; /* Check whether the format is a literal string constant. */ @@ -12345,7 +12265,7 @@ fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt, if (!init_target_chars ()) return NULL_TREE; - destlen = tree_low_cst (destsize, 1); + destlen = tree_to_hwi (destsize); /* If the format doesn't contain % args or %%, use strcpy. */ if (strchr (fmt_str, target_percent) == NULL) @@ -12390,10 +12310,10 @@ fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt, return NULL_TREE; retval = c_strlen (orig, 1); - if (!retval || !host_integerp (retval, 1)) + if (!retval || !tree_fits_uhwi_p (retval)) return NULL_TREE; - origlen = tree_low_cst (retval, 1); + origlen = tree_to_hwi (retval); /* We could expand this as memcpy (str1, str2, cst - 1); str1[cst - 1] = '\0'; or to @@ -12455,7 +12375,7 @@ expand_builtin_object_size (tree exp) return const0_rtx; } - object_size_type = tree_low_cst (ost, 0); + object_size_type = tree_to_shwi (ost); return object_size_type < 2 ? constm1_rtx : const0_rtx; } @@ -12484,10 +12404,10 @@ expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode, len = CALL_EXPR_ARG (exp, 2); size = CALL_EXPR_ARG (exp, 3); - if (! host_integerp (size, 1)) + if (! tree_fits_uhwi_p (size)) return NULL_RTX; - if (host_integerp (len, 1) || integer_all_onesp (size)) + if (tree_fits_uhwi_p (len) || integer_all_onesp (size)) { tree fn; @@ -12618,22 +12538,22 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode) if (!len || !size) return; - if (! host_integerp (size, 1) || integer_all_onesp (size)) + if (! tree_fits_uhwi_p (size) || integer_all_onesp (size)) return; if (is_strlen) { len = c_strlen (len, 1); - if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size)) + if (! len || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size)) return; } else if (fcode == BUILT_IN_STRNCAT_CHK) { tree src = CALL_EXPR_ARG (exp, 1); - if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size)) + if (! src || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size)) return; src = c_strlen (src, 1); - if (! src || ! host_integerp (src, 1)) + if (! src || ! tree_fits_uhwi_p (src)) { warning_at (loc, 0, "%Kcall to %D might overflow destination buffer", exp, get_callee_fndecl (exp)); @@ -12642,7 +12562,7 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode) else if (tree_int_cst_lt (src, size)) return; } - else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len)) + else if (! tree_fits_uhwi_p (len) || ! tree_int_cst_lt (size, len)) return; warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer", @@ -12666,7 +12586,7 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode) size = CALL_EXPR_ARG (exp, 2); fmt = CALL_EXPR_ARG (exp, 3); - if (! host_integerp (size, 1) || integer_all_onesp (size)) + if (! tree_fits_uhwi_p (size) || integer_all_onesp (size)) return; /* Check whether the format is a literal string constant. */ @@ -12694,7 +12614,7 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode) return; len = c_strlen (arg, 1); - if (!len || ! host_integerp (len, 1)) + if (!len || ! tree_fits_uhwi_p (len)) return; } else @@ -12737,6 +12657,7 @@ fold_builtin_object_size (tree ptr, tree ost) { unsigned HOST_WIDE_INT bytes; int object_size_type; + int precision = TYPE_PRECISION (TREE_TYPE (ptr)); if (!validate_arg (ptr, POINTER_TYPE) || !validate_arg (ost, INTEGER_TYPE)) @@ -12749,7 +12670,7 @@ fold_builtin_object_size (tree ptr, tree ost) || compare_tree_int (ost, 3) > 0) return NULL_TREE; - object_size_type = tree_low_cst (ost, 0); + object_size_type = tree_to_shwi (ost); /* __builtin_object_size doesn't evaluate side-effects in its arguments; if there are any side-effects, it returns (size_t) -1 for types 0 and 1 @@ -12759,21 +12680,24 @@ fold_builtin_object_size (tree ptr, tree ost) if (TREE_CODE (ptr) == ADDR_EXPR) { - bytes = compute_builtin_object_size (ptr, object_size_type); - if (double_int_fits_to_tree_p (size_type_node, - double_int::from_uhwi (bytes))) - return build_int_cstu (size_type_node, bytes); + + wide_int wbytes + = wide_int::from_uhwi (compute_builtin_object_size (ptr, object_size_type), + precision); + if (wbytes.fits_to_tree_p (size_type_node)) + return wide_int_to_tree (size_type_node, wbytes); } else if (TREE_CODE (ptr) == SSA_NAME) { /* If object size is not known yet, delay folding until later. Maybe subsequent passes will help determining it. */ + wide_int wbytes; bytes = compute_builtin_object_size (ptr, object_size_type); + wbytes = wide_int::from_uhwi (bytes, precision); if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2 ? -1 : 0) - && double_int_fits_to_tree_p (size_type_node, - double_int::from_uhwi (bytes))) - return build_int_cstu (size_type_node, bytes); + && wbytes.fits_to_tree_p (size_type_node)) + return wide_int_to_tree (size_type_node, wbytes); } return NULL_TREE; @@ -12815,17 +12739,17 @@ fold_builtin_memory_chk (location_t loc, tree fndecl, } } - if (! host_integerp (size, 1)) + if (! tree_fits_uhwi_p (size)) return NULL_TREE; if (! integer_all_onesp (size)) { - if (! host_integerp (len, 1)) + if (! tree_fits_uhwi_p (len)) { /* If LEN is not constant, try MAXLEN too. For MAXLEN only allow optimizing into non-_ocs function if SIZE is >= MAXLEN, never convert to __ocs_fail (). */ - if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1)) + if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen)) { if (fcode == BUILT_IN_MEMPCPY_CHK && ignore) { @@ -12897,18 +12821,18 @@ fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest, if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0)) return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest); - if (! host_integerp (size, 1)) + if (! tree_fits_uhwi_p (size)) return NULL_TREE; if (! integer_all_onesp (size)) { len = c_strlen (src, 1); - if (! len || ! host_integerp (len, 1)) + if (! len || ! tree_fits_uhwi_p (len)) { /* If LEN is not constant, try MAXLEN too. For MAXLEN only allow optimizing into non-_ocs function if SIZE is >= MAXLEN, never convert to __ocs_fail (). */ - if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1)) + if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen)) { if (fcode == BUILT_IN_STPCPY_CHK) { @@ -12984,17 +12908,17 @@ fold_builtin_stxncpy_chk (location_t loc, tree dest, tree src, return build_call_expr_loc (loc, fn, 4, dest, src, len, size); } - if (! host_integerp (size, 1)) + if (! tree_fits_uhwi_p (size)) return NULL_TREE; if (! integer_all_onesp (size)) { - if (! host_integerp (len, 1)) + if (! tree_fits_uhwi_p (len)) { /* If LEN is not constant, try MAXLEN too. For MAXLEN only allow optimizing into non-_ocs function if SIZE is >= MAXLEN, never convert to __ocs_fail (). */ - if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1)) + if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen)) return NULL_TREE; } else @@ -13033,7 +12957,7 @@ fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest, if (p && *p == '\0') return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src); - if (! host_integerp (size, 1) || ! integer_all_onesp (size)) + if (! tree_fits_uhwi_p (size) || ! integer_all_onesp (size)) return NULL_TREE; /* If __builtin_strcat_chk is used, assume strcat is available. */ @@ -13067,15 +12991,15 @@ fold_builtin_strncat_chk (location_t loc, tree fndecl, else if (integer_zerop (len)) return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src); - if (! host_integerp (size, 1)) + if (! tree_fits_uhwi_p (size)) return NULL_TREE; if (! integer_all_onesp (size)) { tree src_len = c_strlen (src, 1); if (src_len - && host_integerp (src_len, 1) - && host_integerp (len, 1) + && tree_fits_uhwi_p (src_len) + && tree_fits_uhwi_p (len) && ! tree_int_cst_lt (len, src_len)) { /* If LEN >= strlen (SRC), optimize into __strcat_chk. */ @@ -13124,7 +13048,7 @@ fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args, if (!validate_arg (fmt, POINTER_TYPE)) return NULL_TREE; - if (! host_integerp (size, 1)) + if (! tree_fits_uhwi_p (size)) return NULL_TREE; len = NULL_TREE; @@ -13155,7 +13079,7 @@ fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args, if (validate_arg (arg, POINTER_TYPE)) { len = c_strlen (arg, 1); - if (! len || ! host_integerp (len, 1)) + if (! len || ! tree_fits_uhwi_p (len)) len = NULL_TREE; } } @@ -13232,17 +13156,17 @@ fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args, if (!validate_arg (fmt, POINTER_TYPE)) return NULL_TREE; - if (! host_integerp (size, 1)) + if (! tree_fits_uhwi_p (size)) return NULL_TREE; if (! integer_all_onesp (size)) { - if (! host_integerp (len, 1)) + if (! tree_fits_uhwi_p (len)) { /* If LEN is not constant, try MAXLEN too. For MAXLEN only allow optimizing into non-_ocs function if SIZE is >= MAXLEN, never convert to __ocs_fail (). */ - if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1)) + if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen)) return NULL_TREE; } else @@ -13887,10 +13811,10 @@ do_mpfr_bessel_n (tree arg1, tree arg2, tree type, /* To proceed, MPFR must exactly represent the target floating point format, which only happens when the target base equals two. */ if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 - && host_integerp (arg1, 0) + && tree_fits_shwi_p (arg1) && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)) { - const HOST_WIDE_INT n = tree_low_cst(arg1, 0); + const HOST_WIDE_INT n = tree_to_hwi(arg1); const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2); if (n == (long)n diff --git a/gcc/dfp.c b/gcc/dfp.c index d15ee8f..f0172c1 100644 --- a/gcc/dfp.c +++ b/gcc/dfp.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "dfp.h" +#include "wide-int.h" /* The order of the following headers is important for making sure decNumber structure is large enough to hold decimal128 digits. */ @@ -631,6 +632,33 @@ decimal_real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh, real_to_integer2 (plow, phigh, &to); } +/* Likewise, but returns a wide_int with PRECISION. Fail + is set if the value does not fit. */ + +wide_int +decimal_real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision) +{ + decContext set; + decNumber dn, dn2, dn3; + REAL_VALUE_TYPE to; + char string[256]; + + decContextDefault (&set, DEC_INIT_DECIMAL128); + set.traps = 0; + set.round = DEC_ROUND_DOWN; + decimal128ToNumber ((const decimal128 *) r->sig, &dn); + + decNumberToIntegralValue (&dn2, &dn, &set); + decNumberZero (&dn3); + decNumberRescale (&dn, &dn2, &dn3, &set); + + /* Convert to REAL_VALUE_TYPE and call appropriate conversion + function. */ + decNumberToString (&dn, string); + real_from_string (&to, string); + return real_to_integer (&to, fail, precision); +} + /* Perform the decimal floating point operation described by CODE. For a unary operation, OP1 will be NULL. This function returns true if the result may be inexact due to loss of precision. */ diff --git a/gcc/real.c b/gcc/real.c index b80aeac..976a973 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -29,6 +29,7 @@ #include "realmpfr.h" #include "tm_p.h" #include "dfp.h" +#include "wide-int.h" /* The floating point model used internally is not exactly IEEE 754 compliant, and close to the description in the ISO C99 standard, @@ -1459,6 +1460,91 @@ real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh, *phigh = high; } +/* Likewise, but producing a wide-int of PRECISION. If + the value cannot be represented in precision, FAIL is set to + TRUE. */ + +wide_int +real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision) +{ + HOST_WIDE_INT val[2 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT]; + int exp; + int words; + wide_int result; + int w; + + switch (r->cl) + { + case rvc_zero: + underflow: + return wide_int::zero (precision); + + case rvc_inf: + case rvc_nan: + overflow: + *fail = true; + + if (r->sign) + return wide_int::set_bit_in_zero (precision - 1, precision); + else + return ~wide_int::set_bit_in_zero (precision - 1, precision); + + case rvc_normal: + if (r->decimal) + return decimal_real_to_integer (r, fail, precision); + + exp = REAL_EXP (r); + if (exp <= 0) + goto underflow; + /* Only force overflow for unsigned overflow. Signed overflow is + undefined, so it doesn't matter what we return, and some callers + expect to be able to use this routine for both signed and + unsigned conversions. */ + if (exp > precision) + goto overflow; + + words = (precision + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT; + + for (int i = 0; i < 2 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT; i++) + val[i] = 0; + +#if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG) + for (int i = 0; i < words; i++) + { + int j = SIGSZ - words + i; + val[i] = (j < 0) ? 0 : r->sig[j]; + } +#else + gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG); + for (int i = 0; i < words; i++) + { + int j = SIGSZ - (words * 2) + (i + 2) + 1; + if (j < 0) + val[i] = 0; + else + { + val[i] = r->sig[j]; + val[i] <<= HOST_BITS_PER_LONG; + val[i] |= r->sig[j - 1]; + } + } +#endif + w = SIGSZ * HOST_BITS_PER_LONG + words * HOST_BITS_PER_WIDE_INT; + result = wide_int::from_array (val, + (w + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT, w, w); + result = result.rshiftu ((words * HOST_BITS_PER_WIDE_INT) - exp); + result = result.force_to_size (precision, wide_int::UNSIGNED); + + if (r->sign) + return result.neg (); + else + return result; + + default: + gcc_unreachable (); + } +} + /* A subroutine of real_to_decimal. Compute the quotient and remainder of NUM / DEN. Return the quotient and place the remainder in NUM. It is expected that NUM / DEN are close enough that the quotient is diff --git a/gcc/tree.h b/gcc/tree.h index be43440..2bd4132 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -735,6 +735,8 @@ enum tree_node_structure_enum { }; #undef DEFTREESTRUCT +#define NULL_TREE (tree) NULL + /* Define accessors for the fields that all tree nodes have (though some fields are not used for all kinds of nodes). */ @@ -4101,6 +4103,113 @@ omp_clause_elt_check (const_tree __t, int __i, #endif +/* Return true if T is an INTEGER_CST whose value must be non-negative + and can be represented in a single unsigned HOST_WIDE_INT. */ + +static inline bool +tree_fits_uhwi_p (const_tree cst) +{ + if (cst == NULL_TREE) + return false; + + if (TREE_CODE (cst) != INTEGER_CST) + return false; + +#ifdef NEW_REP_FOR_INT_CST + return TREE_INT_CST_NUNITS (cst) == 1 + || (TREE_INT_CST_NUNITS (cst) == 2 && TREE_INT_CST_ELT[1] == 0); + +#else + return (TREE_INT_CST_HIGH (cst) == 0); +#endif +} + +/* Return true if CST is an INTEGER_CST whose value can be represented + in a single HOST_WIDE_INT. */ + +static inline bool +tree_fits_shwi_p (const_tree cst) +{ + if (cst == NULL_TREE) + return false; + + if (TREE_CODE (cst) != INTEGER_CST) + return false; + +#ifdef NEW_REP_FOR_INT_CST + return TREE_INT_CST_NUNITS (cst) == 1; +#else + return ((TREE_INT_CST_HIGH (cst) == 0 + && (HOST_WIDE_INT) TREE_INT_CST_LOW (cst) >= 0) + || (TREE_INT_CST_HIGH (cst) == -1 + && (HOST_WIDE_INT) TREE_INT_CST_LOW (cst) < 0 + && !TYPE_UNSIGNED (TREE_TYPE (cst)))); +#endif +} + +/* Return true if T is an INTEGER_CST that can be manipulated + efficiently on the host. If POS is false, the value can be + represented in a single HOST_WIDE_INT. If POS is true, the value + must be non-negative and can be represented in a single unsigned + HOST_WIDE_INT. */ + +static inline bool +tree_fits_hwi_p (const_tree cst, bool pos) +{ + if (cst == NULL_TREE) + return 0; + + if (TREE_CODE (cst) != INTEGER_CST) + return false; + + return pos ? tree_fits_uhwi_p (cst) : tree_fits_shwi_p (cst); +} + +/* Return the unsigned HOST_WIDE_INT least significant bits of CST. + If checking is enabled, this ices if the value does not fit. */ + +static inline unsigned HOST_WIDE_INT +tree_to_uhwi (const_tree cst) +{ + gcc_checking_assert (tree_fits_uhwi_p (cst)); + +#ifdef NEW_REP_FOR_INT_CST + return (unsigned HOST_WIDE_INT)TREE_INT_CST_ELT (cst, 0); +#else + return (unsigned HOST_WIDE_INT)TREE_INT_CST_LOW (cst); +#endif +} + +/* Return the HOST_WIDE_INT least significant bits of CST. If + checking is enabled, this ices if the value does not fit. */ + +static inline HOST_WIDE_INT +tree_to_shwi (const_tree cst) +{ + gcc_checking_assert (tree_fits_shwi_p (cst)); + +#ifdef NEW_REP_FOR_INT_CST + return (HOST_WIDE_INT)TREE_INT_CST_ELT (cst, 0); +#else + return (HOST_WIDE_INT)TREE_INT_CST_LOW (cst); +#endif +} + +/* Return the HOST_WIDE_INT least significant bits of CST. No + checking is done to assure that it fits. It is assumed that one of + tree_fits_uhwi_p or tree_fits_shwi_p was done before this call. */ + +static inline HOST_WIDE_INT +tree_to_hwi (const_tree cst) +{ +#ifdef NEW_REP_FOR_INT_CST + return TREE_INT_CST_ELT (cst, 0); +#else + return TREE_INT_CST_LOW (cst); +#endif +} + + /* Compute the number of operands in an expression node NODE. For tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself, otherwise it is looked up from the node's code. */ @@ -4568,8 +4677,6 @@ enum ptrmemfunc_vbit_where_t ptrmemfunc_vbit_in_delta }; -#define NULL_TREE (tree) NULL - /* True if NODE is an erroneous expression. */ #define error_operand_p(NODE) \