diff options
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. |