mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-14 14:56:47 +00:00
Exposing the noduplicate attribute within Clang, which marks functions so that the optimizer does not duplicate code.
Patch thanks to Marcello Maggioni! llvm-svn: 201941
This commit is contained in:
parent
9d2c15eff7
commit
7c19ab17c7
@ -558,6 +558,50 @@ caveats to this use of name mangling:
|
||||
|
||||
Query for this feature with ``__has_extension(attribute_overloadable)``.
|
||||
|
||||
noduplicate
|
||||
-----------
|
||||
.. csv-table:: Supported Syntaxes
|
||||
:header: "GNU", "C++11", "__declspec", "Keyword"
|
||||
|
||||
"X","X","",""
|
||||
|
||||
The ``noduplicate`` attribute can be placed on function declarations to control
|
||||
whether function calls to this function can be duplicated
|
||||
or not as a result of optimizations. This is required for the implementation
|
||||
of functions with certain special requirements, like the OpenCL "barrier",
|
||||
function that, depending on the hardware, might require to be run concurrently
|
||||
by all the threads that are currently executing in lockstep on the hardware.
|
||||
For example this attribute applied on the function "nodupfunc"
|
||||
avoids that this code:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void nodupfunc() __attribute__((noduplicate));
|
||||
// Setting it as a C++11 attribute is also valid
|
||||
// void nodupfunc() [[clang::noduplicate]];
|
||||
void foo();
|
||||
void bar();
|
||||
|
||||
nodupfunc();
|
||||
if (a > n) {
|
||||
foo();
|
||||
} else {
|
||||
bar();
|
||||
}
|
||||
|
||||
gets possibly modified by some optimization into code similar to this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
if (a > n) {
|
||||
nodupfunc();
|
||||
foo();
|
||||
} else {
|
||||
nodupfunc();
|
||||
bar();
|
||||
}
|
||||
|
||||
where the barrier call is duplicated and sunk into the two branches of the condition.
|
||||
|
||||
Variable Attributes
|
||||
===================
|
||||
|
@ -803,6 +803,12 @@ def NoDebug : InheritableAttr {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def NoDuplicate : InheritableAttr {
|
||||
let Spellings = [GNU<"noduplicate">, CXX11<"clang", "noduplicate">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Documentation = [NoDuplicateDocs];
|
||||
}
|
||||
|
||||
def NoInline : InheritableAttr {
|
||||
let Spellings = [GCC<"noinline">, Declspec<"noinline">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
|
@ -299,6 +299,49 @@ Query for this feature with ``__has_attribute(objc_method_family)``.
|
||||
}];
|
||||
}
|
||||
|
||||
def NoDuplicateDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``noduplicate`` attribute can be placed on function declarations to control
|
||||
whether function calls to this function can be duplicated
|
||||
or not as a result of optimizations. This is required for the implementation
|
||||
of functions with certain special requirements, like the OpenCL "barrier",
|
||||
function that, depending on the hardware, might require to be run concurrently
|
||||
by all the threads that are currently executing in lockstep on the hardware.
|
||||
For example this attribute applied on the function "nodupfunc"
|
||||
avoids that this code:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void nodupfunc() __attribute__((noduplicate));
|
||||
// Setting it as a C++11 attribute is also valid
|
||||
// void nodupfunc() [[clang::noduplicate]];
|
||||
void foo();
|
||||
void bar();
|
||||
|
||||
nodupfunc();
|
||||
if (a > n) {
|
||||
foo();
|
||||
} else {
|
||||
bar();
|
||||
}
|
||||
|
||||
gets possibly modified by some optimization into code similar to this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
if (a > n) {
|
||||
nodupfunc();
|
||||
foo();
|
||||
} else {
|
||||
nodupfunc();
|
||||
bar();
|
||||
}
|
||||
|
||||
where the barrier call is duplicated and sunk into the two branches of the condition.
|
||||
}];
|
||||
}
|
||||
|
||||
def ObjCRequiresSuperDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
@ -842,4 +885,4 @@ Clang implements two kinds of checks with this attribute.
|
||||
the corresponding arguments are annotated. If the arguments are
|
||||
incorrect, the caller of ``foo`` will receive a warning.
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
@ -1052,6 +1052,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
||||
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
|
||||
if (TargetDecl->hasAttr<NoReturnAttr>())
|
||||
FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
|
||||
if (TargetDecl->hasAttr<NoDuplicateAttr>())
|
||||
FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
|
||||
|
||||
if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
|
||||
const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>();
|
||||
|
@ -631,6 +631,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
|
||||
// Naked implies noinline: we should not be inlining such functions.
|
||||
B.addAttribute(llvm::Attribute::Naked);
|
||||
B.addAttribute(llvm::Attribute::NoInline);
|
||||
} else if (D->hasAttr<NoDuplicateAttr>()) {
|
||||
B.addAttribute(llvm::Attribute::NoDuplicate);
|
||||
} else if (D->hasAttr<NoInlineAttr>()) {
|
||||
B.addAttribute(llvm::Attribute::NoInline);
|
||||
} else if ((D->hasAttr<AlwaysInlineAttr>() ||
|
||||
|
@ -4237,6 +4237,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
||||
handleSimpleAttribute<PureAttr>(S, D, Attr); break;
|
||||
case AttributeList::AT_Cleanup: handleCleanupAttr (S, D, Attr); break;
|
||||
case AttributeList::AT_NoDebug: handleNoDebugAttr (S, D, Attr); break;
|
||||
case AttributeList::AT_NoDuplicate:
|
||||
handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr); break;
|
||||
case AttributeList::AT_NoInline:
|
||||
handleSimpleAttribute<NoInlineAttr>(S, D, Attr); break;
|
||||
case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
|
||||
|
20
clang/test/CodeGen/noduplicate-cxx11-test.cpp
Normal file
20
clang/test/CodeGen/noduplicate-cxx11-test.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
// RUN: %clang_cc1 -triple=i686-pc-unknown -std=c++11 %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// This was a problem in Sema, but only shows up as noinline missing
|
||||
// in CodeGen.
|
||||
|
||||
// CHECK: define i32 @_Z15noduplicatedfuni(i32 %a) [[NI:#[0-9]+]]
|
||||
|
||||
int noduplicatedfun [[clang::noduplicate]] (int a) {
|
||||
|
||||
return a+1;
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
return noduplicatedfun(5);
|
||||
|
||||
}
|
||||
|
||||
// CHECK: attributes [[NI]] = { noduplicate nounwind{{.*}} }
|
8
clang/test/Sema/attr-noduplicate.c
Normal file
8
clang/test/Sema/attr-noduplicate.c
Normal file
@ -0,0 +1,8 @@
|
||||
// RUN: %clang_cc1 %s -verify -fsyntax-only
|
||||
|
||||
int a __attribute__((noduplicate)); // expected-warning {{'noduplicate' attribute only applies to functions}}
|
||||
|
||||
void t1() __attribute__((noduplicate));
|
||||
|
||||
void t2() __attribute__((noduplicate(2))); // expected-error {{'noduplicate' attribute takes no arguments}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user