We are experimenting with using LLD for iOS builds(PGO and ThinLTO) and want to clarify what’s actually supported when it comes to PGO.
From what I understand, Swift doesn’t currently support context-sensitive PGO (CS-PGO) - only IR-PGO instrumentation (-profile-generate / -profile-use).
So if we pass CS-PGO generation flags (-fcs-profile-generate) to Clang but only -profile-generate to Swift (since Swift doesn’t support CS-PGO), is that considered a valid combination?
Also, are there known issues that would make the community recommend using a specific commit/revision of LLD or Clang that are tested well in production use-cases?
Or are there recommended practices in the community for mixing Swift + Clang code in iOS apps when using PGO, ThinLTO with LLD?
Would love to hear how others are setting this up in production builds (or if people just stick to IR-PGO only for Swift) and what specific flags (Xllvm, Xcc) flags they pass to swiftc
Yes, Swift PGO via -profile-generate is a front-end instrumentation I believe (it injects instrumentation at the SIL level), and isn’t going to work well with Clang’s -f{cs-}profile-generate (I wish these names were more descriptive).
What we want is for Swift to generate LLVM IR, and have LLVM inject instrumented code with -f{cs-}profile-generate. This works fine, but the flags have not been created to support this. You would need to call PGOOptions() in populatePGOOptions() in the same way the Clang does and call TargetMachine->setPGOOption(PGOOpt);.
I think you’ll also need to make sure compiler-rt is linked in.
Thanks, @ellishg! Really appreciate your insights here.
Do you have suggestions on whether this can be done without compiler changes - for example,
what the swiftc flags would look like to forward -fcs-profile-generate down to LLVM/Clang and ensure the emitted IR is instrumented accordingly OR is modifying the toolchain the only way to go
If swiftc allows you to pass llvm flags, there’s probably a way to spell it, but that also gets complicated if you use LTO, since you often need to pass those same flags to the linker. I’d venture that its an OK approach for experimentation, but that its an entirely reasonable request for Swift to add an option for those profile types if they do not.
We would need to modify the toolchain for it to work in general. Although if you use CSIRPGO and either LTO or thinLTO, I think you can get away with just passing -fcs-profile-generate in the link step.
I have these changes that I’m currently exploring: link. Were you referring specifically to these changes, or would additional modifications be needed as well? I’ll be doing some testing, but I’d like to gather all the inputs so we can prepare a PR next week.
I had to make a few additional changes in swift-driver (commit link). With these updates, temporal profiles are now being parsed correctly for Swift.
I’ll continue running more tests and then start a thread on the Swift forums to gather community feedback. In case I’ve missed anything, please feel free to point it out.