diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-09-06 17:25:49 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-09-06 17:28:24 +0200 |
commit | 4f4fa2501186e43d115238ae938b3df322c9e02a (patch) | |
tree | 175594012bb25f03f599aba0078c082fb98fae81 /gcc/expr.cc | |
parent | 6b96de22d6bcadb45530c1898b264e4738afa4fd (diff) | |
download | gcc-4f4fa2501186e43d115238ae938b3df322c9e02a.zip gcc-4f4fa2501186e43d115238ae938b3df322c9e02a.tar.gz gcc-4f4fa2501186e43d115238ae938b3df322c9e02a.tar.bz2 |
Middle-end _BitInt support [PR102989]
The following patch introduces the middle-end part of the _BitInt
support, a new BITINT_TYPE, handling it where needed, except the lowering
pass and sanitizer support.
2023-09-06 Jakub Jelinek <jakub@redhat.com>
PR c/102989
* tree.def (BITINT_TYPE): New type.
* tree.h (TREE_CHECK6, TREE_NOT_CHECK6): Define.
(NUMERICAL_TYPE_CHECK, INTEGRAL_TYPE_P): Include
BITINT_TYPE.
(BITINT_TYPE_P): Define.
(CONSTRUCTOR_BITFIELD_P): Return true even for BLKmode bit-fields if
they have BITINT_TYPE type.
(tree_check6, tree_not_check6): New inline functions.
(any_integral_type_check): Include BITINT_TYPE.
(build_bitint_type): Declare.
* tree.cc (tree_code_size, wide_int_to_tree_1, cache_integer_cst,
build_zero_cst, type_hash_canon_hash, type_cache_hasher::equal,
type_hash_canon): Handle BITINT_TYPE.
(bitint_type_cache): New variable.
(build_bitint_type): New function.
(signed_or_unsigned_type_for, verify_type_variant, verify_type):
Handle BITINT_TYPE.
(tree_cc_finalize): Free bitint_type_cache.
* builtins.cc (type_to_class): Handle BITINT_TYPE.
(fold_builtin_unordered_cmp): Handle BITINT_TYPE like INTEGER_TYPE.
* cfgexpand.cc (expand_debug_expr): Punt on BLKmode BITINT_TYPE
INTEGER_CSTs.
* convert.cc (convert_to_pointer_1, convert_to_real_1,
convert_to_complex_1): Handle BITINT_TYPE like INTEGER_TYPE.
(convert_to_integer_1): Likewise. For BITINT_TYPE don't check
GET_MODE_PRECISION (TYPE_MODE (type)).
* doc/generic.texi (BITINT_TYPE): Document.
* doc/tm.texi.in (TARGET_C_BITINT_TYPE_INFO): New.
* doc/tm.texi: Regenerated.
* dwarf2out.cc (base_type_die, is_base_type, modified_type_die,
gen_type_die_with_usage): Handle BITINT_TYPE.
(rtl_for_decl_init): Punt on BLKmode BITINT_TYPE INTEGER_CSTs or
handle those which fit into shwi.
* expr.cc (expand_expr_real_1): Define EXTEND_BITINT macro, reduce
to bitfield precision reads from BITINT_TYPE vars, parameters or
memory locations. Expand large/huge BITINT_TYPE INTEGER_CSTs into
memory.
* fold-const.cc (fold_convert_loc, make_range_step): Handle
BITINT_TYPE.
(extract_muldiv_1): For BITINT_TYPE use TYPE_PRECISION rather than
GET_MODE_SIZE (SCALAR_INT_TYPE_MODE).
(native_encode_int, native_interpret_int, native_interpret_expr):
Handle BITINT_TYPE.
* gimple-expr.cc (useless_type_conversion_p): Make BITINT_TYPE
to some other integral type or vice versa conversions non-useless.
* gimple-fold.cc (gimple_fold_builtin_memset): Punt for BITINT_TYPE.
(clear_padding_unit): Mention in comment that _BitInt types don't need
to fit either.
(clear_padding_bitint_needs_padding_p): New function.
(clear_padding_type_may_have_padding_p): Handle BITINT_TYPE.
(clear_padding_type): Likewise.
* internal-fn.cc (expand_mul_overflow): For unsigned non-mode
precision operands force pos_neg? to 1.
(expand_MULBITINT, expand_DIVMODBITINT, expand_FLOATTOBITINT,
expand_BITINTTOFLOAT): New functions.
* internal-fn.def (MULBITINT, DIVMODBITINT, FLOATTOBITINT,
BITINTTOFLOAT): New internal functions.
* internal-fn.h (expand_MULBITINT, expand_DIVMODBITINT,
expand_FLOATTOBITINT, expand_BITINTTOFLOAT): Declare.
* match.pd (non-equality compare simplifications from fold_binary):
Punt if TYPE_MODE (arg1_type) is BLKmode.
* pretty-print.h (pp_wide_int): Handle printing of large precision
wide_ints which would buffer overflow digit_buffer.
* stor-layout.cc (finish_bitfield_representative): For bit-fields
with BITINT_TYPE, prefer representatives with precisions in
multiple of limb precision.
(layout_type): Handle BITINT_TYPE. Handle COMPLEX_TYPE with BLKmode
element type and assert it is BITINT_TYPE.
* target.def (bitint_type_info): New C target hook.
* target.h (struct bitint_info): New type.
* targhooks.cc (default_bitint_type_info): New function.
* targhooks.h (default_bitint_type_info): Declare.
* tree-pretty-print.cc (dump_generic_node): Handle BITINT_TYPE.
Handle printing large wide_ints which would buffer overflow
digit_buffer.
* tree-ssa-sccvn.cc: Include target.h.
(eliminate_dom_walker::eliminate_stmt): Punt for large/huge
BITINT_TYPE.
* tree-switch-conversion.cc (jump_table_cluster::emit): For more than
64-bit BITINT_TYPE subtract low bound from expression and cast to
64-bit integer type both the controlling expression and case labels.
* typeclass.h (enum type_class): Add bitint_type_class enumerator.
* varasm.cc (output_constant): Handle BITINT_TYPE INTEGER_CSTs.
* vr-values.cc (check_for_binary_op_overflow): Use widest2_int rather
than widest_int.
(simplify_using_ranges::simplify_internal_call_using_ranges): Use
unsigned_type_for rather than build_nonstandard_integer_type.
Diffstat (limited to 'gcc/expr.cc')
-rw-r--r-- | gcc/expr.cc | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/gcc/expr.cc b/gcc/expr.cc index 9a37bff..d6b5bd0 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -10650,6 +10650,25 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, tree ssa_name = NULL_TREE; gimple *g; + /* Some ABIs define padding bits in _BitInt uninitialized. Normally, RTL + expansion sign/zero extends integral types with less than mode precision + when reading from bit-fields and after arithmetic operations (see + REDUCE_BIT_FIELD in expand_expr_real_2) and on subsequent loads relies + on those extensions to have been already performed, but because of the + above for _BitInt they need to be sign/zero extended when reading from + locations that could be exposed to ABI boundaries (when loading from + objects in memory, or function arguments, return value). Because we + internally extend after arithmetic operations, we can avoid doing that + when reading from SSA_NAMEs of vars. */ +#define EXTEND_BITINT(expr) \ + ((TREE_CODE (type) == BITINT_TYPE \ + && reduce_bit_field \ + && mode != BLKmode \ + && modifier != EXPAND_MEMORY \ + && modifier != EXPAND_WRITE \ + && modifier != EXPAND_CONST_ADDRESS) \ + ? reduce_to_bit_field_precision ((expr), NULL_RTX, type) : (expr)) + type = TREE_TYPE (exp); mode = TYPE_MODE (type); unsignedp = TYPE_UNSIGNED (type); @@ -10823,6 +10842,13 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, ssa_name = exp; decl_rtl = get_rtx_for_ssa_name (ssa_name); exp = SSA_NAME_VAR (ssa_name); + /* Optimize and avoid to EXTEND_BITINIT doing anything if it is an + SSA_NAME computed within the current function. In such case the + value have been already extended before. While if it is a function + parameter, result or some memory location, we need to be prepared + for some other compiler leaving the bits uninitialized. */ + if (!exp || VAR_P (exp)) + reduce_bit_field = false; goto expand_decl_rtl; case VAR_DECL: @@ -10956,7 +10982,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, temp = expand_misaligned_mem_ref (temp, mode, unsignedp, MEM_ALIGN (temp), NULL_RTX, NULL); - return temp; + return EXTEND_BITINT (temp); } if (exp) @@ -11002,13 +11028,35 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, temp = gen_lowpart_SUBREG (mode, decl_rtl); SUBREG_PROMOTED_VAR_P (temp) = 1; SUBREG_PROMOTED_SET (temp, unsignedp); - return temp; + return EXTEND_BITINT (temp); } - return decl_rtl; + return EXTEND_BITINT (decl_rtl); case INTEGER_CST: { + if (TREE_CODE (type) == BITINT_TYPE) + { + unsigned int prec = TYPE_PRECISION (type); + struct bitint_info info; + gcc_assert (targetm.c.bitint_type_info (prec, &info)); + scalar_int_mode limb_mode + = as_a <scalar_int_mode> (info.limb_mode); + unsigned int limb_prec = GET_MODE_PRECISION (limb_mode); + if (prec > limb_prec) + { + scalar_int_mode arith_mode + = (targetm.scalar_mode_supported_p (TImode) + ? TImode : DImode); + if (prec > GET_MODE_PRECISION (arith_mode)) + { + /* Emit large/huge _BitInt INTEGER_CSTs into memory. */ + exp = tree_output_constant_def (exp); + return expand_expr (exp, target, VOIDmode, modifier); + } + } + } + /* Given that TYPE_PRECISION (type) is not always equal to GET_MODE_PRECISION (TYPE_MODE (type)), we need to extend from the former to the latter according to the signedness of the @@ -11187,7 +11235,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, && align < GET_MODE_ALIGNMENT (mode)) temp = expand_misaligned_mem_ref (temp, mode, unsignedp, align, NULL_RTX, NULL); - return temp; + return EXTEND_BITINT (temp); } case MEM_REF: @@ -11258,7 +11306,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, ? NULL_RTX : target, alt_rtl); if (reverse) temp = flip_storage_order (mode, temp); - return temp; + return EXTEND_BITINT (temp); } case ARRAY_REF: @@ -11810,6 +11858,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, && modifier != EXPAND_WRITE) op0 = flip_storage_order (mode1, op0); + op0 = EXTEND_BITINT (op0); + if (mode == mode1 || mode1 == BLKmode || mode1 == tmode || modifier == EXPAND_CONST_ADDRESS || modifier == EXPAND_INITIALIZER) @@ -12155,6 +12205,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, return expand_expr_real_2 (&ops, target, tmode, modifier); } } +#undef EXTEND_BITINT /* Subroutine of above: reduce EXP to the precision of TYPE (in the signedness of TYPE), possibly returning the result in TARGET. |