GCC Middle and Back End API Reference
double-int.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
Include dependency graph for double-int.cc:

Macros

#define add_double(l1, h1, l2, h2, lv, hv)    add_double_with_sign (l1, h1, l2, h2, lv, hv, false)
 
#define mul_double(l1, h1, l2, h2, lv, hv)    mul_double_wide_with_sign (l1, h1, l2, h2, lv, hv, NULL, NULL, false)
 
#define OVERFLOW_SUM_SIGN(a, b, sum)   ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
 
#define LOWPART(x)    ((x) & ((HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT / 2)) - 1))
 
#define HIGHPART(x)    ((unsigned HOST_WIDE_INT) (x) >> HOST_BITS_PER_WIDE_INT / 2)
 
#define BASE   (HOST_WIDE_INT_1U << HOST_BITS_PER_WIDE_INT / 2)
 

Functions

static int add_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool)
 
static int neg_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *)
 
static int mul_double_wide_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool)
 
static int div_and_round_double (unsigned, int, unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *)
 
static void encode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
 
static void decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low, HOST_WIDE_INT *hi)
 
static void rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, unsigned HOST_WIDE_INT count, unsigned int prec, unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, bool arith)
 
static void lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, unsigned HOST_WIDE_INT count, unsigned int prec, unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
 
static unsigned double_int_split_digit (double_int *cst, unsigned base)
 
void dump_double_int (FILE *file, double_int cst, bool uns)
 
void mpz_set_double_int (mpz_t result, double_int val, bool uns)
 
double_int mpz_get_double_int (const_tree type, mpz_t val, bool wrap)
 

Macro Definition Documentation

◆ add_double

◆ BASE

#define BASE   (HOST_WIDE_INT_1U << HOST_BITS_PER_WIDE_INT / 2)

Referenced by decode(), and div_and_round_double().

◆ HIGHPART

#define HIGHPART ( x)     ((unsigned HOST_WIDE_INT) (x) >> HOST_BITS_PER_WIDE_INT / 2)

◆ LOWPART

#define LOWPART ( x)     ((x) & ((HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT / 2)) - 1))
To do constant folding on INTEGER_CST nodes requires two-word arithmetic.
We do that by representing the two-word integer in 4 words, with only
HOST_BITS_PER_WIDE_INT / 2 bits stored in each word, as a positive
number.  The value of the word is LOWPART + HIGHPART * BASE.   

Referenced by div_and_round_double(), encode(), and mul_double_wide_with_sign().

◆ mul_double

◆ OVERFLOW_SUM_SIGN

#define OVERFLOW_SUM_SIGN ( a,
b,
sum )   ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
overflow.  Suppose A, B and SUM have the same respective signs as A1, B1,
and SUM1.  Then this yields nonzero if overflow occurred during the
addition.

Overflow occurs if A and B have the same sign, but A and SUM differ in
sign.  Use `^' to test whether signs differ, and `< 0' to isolate the
sign.   

Referenced by add_double_with_sign(), and double_int::sub_with_overflow().

Function Documentation

◆ add_double_with_sign()

static int add_double_with_sign ( unsigned HOST_WIDE_INT l1,
HOST_WIDE_INT h1,
unsigned HOST_WIDE_INT l2,
HOST_WIDE_INT h2,
unsigned HOST_WIDE_INT * lv,
HOST_WIDE_INT * hv,
bool unsigned_p )
static
Operations with long integers.
   Copyright (C) 2006-2024 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.

GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.   
Add two doubleword integers with doubleword result.
Return nonzero if the operation overflows according to UNSIGNED_P.
Each argument is given as two `HOST_WIDE_INT' pieces.
One argument is L1 and H1; the other, L2 and H2.
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.   

References ggc_alloc(), and OVERFLOW_SUM_SIGN.

Referenced by double_int::add_with_sign().

◆ decode()

static void decode ( HOST_WIDE_INT * words,
unsigned HOST_WIDE_INT * low,
HOST_WIDE_INT * hi )
static
Pack an array of 4 words into a two-word integer.
WORDS points to the array of words.
The integer is stored into *LOW and *HI as two `HOST_WIDE_INT' pieces.   

References BASE, and ggc_alloc().

Referenced by div_and_round_double(), and mul_double_wide_with_sign().

◆ div_and_round_double()

static int div_and_round_double ( unsigned code,
int uns,
unsigned HOST_WIDE_INT lnum_orig,
HOST_WIDE_INT hnum_orig,
unsigned HOST_WIDE_INT lden_orig,
HOST_WIDE_INT hden_orig,
unsigned HOST_WIDE_INT * lquo,
HOST_WIDE_INT * hquo,
unsigned HOST_WIDE_INT * lrem,
HOST_WIDE_INT * hrem )
static
Divide doubleword integer LNUM, HNUM by doubleword integer LDEN, HDEN
for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM).
CODE is a tree code for a kind of division, one of
TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR, ROUND_DIV_EXPR
or EXACT_DIV_EXPR
It controls how the quotient is rounded to an integer.
Return nonzero if the operation overflows.
UNS nonzero says do unsigned division.   

References add_double, BASE, decode(), encode(), gcc_unreachable, ggc_alloc(), HIGHPART, HOST_WIDE_INT_0, HOST_WIDE_INT_1, HOST_WIDE_INT_M1, i, LOWPART, mul_double, and neg_double().

