Created attachment 44010 [details] This code demonstrates the problem The attached code when compiled with optimizations in LLVM (I'm using 5.0.0) expands the call inline through the auto variables PerformQuickly and PerformSafely. Adding const solves the issue but GCC should be able to determine that the function pointer can never be modified and inline the function invocations as LLVM is doing.
I should add that without the static storage duration specifier even without const specified, it does inline the function invocation.
The issue is you fail to make PerformQuickly and PerformSafely const and GCC doesn't have local analysis to promote it so and IPA analysis is too late for that since it is also the last inlining point. Slight complication is nested functions and OMP outlining which may refer to these variables. But even the initial cgraph build should be able to figure out the const-ness, no? Workaround: make the vars const.
(In reply to Richard Biener from comment #2) > The issue is you fail to make PerformQuickly and PerformSafely const and GCC > doesn't have local analysis to promote it so and IPA analysis is too late > for that since it is also the last inlining point. > > Slight complication is nested functions and OMP outlining which may refer to > these variables. But even the initial cgraph build should be able to figure > out the const-ness, no? > > Workaround: make the vars const. I stated that const solves the issue in the description. If the auto variables have automatic duration (remove the keyword static), the compiler is able to inline the invocation without the const qualifier. As stated, LLVM (clang++) does inline the invocation even if it has static duration. I would expect this is likely true for any non-const static duration function pointer, not just the case when the auto type specifier is used, but I have not confirmed it.
(In reply to ASA from comment #3) > (In reply to Richard Biener from comment #2) > > The issue is you fail to make PerformQuickly and PerformSafely const and GCC > > doesn't have local analysis to promote it so and IPA analysis is too late > > for that since it is also the last inlining point. > > > > Slight complication is nested functions and OMP outlining which may refer to > > these variables. But even the initial cgraph build should be able to figure > > out the const-ness, no? > > > > Workaround: make the vars const. > > > I stated that const solves the issue in the description. If the auto > variables have automatic duration (remove the keyword static), the compiler > is able to inline the invocation without the const qualifier. As stated, > LLVM (clang++) does inline the invocation even if it has static duration. > > I would expect this is likely true for any non-const static duration > function pointer, not just the case when the auto type specifier is used, > but I have not confirmed it. But it is the case for any non-const static duration function pointer. This has nothing to do with 'auto', changing the testcase to static inline bool RunTest( void ) { static bool (*PerformQuickly)(int &, const int &) = Perform< SumQuickly >; static bool (*PerformSafely)(int &, const int &) = Perform< SumSafely >; int i = 0; return PerformQuickly( i, 1 ) && !PerformSafely( i, INT_MAX ); } has no effect.
> > I would expect this is likely true for any non-const static duration > > function pointer, not just the case when the auto type specifier is used, > > but I have not confirmed it. > > But it is the case for any non-const static duration function pointer. > This has nothing to do with 'auto', changing the testcase to > > static inline bool > RunTest( void ) { > static bool (*PerformQuickly)(int &, const int &) = Perform< SumQuickly > >; > static bool (*PerformSafely)(int &, const int &) = Perform< SumSafely >; > int i = 0; > return PerformQuickly( i, 1 ) && !PerformSafely( i, INT_MAX ); > } > > has no effect. Which is exactly what I stated I would have expected. Thank you for the confirmation of that expectation, though very oddly worded.
For some reason CCP1 is not able to do it but CCP2 can; though CCP2 is after inlining so IPA so nothing is done with respect to inlining and such. CCP1 dump: Visiting statement: # VUSE <.MEM_13> PerformSafely.3_3 = _ZZL7RunTestvE13PerformSafelyD.2380; which is likely CONSTANT Lattice value changed to VARYING. Adding SSA edges to worklist. CCP2 dump: Visiting statement: # VUSE <.MEM_8> # PT = nonlocal escaped null PerformSafely.2_2 = _ZZ7RunTestvE13PerformSafelyD.2379; which is likely CONSTANT Lattice value changed to CONSTANT _Z7PerformIL_ZL9SumSafelyRiRKiEEbS0_S2_D.2380. Adding SSA edges to worklist. marking stmt to be not simulated again
CCP2 is after IPA promoting the variable 'const', but CCP2 is too late for inlining (and IPA opts don't do value-numbering to discover the indirect inline target).