Bug 101064 - long compile time in var_tracking for Go package
Summary: long compile time in var_tracking for Go package
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 12.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: compile-time-hog
Depends on:
Blocks:
 
Reported: 2021-06-14 13:01 UTC by Than McIntosh
Modified: 2021-06-29 19:00 UTC (History)
1 user (show)

See Also:
Host:
Target: x86_64-linux-gnu
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
testcase to reproduce (Go files, some profile reports) (228.41 KB, application/x-compressed-tar)
2021-06-14 13:01 UTC, Than McIntosh
Details
C test case (100.17 KB, text/plain)
2021-06-29 18:56 UTC, Ian Lance Taylor
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Than McIntosh 2021-06-14 13:01:13 UTC
Created attachment 51008 [details]
testcase to reproduce (Go files, some profile reports)

Building the attached Go package with gccgo results in a very long compile time, apparently due to var_tracking. To reproduce, unpack the tar file and build with either:

  A) go clean -cache; go build .

or

  B) gccgo  -c -O2 -g -m64 -fgo-pkgpath=xyz ./aenum.go ./avx_optabs.go


[Note: this issue is first posted on the main Go issue tracker at https://github.com/golang/go/issues/46600; more details there].

This is a fairly modest sized Go package; building it with the main (non-gcc) Go compiler takes about a third of a second (user + sys, reported by /bin/time).

For gccgo, building with -O0 takes about a second, but the time taken at -O1 and -O2 are much longer:

  -O1:	   450 seconds
  -O2:     257 seconds

Along with the test case, I am attaching some profiles collected using 'pprof'.

The pass consuming the extra compile time appears to be variable_tracking; from the profiles the problem looks to be related to alias analysis / memory disambiguation.
Comment 1 CVS Commits 2021-06-29 18:01:28 UTC
The master branch has been updated by Ian Lance Taylor <ian@gcc.gnu.org>:

https://gcc.gnu.org/g:8a8a7d332d5d01db5aea7336a36d9fd71a679fb1

commit r12-1913-g8a8a7d332d5d01db5aea7336a36d9fd71a679fb1
Author: Ian Lance Taylor <iant@golang.org>
Date:   Mon Jun 28 16:47:55 2021 -0700

    compiler: in composite literals use temps only for interfaces
    
    For a composite literal we only need to introduce a temporary variable
    if we may be converting to an interface type, so only do it then.
    This saves over 80% of compilation time when using gccgo to compile
    cmd/internal/obj/x86, as the GCC middle-end spends a lot of time
    pointlessly computing interactions between temporary variables.
    
    For PR debug/101064
    For golang/go#46600
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/331513
Comment 2 CVS Commits 2021-06-29 18:01:57 UTC
The releases/gcc-11 branch has been updated by Ian Lance Taylor <ian@gcc.gnu.org>:

https://gcc.gnu.org/g:528ed794016472a209d6cfaa921307f30eee58da

commit r11-8663-g528ed794016472a209d6cfaa921307f30eee58da
Author: Ian Lance Taylor <iant@golang.org>
Date:   Tue Jun 29 11:00:13 2021 -0700

    compiler: in composite literals use temps only for interfaces
    
    For a composite literal we only need to introduce a temporary variable
    if we may be converting to an interface type, so only do it then.
    This saves over 80% of compilation time when using gccgo to compile
    cmd/internal/obj/x86, as the GCC middle-end spends a lot of time
    pointlessly computing interactions between temporary variables.
    
    For PR debug/101064
    For golang/go#46600
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/331513
Comment 3 Ian Lance Taylor 2021-06-29 18:54:56 UTC
I've committed fixes to the Go frontend that speed up this test case significantly by generating fewer temporary variables.
Comment 4 Ian Lance Taylor 2021-06-29 18:56:10 UTC
Created attachment 51086 [details]
C test case
Comment 5 Ian Lance Taylor 2021-06-29 19:00:37 UTC
I have attached a C test case that demonstrates the problem.  The C case may be somewhat worse because I had to use ordinary variables, whereas the Go test case is used compiler-generated temporary variables.

When I compiled the C test case with mainline GCC with "-g -O2" on my laptop the compilation takes 20 minutes, and according to -ftime-report 91% of that time is spent on var-tracking:

 var-tracking dataflow              : 541.98 ( 44%)   0.02 (  2%) 542.26 ( 44%)  1288k (  0%)
 var-tracking emit                  : 575.86 ( 47%)   0.04 (  4%) 576.31 ( 47%)  3125k (  0%)

This test case is, of course, generated code, as is the original Go test case (the generated Go code is https://go.googlesource.com/go/+/refs/heads/master/src/cmd/internal/obj/x86/avx_optabs.go).

The var-tracking pass already has a fast exit for functions with lots of basic blocks.  Perhaps it also needs a fast exit for functions that are very long even if they don't have many basic blocks.