The tile directive is in OpenMP's Technical Report 8 and foreseeably will be part of the upcoming OpenMP 5.1 standard. This implementation is based on an AST transformation providing a de-sugared loop nest. This makes it simple to forward the de-sugared transformation to loop associated directives taking the tiled loops. In contrast to other loop associated directives, the OMPTileDirective does not use CapturedStmts. Letting loop associated directives consume loops from different capture context would be difficult. A significant amount of code generation logic is taking place in the Sema class. Eventually, I would prefer if these would move into the CodeGen component such that we could make use of the OpenMPIRBuilder, together with flang. Only expressions converting between the language's iteration variable and the logical iteration space need to take place in the semantic analyzer: Getting the of iterations (e.g. the overload resolution of `std::distance`) and converting the logical iteration number to the iteration variable (e.g. overload resolution of `iteration + .omp.iv`). In clang, only CXXForRangeStmt is also represented by its de-sugared components. However, OpenMP loop are not defined as syntatic sugar. Starting with an AST-based approach allows us to gradually move generated AST statements into CodeGen, instead all at once. I would also like to refactor `checkOpenMPLoop` into its functionalities in a follow-up. In this patch it is used twice. Once for checking proper nesting and emitting diagnostics, and additionally for deriving the logical iteration space per-loop (instead of for the loop nest). Differential Revision: https://reviews.llvm.org/D76342
166 lines
5.0 KiB
C++
166 lines
5.0 KiB
C++
// Check no warnings/errors
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 -fsyntax-only -verify %s
|
|
// expected-no-diagnostics
|
|
|
|
// Check AST and unparsing
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 -ast-dump %s | FileCheck %s --check-prefix=DUMP
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 -ast-print %s | FileCheck %s --check-prefix=PRINT
|
|
|
|
// Check same results after serialization round-trip
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 -emit-pch -o %t %s
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 -include-pch %t -ast-print %s | FileCheck %s --check-prefix=PRINT
|
|
|
|
#ifndef HEADER
|
|
#define HEADER
|
|
|
|
// placeholder for loop body code.
|
|
extern "C" void body(...);
|
|
|
|
|
|
// PRINT-LABEL: void foo1(
|
|
// DUMP-LABEL: FunctionDecl {{.*}} foo1
|
|
void foo1() {
|
|
// PRINT: #pragma omp tile sizes(5, 5)
|
|
// DUMP: OMPTileDirective
|
|
// DUMP-NEXT: OMPSizesClause
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 5
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 5
|
|
#pragma omp tile sizes(5,5)
|
|
// PRINT: for (int i = 7; i < 17; i += 3)
|
|
// DUMP-NEXT: ForStmt
|
|
for (int i = 7; i < 17; i += 3)
|
|
// PRINT: for (int j = 7; j < 17; j += 3)
|
|
// DUMP: ForStmt
|
|
for (int j = 7; j < 17; j += 3)
|
|
// PRINT: body(i, j);
|
|
// DUMP: CallExpr
|
|
body(i, j);
|
|
}
|
|
|
|
|
|
// PRINT-LABEL: void foo2(
|
|
// DUMP-LABEL: FunctionDecl {{.*}} foo2
|
|
void foo2(int start1, int start2, int end1, int end2) {
|
|
// PRINT: #pragma omp tile sizes(5, 5)
|
|
// DUMP: OMPTileDirective
|
|
// DUMP-NEXT: OMPSizesClause
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 5
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 5
|
|
#pragma omp tile sizes(5,5)
|
|
// PRINT: for (int i = start1; i < end1; i += 1)
|
|
// DUMP-NEXT: ForStmt
|
|
for (int i = start1; i < end1; i += 1)
|
|
// PRINT: for (int j = start2; j < end2; j += 1)
|
|
// DUMP: ForStmt
|
|
for (int j = start2; j < end2; j += 1)
|
|
// PRINT: body(i, j);
|
|
// DUMP: CallExpr
|
|
body(i, j);
|
|
}
|
|
|
|
|
|
// PRINT-LABEL: void foo3(
|
|
// DUMP-LABEL: FunctionDecl {{.*}} foo3
|
|
void foo3() {
|
|
// PRINT: #pragma omp for
|
|
// DUMP: OMPForDirective
|
|
// DUMP-NEXT: CapturedStmt
|
|
// DUMP-NEXT: CapturedDecl
|
|
#pragma omp for
|
|
// PRINT: #pragma omp tile sizes(5)
|
|
// DUMP-NEXT: OMPTileDirective
|
|
// DUMP-NEXT: OMPSizesClause
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 5
|
|
#pragma omp tile sizes(5)
|
|
for (int i = 7; i < 17; i += 3)
|
|
// PRINT: body(i);
|
|
// DUMP: CallExpr
|
|
body(i);
|
|
}
|
|
|
|
|
|
// PRINT-LABEL: void foo4(
|
|
// DUMP-LABEL: FunctionDecl {{.*}} foo4
|
|
void foo4() {
|
|
// PRINT: #pragma omp for collapse(3)
|
|
// DUMP: OMPForDirective
|
|
// DUMP-NEXT: OMPCollapseClause
|
|
// DUMP-NEXT: ConstantExpr
|
|
// DUMP-NEXT: value: Int 3
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 3
|
|
// DUMP-NEXT: CapturedStmt
|
|
// DUMP-NEXT: CapturedDecl
|
|
#pragma omp for collapse(3)
|
|
// PRINT: #pragma omp tile sizes(5, 5)
|
|
// DUMP: OMPTileDirective
|
|
// DUMP-NEXT: OMPSizesClause
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 5
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 5
|
|
#pragma omp tile sizes(5, 5)
|
|
// PRINT: for (int i = 7; i < 17; i += 1)
|
|
// DUMP-NEXT: ForStmt
|
|
for (int i = 7; i < 17; i += 1)
|
|
// PRINT: for (int j = 7; j < 17; j += 1)
|
|
// DUMP: ForStmt
|
|
for (int j = 7; j < 17; j += 1)
|
|
// PRINT: body(i, j);
|
|
// DUMP: CallExpr
|
|
body(i, j);
|
|
}
|
|
|
|
|
|
// PRINT-LABEL: void foo5(
|
|
// DUMP-LABEL: FunctionDecl {{.*}} foo5
|
|
void foo5(int start, int end, int step) {
|
|
// PRINT: #pragma omp for collapse(2)
|
|
// DUMP: OMPForDirective
|
|
// DUMP-NEXT: OMPCollapseClause
|
|
// DUMP-NEXT: ConstantExpr
|
|
// DUMP-NEXT: value: Int 2
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 2
|
|
// DUMP-NEXT: CapturedStmt
|
|
// DUMP-NEXT: CapturedDecl
|
|
#pragma omp for collapse(2)
|
|
// PRINT: for (int i = 7; i < 17; i += 1)
|
|
// DUMP-NEXT: ForStmt
|
|
for (int i = 7; i < 17; i += 1)
|
|
// PRINT: #pragma omp tile sizes(5)
|
|
// DUMP: OMPTileDirective
|
|
// DUMP-NEXT: OMPSizesClause
|
|
// DUMP-NEXT: IntegerLiteral {{.*}} 5
|
|
#pragma omp tile sizes(5)
|
|
// PRINT: for (int j = 7; j < 17; j += 1)
|
|
// DUMP-NEXT: ForStmt
|
|
for (int j = 7; j < 17; j += 1)
|
|
// PRINT: body(i, j);
|
|
// DUMP: CallExpr
|
|
body(i, j);
|
|
}
|
|
|
|
|
|
// PRINT-LABEL: void foo6(
|
|
// DUMP-LABEL: FunctionTemplateDecl {{.*}} foo6
|
|
template<typename T, T Step, T Tile>
|
|
void foo6(T start, T end) {
|
|
// PRINT: #pragma omp tile sizes(Tile)
|
|
// DUMP: OMPTileDirective
|
|
// DUMP-NEXT: OMPSizesClause
|
|
// DUMP-NEXT: DeclRefExpr {{.*}} 'Tile' 'T'
|
|
#pragma omp tile sizes(Tile)
|
|
// PRINT-NEXT: for (T i = start; i < end; i += Step)
|
|
// DUMP-NEXT: ForStmt
|
|
for (T i = start; i < end; i += Step)
|
|
// PRINT-NEXT: body(i);
|
|
// DUMP: CallExpr
|
|
body(i);
|
|
}
|
|
|
|
// Also test instantiating the template.
|
|
void tfoo6() {
|
|
foo6<int,3,5>(0, 42);
|
|
}
|
|
|
|
|
|
#endif
|