diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 3e78949c7a661dc9eae1cd45301569fd5a3c95a6..0bba93f651fcae2cd230582d0e01311264fdf1e6 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -25679,6 +25679,7 @@ ix86_bitint_type_info (int n, struct bitint_info *info) info->limb_mode = SImode; else info->limb_mode = DImode; + info->abi_limb_mode = info->limb_mode; info->big_endian = false; info->extended = false; return true; diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 768ada0af52227a62f666ead3d303887041a9544..0bb6da080f8492629537b6c0160674edb425de9c 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1032,8 +1032,8 @@ applied. @deftypefn {Target Hook} bool TARGET_C_BITINT_TYPE_INFO (int @var{n}, struct bitint_info *@var{info}) This target hook returns true if @code{_BitInt(@var{N})} is supported and provides details on it. @code{_BitInt(@var{N})} is to be represented as -series of @code{info->limb_mode} -@code{CEIL (@var{N}, GET_MODE_PRECISION (info->limb_mode))} limbs, +series of @code{info->abi_limb_mode} +@code{CEIL (@var{N}, GET_MODE_PRECISION (info->abi_limb_mode))} limbs, ordered from least significant to most significant if @code{!info->big_endian}, otherwise from most significant to least significant. If @code{info->extended} is false, the bits above or equal to diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index a5be2ee048bd60c4439f808a239ce600c04370bc..cb4b57250a825b5c4a43566bff0f72e1e803c207 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -4604,7 +4604,7 @@ clear_padding_bitint_needs_padding_p (tree type) gcc_assert (ok); if (info.extended) return false; - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); + scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.abi_limb_mode); if (TYPE_PRECISION (type) < GET_MODE_PRECISION (limb_mode)) return true; else if (TYPE_PRECISION (type) == GET_MODE_PRECISION (limb_mode)) @@ -4881,7 +4881,8 @@ clear_padding_type (clear_padding_struct *buf, tree type, struct bitint_info info; bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); gcc_assert (ok); - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); + scalar_int_mode limb_mode + = as_a <scalar_int_mode> (info.abi_limb_mode); if (TYPE_PRECISION (type) <= GET_MODE_PRECISION (limb_mode)) { gcc_assert ((size_t) sz <= clear_padding_unit); diff --git a/gcc/stor-layout.cc b/gcc/stor-layout.cc index ba375fa423c95be4bb021226e69d98954b080f36..0c095aa3c3ce087663ee5edf93689116ef9c0f26 100644 --- a/gcc/stor-layout.cc +++ b/gcc/stor-layout.cc @@ -2154,7 +2154,8 @@ finish_bitfield_representative (tree repr, tree field) unsigned prec = TYPE_PRECISION (TREE_TYPE (field)); bool ok = targetm.c.bitint_type_info (prec, &info); gcc_assert (ok); - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); + scalar_int_mode limb_mode + = as_a <scalar_int_mode> (info.abi_limb_mode); unsigned lprec = GET_MODE_PRECISION (limb_mode); if (prec > lprec) { @@ -2416,16 +2417,20 @@ layout_type (tree type) int cnt; bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); gcc_assert (ok); - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); + scalar_int_mode limb_mode + = as_a <scalar_int_mode> (info.abi_limb_mode); if (TYPE_PRECISION (type) <= GET_MODE_PRECISION (limb_mode)) { SET_TYPE_MODE (type, limb_mode); + gcc_assert (info.abi_limb_mode == info.limb_mode); cnt = 1; } else { SET_TYPE_MODE (type, BLKmode); cnt = CEIL (TYPE_PRECISION (type), GET_MODE_PRECISION (limb_mode)); + gcc_assert (info.abi_limb_mode == info.limb_mode + || !info.big_endian == !WORDS_BIG_ENDIAN); } TYPE_SIZE (type) = bitsize_int (cnt * GET_MODE_BITSIZE (limb_mode)); TYPE_SIZE_UNIT (type) = size_int (cnt * GET_MODE_SIZE (limb_mode)); diff --git a/gcc/target.def b/gcc/target.def index 08218f3a42adff15150fa815391a9096832665c4..ca030abab6c6694ded178a62dbc4e1dbd20540ca 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -6357,8 +6357,8 @@ DEFHOOK (bitint_type_info, "This target hook returns true if @code{_BitInt(@var{N})} is supported and\n\ provides details on it. @code{_BitInt(@var{N})} is to be represented as\n\ -series of @code{info->limb_mode}\n\ -@code{CEIL (@var{N}, GET_MODE_PRECISION (info->limb_mode))} limbs,\n\ +series of @code{info->abi_limb_mode}\n\ +@code{CEIL (@var{N}, GET_MODE_PRECISION (info->abi_limb_mode))} limbs,\n\ ordered from least significant to most significant if\n\ @code{!info->big_endian}, otherwise from most significant to least\n\ significant. If @code{info->extended} is false, the bits above or equal to\n\ diff --git a/gcc/target.h b/gcc/target.h index a055b25af7cc77a2d7cce2a4306b9c6b2df450bb..53f03b3efbde118448bbdb86c7519c3c0ac73829 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -69,15 +69,23 @@ union cumulative_args_t { void *p; }; #endif /* !CHECKING_P */ /* Target properties of _BitInt(N) type. _BitInt(N) is to be represented - as series of limb_mode CEIL (N, GET_MODE_PRECISION (limb_mode)) limbs, - ordered from least significant to most significant if !big_endian, + as series of abi_limb_mode CEIL (N, GET_MODE_PRECISION (abi_limb_mode)) + limbs, ordered from least significant to most significant if !big_endian, otherwise from most significant to least significant. If extended is false, the bits above or equal to N are undefined when stored in a register or memory, otherwise they are zero or sign extended depending on if - it is unsigned _BitInt(N) or _BitInt(N) / signed _BitInt(N). */ + it is unsigned _BitInt(N) or _BitInt(N) / signed _BitInt(N). + limb_mode is either the same as abi_limb_mode, or some narrower mode + in which _BitInt lowering should actually perform operations in and + what libgcc _BitInt helpers should use. + E.g. abi_limb_mode could be TImode which is something some processor + specific ABI would specify to use, but it would be desirable to handle + it as an array of DImode instead for efficiency. + Note, abi_limb_mode can be different from limb_mode only if big_endian + matches WORDS_BIG_ENDIAN. */ struct bitint_info { - machine_mode limb_mode; + machine_mode abi_limb_mode, limb_mode; bool big_endian; bool extended; }; diff --git a/gcc/varasm.cc b/gcc/varasm.cc index 167aea87091d17be0ee9be2d0e52269a655129c9..69f8f8ee01866b124fc77bdd5bd009dc83c85dca 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -5315,7 +5315,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, tree type = TREE_TYPE (exp); bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); gcc_assert (ok); - scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); + scalar_int_mode limb_mode + = as_a <scalar_int_mode> (info.abi_limb_mode); if (TYPE_PRECISION (type) <= GET_MODE_PRECISION (limb_mode)) { cst = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);