[Clang] Refactor __attribute__((assume))
(#84934)
This is a followup to #81014 and #84582: Before this patch, Clang would accept `__attribute__((assume))` and `[[clang::assume]]` as nonstandard spellings for the `[[omp::assume]]` attribute; this resulted in a potentially very confusing name clash with C++23’s `[[assume]]` attribute (and GCC’s `assume` attribute with the same semantics). This pr replaces every usage of `__attribute__((assume))` with `[[omp::assume]]` and makes `__attribute__((assume))` and `[[clang::assume]]` alternative spellings for C++23’s `[[assume]]`; this shouldn’t cause any problems due to differences in appertainment and because almost no-one was using this variant spelling to begin with (a use in libclc has already been changed to use a different attribute).
This commit is contained in:
parent
4fbc95d136
commit
c44fa3e8a9
@ -1640,10 +1640,11 @@ def Unlikely : StmtAttr {
|
||||
def : MutualExclusions<[Likely, Unlikely]>;
|
||||
|
||||
def CXXAssume : StmtAttr {
|
||||
let Spellings = [CXX11<"", "assume", 202207>];
|
||||
let Spellings = [CXX11<"", "assume", 202207>, Clang<"assume">];
|
||||
let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">;
|
||||
let Args = [ExprArgument<"Assumption">];
|
||||
let Documentation = [CXXAssumeDocs];
|
||||
let HasCustomParsing = 1;
|
||||
}
|
||||
|
||||
def NoMerge : DeclOrStmtAttr {
|
||||
@ -4255,7 +4256,7 @@ def OMPDeclareVariant : InheritableAttr {
|
||||
}
|
||||
|
||||
def OMPAssume : InheritableAttr {
|
||||
let Spellings = [Clang<"assume">, CXX11<"omp", "assume">];
|
||||
let Spellings = [CXX11<"omp", "assume">];
|
||||
let Subjects = SubjectList<[Function, ObjCMethod]>;
|
||||
let InheritEvenIfAlreadyPresent = 1;
|
||||
let Documentation = [OMPAssumeDocs];
|
||||
|
@ -2027,9 +2027,6 @@ Different optimisers are likely to react differently to the presence of
|
||||
this attribute; in some cases, adding ``assume`` may affect performance
|
||||
negatively. It should be used with parsimony and care.
|
||||
|
||||
Note that `clang::assume` is a different attribute. Always write ``assume``
|
||||
without a namespace if you intend to use the standard C++ attribute.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: c++
|
||||
@ -4740,7 +4737,7 @@ def OMPAssumeDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Heading = "assume";
|
||||
let Content = [{
|
||||
Clang supports the ``__attribute__((assume("assumption")))`` attribute to
|
||||
Clang supports the ``[[omp::assume("assumption")]]`` attribute to
|
||||
provide additional information to the optimizer. The string-literal, here
|
||||
"assumption", will be attached to the function declaration such that later
|
||||
analysis and optimization passes can assume the "assumption" to hold.
|
||||
@ -4752,7 +4749,7 @@ A function can have multiple assume attributes and they propagate from prior
|
||||
declarations to later definitions. Multiple assumptions are aggregated into a
|
||||
single comma separated string. Thus, one can provide multiple assumptions via
|
||||
a comma separated string, i.a.,
|
||||
``__attribute__((assume("assumption1,assumption2")))``.
|
||||
``[[omp::assume("assumption1,assumption2")]]``.
|
||||
|
||||
While LLVM plugins might provide more assumption strings, the default LLVM
|
||||
optimization passes are aware of the following assumptions:
|
||||
|
@ -10237,9 +10237,6 @@ def err_fallthrough_attr_outside_switch : Error<
|
||||
def err_fallthrough_attr_invalid_placement : Error<
|
||||
"fallthrough annotation does not directly precede switch label">;
|
||||
|
||||
def err_assume_attr_args : Error<
|
||||
"attribute '%0' requires a single expression argument">;
|
||||
|
||||
def warn_unreachable_default : Warning<
|
||||
"default label in switch which covers all enumeration values">,
|
||||
InGroup<CoveredSwitchDefault>, DefaultIgnore;
|
||||
|
@ -2997,7 +2997,8 @@ private:
|
||||
bool ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs,
|
||||
IdentifierInfo *AttrName,
|
||||
SourceLocation AttrNameLoc,
|
||||
SourceLocation *EndLoc);
|
||||
SourceLocation *EndLoc,
|
||||
ParsedAttr::Form Form);
|
||||
|
||||
IdentifierInfo *TryParseCXX11AttributeIdentifier(
|
||||
SourceLocation &Loc,
|
||||
|
@ -666,6 +666,9 @@ void Parser::ParseGNUAttributeArgs(
|
||||
ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
|
||||
Form);
|
||||
return;
|
||||
} else if (AttrKind == ParsedAttr::AT_CXXAssume) {
|
||||
ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);
|
||||
return;
|
||||
}
|
||||
|
||||
// These may refer to the function arguments, but need to be parsed early to
|
||||
@ -720,6 +723,10 @@ unsigned Parser::ParseClangAttributeArgs(
|
||||
ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
|
||||
ScopeName, ScopeLoc, Form);
|
||||
break;
|
||||
|
||||
case ParsedAttr::AT_CXXAssume:
|
||||
ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);
|
||||
break;
|
||||
}
|
||||
return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0;
|
||||
}
|
||||
|
@ -4560,7 +4560,8 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
|
||||
bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs,
|
||||
IdentifierInfo *AttrName,
|
||||
SourceLocation AttrNameLoc,
|
||||
SourceLocation *EndLoc) {
|
||||
SourceLocation *EndLoc,
|
||||
ParsedAttr::Form Form) {
|
||||
assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren);
|
||||
T.consumeOpen();
|
||||
@ -4603,7 +4604,7 @@ bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs,
|
||||
auto RParen = Tok.getLocation();
|
||||
T.consumeClose();
|
||||
Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), nullptr,
|
||||
SourceLocation(), &Assumption, 1, ParsedAttr::Form::CXX11());
|
||||
SourceLocation(), &Assumption, 1, Form);
|
||||
|
||||
if (EndLoc)
|
||||
*EndLoc = RParen;
|
||||
@ -4683,7 +4684,7 @@ bool Parser::ParseCXX11AttributeArgs(
|
||||
ScopeName, ScopeLoc, Form);
|
||||
// So does C++23's assume() attribute.
|
||||
else if (!ScopeName && AttrName->isStr("assume")) {
|
||||
if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc))
|
||||
if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form))
|
||||
return true;
|
||||
NumArgs = 1;
|
||||
} else
|
||||
|
@ -665,7 +665,8 @@ bool Sema::CheckRebuiltStmtAttributes(ArrayRef<const Attr *> Attrs) {
|
||||
ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A,
|
||||
SourceRange Range) {
|
||||
if (A.getNumArgs() != 1 || !A.getArgAsExpr(0)) {
|
||||
Diag(A.getLoc(), diag::err_assume_attr_args) << A.getAttrName() << Range;
|
||||
Diag(A.getLoc(), diag::err_attribute_wrong_number_arguments)
|
||||
<< A.getAttrName() << 1 << Range;
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
@ -682,8 +683,11 @@ ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A,
|
||||
Assumption = Res.get();
|
||||
}
|
||||
|
||||
if (!getLangOpts().CPlusPlus23)
|
||||
if (!getLangOpts().CPlusPlus23 &&
|
||||
A.getSyntax() == AttributeCommonInfo::AS_CXX11) {
|
||||
llvm::dbgs() << "Syntax: " << int(A.getSyntax()) << "\n";
|
||||
Diag(A.getLoc(), diag::ext_cxx23_attr) << A << Range;
|
||||
}
|
||||
|
||||
return Assumption;
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
// RUN: %clang_cc1 -emit-llvm -triple i386-linux-gnu %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// TODO: for "foo" and "bar", "after" is not added as it appears "after" the first use or definition respectively. There might be a way to allow that.
|
||||
|
||||
// CHECK: define{{.*}} void @bar() #0
|
||||
// CHECK: define{{.*}} void @baz() #1
|
||||
// CHECK: declare{{.*}} void @foo() #2
|
||||
// CHECK: attributes #0
|
||||
// CHECK-SAME: "llvm.assume"="bar:before1,bar:before2,bar:before3,bar:def1,bar:def2"
|
||||
// CHECK: attributes #1
|
||||
// CHECK-SAME: "llvm.assume"="baz:before1,baz:before2,baz:before3,baz:def1,baz:def2,baz:after"
|
||||
// CHECK: attributes #2
|
||||
// CHECK-SAME: "llvm.assume"="foo:before1,foo:before2,foo:before3"
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
/// foo: declarations only
|
||||
|
||||
__attribute__((assume("foo:before1"))) void foo(void);
|
||||
|
||||
__attribute__((assume("foo:before2")))
|
||||
__attribute__((assume("foo:before3"))) void
|
||||
foo(void);
|
||||
|
||||
/// baz: static function declarations and a definition
|
||||
|
||||
__attribute__((assume("baz:before1"))) static void baz(void);
|
||||
|
||||
__attribute__((assume("baz:before2")))
|
||||
__attribute__((assume("baz:before3"))) static void
|
||||
baz(void);
|
||||
|
||||
// Definition
|
||||
__attribute__((assume("baz:def1,baz:def2"))) static void baz(void) { foo(); }
|
||||
|
||||
__attribute__((assume("baz:after"))) static void baz(void);
|
||||
|
||||
/// bar: external function declarations and a definition
|
||||
|
||||
__attribute__((assume("bar:before1"))) void bar(void);
|
||||
|
||||
__attribute__((assume("bar:before2")))
|
||||
__attribute__((assume("bar:before3"))) void
|
||||
bar(void);
|
||||
|
||||
// Definition
|
||||
__attribute__((assume("bar:def1,bar:def2"))) void bar(void) { baz(); }
|
||||
|
||||
__attribute__((assume("bar:after"))) void bar(void);
|
||||
|
||||
/// back to foo
|
||||
|
||||
__attribute__((assume("foo:after"))) void foo(void);
|
||||
|
||||
#endif
|
@ -8,77 +8,77 @@
|
||||
|
||||
/// foo: declarations only
|
||||
|
||||
__attribute__((assume("foo:before1"))) void foo();
|
||||
[[omp::assume("foo:before1")]] void foo();
|
||||
|
||||
__attribute__((assume("foo:before2")))
|
||||
__attribute__((assume("foo:before3"))) void
|
||||
[[omp::assume("foo:before2")]]
|
||||
[[omp::assume("foo:before3")]] void
|
||||
foo();
|
||||
|
||||
/// baz: static function declarations and a definition
|
||||
|
||||
__attribute__((assume("baz:before1"))) static void baz();
|
||||
[[omp::assume("baz:before1")]] static void baz();
|
||||
|
||||
__attribute__((assume("baz:before2")))
|
||||
__attribute__((assume("baz:before3"))) static void
|
||||
[[omp::assume("baz:before2")]]
|
||||
[[omp::assume("baz:before3")]] static void
|
||||
baz();
|
||||
|
||||
// Definition
|
||||
__attribute__((assume("baz:def1,baz:def2"))) static void baz() { foo(); }
|
||||
[[omp::assume("baz:def1,baz:def2")]] static void baz() { foo(); }
|
||||
|
||||
__attribute__((assume("baz:after"))) static void baz();
|
||||
[[omp::assume("baz:after")]] static void baz();
|
||||
|
||||
/// bar: external function declarations and a definition
|
||||
|
||||
__attribute__((assume("bar:before1"))) void bar();
|
||||
[[omp::assume("bar:before1")]] void bar();
|
||||
|
||||
__attribute__((assume("bar:before2")))
|
||||
__attribute__((assume("bar:before3"))) void
|
||||
[[omp::assume("bar:before2")]]
|
||||
[[omp::assume("bar:before3")]] void
|
||||
bar();
|
||||
|
||||
// Definition
|
||||
__attribute__((assume("bar:def1,bar:def2"))) void bar() { baz(); }
|
||||
[[omp::assume("bar:def1,bar:def2")]] void bar() { baz(); }
|
||||
|
||||
__attribute__((assume("bar:after"))) void bar();
|
||||
[[omp::assume("bar:after")]] void bar();
|
||||
|
||||
/// back to foo
|
||||
|
||||
__attribute__((assume("foo:after"))) void foo();
|
||||
[[omp::assume("foo:after")]] void foo();
|
||||
|
||||
/// class tests
|
||||
class C {
|
||||
__attribute__((assume("C:private_method"))) void private_method();
|
||||
__attribute__((assume("C:private_static"))) static void private_static();
|
||||
[[omp::assume("C:private_method")]] void private_method();
|
||||
[[omp::assume("C:private_static")]] static void private_static();
|
||||
|
||||
public:
|
||||
__attribute__((assume("C:public_method1"))) void public_method();
|
||||
__attribute__((assume("C:public_static1"))) static void public_static();
|
||||
[[omp::assume("C:public_method1")]] void public_method();
|
||||
[[omp::assume("C:public_static1")]] static void public_static();
|
||||
};
|
||||
|
||||
__attribute__((assume("C:public_method2"))) void C::public_method() {
|
||||
[[omp::assume("C:public_method2")]] void C::public_method() {
|
||||
private_method();
|
||||
}
|
||||
|
||||
__attribute__((assume("C:public_static2"))) void C::public_static() {
|
||||
[[omp::assume("C:public_static2")]] void C::public_static() {
|
||||
private_static();
|
||||
}
|
||||
|
||||
/// template tests
|
||||
template <typename T>
|
||||
__attribute__((assume("template_func<T>"))) void template_func() {}
|
||||
[[omp::assume("template_func<T>")]] void template_func() {}
|
||||
|
||||
template <>
|
||||
__attribute__((assume("template_func<float>"))) void template_func<float>() {}
|
||||
[[omp::assume("template_func<float>")]] void template_func<float>() {}
|
||||
|
||||
template <>
|
||||
void template_func<int>() {}
|
||||
|
||||
template <typename T>
|
||||
struct S {
|
||||
__attribute__((assume("S<T>::method"))) void method();
|
||||
[[omp::assume("S<T>::method")]] void method();
|
||||
};
|
||||
|
||||
template <>
|
||||
__attribute__((assume("S<float>::method"))) void S<float>::method() {}
|
||||
[[omp::assume("S<float>::method")]] void S<float>::method() {}
|
||||
|
||||
template <>
|
||||
void S<int>::method() {}
|
||||
|
@ -67,46 +67,46 @@ int lambda_outer() {
|
||||
}
|
||||
#pragma omp end assumes
|
||||
|
||||
// AST: void foo() __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: class BAR {
|
||||
// AST-NEXT: public:
|
||||
// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAR() {
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar1() {
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void bar2() {
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: };
|
||||
// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar() {
|
||||
// AST-NEXT: BAR b;
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz();
|
||||
// AST-NEXT: template <typename T> class BAZ {
|
||||
// AST-NEXT: public:
|
||||
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ<T>() {
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz1() {
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void baz2() {
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: };
|
||||
// AST-NEXT: template<> class BAZ<float> {
|
||||
// AST-NEXT: public:
|
||||
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ() {
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz1();
|
||||
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void baz2();
|
||||
// AST-NEXT: };
|
||||
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz() {
|
||||
// AST-NEXT: BAZ<float> b;
|
||||
// AST-NEXT: }
|
||||
// AST-NEXT: __attribute__((assume("ompx_lambda_assumption"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) int lambda_outer() {
|
||||
// AST-NEXT: auto lambda_inner = []() {
|
||||
// AST-NEXT: return 42;
|
||||
// AST-NEXT: };
|
||||
// AST-NEXT: return lambda_inner();
|
||||
// AST-NEXT: }
|
||||
// AST{LITERAL}: void foo() [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] {
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: class BAR {
|
||||
// AST-NEXT{LITERAL}: public:
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] BAR() {
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void bar1() {
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] static void bar2() {
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: };
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void bar() {
|
||||
// AST-NEXT{LITERAL}: BAR b;
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void baz();
|
||||
// AST-NEXT{LITERAL}: template <typename T> class BAZ {
|
||||
// AST-NEXT{LITERAL}: public:
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] BAZ<T>() {
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void baz1() {
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] static void baz2() {
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: };
|
||||
// AST-NEXT{LITERAL}: template<> class BAZ<float> {
|
||||
// AST-NEXT{LITERAL}: public:
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] BAZ() {
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void baz1();
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] static void baz2();
|
||||
// AST-NEXT{LITERAL}: };
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void baz() {
|
||||
// AST-NEXT{LITERAL}: BAZ<float> b;
|
||||
// AST-NEXT{LITERAL}: }
|
||||
// AST-NEXT{LITERAL}: [[omp::assume("ompx_lambda_assumption")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] int lambda_outer() {
|
||||
// AST-NEXT{LITERAL}: auto lambda_inner = []() {
|
||||
// AST-NEXT{LITERAL}: return 42;
|
||||
// AST-NEXT{LITERAL}: };
|
||||
// AST-NEXT{LITERAL}: return lambda_inner();
|
||||
// AST-NEXT{LITERAL}: }
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -37,8 +37,8 @@ void baz() {
|
||||
}
|
||||
#pragma omp end assumes
|
||||
|
||||
// CHECK: void foo() __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
|
||||
// CHECK: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void bar()
|
||||
// CHECK: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void baz()
|
||||
// CHECK{LITERAL}: void foo() [[omp::assume("omp_no_openmp_routines")]] [[omp::assume("omp_no_openmp")]]
|
||||
// CHECK{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines")]] [[omp::assume("omp_no_openmp")]] void bar()
|
||||
// CHECK{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines")]] [[omp::assume("omp_no_openmp")]] void baz()
|
||||
|
||||
#endif
|
||||
|
@ -17,7 +17,7 @@ template <typename T>
|
||||
struct S {
|
||||
int a;
|
||||
// CHECK: template <typename T> struct S {
|
||||
// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) {
|
||||
// CHECK{LITERAL}: void foo() [[omp::assume("ompx_global_assumption")]] {
|
||||
void foo() {
|
||||
#pragma omp parallel
|
||||
{}
|
||||
@ -25,15 +25,15 @@ struct S {
|
||||
};
|
||||
|
||||
// CHECK: template<> struct S<int> {
|
||||
// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) {
|
||||
// CHECK{LITERAL}: void foo() [[omp::assume("ompx_global_assumption")]] {
|
||||
|
||||
#pragma omp begin assumes no_openmp
|
||||
// CHECK: __attribute__((assume("omp_no_openmp"))) void S_with_assumes_no_call() __attribute__((assume("ompx_global_assumption"))) {
|
||||
// CHECK{LITERAL}: [[omp::assume("omp_no_openmp")]] void S_with_assumes_no_call() [[omp::assume("ompx_global_assumption")]] {
|
||||
void S_with_assumes_no_call() {
|
||||
S<int> s;
|
||||
s.a = 0;
|
||||
}
|
||||
// CHECK: __attribute__((assume("omp_no_openmp"))) void S_with_assumes_call() __attribute__((assume("ompx_global_assumption"))) {
|
||||
// CHECK{LITERAL}: [[omp::assume("omp_no_openmp")]] void S_with_assumes_call() [[omp::assume("ompx_global_assumption")]] {
|
||||
void S_with_assumes_call() {
|
||||
S<int> s;
|
||||
s.a = 0;
|
||||
@ -42,7 +42,7 @@ void S_with_assumes_call() {
|
||||
}
|
||||
#pragma omp end assumes
|
||||
|
||||
// CHECK: void S_without_assumes() __attribute__((assume("ompx_global_assumption"))) {
|
||||
// CHECK{LITERAL}: void S_without_assumes() [[omp::assume("ompx_global_assumption")]] {
|
||||
void S_without_assumes() {
|
||||
S<int> s;
|
||||
s.foo();
|
||||
@ -54,7 +54,7 @@ void S_without_assumes() {
|
||||
template <typename T>
|
||||
struct P {
|
||||
// CHECK: template <typename T> struct P {
|
||||
// CHECK: __attribute__((assume("ompx_global_assumption"))) void foo() {
|
||||
// CHECK{LITERAL}: [[omp::assume("ompx_global_assumption")]] void foo() {
|
||||
int a;
|
||||
void foo() {
|
||||
#pragma omp parallel
|
||||
@ -65,21 +65,21 @@ struct P {
|
||||
// TODO: Avoid the duplication here:
|
||||
|
||||
// CHECK: template<> struct P<int> {
|
||||
// CHECK: __attribute__((assume("ompx_global_assumption"))) __attribute__((assume("ompx_global_assumption"))) void foo() {
|
||||
// CHECK{LITERAL}: [[omp::assume("ompx_global_assumption")]] [[omp::assume("ompx_global_assumption")]] void foo() {
|
||||
|
||||
// CHECK: __attribute__((assume("ompx_global_assumption"))) void P_without_assumes() {
|
||||
// CHECK{LITERAL}: [[omp::assume("ompx_global_assumption")]] void P_without_assumes() {
|
||||
void P_without_assumes() {
|
||||
P<int> p;
|
||||
p.foo();
|
||||
}
|
||||
|
||||
#pragma omp begin assumes no_openmp
|
||||
// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void P_with_assumes_no_call() {
|
||||
// CHECK{LITERAL}: [[omp::assume("omp_no_openmp")]] [[omp::assume("ompx_global_assumption")]] void P_with_assumes_no_call() {
|
||||
void P_with_assumes_no_call() {
|
||||
P<int> p;
|
||||
p.a = 0;
|
||||
}
|
||||
// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void P_with_assumes_call() {
|
||||
// CHECK{LITERAL}: [[omp::assume("omp_no_openmp")]] [[omp::assume("ompx_global_assumption")]] void P_with_assumes_call() {
|
||||
void P_with_assumes_call() {
|
||||
P<int> p;
|
||||
p.a = 0;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// host-no-diagnostics
|
||||
|
||||
void baz(void) __attribute__((assume("omp_no_openmp")));
|
||||
[[omp::assume("omp_no_openmp")]] void baz(void);
|
||||
|
||||
void bar1(void) {
|
||||
#pragma omp parallel // #0
|
||||
@ -24,7 +24,7 @@ void foo1(void) {
|
||||
// all-remark@#2 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}}
|
||||
|
||||
{
|
||||
baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}}
|
||||
baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. [OMP121]}}
|
||||
#pragma omp parallel // #3
|
||||
{
|
||||
}
|
||||
@ -39,7 +39,7 @@ void foo2(void) {
|
||||
#pragma omp target teams // #5
|
||||
// all-remark@#5 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}}
|
||||
{
|
||||
baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}}
|
||||
baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. [OMP121]}}
|
||||
#pragma omp parallel // #6
|
||||
{
|
||||
}
|
||||
@ -57,7 +57,7 @@ void foo3(void) {
|
||||
#pragma omp target teams // #8
|
||||
// all-remark@#8 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}}
|
||||
{
|
||||
baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}}
|
||||
baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. [OMP121]}}
|
||||
#pragma omp parallel // #9
|
||||
{
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
// host-no-diagnostics
|
||||
|
||||
void baz(void) __attribute__((assume("omp_no_openmp")));
|
||||
[[omp::assume("omp_no_openmp")]] void baz(void);
|
||||
|
||||
void bar(void) {
|
||||
#pragma omp parallel // #1 \
|
||||
@ -16,7 +16,7 @@ void foo(void) {
|
||||
#pragma omp target teams // #2
|
||||
// expected-remark@#2 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}}
|
||||
{
|
||||
baz(); // expected-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}}
|
||||
baz(); // expected-remark {{Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. [OMP121]}}
|
||||
#pragma omp parallel
|
||||
{
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s
|
||||
|
||||
void f1(void) __attribute__((assume(3))); // expected-error {{expected string literal as argument of 'assume' attribute}}
|
||||
void f2(void) __attribute__((assume(int))); // expected-error {{expected string literal as argument of 'assume' attribute}}
|
||||
void f3(void) __attribute__((assume(for))); // expected-error {{expected string literal as argument of 'assume' attribute}}
|
||||
void f4(void) __attribute__((assume("QQQQ"))); // expected-warning {{unknown assumption string 'QQQQ'; attribute is potentially ignored}}
|
||||
void f5(void) __attribute__((assume("omp_no_openmp")));
|
||||
void f6(void) __attribute__((assume("omp_noopenmp"))); // expected-warning {{unknown assumption string 'omp_noopenmp' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}}
|
||||
void f7(void) __attribute__((assume("omp_no_openmp_routine"))); // expected-warning {{unknown assumption string 'omp_no_openmp_routine' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp_routines'?}}
|
||||
void f8(void) __attribute__((assume("omp_no_openmp1"))); // expected-warning {{unknown assumption string 'omp_no_openmp1' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}}
|
||||
void f9(void) __attribute__((assume("omp_no_openmp", "omp_no_openmp"))); // expected-error {{'assume' attribute takes one argument}}
|
||||
|
||||
int g1 __attribute__((assume(0))); // expected-error {{expected string literal as argument of 'assume' attribute}}
|
||||
int g2 __attribute__((assume("omp_no_openmp"))); // expected-warning {{'assume' attribute only applies to functions and Objective-C methods}}
|
@ -58,6 +58,11 @@ void g(int x) {
|
||||
[[assume(true)]] while (false) {} // expected-error {{only applies to empty statements}}
|
||||
[[assume(true)]] label:; // expected-error {{cannot be applied to a declaration}}
|
||||
[[assume(true)]] goto label; // expected-error {{only applies to empty statements}}
|
||||
|
||||
// Also check variant spellings.
|
||||
__attribute__((__assume__(true))); // Should not issue a warning because it doesn't use the [[]] spelling.
|
||||
__attribute__((assume(true))) {}; // expected-error {{only applies to empty statements}}
|
||||
[[clang::assume(true)]] {}; // expected-error {{only applies to empty statements}}
|
||||
}
|
||||
|
||||
// Check that 'x' is ODR-used here.
|
||||
@ -143,3 +148,13 @@ template <bool ...val>
|
||||
void f() {
|
||||
[[assume(val)]]; // expected-error {{expression contains unexpanded parameter pack}}
|
||||
}
|
||||
|
||||
namespace gh71858 {
|
||||
int
|
||||
foo (int x, int y)
|
||||
{
|
||||
__attribute__((assume(x == 42)));
|
||||
__attribute__((assume(++y == 43))); // expected-warning {{has side effects that will be discarded}}
|
||||
return x + y;
|
||||
}
|
||||
}
|
||||
|
@ -4238,7 +4238,7 @@ struct AAKernelInfoFunction : AAKernelInfo {
|
||||
ORA << "Value has potential side effects preventing SPMD-mode "
|
||||
"execution";
|
||||
if (isa<CallBase>(NonCompatibleI)) {
|
||||
ORA << ". Add `__attribute__((assume(\"ompx_spmd_amenable\")))` to "
|
||||
ORA << ". Add `[[omp::assume(\"ompx_spmd_amenable\")]]` to "
|
||||
"the called function to override";
|
||||
}
|
||||
return ORA << ".";
|
||||
@ -4380,7 +4380,7 @@ struct AAKernelInfoFunction : AAKernelInfo {
|
||||
continue;
|
||||
auto Remark = [&](OptimizationRemarkAnalysis ORA) {
|
||||
return ORA << "Call may contain unknown parallel regions. Use "
|
||||
<< "`__attribute__((assume(\"omp_no_parallelism\")))` to "
|
||||
<< "`[[omp::assume(\"omp_no_parallelism\")]]` to "
|
||||
"override.";
|
||||
};
|
||||
A.emitRemark<OptimizationRemarkAnalysis>(UnknownParallelRegionCB,
|
||||
|
@ -8,7 +8,7 @@
|
||||
;; void p1(void);
|
||||
;; int unknown(void);
|
||||
;; void unknown_pure(void) __attribute__((pure));
|
||||
;; void unknown_no_openmp(void) __attribute__((assume("omp_no_openmp")));
|
||||
;; [[omp::assume("omp_no_openmp")]] void unknown_no_openmp(void);
|
||||
;;
|
||||
;; int G;
|
||||
;; void no_parallel_region_in_here(void) {
|
||||
|
@ -10,7 +10,7 @@
|
||||
;; void p1(void);
|
||||
;; int unknown(void);
|
||||
;; void unknown_pure(void) __attribute__((pure));
|
||||
;; void unknown_no_openmp(void) __attribute__((assume("omp_no_openmp")));
|
||||
;; [[omp::assume("omp_no_openmp")]] void unknown_no_openmp(void);
|
||||
;;
|
||||
;; int G;
|
||||
;; void no_parallel_region_in_here(void) {
|
||||
|
@ -1,10 +1,10 @@
|
||||
; RUN: opt -passes=openmp-opt -pass-remarks=openmp-opt -pass-remarks-missed=openmp-opt -pass-remarks-analysis=openmp-opt -disable-output < %s 2>&1 | FileCheck %s
|
||||
target triple = "nvptx64"
|
||||
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:11:1: Generic-mode kernel is executed with a customized state machine that requires a fallback.
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:13:5: Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override.
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:15:5: Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override.
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:20:1: Rewriting generic-mode kernel with a customized state machine.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:11:1: Generic-mode kernel is executed with a customized state machine that requires a fallback.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:13:5: Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:15:5: Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:20:1: Rewriting generic-mode kernel with a customized state machine.
|
||||
|
||||
|
||||
;; void unknown(void);
|
||||
@ -24,7 +24,7 @@ target triple = "nvptx64"
|
||||
;; }
|
||||
;; }
|
||||
;;
|
||||
;; void no_openmp(void) __attribute__((assume("omp_no_openmp")));
|
||||
;; [[omp::assume("omp_no_openmp")]] void no_openmp(void);
|
||||
;; void test_no_fallback(void) {
|
||||
;; #pragma omp target teams
|
||||
;; {
|
||||
|
@ -7,7 +7,7 @@
|
||||
; RUN: opt --mtriple=nvptx64-- -S -passes=openmp-opt-postlink < %s | FileCheck %s --check-prefix=NVPTX-DISABLED2
|
||||
|
||||
;; void unknown(void);
|
||||
;; void spmd_amenable(void) __attribute__((assume("ompx_spmd_amenable")));
|
||||
;; [[omp::assume("ompx_spmd_amenable")]] void spmd_amenable(void);
|
||||
;;
|
||||
;; void sequential_loop() {
|
||||
;; #pragma omp target teams
|
||||
@ -22,7 +22,7 @@
|
||||
;; }
|
||||
;; }
|
||||
;;
|
||||
;; void use(__attribute__((noescape)) int *) __attribute__((assume("ompx_spmd_amenable")));
|
||||
;; [[omp::assume("ompx_spmd_amenable")]] void use(__attribute__((noescape)) int *);
|
||||
;;
|
||||
;; void sequential_loop_to_stack_var() {
|
||||
;; #pragma omp target teams
|
||||
|
@ -2,8 +2,8 @@
|
||||
; RUN: opt -S -passes=openmp-opt < %s | FileCheck %s
|
||||
; RUN: opt -S -passes=openmp-opt -openmp-opt-disable-spmdization < %s | FileCheck %s --check-prefix=CHECK-DISABLED
|
||||
;
|
||||
; void pure(void) __attribute__((pure, assume("ompx_spmd_amenable")));
|
||||
; int no_openmp(int *) __attribute__((assume("omp_no_openmp","ompx_spmd_amenable")));
|
||||
; [[omp::assume("ompx_spmd_amenable")]] void pure(void) __attribute__((pure));
|
||||
; [[omp::assume("omp_no_openmp","ompx_spmd_amenable")]] int no_openmp(int *);
|
||||
;
|
||||
; void sequential_loop(int *x, int N) {
|
||||
; #pragma omp target teams
|
||||
|
@ -1,12 +1,12 @@
|
||||
; RUN: opt -passes=openmp-opt -pass-remarks=openmp-opt -pass-remarks-missed=openmp-opt -pass-remarks-analysis=openmp-opt -disable-output < %s 2>&1 | FileCheck %s
|
||||
target triple = "nvptx64"
|
||||
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:13:5: Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override.
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:15:5: Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override.
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:11:1: Generic-mode kernel is executed with a customized state machine that requires a fallback.
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:13:5: Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override.
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:15:5: Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override.
|
||||
; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:20:1: Transformed generic-mode kernel to SPMD-mode.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:13:5: Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:15:5: Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:11:1: Generic-mode kernel is executed with a customized state machine that requires a fallback.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:13:5: Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:15:5: Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override.
|
||||
; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:20:1: Transformed generic-mode kernel to SPMD-mode.
|
||||
|
||||
|
||||
;; void unknown(void);
|
||||
@ -26,7 +26,7 @@ target triple = "nvptx64"
|
||||
;; }
|
||||
;; }
|
||||
;;
|
||||
;; void no_openmp(void) __attribute__((assume("omp_no_openmp")));
|
||||
;; void no_openmp(void) [[omp::assume("omp_no_openmp")]];
|
||||
;; void test_no_fallback(void) {
|
||||
;; #pragma omp target teams
|
||||
;; {
|
||||
|
@ -1,6 +1,6 @@
|
||||
.. _omp121:
|
||||
|
||||
Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume(\"ompx_spmd_amenable\")))` to the called function to override. [OMP121]
|
||||
Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume(\"ompx_spmd_amenable\")]]` to the called function to override. [OMP121]
|
||||
===================================================================================================================================================================
|
||||
|
||||
This analysis remarks indicates that a potential side-effect that cannot be
|
||||
@ -42,7 +42,7 @@ or operations that cannot be executed in SPMD-mode.
|
||||
|
||||
$ clang++ -fopenmp -fopenmp-targets=nvptx64 -O2 -Rpass-analysis=openmp-opt omp121.cpp
|
||||
omp121.cpp:8:13: remark: Value has potential side effects preventing SPMD-mode
|
||||
execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function
|
||||
execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function
|
||||
to override. [OMP121]
|
||||
int x = work();
|
||||
^
|
||||
@ -53,7 +53,7 @@ contain any code that prevents SPMD-mode execution.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
__attribute__((assume("ompx_spmd_amenable"))) extern int work();
|
||||
[[omp::assume("ompx_spmd_amenable")]] extern int work();
|
||||
|
||||
void use(int x);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override. [OMP133]
|
||||
Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override. [OMP133]
|
||||
====================================================================================================================
|
||||
|
||||
.. _omp133:
|
||||
@ -33,7 +33,7 @@ regions. This is typically coupled with the :ref:`OMP132 <omp132>` remark.
|
||||
|
||||
$ clang++ -fopenmp -fopenmp-targets=nvptx64 -O2 -Rpass-analysis=openmp-opt omp133.cpp
|
||||
omp133.cpp:6:5: remark: Call may contain unknown parallel regions. Use
|
||||
`__attribute__((assume("omp_no_parallelism")))` to override. [OMP133]
|
||||
`[[omp::assume("omp_no_parallelism")]]` to override. [OMP133]
|
||||
setup();
|
||||
^
|
||||
|
||||
@ -43,7 +43,7 @@ specialized state machine.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
__attribute__((assume("omp_no_parallelism"))) extern void setup();
|
||||
[[omp::assume("omp_no_parallelism")]] extern void setup();
|
||||
|
||||
|
||||
void foo() {
|
||||
|
@ -81,7 +81,7 @@ OpenMP Remarks
|
||||
* - :ref:`OMP121 <omp121>`
|
||||
- Analysis
|
||||
- Value has potential side effects preventing SPMD-mode execution. Add
|
||||
`__attribute__((assume(\"ompx_spmd_amenable\")))` to the called function
|
||||
`[[omp::assume(\"ompx_spmd_amenable\")]]` to the called function
|
||||
to override.
|
||||
* - :ref:`OMP130 <omp130>`
|
||||
- Optimization
|
||||
@ -96,7 +96,7 @@ OpenMP Remarks
|
||||
* - :ref:`OMP133 <omp133>`
|
||||
- Analysis
|
||||
- Call may contain unknown parallel regions. Use
|
||||
`__attribute__((assume("omp_no_parallelism")))` to override.
|
||||
`[[omp::assume("omp_no_parallelism")]]` to override.
|
||||
* - :ref:`OMP140 <omp140>`
|
||||
- Analysis
|
||||
- Could not internalize function. Some optimizations may not be possible.
|
||||
|
Loading…
x
Reference in New Issue
Block a user