RE: COBOL: Hoping for insight with middle-end computation time.
Robert Dubner <[email protected]>
| Newsgroups | gmane.comp.gcc.devel |
|---|---|
| Message-ID | <[email protected]> |
> -----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 > > > > >