On Fri, Mar 9, 2018 at 11:32 AM, Richard Biener <richard.guent...@gmail.com> wrote: > On Fri, Mar 9, 2018 at 3:33 AM, Fis Trivial <ybbs.da...@hotmail.com> wrote: >> >> I tried to use c++ template to generate code for a personal project, but >> found that the compilation time needed with g++ is much >> slower(exponentially) than with clang++. >> >> This is a code snippet for testing purpose: >> >> #include <iostream> >> >> template <int a, int b> >> struct v : v<a-1, b>, v<a, b-1> >> { >> static int constexpr m = a; >> static int constexpr n = b; >> static int constexpr s = a + b; >> }; >> >> template <int b> >> struct v<1, b> : v<1, b-1> >> { >> static int constexpr m = 1; >> static int constexpr n = b; >> static int constexpr s = b + 1; >> }; >> template <int a> >> struct v<a, 1> : v<a-1, 1> >> { >> static int constexpr m = a; >> static int constexpr n = 1; >> static int constexpr s = a + 1; >> }; >> template <> >> struct v<1, 1> >> { >> static int constexpr m = 1; >> static int constexpr n = 1; >> static int constexpr s = 2; >> }; >> >> int main() >> { >> std::cout << v<7, 12>::s << std::endl; >> std::cout << v<4, 3>::s << std::endl; >> }; >> >> >> Here is the time information: >> --- >> $ time g++ -std=c++11 generate.cc -o bygcc >> >> real 0m39.529s >> user 0m39.418s >> sys 0m0.053s >> >> $ time clang++ -std=c++11 generate.cc -o byclang >> >> real 0m0.310s >> user 0m0.273s >> sys 0m0.024s >> --- >> >> When using greater value, gcc will require exponentially more time to >> compile while the needed time from clang grows linearly. For example, >> replacing the `main` function from above code to: >> >> int main() >> { >> // change 7 to 8 and drop <4, 3> >> std::cout << v<8, 12>::s << std::endl; >> }; >> >> --- >> $ time g++ -std=c++11 generate.cc -o bygcc >> >> real 5m20.755s >> user 5m8.509s >> sys 0m0.260s > > I can confirm this and suggest to open a bugreport.
callgrind shows that propagate_binfo_offsets recursing to self very many times is likely the issue. Your templates build a very deep inheritance chain and it seems that the binfo offset propagation ends up being exponential here. I would have expected that any bases have already correct offsets so we don't need the recursion to bases of bases? Ah, so in this case we have offset of 1 because sizeof is always nonzero. So the issue might just be that BINFO_OFFSET is not relative to the parent? Anyway, Index: gcc/cp/class.c =================================================================== --- gcc/cp/class.c (revision 258380) +++ gcc/cp/class.c (working copy) @@ -5755,6 +5755,9 @@ propagate_binfo_offsets (tree binfo, tre tree primary_binfo; tree base_binfo; + if (integer_zerop (offset)) + return; + /* Update BINFO's offset. */ BINFO_OFFSET (binfo) = fold_convert (sizetype, doens't improve things. We call this functions millions of times creating millions of INTEGER_CSTs. Can BINFO_OFFSET be non-constant? Richard. >> $ time clang++ -std=c++11 generate.cc -o byclang >> >> real 0m0.314s >> user 0m0.281s >> sys 0m0.020s >> --- >> >> >> Just for fun, making the template parameter to 128: >> --- >> $ time g++ -std=c++11 generate.cc -o bygcc >> ... not gonna happen :). >> >> $ time clang++ -std=c++11 generate.cc -o byclang >> >> real 0m18.549s >> user 0m18.410s >> sys 0m0.066s >> --- >> >> >> I am currently running Fedora 27 with following version of gcc and >> clang: >> >> $ g++ --version >> g++ (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5) >> Copyright (C) 2017 Free Software Foundation, Inc. >> This is free software; see the source for copying conditions. There is NO >> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. >> >> $ clang++ --version >> clang version 5.0.1 (tags/RELEASE_501/final) >> Target: x86_64-unknown-linux-gnu >> Thread model: posix >> InstalledDir: /usr/bin