Skip to content

Conversation

chiragramani
Copy link

@chiragramani chiragramani commented Sep 17, 2025

This PR introduces three new instrumentation flags and plumbs them through to IRGen:

  1. -ir-profile-generate - enable IR-level instrumentation.
  2. -cs-profile-generate - enable context-sensitive IR-level instrumentation.
  3. -ir-profile-use - IR-level PGO input profdata file to enable profile-guided optimization (both IRPGO and CSIRPGO)

Context: https://forums.swift.org/t/ir-level-pgo-instrumentation-in-swift/82123

Swift-driver PR: swiftlang/swift-driver#1992

Tests and validation:
This PR includes ir level verification tests, also checks few edge-cases when -ir-profile-use supplied profile is either missing or is an invalid IR profile.

However, for argument validation, linking, and generating IR profiles that can later be consumed by -cs-profile-generate, I’ll need corresponding swift-driver changes. Those changes are being tracked in swiftlang/swift-driver#1992

The plan is:

  1. Land this PR first.
  2. Then update swift-driver with the required changes.
  3. Then add the remaining set of test cases in this repo.

Open Questions (Reviewer Input Requested)

1. Naming:
Is -ir-profile-generate a good flag name?
-cs-profile-generate pairs nicely with Clang’s -fcs-profile-generate. However, -ir-profile-generate feels closer to Clang's -fprofile-generate but -profile-generate already exists in Swift as a frontend level and not IR level. Should it stay as is, or is there a clearer alternative?

2. Missing LLVM runtime + Blocked on tests

At the moment, I haven’t added tests because they currently fail locally due to missing LLVM runtime symbols. This is expected, since the required runtime linking through libclang APIs will be handled in swift-driver(swiftlang/swift-driver#1992). However, swift-driver itself depends on these new options being available in Swift.

Does that mean the correct order of the PRs should be the following?

1. Create a PR in Swift that introduces just the new options, and land that PR first.
2. Land the corresponding swift-driver PR to handle runtime linking,
3. Then follow up with a Swift PR adding the full functionality and tests?

~~

@aschwaighofer
Copy link
Contributor

I don't have a strong opinion on naming. My feeling is that context sensitive and non context sensitive LLVM IR level instrumentation should follow a similar pattern to make clear they are related. We have already deviated from clang's naming scheme -- that is, clang's fprofile-generate(llvm ir level instrumentation) is not equal swift's -profile-generate ("AST" based insertion of instrumentation). -ir-profile-generate and -cs-ir-profile-generate would make it clearer that they are related.

@aschwaighofer
Copy link
Contributor

Does that mean the correct order of the PRs should be the following?
Create a PR in Swift that introduces just the new options, and land that PR first.
Land the corresponding swift-driver PR to handle runtime linking,
Then follow up with a Swift PR adding the full functionality and tests?

You could add LLVM IR level tests that test the functionality of this PR (look at most tests in test/IRGen) and merge this PR first. Then you could land the corresponding swift-driver PR. Then you could at a swiftlang/swift repo commit to add execution tests.

// RUN: %target-swift-frontend -ir-profile-generate -emit-ir %s | %FileCheck %s

// CHECK: define @mangleNameOfA
// CHECK: the llvm ir you expect to see (calls to profile runtime function/intrinsics)
public func a(_ cond: Bool) {
  if cond {
     b()
  } else {
    c()
  }
}

Preferably, you would as .sil tests rather than .swift tests as that would make them more "stable".

That would look something like the following (I ran swiftc -emit-sil test.swift and edited the output a little bit):

// RUN: %target-swift-frontend -ir-profile-generate -emit-ir %s | %FileCheck %s

sil_stage canonical

import Builtin
import Swift
import SwiftShims

sil @b : $@convention(thin) () -> ()

sil @c : $@convention(thin) () -> ()

// CHECK: define {{.*}} void @a
// CHECK: the llvm ir you expect to see (calls to profile runtime function/intrinsics)

sil @a : $@convention(thin) (Bool) -> () {
bb0(%0 : $Bool):
  %2 = struct_extract %0, #Bool._value
  cond_br %2, bb1, bb2

bb1:
  // function_ref b()
  %4 = function_ref @b : $@convention(thin) () -> ()
  %5 = apply %4() : $@convention(thin) () -> ()
  br bb3 

bb2:
  // function_ref c()
  %7 = function_ref @c: $@convention(thin) () -> ()
  %8 = apply %7() : $@convention(thin) () -> ()
  br bb3 

bb3:
  %10 = tuple ()
  return %10
}

@chiragramani
Copy link
Author

Preferably, you would as .sil tests rather than .swift tests as that would make them more "stable".

You could add LLVM IR level tests that test the functionality of this PR (look at most tests in test/IRGen) and merge this PR first. Then you could land the corresponding swift-driver PR. Then you could at a swiftlang/swift repo commit to add execution tests.

Thanks for the guidance here, it definitely helped me understand things better!

Added tests
@chiragramani
Copy link
Author

Hi @aschwaighofer, I've added the tests based on your suggestions. When you have a moment, could you please review the changes and share your feedback? Thanks

@chiragramani
Copy link
Author

@kavon would love to hear your perspective on this PR as well, when you have a moment.

@chiragramani
Copy link
Author

@swift-ci test

@chiragramani
Copy link
Author

Hey @aschwaighofer, would it be possible for you to tag or add the respective POCs who could help review this PR please? I’d really appreciate it.

@drodriguez
Copy link
Contributor

@swift-ci please test

@chiragramani
Copy link
Author

@swift-ci please test

@drodriguez
Copy link
Contributor

@swift-ci please test

@drodriguez
Copy link
Contributor

please test

@chiragramani sadly you need a special role for starting the tests. The details are in https://www.swift.org/contributing/#member (still some hoops to jump through, but easier than before)

@aschwaighofer
Copy link
Contributor

@swift-ci test

Copy link
Contributor

@aschwaighofer aschwaighofer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@drodriguez
Copy link
Contributor

@swift-ci please test

@chiragramani
Copy link
Author

chiragramani commented Oct 1, 2025

@chiragramani sadly you need a special role for starting the tests. The details are in https://www.swift.org/contributing/#member (still some hoops to jump through, but easier than before)

Really appreciate you helping trigger the tests and sharing the process. I’ll send in a request soon.

@aschwaighofer
Copy link
Contributor

@swift-ci please test

@chiragramani
Copy link
Author

Swift Test Linux Platform — Failed

I noticed that the above job has failed, but I’m unable to open the link for the Linux job details. Could someone with access kindly share the logs or error message? Thanks

@drodriguez
Copy link
Contributor

ci.swift.org seems to give me time-outs. It might be having a bad day.

@chiragramani
Copy link
Author

ci.swift.org seems to give me time-outs. It might be having a bad day.

Thanks for checking. It looks like the link works now, but the error seems related to a CI infra issue (agent removal). Would it be possible to retry the job?

@drodriguez
Copy link
Contributor

@swift-ci please test Linux platform

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants