Re: COBOL: Hoping for insight with middle-end computation time.

Richard Biener via Gcc <[email protected]>
Newsgroups gmane.comp.gcc.devel
Message-ID <CAFiYyc2zQZx-R_ynySAEMS1juRPeviNv4pBTbYP-ahKfaqiq-w@mail.gmail.com>
On Sat, Mar 21, 2026 at 10:25 AM Jakub Jelinek <[email protected]> wrote:
>
> On Fri, Mar 20, 2026 at 10:17:50PM -0500, Robert Dubner wrote:
> > 10,000 repeats of that code in the C++ program compiles in 1.36 seconds.
> > 20,000 repeats                                             3.18 seconds.
> > 40,000 repeats                                             7.92 seconds.
> >
> > 10,000 repeats in the COBOL program                       16.76 seconds.
> > 20,000 repeats in the COBOL program                       97.40 seconds.
> > 10,000 repeats in the COBOL program                      551.56 seconds.
>
> Perhaps also look at -fdump-tree-ssa-vops dump differences too, that will
> make it clearer if there aren't differences in what is TREE_ADDRESSABLE and
> what is not, or what is a global var and what could have been rewritten into
> SSA form.

Looking at -gimple there's a single scope block with try/finally and all
clobbers in the finally block.  I suppose given that cobol emits a single
function only we could elide the end-of-function clobbers for it.

The D.nnn are registers, not memory AFAICS.

What's a bit odd is that there seems to be global variables
called __gg__treeplet_{1,2,3}{f,o,s} where we store addresses
of aaa, etc, into:

      __gg__treeplet_1f.58_103 = __gg__treeplet_1f;
      _104 = 0;
      _105 = __gg__treeplet_1f.58_103 + _104;
      *_105 = &aaa.73.0;

and the actual computation happens in

      __gg__add_fixed_phase1 (2, 2, 0, 0,
__gg__arithmetic_rounds.64_121, 0, &D.321);

I assume which seems to indicate that argumets get passed via global variables
rather than formal arguments.  That might in practice help code
generation at -O0
though.

I suspect it's simply very many life variables (the D.nnnn) that need stack
space and make the x86 stack var analysis code slow.

I do wonder about

      _intermediate__stack327_329.0.0.data = &_stack327_data_330.0;
      _intermediate__stack327_329.0.0.capacity = 16;
      _intermediate__stack327_329.0.0.allocated = 16;
      _intermediate__stack327_329.0.0.offset = 0;
      _intermediate__stack327_329.0.0.name = &"_stack327"[0];
      _intermediate__stack327_329.0.0.picture = &""[0];
      _intermediate__stack327_329.0.0.initial = 0B;
      _intermediate__stack327_329.0.0.parent = 0B;
      _intermediate__stack327_329.0.0.occurs_lower = 0;
      _intermediate__stack327_329.0.0.occurs_upper = 0;
      _intermediate__stack327_329.0.0.attr = 4160;
      _intermediate__stack327_329.0.0.type = 6;
      _intermediate__stack327_329.0.0.level = 0;
      _intermediate__stack327_329.0.0.digits = 37;
      _intermediate__stack327_329.0.0.rdigits = 0;
      _intermediate__stack327_329.0.0.encoding = 1;
      _intermediate__stack327_329.0.0.alphabet = 0;
      __gg__initialize_variable_clean (&_intermediate__stack327_329.0.0, 32768);

so why do we have inline initialization of the variable but also a call to
apparently do sth similar?  That seems to be abstraction that is at least
oddly designed.

With all of the above it would help if those temporary variables like
_intermediate__stack327_329.0.0 or the D.nnn would be wrapped
in their own scope block as to limit their lifetime given at least
the stack ones are address-taken.  So in C terms, have

  {
    compute ddd = aaa + bbb
 }
 {
    compute ddd = aaa + bbb
  }
...

so the frontend emits those temporaries into its own scope wrapping
the computes to limit their lifetime.  Scopes in GENERIC are BLOCKs
and in the IL you'd have BIND_EXPRs.

Richard.

>
>         Jakub
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.