Skip to content

Commit 8ecca58

Browse files
[LLVM] Autoupgrade function attributes from Module attributes.
Refactoring #82763 to cache module attributes.
1 parent 280c7a9 commit 8ecca58

File tree

7 files changed

+160
-3
lines changed

7 files changed

+160
-3
lines changed

lld/test/ELF/lto/aarch64_inline.ll

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
; REQUIRES: aarch64
2+
;; Test verifies inlining happens cross module when module flags are upgraded
3+
;; by the thin-lto linker/IRMover.
4+
;; Regression test for #82763
5+
6+
; RUN: split-file %s %t
7+
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -unified-lto %t/foo.s -o %t/foo.o
8+
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -unified-lto %t/main.s -o %t/main.o
9+
; RUN: ld.lld -O2 --lto=thin --entry=main %t/main.o %t/foo.o -o %t/exe
10+
; RUN: llvm-objdump -d %t/exe | FileCheck %s
11+
12+
13+
; CHECK-LABEL: <main>:
14+
; CHECK-NEXT: pacibsp
15+
; CHECK-NEXT: mov w0, #0x22
16+
; CHECK-NEXT: autibsp
17+
; CHECK-NEXT: ret
18+
19+
;--- foo.s
20+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
21+
target triple = "aarch64-unknown-linux-gnu"
22+
23+
define dso_local noundef i32 @foo() local_unnamed_addr #0 {
24+
entry:
25+
ret i32 34
26+
}
27+
28+
attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
29+
!llvm.module.flags = !{!0, !1, !2, !3 }
30+
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
31+
!1 = !{i32 8, !"sign-return-address", i32 1}
32+
!2 = !{i32 8, !"sign-return-address-all", i32 1}
33+
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}
34+
35+
;--- main.s
36+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
37+
target triple = "aarch64-unknown-linux-gnu"
38+
39+
declare i32 @foo();
40+
41+
define i32 @main() {
42+
entry:
43+
%1 = call i32 @foo()
44+
ret i32 %1
45+
}
46+
47+
!llvm.module.flags = !{!0, !1, !2, !3 }
48+
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
49+
!1 = !{i32 8, !"sign-return-address", i32 1}
50+
!2 = !{i32 8, !"sign-return-address-all", i32 1}
51+
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}

llvm/include/llvm/IR/AutoUpgrade.h

