-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[LLVM] Refactor Autoupgrade function attributes from Module attributes. #84494
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
[LLVM] Refactor Autoupgrade function attributes from Module attributes. #84494
Conversation
@llvm/pr-subscribers-lld @llvm/pr-subscribers-llvm-ir Author: Dani (DanielKristofKiss) ChangesRefactoring #82763. Caching the module attributes should help. Full diff: https://github.com/llvm/llvm-project/pull/84494.diff 1 Files Affected:
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 25992395e471b3..4c351a69fabf8e 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -5185,62 +5185,39 @@ static bool isModuleAttributeSet(Module &M, const StringRef &ModAttr) {
return Attr && Attr->getZExtValue();
}
-// Copy an attribute from module to the function if exists.
-// First value of the pair is used when the module attribute is not zero
-// the second otherwise.
-static void
-CopyModuleAttributeToFunction(Function &F, StringRef FnAttrName,
- StringRef ModAttrName,
- std::pair<StringRef, StringRef> Values) {
- if (F.hasFnAttribute(FnAttrName))
- return;
- F.addFnAttr(FnAttrName, isModuleAttributeSet(*F.getParent(), ModAttrName)
- ? Values.first
- : Values.second);
-}
-
-// Copy a boolean attribute from module to the function if exists.
-// Module attribute treated false if zero otherwise true.
-static void CopyModuleAttributeToFunction(Function &F, StringRef AttrName) {
- CopyModuleAttributeToFunction(
- F, AttrName, AttrName,
- std::make_pair<StringRef, StringRef>("true", "false"));
-}
-
-// Copy an attribute from module to the function if exists.
-// First value of the pair is used when the module attribute is not zero
-// the second otherwise.
-static void
-CopyModuleAttributeToFunction(Function &F, StringRef AttrName,
- std::pair<StringRef, StringRef> Values) {
- CopyModuleAttributeToFunction(F, AttrName, AttrName, Values);
-}
-
void llvm::CopyModuleAttrToFunctions(Module &M) {
Triple T(M.getTargetTriple());
if (!T.isThumb() && !T.isARM() && !T.isAArch64())
return;
+ StringRef SignTypeValue = "none";
+ if (isModuleAttributeSet(M, "sign-return-address"))
+ SignTypeValue = "non-leaf";
+ if (isModuleAttributeSet(M, "sign-return-address-all"))
+ SignTypeValue = "all";
+
+ StringRef BTEValue =
+ isModuleAttributeSet(M, "branch-target-enforcement") ? "true" : "false";
+ StringRef BPPLValue =
+ isModuleAttributeSet(M, "branch-protection-pauth-lr") ? "true" : "false";
+ StringRef GCSValue =
+ isModuleAttributeSet(M, "guarded-control-stack") ? "true" : "false";
+ StringRef SignKeyValue =
+ isModuleAttributeSet(M, "sign-return-address-key") ? "b_key" : "a_key";
+
for (Function &F : M.getFunctionList()) {
if (F.isDeclaration())
continue;
+ auto SetFunctionAttrIfNotSet = [&](StringRef FnAttrName, StringRef Value) {
+ if (!F.hasFnAttribute(FnAttrName))
+ F.addFnAttr(FnAttrName, Value);
+ };
- if (!F.hasFnAttribute("sign-return-address")) {
- StringRef SignType = "none";
- if (isModuleAttributeSet(M, "sign-return-address"))
- SignType = "non-leaf";
-
- if (isModuleAttributeSet(M, "sign-return-address-all"))
- SignType = "all";
-
- F.addFnAttr("sign-return-address", SignType);
- }
- CopyModuleAttributeToFunction(F, "branch-target-enforcement");
- CopyModuleAttributeToFunction(F, "branch-protection-pauth-lr");
- CopyModuleAttributeToFunction(F, "guarded-control-stack");
- CopyModuleAttributeToFunction(
- F, "sign-return-address-key",
- std::make_pair<StringRef, StringRef>("b_key", "a_key"));
+ SetFunctionAttrIfNotSet("sign-return-address", SignTypeValue);
+ SetFunctionAttrIfNotSet("branch-target-enforcement", BTEValue);
+ SetFunctionAttrIfNotSet("branch-protection-pauth-lr", BPPLValue);
+ SetFunctionAttrIfNotSet("guarded-control-stack", GCSValue);
+ SetFunctionAttrIfNotSet("sign-return-address-key", SignKeyValue);
}
}
|
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.
Looks reasonable
84eae9d
to
36544d9
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
llvm/lib/IR/AutoUpgrade.cpp
Outdated
if (isModuleAttributeSet(M, "sign-return-address")) | ||
SignTypeValue = "non-leaf"; | ||
if (isModuleAttributeSet(M, "sign-return-address-all")) |
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.
Unhelpful comment orthogonal to this PR:
It seems that the module attributes are either:
- sign-return-address (i32 0 or 1)
- sign-return-address-all (i32 0 or 1)
But then the function attribute is:
- sign-return-address (string "none", "non-leaf", or "all")
Is that correct? If so, there's something about that asymmetry that is grinding.
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.
sign-return-address 0 / sign-return-address-all 0 -> "none"
sign-return-address 0 / sign-return-address-all 0 -> "non-leaf"
sign-return-address 1 / sign-return-address-all 1 -> "all"
sign-return-address 0 / sign-return-address-all 1 -> "invalid". - on my list of missing validations.
I didn't find they not a just 0,1,2 are used for the module values with direct "none", "non-leaf", or "all" mapping.
Looks like the build bot timed out. You may need to push to rekick it. Or you might be able to in the buildkite UI. |
llvm/lib/IR/AutoUpgrade.cpp
Outdated
CopyModuleAttributeToFunction(F, "branch-protection-pauth-lr"); | ||
CopyModuleAttributeToFunction(F, "guarded-control-stack"); | ||
CopyModuleAttributeToFunction( | ||
F, "sign-return-address-key", |
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.
the module flag is "sign-return-address-with-bkey" instead of "sign-return-address-key".
fixed now.
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.
err...was that a recently introduced bug? Do we need to backport that specific fix (and thus the test modification)? That makes this change no long NFC.
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.
The bug is not yet backported, but due to performance the original PR should go with this change anyway.
Once all patches around the flag handling landed we can further reduce the work here #84804 so only would do any work if we import an older version the IR. |
So I think @dhoekwater and @pranavk have pointed out where the suspected reported regression may have come from in the base commit. What happens when a module never had these module level metadata set? There's a difference between |
If you have something that I can reproduce I'd try to debug it too.
All module goes thru here so we should not have mix of |
Minimal reproducer: file1.c
file2.c
$CLANG -flto=thin -target aarch64-none-linux-gnu -O2 file1.c file2.c -c foo used to get inlined earlier, not anymore because attributes are different now. This is what I believe is the cause of severe performance regression. Up to 30% degradation on multiple benchmarks. |
@@ -5182,65 +5182,46 @@ void llvm::UpgradeFunctionAttributes(Function &F) { | |||
static bool isModuleAttributeSet(Module &M, const StringRef &ModAttr) { |
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.
Currently, this function treats "Attribute X is set with value 0" the same as "Attribute X is unset" for a given module.
This behavior causes functions within modules with no attributes to be annotated with the sign-return-address
, branch-target-enforcement
, branch-protection-pauth-lr
, guarded-control-stack
, and sign-return-address-key
attributes.
} | ||
|
||
void llvm::CopyModuleAttrToFunctions(Module &M) { | ||
Triple T(M.getTargetTriple()); | ||
if (!T.isThumb() && !T.isARM() && !T.isAArch64()) | ||
return; | ||
|
||
StringRef SignTypeValue = "none"; |
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 adding the sign-return-address=none
attribute is not a noop (it should not be set if pac and bti are disabled), is there something we can predicate adding this attribute on? For example, is sign-return-address
only set when sign-return-address-with-bkey
is non-null for the module?
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.
Answering my own question, it looks like uses of this function attribute fall back to the module's attribute if sign-return-address
is not set. You should then be able to only set this module's value if it is all
or non-leaf
.
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.
@dhoekwater I have a few changes that changes this behaviour to set flag only when enabled so if all dependency merged then the module flag won't be used anymore for function attribute so here could set only the positive flags.
also run the code only when the LTO object is from an older frontend.
#84804
isModuleAttributeSet(M, "branch-protection-pauth-lr") ? "true" : "false"; | ||
StringRef GCSValue = | ||
isModuleAttributeSet(M, "guarded-control-stack") ? "true" : "false"; | ||
StringRef SignKeyValue = |
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 looks like sign-return-address-key
is only present if sign-return-address
is all
or non-leaf
. You should be able to do the same thing here and avoid setting this function attribute in those cases.
} | ||
|
||
void llvm::CopyModuleAttrToFunctions(Module &M) { | ||
Triple T(M.getTargetTriple()); | ||
if (!T.isThumb() && !T.isARM() && !T.isAArch64()) | ||
return; | ||
|
||
StringRef SignTypeValue = "none"; |
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.
Answering my own question, it looks like uses of this function attribute fall back to the module's attribute if sign-return-address
is not set. You should then be able to only set this module's value if it is all
or non-leaf
.
…ttributes." (#85291) Reverts #82763 because caused a regressions with inlining. See #84494 (comment)
Refactoring llvm#82763 to cache module attributes.
5a062e9
to
8ecca58
Compare
;; by the thin-lto linker/IRMover. | ||
;; Regression test for #82763 | ||
|
||
; RUN: split-file %s %t |
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 seems unneeded. You can add ThinLTO tests to llvm/test/ThinLTO
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 added the test here because I'd use ld.lld
as it invokes the IRMover differently than llvm-lto
.
and under llvm/test/ThinLTO
ld.lld
is not available.
llvm-lto merges modules to an empty module, while ld.lld merges modules into the first module.
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.
Drive by comment: To mimic the ThinLTO behavior of lld use llvm-lto2 not llvm-lto - the former uses the same LTO API (linker resolution-based) whereas the latter uses the legacy one.
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 @MaskRay and @teresajohnson !
Moved the test, cheers. (in #86212 )
Closing this in favour of #86212 |
Refactoring #82763. Caching the module attributes should help with the performance.
Patch also corrects the b-key handling.