On Wed, Apr 02, 2025 at 09:22:54PM +0100, Richard Sandiford wrote: > I'm not sure the _1 template is worth it. wi::to_widest -> > const wide_int_ref & should be very cheap (it doesn't for example > construct a widest_int), so I think native_encode_int could call > native_encode_wide_int.
You're right, I was afraid it would construct something expensive. Looking at --enable-checking=release build, I see native_encode_int is inlined into native_encode_expr and does MEM[(struct wide_int_ref_storage *)&D.261480] ={v} {CLOBBER}; _30 = *expr_10.base.u.int_length.extended; _31 = (unsigned int) _30; _32 = &expr_10->int_cst.val[0]; MEM <const long int *> [(struct wide_int_ref_storage *)&D.261480] = _32; MEM <unsigned int> [(struct wide_int_ref_storage *)&D.261480 + 8B] = _31; MEM <unsigned int> [(struct wide_int_ref_storage *)&D.261480 + 12B] = 131072; _33 = expr_10->typed.type; _34 = native_encode_wide_int (_33, &D.261480, ptr_11, len_12, off_8); there in optimized dump, which is temp.val = &TREE_INT_CST_ELT (expr, 0); temp.len = TREE_INT_CST_EXT_NUNITS (expr); temp.precision = WIDEST_INT_MAX_PRECISION; so that seems fairly cheap. So I'll retest: 2025-04-02 Jakub Jelinek <ja...@redhat.com> PR cobol/119242 gcc/ * fold-const.h (native_encode_wide_int): Declare. * fold-const.cc (native_encode_wide_int): New function. (native_encode_int): Use it. gcc/cobol/ * genapi.cc (binary_initial_from_float128): Use native_encode_wide_int. --- gcc/fold-const.h.jj 2025-04-02 19:26:55.300272195 +0200 +++ gcc/fold-const.h 2025-04-02 22:36:19.066641205 +0200 @@ -35,6 +35,8 @@ extern bool folding_cxx_constexpr; extern int native_encode_expr (const_tree, unsigned char *, int, int off = -1); extern int native_encode_initializer (tree, unsigned char *, int, int off = -1, unsigned char * = nullptr); +extern int native_encode_wide_int (tree, const wide_int_ref &, + unsigned char *, int, int off = -1); extern int native_encode_real (scalar_float_mode, const REAL_VALUE_TYPE *, unsigned char *, int, int off = -1); extern tree native_interpret_expr (tree, const unsigned char *, int); --- gcc/fold-const.cc.jj 2025-04-02 19:26:55.300272195 +0200 +++ gcc/fold-const.cc 2025-04-02 22:39:04.932113465 +0200 @@ -7465,15 +7465,16 @@ fold_plusminus_mult_expr (location_t loc return NULL_TREE; } -/* Subroutine of native_encode_expr. Encode the INTEGER_CST - specified by EXPR into the buffer PTR of length LEN bytes. + +/* Subroutine of native_encode_int. Encode the integer VAL with type TYPE + into the buffer PTR of length LEN bytes. Return the number of bytes placed in the buffer, or zero upon failure. */ -static int -native_encode_int (const_tree expr, unsigned char *ptr, int len, int off) +int +native_encode_wide_int (tree type, const wide_int_ref &val, + unsigned char *ptr, int len, int off) { - tree type = TREE_TYPE (expr); int total_bytes; if (TREE_CODE (type) == BITINT_TYPE) { @@ -7516,7 +7517,7 @@ native_encode_int (const_tree expr, unsi int bitpos = byte * BITS_PER_UNIT; /* Extend EXPR according to TYPE_SIGN if the precision isn't a whole number of bytes. */ - value = wi::extract_uhwi (wi::to_widest (expr), bitpos, BITS_PER_UNIT); + value = wi::extract_uhwi (val, bitpos, BITS_PER_UNIT); if (total_bytes > UNITS_PER_WORD) { @@ -7537,6 +7538,18 @@ native_encode_int (const_tree expr, unsi return MIN (len, total_bytes - off); } +/* Subroutine of native_encode_expr. Encode the INTEGER_CST + specified by EXPR into the buffer PTR of length LEN bytes. + Return the number of bytes placed in the buffer, or zero + upon failure. */ + +static int +native_encode_int (const_tree expr, unsigned char *ptr, int len, int off) +{ + return native_encode_wide_int (TREE_TYPE (expr), wi::to_widest (expr), + ptr, len, off); +} + /* Subroutine of native_encode_expr. Encode the FIXED_CST specified by EXPR into the buffer PTR of length LEN bytes. --- gcc/cobol/genapi.cc.jj 2025-04-02 19:26:55.265272660 +0200 +++ gcc/cobol/genapi.cc 2025-04-02 22:36:19.071641137 +0200 @@ -15216,25 +15216,19 @@ binary_initial_from_float128(cbl_field_t FIXED_WIDE_INT(128) i = FIXED_WIDE_INT(128)::from (real_to_integer (&value, &fail, 128), SIGNED); - /* ??? Use native_encode_* below. */ retval = (char *)xmalloc(field->data.capacity); switch(field->data.capacity) { + tree type; case 1: - *(signed char *)retval = (signed char)i.slow (); - break; case 2: - *(signed short *)retval = (signed short)i.slow (); - break; case 4: - *(signed int *)retval = (signed int)i.slow (); - break; case 8: - *(signed long *)retval = (signed long)i.slow (); - break; case 16: - *(unsigned long *)retval = (unsigned long)i.ulow (); - *((signed long *)retval + 1) = (signed long)i.shigh (); + type = build_nonstandard_integer_type (field->data.capacity + * BITS_PER_UNIT, 0); + native_encode_wide_int (type, i, (unsigned char *)retval, + field->data.capacity); break; default: fprintf(stderr, Jakub