-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Add PGO support for Clang/LLVM on Unix #10533
Conversation
/cc @ellismg |
pgosupport.cmake
Outdated
endfunction(add_pgo) | ||
|
||
# Detect whether PGO is supported | ||
if(UNIX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other places in coreclr, we have configure.cmake which we use to do configure like tests. Can we do the same thing here? Using check_cxx_source_compiles should let you do this check without having to check in a new file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I wasn't aware of configure.cmake, but it definitely looks like the better approach. Will make the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @ellismg
/cc @janvorli who may be a better reviewer. |
pgosupport.cmake
Outdated
if(CLR_CMAKE_PGO_INSTRUMENT) | ||
if(CLR_CMAKE_PGO_INSTRUMENT) | ||
# Unfortunately LINK_FLAGS_* don't support generator expressions, so we need to use a loop | ||
foreach(Config IN LISTS ConfigList) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems all this machinery of config lists and enumerations through it makes it a bit difficult to read. It seems that putting in just the two following lines for Win32 would be much simpler and would work the same way:
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE /LTCG /GENPROFILE)
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY LINK_FLAGS_RELWITHDEBINFO /LTCG /GENPROFILE)
And for Unix, since makefile generator is not a multi-config generator, you can just use LINK_FLAGS with no build type added:
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY LINK_FLAGS -flto -fuse-ld=gold -fprofile-instr-generate)
Similar for the CLR_CMAKE_PGO_INSTRUMENT case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'm happy to rewrite it without the loop and without the helper function to keep it easier to follow.
Problem with the suggestion for LINK_FLAGS is that even on Unix, we need the flags applied only when configuring for release or relwithdebinfo. If I add it to LINK_FLAGS, they would get applied even during a debug build. Generator expressions would be the go-to answer, but they're not supported for LINK_FLAGS or its variants.
I did some private testing and it seems like cmake does the right thing with LINK_FLAGS_{CONFIG}, even when targeting a single-config build system like make
. The only other approach I can think of is to use target_link_libraries() to add linker flags instead--which do support generator expressions--but they end up putting the flags inside of the "additional libraries" msbuild property, which I didn't like the sight of (it works, but seems like more of a hack to me).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am sorry. I don't know why I have not taken into account the fact that it should be set for optimized builds only for Unix too. So I'd also use the if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELEASE OR UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELWITHDEBINFO)
for Unix like in the other place I've suggested or use double set_property the same way as on Windows, whichever you prefer.
pgosupport.cmake
Outdated
if(WIN32) | ||
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY ${LinkFlagsProperty} "/LTCG /GENPROFILE") | ||
append_prop_strings(${TargetName} LINK_FLAGS_${Config} /LTCG /GENPROFILE) | ||
elseif(UNIX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At all other places, we assume that WIN32 means !UNIX and vice versa and only use WIN32 as a condition. So it would be nice to keep it aligned with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, I'll change it.
pgosupport.cmake
Outdated
foreach(Config IN LISTS ConfigList) | ||
if(WIN32) | ||
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY ${LinkFlagsProperty} "/LTCG /GENPROFILE") | ||
append_prop_strings(${TargetName} LINK_FLAGS_${Config} /LTCG /GENPROFILE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already set the LTCG option in the root CMakeLists.txt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can remove it, but I've already been setting it (on Windows) and it seems harmless to repeat it (PGO doesn't work without LTCG). Do we prefer for /LTCG to be centralized and a hard-fail if missed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I guess it is safer to keep it at both places then.
pgosupport.cmake
Outdated
endforeach(Config) | ||
if(UNIX) | ||
## On Unix we need to pass PGO flags to the compiler as well as the linker | ||
target_compile_options(${TargetName} PRIVATE $<${IsReleaseConfig}:-flto -fprofile-instr-use=${ProfilePath}>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the makefile generator is not a multi-target one, you could just use if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELEASE OR UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELWITHDEBINFO)
, which we do in other places. Unless something leaked in without my knowledge, we use the generator expressions for WIN32 only, which uses a multi-target generator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seemed to work, at least on the version of cmake I was testing, but I'll double-check. Happy to change it if necessary, although if this does work down to the minimum version we officially support, I like the generator approach if only to keep it parallel with WIN32
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My point was that this is the only place that uses generator expressions for non WIN32, so it would be inconsistent with the rest of the stuff. I'd prefer keeping the convention used at other places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, okay. I'll make the change.
pgosupport.cmake
Outdated
endfunction(add_pgo) | ||
|
||
# Detect whether PGO is supported | ||
if(UNIX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @ellismg
* Move HAVE_PGO check into cmake.configure - Also renaming to HAVE_LTO to make intent more clear and reusable * Remove loop over release configs to make code easier to follow * Assume !WIN32 == UNIX (as is the case throughout the repo) * Use plain if condition instead of generator expression on UNIX
@janvorli Thanks for the feedback, made the changes. PTAL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you!
Extend PGO support from VC++ on WIN32 to Clang/LLVM on UNIX as well.
ld.gold
andLLVMgold.so
). To protect against broken support and keep the build flexible across a wider array of distros, attempt to detect whether PGO compilation would work (using cmake'stry_compile()
), and fall back to a non-PGO/non-LTO build if the test fails.