Skip to content

Commit 4337a97

Browse files
committed
[OpenMP] OpenMP 5.1 "assume" directive parsing support
This is a minimal patch to support parsing for "omp assume" directives. These are meant to be hints to a compiler' optimisers: as such, it is legitimate (if not very useful) to ignore them. The patch builds on top of the existing support for "omp assumes" directives (note spelling!). Unlike the "omp [begin/end] assumes" directives, "omp assume" is associated with a compound statement, i.e. it can appear within a function. The "holds" assumption could (theoretically) be mapped onto the existing builtin "__builtin_assume", though the latter applies to a single point in the program, and the former to a range (i.e. the whole of the associated compound statement). This patch fixes sollve's OpenMP 5.1 "omp assume"-based tests. Change-Id: Ibd4a0e2af82c4ac818eaa3de8867a006307361ec
1 parent bf4eaec commit 4337a97

File tree

7 files changed

+146
-1
lines changed

7 files changed

+146
-1
lines changed

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2444,6 +2444,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
24442444
case OMPD_target_teams_loop:
24452445
case OMPD_parallel_loop:
24462446
case OMPD_target_parallel_loop:
2447+
case OMPD_assume:
24472448
Diag(Tok, diag::err_omp_unexpected_directive)
24482449
<< 1 << getOpenMPDirectiveName(DKind);
24492450
break;
@@ -3023,6 +3024,27 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
30233024
<< 1 << getOpenMPDirectiveName(DKind);
30243025
SkipUntil(tok::annot_pragma_openmp_end);
30253026
break;
3027+
case OMPD_assume: {
3028+
ParseScope OMPDirectiveScope(this, Scope::FnScope | Scope::DeclScope |
3029+
Scope::CompoundStmtScope);
3030+
ParseOpenMPAssumesDirective(DKind, ConsumeToken());
3031+
3032+
SkipUntil(tok::annot_pragma_openmp_end);
3033+
3034+
ParsingOpenMPDirectiveRAII NormalScope(*this);
3035+
StmtResult AssociatedStmt;
3036+
{
3037+
Sema::CompoundScopeRAII Scope(Actions);
3038+
AssociatedStmt = ParseStatement();
3039+
EndLoc = Tok.getLocation();
3040+
Directive = Actions.ActOnCompoundStmt(Loc, EndLoc,
3041+
AssociatedStmt.get(),
3042+
/*isStmtExpr=*/false);
3043+
}
3044+
ParseOpenMPEndAssumesDirective(Loc);
3045+
OMPDirectiveScope.Exit();
3046+
break;
3047+
}
30263048
case OMPD_unknown:
30273049
default:
30283050
Diag(Tok, diag::err_omp_unknown_directive);

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3511,7 +3511,8 @@ void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
35113511

35123512
auto *AA =
35133513
OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3514-
if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3514+
if (DKind == llvm::omp::Directive::OMPD_begin_assumes ||
3515+
DKind == llvm::omp::Directive::OMPD_assume) {
35153516
OMPAssumeScoped.push_back(AA);
35163517
return;
35173518
}

clang/test/OpenMP/assume_lambda.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -ast-print %s | FileCheck %s
2+
// expected-no-diagnostics
3+
4+
extern int bar(int);
5+
6+
int foo(int arg)
7+
{
8+
#pragma omp assume no_openmp_routines
9+
{
10+
auto fn = [](int x) { return bar(x); };
11+
// CHECK: auto fn = [](int x) {
12+
return fn(5);
13+
}
14+
}
15+
16+
class C {
17+
public:
18+
int foo(int a);
19+
};
20+
21+
// We're really just checking that this parses. All the assumptions are thrown
22+
// away immediately for now.
23+
int C::foo(int a)
24+
{
25+
#pragma omp assume holds(sizeof(T) == 8) absent(parallel)
26+
{
27+
auto fn = [](int x) { return bar(x); };
28+
// CHECK: auto fn = [](int x) {
29+
return fn(5);
30+
}
31+
}

clang/test/OpenMP/assume_messages.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp -x c -std=c99 %s
2+
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp-simd -x c -std=c99 %s
3+
4+
#pragma omp assume no_openmp // expected-error {{unexpected OpenMP directive '#pragma omp assume'}}
5+
6+
void foo(void) {
7+
#pragma omp assume hold(1==1) // expected-warning {{valid assume clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note {{the ignored tokens spans until here}}
8+
{}
9+
}
10+
11+
void bar(void) {
12+
#pragma omp assume absent(target)
13+
} // expected-error {{expected statement}}
14+
15+
void qux(void) {
16+
#pragma omp assume extra_bits // expected-warning {{valid assume clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}}
17+
{}
18+
}
19+
20+
void quux(void) {
21+
#pragma omp assume ext_spelled_properly
22+
{}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp -x c -std=c99 %s
2+
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp-simd -x c -std=c99 %s
3+
4+
[[omp::directive(assume no_openmp)]] // expected-error {{unexpected OpenMP directive '#pragma omp assume'}}
5+
6+
void foo(void) {
7+
[[omp::directive(assume hold(1==1))]] // expected-warning {{valid assume clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note {{the ignored tokens spans until here}}
8+
{}
9+
}
10+
11+
void bar(void) {
12+
[[omp::directive(assume absent(target))]]
13+
} // expected-error {{expected statement}}
14+
15+
void qux(void) {
16+
[[omp::directive(assume extra_bits)]] // expected-warning {{valid assume clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}}
17+
{}
18+
}
19+
20+
void quux(void) {
21+
[[omp::directive(assume ext_spelled_properly)]]
22+
{}
23+
}

clang/test/OpenMP/assume_template.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
2+
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
3+
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -verify %s -ast-print | FileCheck %s
4+
// expected-no-diagnostics
5+
6+
#ifndef HEADER
7+
#define HEADER
8+
9+
extern int qux(int);
10+
11+
template<typename T>
12+
int foo(T arg)
13+
{
14+
#pragma omp assume no_openmp_routines
15+
{
16+
auto fn = [](int x) { return qux(x); };
17+
// CHECK: auto fn = [](int x) {
18+
return fn(5);
19+
}
20+
}
21+
22+
template<typename T>
23+
class C {
24+
T m;
25+
26+
public:
27+
T bar(T a);
28+
};
29+
30+
// We're really just checking this parses. All the assumptions are thrown
31+
// away immediately for now.
32+
template<typename T>
33+
T C<T>::bar(T a)
34+
{
35+
#pragma omp assume holds(sizeof(T) == 8) absent(parallel)
36+
{
37+
return (T)qux((int)a);
38+
// CHECK: return (T)qux((int)a);
39+
}
40+
}
41+
42+
#endif

llvm/include/llvm/Frontend/OpenMP/OMP.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,6 +2088,9 @@ def OMP_Scan : Directive<"scan"> {
20882088
];
20892089
let association = AS_Separating;
20902090
}
2091+
def OMP_Assume : Directive<"assume"> {
2092+
let association = AS_Block;
2093+
}
20912094
def OMP_Assumes : Directive<"assumes"> {
20922095
let association = AS_None;
20932096
}

0 commit comments

Comments
 (0)