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

Reply via email to