Skip to content

Commit 52c8489

Browse files
[Transforms] Implement always_specialise attribute lowering
1 parent 6f3e2c0 commit 52c8489

34 files changed

+1279
-1
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,14 @@ def AlwaysInline : DeclOrStmtAttr {
905905
let Documentation = [AlwaysInlineDocs];
906906
}
907907

908+
def AlwaysSpecialize : InheritableParamAttr {
909+
let Spellings = [GNU<"always_specialize">, CXX11<"clang", "always_specialize">,
910+
C23<"clang", "always_specialize">];
911+
let Subjects = SubjectList<[ParmVar]>;
912+
let Documentation = [AlwaysSpecializeDocs];
913+
let SimpleHandler = 1;
914+
}
915+
908916
def Artificial : InheritableAttr {
909917
let Spellings = [GCC<"artificial">];
910918
let Subjects = SubjectList<[InlineFunction]>;

clang/include/clang/Basic/AttrDocs.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8126,6 +8126,17 @@ Attribute docs`_, and `the GCC Inline docs`_.
81268126
let Heading = "always_inline, __force_inline";
81278127
}
81288128

8129+
def AlwaysSpecializeDocs : Documentation {
8130+
let Category = DocCatConsumed;
8131+
let Content = [{
8132+
The ``always_specialize`` attribute on a function parameter indicates that
8133+
the function shall be duplicated and specialized with respect to constant
8134+
arguments. This will usually increase code size. It controls an IR transform
8135+
similar in spirit to ``always_inline``.
8136+
}];
8137+
let Heading = "always_specialize";
8138+
}
8139+
81298140
def EnforceTCBDocs : Documentation {
81308141
let Category = DocCatFunction;
81318142
let Content = [{

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,9 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
25592559
B.addAttribute("aarch64_new_zt0");
25602560
}
25612561

2562+
if (D->hasAttr<AlwaysSpecializeAttr>())
2563+
B.addAttribute(llvm::Attribute::AlwaysSpecialize);
2564+
25622565
// Track whether we need to add the optnone LLVM attribute,
25632566
// starting with the default for this optimization level.
25642567
bool ShouldAddOptNone =
@@ -2978,6 +2981,12 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
29782981
F->addParamAttr(0, llvm::Attribute::Returned);
29792982
}
29802983

2984+
for (auto [Index, Param] : enumerate(FD->parameters()))
2985+
if (Param->hasAttrs())
2986+
for (auto *A : Param->getAttrs())
2987+
if (A->getKind() == attr::AlwaysSpecialize)
2988+
F->addParamAttr(Index, llvm::Attribute::AlwaysSpecialize);
2989+
29812990
// Only a few attributes are set on declarations; these may later be
29822991
// overridden by a definition.
29832992

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7137,6 +7137,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
71377137
case ParsedAttr::AT_AlwaysInline:
71387138
handleAlwaysInlineAttr(S, D, AL);
71397139
break;
7140+
case ParsedAttr::AT_AlwaysSpecialize:
7141+
handleSimpleAttribute<AlwaysSpecializeAttr>(S, D, AL);
7142+
break;
71407143
case ParsedAttr::AT_AnalyzerNoReturn:
71417144
handleAnalyzerNoReturnAttr(S, D, AL);
71427145
break;

clang/test/CodeGen/lto-newpm-pipeline.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
// CHECK-FULL-O0-NEXT: Running pass: EntryExitInstrumenterPass
3232
// CHECK-FULL-O0-NEXT: Running pass: AlwaysInlinerPass
3333
// CHECK-FULL-O0-NEXT: Running analysis: ProfileSummaryAnalysis
34+
// CHECK-FULL-O0-NEXT: Running pass: AlwaysSpecializerPass
3435
// CHECK-FULL-O0-NEXT: Running pass: CoroConditionalWrapper
3536
// CHECK-FULL-O0-NEXT: Running pass: CanonicalizeAliasesPass
3637
// CHECK-FULL-O0-NEXT: Running pass: NameAnonGlobalPass
@@ -45,6 +46,7 @@
4546
// CHECK-THIN-O0-NEXT: Running pass: EntryExitInstrumenterPass
4647
// CHECK-THIN-O0-NEXT: Running pass: AlwaysInlinerPass
4748
// CHECK-THIN-O0-NEXT: Running analysis: ProfileSummaryAnalysis
49+
// CHECK-THIN-O0-NEXT: Running pass: AlwaysSpecializerPass
4850
// CHECK-THIN-O0-NEXT: Running pass: CoroConditionalWrapper
4951
// CHECK-THIN-O0-NEXT: Running pass: CanonicalizeAliasesPass
5052
// CHECK-THIN-O0-NEXT: Running pass: NameAnonGlobalPass

clang/test/Misc/pragma-attribute-supported-attributes-list.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// CHECK-NEXT: AlignValue (SubjectMatchRule_variable, SubjectMatchRule_type_alias)
1616
// CHECK-NEXT: AlwaysDestroy (SubjectMatchRule_variable)
1717
// CHECK-NEXT: AlwaysInline (SubjectMatchRule_function)
18+
// CHECK-NEXT: AlwaysSpecialize (SubjectMatchRule_variable_is_parameter)
1819
// CHECK-NEXT: Annotate ()
1920
// CHECK-NEXT: AnyX86NoCfCheck (SubjectMatchRule_hasType_functionType)
2021
// CHECK-NEXT: ArcWeakrefUnavailable (SubjectMatchRule_objc_interface)

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,7 @@ enum AttributeKindCodes {
798798
ATTR_KIND_NO_DIVERGENCE_SOURCE = 100,
799799
ATTR_KIND_SANITIZE_TYPE = 101,
800800
ATTR_KIND_CAPTURES = 102,
801+
ATTR_KIND_ALWAYS_SPECIALIZE = 103,
801802
};
802803

803804
enum ComdatSelectionKindCodes {

llvm/include/llvm/IR/Attributes.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ def AllocSize : IntAttr<"allocsize", IntersectPreserve, [FnAttr]>;
9898
/// inline=always.
9999
def AlwaysInline : EnumAttr<"alwaysinline", IntersectPreserve, [FnAttr]>;
100100

101+
/// Specialize function when argument at call site is known constant
102+
def AlwaysSpecialize : EnumAttr<"alwaysspecialize", IntersectPreserve, [ParamAttr]>;
103+
101104
/// Callee is recognized as a builtin, despite nobuiltin attribute on its
102105
/// declaration.
103106
def Builtin : EnumAttr<"builtin", IntersectPreserve, [FnAttr]>;

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ void initializeTarget(PassRegistry &);
5050

5151
void initializeAAResultsWrapperPassPass(PassRegistry &);
5252
void initializeAlwaysInlinerLegacyPassPass(PassRegistry &);
53+
void initializeAlwaysSpecializerPass(PassRegistry &);
5354
void initializeAssignmentTrackingAnalysisPass(PassRegistry &);
5455
void initializeAssumptionCacheTrackerPass(PassRegistry &);
5556
void initializeAtomicExpandLegacyPass(PassRegistry &);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//=== AlwaysSpecializer.h - implementation of always_specialize -*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
#ifndef LLVM_TRANSFORMS_IPO_ALWAYSSPECIALIZER_H
9+
#define LLVM_TRANSFORMS_IPO_ALWAYSSPECIALIZER_H
10+
11+
#include "llvm/IR/PassManager.h"
12+
13+
namespace llvm {
14+
15+
class Module;
16+
class ModulePass;
17+
18+
class AlwaysSpecializerPass : public PassInfoMixin<AlwaysSpecializerPass> {
19+
public:
20+
AlwaysSpecializerPass();
21+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
22+
static bool isRequired() { return true; }
23+
};
24+
25+
ModulePass *createAlwaysSpecializerPass();
26+
27+
} // end namespace llvm
28+
29+
#endif // LLVM_TRANSFORMS_IPO_ALWAYSSPECIALIZER_H

0 commit comments

Comments
 (0)