Referenced by double_int::divmod(), double_int::divmod_with_overflow(), and double_int_split_digit().

◆ double_int_split_digit()

static unsigned double_int_split_digit ( double_int * cst,
unsigned base )
static
Splits last digit of *CST (taken as unsigned) in BASE and returns it.   

References div_and_round_double(), and ggc_alloc().

Referenced by dump_double_int().

◆ dump_double_int()

void dump_double_int ( FILE * file,
double_int cst,
bool uns )
Dumps CST to FILE.  If UNS is true, CST is considered to be unsigned,
otherwise it is signed.   

References double_int_split_digit(), ggc_alloc(), and i.

◆ encode()

static void encode ( HOST_WIDE_INT * words,
unsigned HOST_WIDE_INT low,
HOST_WIDE_INT hi )
static
Unpack a two-word integer into 4 words.
LOW and HI are the integer, as two `HOST_WIDE_INT' pieces.
WORDS points to the array of HOST_WIDE_INTs.   

References ggc_alloc(), HIGHPART, and LOWPART.

Referenced by div_and_round_double(), and mul_double_wide_with_sign().

◆ lshift_double()

static void lshift_double ( unsigned HOST_WIDE_INT l1,
HOST_WIDE_INT h1,
unsigned HOST_WIDE_INT count,
unsigned int prec,
unsigned HOST_WIDE_INT * lv,
HOST_WIDE_INT * hv )
static
Shift the doubleword integer in L1, H1 left by COUNT places
keeping only PREC bits of result.
Shift right if COUNT is negative.
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.   

References count, ggc_alloc(), HOST_BITS_PER_DOUBLE_INT, HOST_BITS_PER_WIDE_INT, and HOST_WIDE_INT_M1U.

Referenced by double_int::alshift(), double_int::arshift(), double_int::llshift(), double_int::lrshift(), double_int::lshift(), and double_int::rshift().

◆ mpz_get_double_int()

double_int mpz_get_double_int ( const_tree type,
mpz_t val,
bool wrap )
Returns VAL converted to TYPE.  If WRAP is true, then out-of-range
values of VAL will be wrapped; otherwise, they will be set to the
appropriate minimum or maximum TYPE bound.   

References alloca, count, double_int::ext(), gcc_assert, get_type_static_bounds(), ggc_alloc(), double_int::high, double_int::low, TYPE_PRECISION, and TYPE_UNSIGNED.

◆ mpz_set_double_int()

void mpz_set_double_int ( mpz_t result,
double_int val,
bool uns )
Sets RESULT to VAL, taken unsigned if UNS is true and as signed
otherwise.   

References ggc_alloc(), double_int::high, double_int::is_negative(), and double_int::low.

◆ mul_double_wide_with_sign()

static int mul_double_wide_with_sign ( unsigned HOST_WIDE_INT l1,
HOST_WIDE_INT h1,
unsigned HOST_WIDE_INT l2,
HOST_WIDE_INT h2,
unsigned HOST_WIDE_INT * lv,
HOST_WIDE_INT * hv,
unsigned HOST_WIDE_INT * lw,
HOST_WIDE_INT * hw,
bool unsigned_p )
static
Multiply two doubleword integers with quadword result.
Return nonzero if the operation overflows according to UNSIGNED_P.
Each argument is given as two `HOST_WIDE_INT' pieces.
One argument is L1 and H1; the other, L2 and H2.
The value is stored as four `HOST_WIDE_INT' pieces in *LV and *HV,
*LW and *HW.
If lw is NULL then only the low part and no overflow is computed.   

References add_double, decode(), encode(), ggc_alloc(), HIGHPART, i, LOWPART, neg_double(), and NULL.

Referenced by double_int::mul_with_sign(), and double_int::wide_mul_with_sign().

◆ neg_double()

static int neg_double ( unsigned HOST_WIDE_INT l1,
HOST_WIDE_INT h1,
unsigned HOST_WIDE_INT * lv,
HOST_WIDE_INT * hv )
static
Negate a doubleword integer with doubleword result.
Return nonzero if the operation overflows, assuming it's signed.
The argument is given as two `HOST_WIDE_INT' pieces in L1 and H1.
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.   

References ggc_alloc().

Referenced by div_and_round_double(), mul_double_wide_with_sign(), double_int::neg_with_overflow(), double_int::operator-(), double_int::operator-(), double_int::operator-=(), and double_int::sub_with_overflow().

◆ rshift_double()

static void rshift_double ( unsigned HOST_WIDE_INT l1,
HOST_WIDE_INT h1,
unsigned HOST_WIDE_INT count,
unsigned int prec,
unsigned HOST_WIDE_INT * lv,
HOST_WIDE_INT * hv,
bool arith )
static
Shift the doubleword integer in L1, H1 right by COUNT places
keeping only PREC bits of result.  ARITH nonzero specifies
arithmetic shifting; otherwise use logical shift.
Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.   

References count, ggc_alloc(), HOST_BITS_PER_DOUBLE_INT, HOST_BITS_PER_WIDE_INT, and HOST_WIDE_INT_M1U.

Referenced by double_int::alshift(), double_int::arshift(), double_int::llshift(), double_int::lrshift(), double_int::lshift(), and double_int::rshift().