Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IRGen: Default to clang's frame pointer elimination settings #31986

Merged

Conversation

aschwaighofer
Copy link
Member

@aschwaighofer aschwaighofer commented May 22, 2020

Clang provides options to override that default value.
These options are accessible via the -Xcc flag.

Some Swift functions explicitly disable the frame pointer.

The clang options will not override those.

@aschwaighofer
Copy link
Member Author

@swift-ci Please test

@aschwaighofer aschwaighofer marked this pull request as draft May 22, 2020 23:37
@swift-ci
Copy link
Collaborator

Build failed
Swift Test Linux Platform
Git Sha - cf280e8fe8fca53386c26036c79e67466fe530d0

@swift-ci
Copy link
Collaborator

Build failed
Swift Test OS X Platform
Git Sha - cf280e8fe8fca53386c26036c79e67466fe530d0

@aschwaighofer
Copy link
Member Author

@swift-ci Please test

@swift-ci
Copy link
Collaborator

Build failed
Swift Test OS X Platform
Git Sha - cf280e8fe8fca53386c26036c79e67466fe530d0

@swift-ci
Copy link
Collaborator

Build failed
Swift Test Linux Platform
Git Sha - cf280e8fe8fca53386c26036c79e67466fe530d0

@aschwaighofer aschwaighofer marked this pull request as ready for review May 23, 2020 13:16
@aschwaighofer aschwaighofer requested a review from atrick May 28, 2020 14:39
Copy link
Member

@atrick atrick left a comment

Choose a reason for hiding this comment

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

This covers the important issues

  • inherit Clang's default
  • Make IRGen readable.

I don't know for sure what we should be doing for the driver flags, or whether they should be overriding IRGen's decisions. Whatever we do I just want to know that it was intentional.

It seems like the only thing that should override IRGen's decision is if we have framePointer==All. Changing leaf FP's should not override them right?

If only the leaf flag is used, we either need to assume a clang default or ask clang for the default. Either way, I think that should be clearly commented because it's not obvious that changing leaf-fp will override non-leaf fp behavior.

It's very strange that -no-omit-frame-pointer and -no-omit-frame-pointer-leaf are actually the same option.

I think we have the option of either copying clang's current logic, or handling the full matrix of possibilities. This case is especially confusing

-omit-frame-pointer + -no-omit-frame-pointer-leaf

bool omitLeafFP = Args.hasArg(options::OPT_omit_frame_pointer_leaf);
bool requiresAllFP = Args.hasArg(options::OPT_no_omit_frame_pointer);

// If the user explicitly requests -omit-frame-pointer do we emit no
Copy link
Member

Choose a reason for hiding this comment

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

/s/do//