+3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ namespace llvm {
8888
/// info. Return true if module is modified.
8989
bool UpgradeDebugInfo(Module &M);
9090

91+
/// Copies module attributes to the functions in the module.
92+
void CopyModuleAttrToFunctions(Module &M);
93+
9194
/// Check whether a string looks like an old loop attachment tag.
9295
inline bool mayBeOldLoopAttachmentTag(StringRef Name) {
9396
return Name.starts_with("llvm.vectorizer.");

llvm/lib/IR/AutoUpgrade.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -5178,6 +5178,53 @@ void llvm::UpgradeFunctionAttributes(Function &F) {
51785178
Arg.removeAttrs(AttributeFuncs::typeIncompatible(Arg.getType()));
51795179
}
51805180

5181+
// Check if the module attribute is present and not zero.
5182+
static bool isModuleAttributeSet(Module &M, const StringRef &ModAttr) {
5183+
const auto *Attr =
5184+
mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(ModAttr));
5185+
return Attr && Attr->isOne();
5186+
}
5187+
5188+
// Check if the function attribute is not present and set it.
5189+
static void SetFunctionAttrIfNotSet(Function &F, StringRef FnAttrName,
5190+
StringRef Value) {
5191+
if (!F.hasFnAttribute(FnAttrName))
5192+
F.addFnAttr(FnAttrName, Value);
5193+
}
5194+
5195+
void llvm::CopyModuleAttrToFunctions(Module &M) {
5196+
Triple T(M.getTargetTriple());
5197+
if (!T.isThumb() && !T.isARM() && !T.isAArch64())
5198+
return;
5199+
5200+
StringRef SignTypeValue = "none";
5201+
if (isModuleAttributeSet(M, "sign-return-address-all"))
5202+
SignTypeValue = "all";
5203+
else if (isModuleAttributeSet(M, "sign-return-address"))
5204+
SignTypeValue = "non-leaf";
5205+
5206+
StringRef BTEValue =
5207+
isModuleAttributeSet(M, "branch-target-enforcement") ? "true" : "false";
5208+
StringRef BPPLValue =
5209+
isModuleAttributeSet(M, "branch-protection-pauth-lr") ? "true" : "false";
5210+
StringRef GCSValue =
5211+
isModuleAttributeSet(M, "guarded-control-stack") ? "true" : "false";
5212+
StringRef SignKeyValue =
5213+
isModuleAttributeSet(M, "sign-return-address-with-bkey") ? "b_key"
5214+
: "a_key";
5215+
5216+
for (Function &F : M.getFunctionList()) {
5217+
if (F.isDeclaration())
5218+
continue;
5219+
5220+
SetFunctionAttrIfNotSet(F, "sign-return-address", SignTypeValue);
5221+
SetFunctionAttrIfNotSet(F, "branch-target-enforcement", BTEValue);
5222+
SetFunctionAttrIfNotSet(F, "branch-protection-pauth-lr", BPPLValue);
5223+
SetFunctionAttrIfNotSet(F, "guarded-control-stack", GCSValue);
5224+
SetFunctionAttrIfNotSet(F, "sign-return-address-key", SignKeyValue);
5225+
}
5226+
}
5227+
51815228
static bool isOldLoopArgument(Metadata *MD) {
51825229
auto *T = dyn_cast_or_null<MDTuple>(MD);
51835230
if (!T)

llvm/lib/Linker/IRMover.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -1623,6 +1623,11 @@ Error IRLinker::run() {
16231623
// Loop over all of the linked values to compute type mappings.
16241624
computeTypeMapping();
16251625

1626+
// Convert module level attributes to function level attributes because
1627+
// after merging modules the attributes might change and would have different
1628+
// effect on the functions as the original module would have.
1629+
CopyModuleAttrToFunctions(*SrcM);
1630+
16261631
std::reverse(Worklist.begin(), Worklist.end());
16271632
while (!Worklist.empty()) {
16281633
GlobalValue *GV = Worklist.back();
@@ -1787,6 +1792,11 @@ IRMover::IRMover(Module &M) : Composite(M) {
17871792
for (const auto *MD : StructTypes.getVisitedMetadata()) {
17881793
SharedMDs[MD].reset(const_cast<MDNode *>(MD));
17891794
}
1795+
1796+
// Convert module level attributes to function level attributes because
1797+
// after merging modules the attributes might change and would have different
1798+
// effect on the functions as the original module would have.
1799+
CopyModuleAttrToFunctions(M);
17901800
}
17911801

17921802
Error IRMover::move(std::unique_ptr<Module> Src,

llvm/test/LTO/AArch64/link-branch-target-enforcement.ll

+3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ entry:
3030

3131
; CHECK-NOT: linking module flags 'branch-target-enforcement': IDs have conflicting values in
3232
; CHECK-DUMP: <main>:
33+
; CHECK-DUMP: paciasp
34+
; CHECK-DUMP: str
3335
; CHECK-DUMP: bl 0x8 <main+0x8>
3436
; CHECK-DUMP: <foo>:
37+
; CHECK-DUMP: pacibsp
3538

3639
; `main` doesn't support BTI while `foo` does, so in the binary
3740
; we should see only PAC which is supported by both.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; Testcase to check that module with different sign return address can
2+
; be mixed.
3+
;
4+
; RUN: llvm-as %s -o %t1.bc
5+
; RUN: llvm-as %p/Inputs/foo.ll -o %t2.bc
6+
; RUN: llvm-lto -exported-symbol main \
7+
; RUN: -exported-symbol foo \
8+
; RUN: -filetype=obj \
9+
; RUN: %t2.bc %t1.bc \
10+
; RUN: -o %t1.exe 2>&1
11+
; RUN: llvm-objdump -d %t1.exe | FileCheck --check-prefix=CHECK-DUMP %s
12+
; RUN: llvm-readelf -n %t1.exe | FileCheck --allow-empty --check-prefix=CHECK-PROP %s
13+
14+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
15+
target triple = "aarch64-unknown-linux-gnu"
16+
17+
declare i32 @foo();
18+
19+
define i32 @main() {
20+
entry:
21+
%add = call i32 @foo()
22+
ret i32 %add
23+
}
24+
25+
!llvm.module.flags = !{!0, !1, !2, !3 }
26+
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
27+
!1 = !{i32 8, !"sign-return-address", i32 0}
28+
!2 = !{i32 8, !"sign-return-address-all", i32 0}
29+
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
30+
31+
; CHECK-DUMP: <foo>:
32+
; CHECK-DUMP: pacibsp
33+
; CHECK-DUMP: mov w0, #0x2a
34+
; CHECK-DUMP: autibsp
35+
; CHECK-DUMP: ret
36+
; CHECK-DUMP: <main>:
37+
; CHECK-DUMP-NOT: paciasp
38+
; CHECK-DUMP: str x30,
39+
; CHECK-DUMP: bl 0x14 <main+0x4>
40+
41+
; `main` doesn't support PAC sign-return-address while `foo` does, so in the binary
42+
; we should not see anything.
43+
; CHECK-PROP-NOT: Properties: aarch64 feature: PAC

llvm/test/Linker/link-arm-and-thumb.ll

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ entry:
1313
ret i32 %add
1414
}
1515

16-
; CHECK: define i32 @main() {
16+
; CHECK: define i32 @main()
1717
; CHECK: define i32 @foo(i32 %a, i32 %b) [[ARM_ATTRS:#[0-9]+]]
1818
; CHECK: define i32 @bar(i32 %a, i32 %b) [[THUMB_ATTRS:#[0-9]+]]
1919

20-
; CHECK: attributes [[ARM_ATTRS]] = { "target-features"="-thumb-mode" }
21-
; CHECK: attributes [[THUMB_ATTRS]] = { "target-features"="+thumb-mode" }
20+
; CHECK: attributes [[ARM_ATTRS]] = {{{.*}}"target-features"="-thumb-mode" }
21+
; CHECK: attributes [[THUMB_ATTRS]] = {{{.*}}"target-features"="+thumb-mode" }
2222

2323
; STDERR-NOT: warning: Linking two modules of different target triples:

0 commit comments

Comments
 (0)