> -----Original Message-----
> From: Richard Biener <[email protected]>
> Sent: Saturday, March 21, 2026 03:33
> To: Robert Dubner <[email protected]>
> Cc: David Malcolm <[email protected]>; H. J. Lu <[email protected]>;
> [email protected]; James K. Lowden <[email protected]>
> Subject: Re: COBOL: Hoping for insight with middle-end computation time.
>
>
>
> > Am 21.03.2026 um 04:17 schrieb Robert Dubner <[email protected]>:
> >
> > Let's try another line of query.
> >
> > Maybe here are things I should be doing that I am not, or things that I
> > am
> > doing that I shouldn't.
> >
> > As described earlier, I created a version of the gcobol/cobol1 compiler
> > that
> > produced a stripped-down GENERIC that resulted in this repeated pattern
> > in
> > the -fdump-tree-original output.
> >
> > _intermediate__stack1_3.0.0.data = &_stack1_data_17.0;
> > _intermediate__stack1_3.0.0.capacity = 16;
> > _intermediate__stack1_3.0.0.allocated = 16;
> > _intermediate__stack1_3.0.0.offset = 0;
> > _intermediate__stack1_3.0.0.name = &"_stack1"[0];
> > _intermediate__stack1_3.0.0.picture = &""[0];
> > _intermediate__stack1_3.0.0.initial = 0B;
> > _intermediate__stack1_3.0.0.parent = 0B;
> > _intermediate__stack1_3.0.0.occurs_lower = 0;
> > _intermediate__stack1_3.0.0.occurs_upper = 0;
> > _intermediate__stack1_3.0.0.attr = 4160;
> > _intermediate__stack1_3.0.0.type = 6;
> > _intermediate__stack1_3.0.0.level = 0;
> > _intermediate__stack1_3.0.0.digits = 37;
> > _intermediate__stack1_3.0.0.rdigits = 0;
> > _intermediate__stack1_3.0.0.encoding = 1;
> > _intermediate__stack1_3.0.0.alphabet = 0;
> > D.311 = 0;
> > D.312 = 0;
> > _13 = D.311 & 18;
> > if (_13 != 0) goto <D.369>; else goto <D.370>;
> > <D.369>:
> > goto <D.371>;
> > <D.370>:
> > D.314 = 0;
> > ..pa_erf.19_14 = ..pa_erf;
> > D.312 = D.312 | ..pa_erf.19_14;
> > if (D.312 != 0) goto <D.373>; else goto <D.374>;
> > <D.373>:
> > goto <D.375>;
> > <D.374>:
> > <D.375>:
> > <D.371>:
> >
> > I have experimented with a C program until I came up with the same
> > .gimple:
> >
> > typedef struct strct
> > {
> > int a0; int a1; int a2; int a3; int a4; int a5; int a6; int a7; int a8;
> > int a9;
> > }strct;
> >
> > int
> > main(int argc, char **argv)
> > {
> > strct strc0{0,1,2,3,4,5,6,7,8,9};
> > int x0=0;
> > int y0=0;
> > int z0;
> > y0=x0&18;
> > if(y0!=0)
> > {}
> > else
> > {
> > z0=z0|pa_erf;
> > if(z0!=0)
> > {}
> > }
> > }
> >
> > Here is a side-by-side comparison of the repetitive .gimple generated by
> > the
> > two compilations:
> >
> > From the gcobol compilation From the xg++
> > compilation
>
> > -------- -------------------------
> > D.322 = 0; x3 = 0;
> > D.323 = 0; y3 = 0;
> > _17 = D.322 & 18; y3 = x3 & 18;
> > if (_17 != 0) goto <D.385>; else goto <D.386>; if (y3 != 0) goto
> > <D.3063>;
> > else goto <D.3064>;
> > <D.385>: <D.3063>:
> > goto <D.387>; goto <D.3065>;
> > <D.386>: <D.3064>:
> > D.324 = 0;
> > ..pa_erf.25_18 = ..pa_erf; pa_erf.3_4 = pa_erf;
> > D.323 = D.323 | ..pa_erf.25_18; z3 = z3 | pa_erf.3_4;
> > if (D.323 != 0) goto <D.389>; else goto <D.390>; if (z3 != 0) goto
> > <D.3066>;
> > else goto <D.3067>;
> > <D.389>: <D.3066>:
> > goto <D.391>; goto <D.3068>;
> > <D.390>: <D.3067>:
> > <D.391>: <D.3068>:
> > <D.387>: <D.3065>:
> > You can see they are essentially identical.
>
> Could it be your D.324 is global? Comparing the GIMPLE would tell.
> Possibly
> also BIND_EXPRs matter. -blocks dumps (some) also dump the scope tree.
>
> > However!
> >
> > 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.
> >
> > Those times are -O0 compilations from the same build of gcc, invoked in
> > the
> > same ways.
> >
> > So. I am obviously doing something different in gcobol than whatever is
> > happening in xg++.
> >
> > The GENERIC I am creating is apparently about right. So, now I have to
> > ask
> > a question that I probably should have asked years ago:
> >
> > What do I need to do before creating the GENERIC for a function?
> >
> > What do I need to do afterward?
> >
> > Right now I don't think I am doing anything special before generating
> > any
> > GENERIC.
> >
> > At the end of a source code module, I call
> >
> > cgraph_node::finalize_function(function_decl, true);
> >
> > for each function I created in that module.
> >
> > What am I missing? What could I be doing, or not doing, that's causing
> > that
> > N-squared behavior?
>
> I don’t think you are doing anything obviously wrong. With cobol you are
> going
> to have a single large function which is somewhat special and more prone
> to run
> into such bugs where people were lazy and never imagined there’s so large
> data.
> We’ll have to fix those algorithms eventually.
>
> > I am feeling like somebody who has found a car, and figured out how to
> > get
> > it started and get it moving in first gear, but hasn't figured out how
> > to
> > get to any of the higher gears.
>
> There might be things you can do in the frontend to avoid running into
> such
> issues, but at least from the above it’s not obvious what that should be.
>
You folks have been giving me additional lines of investigation to follow,
and I will.
I have a C program and a COBOL program that produce essentially identical
output from -fdump-tree-gimple. I see that the outputs
from -fdump-tree-original are not very much alike:
>From C:
<<cleanup_point struct strctD.2994 strc1D.3033 = {.a0D.2984=0,
.a1D.2985=1, .a2D.2986=2, .a3D.2987=3, .a4D.2988=4, .a5D.2989=5,
.a6D.2990=6, .a7D.2991=7, .a8D.2992=8, .a9D.2993=9};>>;
<<cleanup_point intD.9 x1D.3034 = 0;>>;
<<cleanup_point intD.9 y1D.3035 = 0;>>;
intD.9 z1D.3036;
<<cleanup_point <<< Unknown tree: expr_stmt
(voidD.54) (y1D.3035 = x1D.3034 & 18) >>>>>;
if (y1D.3035 != 0)
{
}
else
{
<<cleanup_point <<< Unknown tree: expr_stmt
(voidD.54) (z1D.3036 = z1D.3036 | pa_erfD.2981) >>>>>;
if (z1D.3036 != 0)
{
}
}
And from GCOBOL
struct _intermediate__stack1_3.0.0 = {.data=&_stack1_data_17.0,
.capacity=16, .allocated=16, .offset=0, .name=&"_stack1"[0],
.picture=&""[0], .initial=0B, .parent=0B, .occurs_lower=0, .occurs_upper=0,
.attr=4160, .type=6, .level=0, .digits=37, .rdigits=0, .encoding=1,
.alphabet=0};
unsigned char _stack1_data_17.0[16];
signed int D.311 = 0;
signed int D.312 = 0;
(D.311 & 18) != 0 ? : unsigned long D.314;
D.314 = 0;
D.312 = D.312 | ..pa_erf;
D.312 != 0 ? : ;;
What I don't yet know is what's significant.
I'll keep looking. I'll try not to ask too many questions.
> Richard
>
> >
> >