/// Determine which frame pointer setting to use. Per default if no flag is set
/// we will use clang's default setting. This case is denoted by returning None.
static Optional<clang::CodeGenOptions::FramePointerKind>
determineFramePointerUse(ArgList &Args) {
Copy link
Member

Choose a reason for hiding this comment

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

Does this follow the same logic in the clang driver? I didn't check.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes mostly.

if (omitAllFP)
return clang::CodeGenOptions::FramePointerKind::None;

// If the user explicitly requests -omit-frame-pointer do we emit no
Copy link
Member

Choose a reason for hiding this comment

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

s/pointer/pointer_leaf/
s/do//

if (omitLeafFP)
return clang::CodeGenOptions::FramePointerKind::NonLeaf;

// Otherwise, if the users requires leaf frame pointer we emit all frame
Copy link
Member

Choose a reason for hiding this comment

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

s/users/user/

// If the user explicitly requests -omit-frame-pointer do we emit no
// frame pointers.
if (omitAllFP)
return clang::CodeGenOptions::FramePointerKind::None;
Copy link
Member

Choose a reason for hiding this comment

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

What if no_omit_frame_pointer_leaf is set? then shouldn't it be NonLeaf?

Copy link
Member Author

Choose a reason for hiding this comment

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

omit_frame_pointer + no_omit_frame_pointer_leaf means omitting the frame pointer in all frames except for leaf frames.

frame-pointer="non-leaf" means to have a frame pointer only in non-leaf functions.

LLVM has no way of expressing this combination. So omit-frame-pointer overriding everything else makes sense.

This is also what clang does, it calls this combination invalid: https://github.com/apple/llvm-project/blob/apple/master/clang/lib/Driver/ToolChains/Clang.cpp#L594

// If the user explicitly requests -omit-frame-pointer do we emit no
// frame pointers.
if (omitLeafFP)
return clang::CodeGenOptions::FramePointerKind::NonLeaf;
Copy link
Member

Choose a reason for hiding this comment

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

Assumes a default of no_omit_frame_pointer. I don't know if that's intended.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes this is intended.

I don't know what case you are concerned about?

In this branch we can only have:
-fomit-frame-pointer-leaf in which case frame-pointer="non-leaf' is the right thing
-fno-omit-frame-pointer -fomit-frame-pointer-leaf in which case frame-pointer="non-leaf' is also right thing
We can't have
-fomit-frame-pointer because that is already checked at this point.

If clang defaults to none then we will override this here.

// Otherwise, if the users requires leaf frame pointer we emit all frame
// pointers.
if (requiresLeafFramePointers)
return clang::CodeGenOptions::FramePointerKind::All;
Copy link
Member

Choose a reason for hiding this comment

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

Assumes a default of no_omit_frame_pointer. I don't know if that's intended.
What if we also have requiresFP?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is intended.

In the branch we can only have:
-fno-omit-frame-pointer-leaf in which case frame-pointer="all" makes sense
-fno-omit-frame-pointer-leaf -fno-omit-frame-pointer in which case "all" also makes sense.

@aschwaighofer
Copy link
Member Author

aschwaighofer commented May 28, 2020

It's very strange that -no-omit-frame-pointer and -no-omit-frame-pointer-leaf are actually the same option.

It is a reasonable consequence from the fact that we can't represent frame-pointer = "only-leaf".

default=all
-no-omit-fp = all
-no-omit-fp-leaf = all
default = none
-no-omit-fp = all
-no-omit-fp-leaf = all

@aschwaighofer
Copy link
Member Author

aschwaighofer commented May 28, 2020

If only the leaf flag is used, we either need to assume a clang default or ask clang for the default. Either way, I think that should be clearly commented because it's not obvious that changing leaf-fp will override non-leaf fp behavior.

You are concerned about the case with a clang default of frame-pointer=none and -omit-frame-pointer-leaf we get frame-pointer=non-leaf instead of staying in none.

I see. I find it more confusing that I have to know what the default is to gauge the outcome but I see your point.

@aschwaighofer
Copy link
Member Author

We can get around all of this by just letting clang options set whatever is wanted and don't have to add swift options for this i.e it is possible to just specify -Xcc -fomit-frame-pointer.

@aschwaighofer
Copy link
Member Author

@swift-ci Please test

@swift-ci
Copy link
Collaborator

Build failed
Swift Test Linux Platform
Git Sha - e19ce39cf6a99ac985f41a81287dc70b95fec254

@swift-ci
Copy link
Collaborator

Build failed
Swift Test OS X Platform
Git Sha - e19ce39cf6a99ac985f41a81287dc70b95fec254

Clang provides options to override that default value.
These options are accessible via the -Xcc flag.

Some Swift functions explicitly disable the frame pointer.

The clang options will not override those.
@aschwaighofer
Copy link
Member Author

@swift-ci Please test

@swift-ci
Copy link
Collaborator

Build failed
Swift Test OS X Platform
Git Sha - d0184dec059d37ca75a7ea48e6e4474cef8e8690

@swift-ci
Copy link
Collaborator

Build failed
Swift Test Linux Platform
Git Sha - d0184dec059d37ca75a7ea48e6e4474cef8e8690

@aschwaighofer
Copy link
Member Author

@swift-ci please test linux

@swift-ci
Copy link
Collaborator

Build failed
Swift Test Linux Platform
Git Sha - 20f4ef9

@aschwaighofer
Copy link
Member Author

@swift-ci Please smoke test linux

@aschwaighofer
Copy link
Member Author

@swift-ci Please test linux

@swift-ci
Copy link
Collaborator

swift-ci commented Jun 2, 2020

Build failed
Swift Test Linux Platform
Git Sha - 20f4ef9

@aschwaighofer
Copy link
Member Author

@swift-ci Please clean test linux

@aschwaighofer aschwaighofer merged commit 3f903b4 into apple:master Jun 3, 2020
@compnerd
Copy link
Collaborator

compnerd commented Jun 3, 2020

This seems to have regressed the windows builders: https://ci-external.swift.org/job/oss-swift-windows-x86_64-vs2019/1563/consoleText

@aschwaighofer
Copy link
Member Author

@compnerd Swift now behaves the same as clang does wrt to frame pointers. It is possible that that means on windows it behaves slightly differently to what the test expects. Let me see.

@aschwaighofer
Copy link
Member Author

#32162

drodriguez added a commit to drodriguez/swift that referenced this pull request Aug 10, 2020
…S2017.

In order to generate stack traces when exceptions happen, it seems that VS2017 needs of frame pointers in some of the functions. This recovers a small override that was present up to the introduction of apple#31986 but only for VS2017.

Without this change crash-in-user-code.swift test fails (because the output doesn't include the stack trace as provided by LLVM exception stack trace capturing), but the test passes with it. In order to not change VS2019 (or other compilers), which succeed at the test already, the fix is gated to only compile in VS2017.
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.

None yet

4 participants