Skip to content

Commit 73165de

Browse files
authored
[OpenMP] implementation set controls elision for begin declare variant (#139287)
The device and implementation set should trigger elision of tokens if they do not match statically in a begin/end declare variant. This simply extends the logic from the device set only and includes the implementation set. Reported by @kkwli.
1 parent a3d027f commit 73165de

File tree

6 files changed

+59
-82
lines changed

6 files changed

+59
-82
lines changed

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2282,7 +2282,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
22822282
/* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>(),
22832283
Actions.OpenMP().getOpenMPDeviceNum());
22842284

2285-
if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) {
2285+
if (isVariantApplicableInContext(VMI, OMPCtx,
2286+
/*DeviceOrImplementationSetOnly=*/true)) {
22862287
Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);
22872288
break;
22882289
}

clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,13 @@ int main(void) {
2929
// - we do use the original pointers for the calls as the variants are not applicable (this is not the ibm compiler).
3030

3131
// CHECK: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
32-
// CHECK-NEXT: | |-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
33-
// CHECK-NEXT: | | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
34-
// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 0
35-
// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_4:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(ibm)}
36-
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_5:0x[a-z0-9]*]] <line:13:1> 'int ({{.*}})' Function [[ADDR_6:0x[a-z0-9]*]] 'also_before[implementation={vendor(ibm)}]' 'int ({{.*}})'
37-
// CHECK-NEXT: |-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] <line:10:1, col:20> col:5 implicit used also_after 'int ({{.*}})'
38-
// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_8:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(ibm)}
39-
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_9:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_10:0x[a-z0-9]*]] 'also_after[implementation={vendor(ibm)}]' 'int ({{.*}})'
40-
// CHECK-NEXT: |-FunctionDecl [[ADDR_10]] <col:1, line:12:1> line:10:1 also_after[implementation={vendor(ibm)}] 'int ({{.*}})'
41-
// CHECK-NEXT: | `-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] <col:22, line:12:1>
42-
// CHECK-NEXT: | `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] <line:11:3, col:10>
43-
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] <col:10> 'int' 1
44-
// CHECK-NEXT: |-FunctionDecl [[ADDR_6]] <line:13:1, line:15:1> line:13:1 also_before[implementation={vendor(ibm)}] 'int ({{.*}})'
45-
// CHECK-NEXT: | `-CompoundStmt [[ADDR_14:0x[a-z0-9]*]] <col:23, line:15:1>
46-
// CHECK-NEXT: | `-ReturnStmt [[ADDR_15:0x[a-z0-9]*]] <line:14:3, col:10>
47-
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_16:0x[a-z0-9]*]] <col:10> 'int' 2
48-
// CHECK-NEXT: |-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] prev [[ADDR_7]] <line:18:1, line:20:1> line:18:5 used also_after 'int ({{.*}})'
49-
// CHECK-NEXT: | |-CompoundStmt [[ADDR_18:0x[a-z0-9]*]] <col:22, line:20:1>
50-
// CHECK-NEXT: | | `-ReturnStmt [[ADDR_19:0x[a-z0-9]*]] <line:19:3, col:10>
51-
// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_20:0x[a-z0-9]*]] <col:10> 'int' 0
52-
// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_21:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(ibm)}
53-
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_9]] <line:10:1> 'int ({{.*}})' Function [[ADDR_10]] 'also_after[implementation={vendor(ibm)}]' 'int ({{.*}})'
32+
// CHECK-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
33+
// CHECK-NEXT: | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
34+
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 0
35+
// CHECK-NEXT: |-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] <line:18:1, line:20:1> line:18:5 used also_after 'int ({{.*}})'
36+
// CHECK-NEXT: | `-CompoundStmt [[ADDR_18:0x[a-z0-9]*]] <col:22, line:20:1>
37+
// CHECK-NEXT: | `-ReturnStmt [[ADDR_19:0x[a-z0-9]*]] <line:19:3, col:10>
38+
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_20:0x[a-z0-9]*]] <col:10> 'int' 0
5439
// CHECK-NEXT: `-FunctionDecl [[ADDR_22:0x[a-z0-9]*]] <line:22:1, line:25:1> line:22:5 main 'int ({{.*}})'
5540
// CHECK-NEXT: `-CompoundStmt [[ADDR_23:0x[a-z0-9]*]] <col:16, line:25:1>
5641
// CHECK-NEXT: `-ReturnStmt [[ADDR_24:0x[a-z0-9]*]] <line:24:3, col:37>
Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s
2-
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s
3-
// expected-no-diagnostics
1+
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify=C -ast-dump %s | FileCheck %s --check-prefixes=CHECK,C
2+
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify=CXX -ast-dump %s -x c++| FileCheck %s --check-prefixes=CHECK,CXX
3+
44

55
int OK_1(void);
66

@@ -23,59 +23,30 @@ int OK_3(void);
2323

2424
int test(void) {
2525
// Should cause an error due to not_OK()
26-
return OK_1() + not_OK() + OK_3();
26+
return OK_1() + not_OK() + OK_3(); // CXX-error {{use of undeclared identifier 'not_OK'}} C-error {{call to undeclared function 'not_OK'; ISO C99 and later do not support implicit function declarations}}
2727
}
2828

2929
// Make sure:
3030
// - we see a single error for `not_OK`
3131
// - we do not see errors for OK_{1,2,3}
32-
// FIXME: We actually do not see there error here.
33-
// This case is unlikely to happen in practise and hard to diagnose during SEMA.
34-
// We will issue an error during code generation instead. This is similar to the
35-
// diagnosis in other multi-versioning schemes.
3632

3733
// CHECK: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, col:14> col:5 used OK_1 'int ({{.*}})'
38-
// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_1:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(intel)}
39-
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_2:0x[a-z0-9]*]] <line:8:1> 'int ({{.*}})' Function [[ADDR_3:0x[a-z0-9]*]] 'OK_1[implementation={vendor(intel)}]' 'int ({{.*}})'
40-
// CHECK-NEXT: |-FunctionDecl [[ADDR_3]] <col:1, line:10:1> line:8:1 OK_1[implementation={vendor(intel)}] 'int ({{.*}})'
41-
// CHECK-NEXT: | `-CompoundStmt [[ADDR_4:0x[a-z0-9]*]] <col:16, line:10:1>
42-
// CHECK-NEXT: | `-ReturnStmt [[ADDR_5:0x[a-z0-9]*]] <line:9:3, col:10>
43-
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_6:0x[a-z0-9]*]] <col:10> 'int' 1
44-
// CHECK-NEXT: |-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] <line:11:1, col:14> col:5 implicit OK_2 'int ({{.*}})'
45-
// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_8:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(intel)}
46-
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_9:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_10:0x[a-z0-9]*]] 'OK_2[implementation={vendor(intel)}]' 'int ({{.*}})'
47-
// CHECK-NEXT: |-FunctionDecl [[ADDR_10]] <col:1, line:13:1> line:11:1 OK_2[implementation={vendor(intel)}] 'int ({{.*}})'
48-
// CHECK-NEXT: | `-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] <col:16, line:13:1>
49-
// CHECK-NEXT: | `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] <line:12:3, col:10>
50-
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] <col:10> 'int' 1
51-
// CHECK-NEXT: |-FunctionDecl [[ADDR_14:0x[a-z0-9]*]] <line:14:1, col:16> col:5 implicit used not_OK 'int ({{.*}})'
52-
// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_15:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(intel)}
53-
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_16:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_17:0x[a-z0-9]*]] 'not_OK[implementation={vendor(intel)}]' 'int ({{.*}})'
54-
// CHECK-NEXT: |-FunctionDecl [[ADDR_17]] <col:1, line:16:1> line:14:1 not_OK[implementation={vendor(intel)}] 'int ({{.*}})'
55-
// CHECK-NEXT: | `-CompoundStmt [[ADDR_18:0x[a-z0-9]*]] <col:18, line:16:1>
56-
// CHECK-NEXT: | `-ReturnStmt [[ADDR_19:0x[a-z0-9]*]] <line:15:3, col:10>
57-
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_20:0x[a-z0-9]*]] <col:10> 'int' 1
58-
// CHECK-NEXT: |-FunctionDecl [[ADDR_21:0x[a-z0-9]*]] <line:17:1, col:14> col:5 implicit used OK_3 'int ({{.*}})'
59-
// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_22:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(intel)}
60-
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_23:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_24:0x[a-z0-9]*]] 'OK_3[implementation={vendor(intel)}]' 'int ({{.*}})'
61-
// CHECK-NEXT: |-FunctionDecl [[ADDR_24]] <col:1, line:19:1> line:17:1 OK_3[implementation={vendor(intel)}] 'int ({{.*}})'
62-
// CHECK-NEXT: | `-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] <col:16, line:19:1>
63-
// CHECK-NEXT: | `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] <line:18:3, col:10>
64-
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_27:0x[a-z0-9]*]] <col:10> 'int' 1
65-
// CHECK-NEXT: |-FunctionDecl [[ADDR_28:0x[a-z0-9]*]] prev [[ADDR_21]] <line:22:1, col:14> col:5 used OK_3 'int ({{.*}})'
66-
// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_29:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(intel)}
67-
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_23]] <line:17:1> 'int ({{.*}})' Function [[ADDR_24]] 'OK_3[implementation={vendor(intel)}]' 'int ({{.*}})'
34+
// CHECK-NEXT: |-FunctionDecl [[ADDR_28:0x[a-z0-9]*]] <line:22:1, col:14> col:5 used OK_3 'int ({{.*}})'
6835
// CHECK-NEXT: `-FunctionDecl [[ADDR_30:0x[a-z0-9]*]] <line:24:1, line:27:1> line:24:5 test 'int ({{.*}})'
6936
// CHECK-NEXT: `-CompoundStmt [[ADDR_31:0x[a-z0-9]*]] <col:16, line:27:1>
7037
// CHECK-NEXT: `-ReturnStmt [[ADDR_32:0x[a-z0-9]*]] <line:26:3, col:35>
71-
// CHECK-NEXT: `-BinaryOperator [[ADDR_33:0x[a-z0-9]*]] <col:10, col:35> 'int' '+'
72-
// CHECK-NEXT: |-BinaryOperator [[ADDR_34:0x[a-z0-9]*]] <col:10, col:26> 'int' '+'
38+
// C: `-BinaryOperator [[ADDR_33:0x[a-z0-9]*]] <col:10, col:35> 'int' '+'
39+
// C-NEXT: |-BinaryOperator [[ADDR_34:0x[a-z0-9]*]] <col:10, col:26> 'int' '+'
40+
// CXX: `-BinaryOperator [[ADDR_33:0x[a-z0-9]*]] <col:10, col:35> '<dependent type>' contains-errors '+'
41+
// CXX-NEXT: |-BinaryOperator [[ADDR_34:0x[a-z0-9]*]] <col:10, col:26> '<dependent type>' contains-errors '+'
7342
// CHECK-NEXT: | |-CallExpr [[ADDR_35:0x[a-z0-9]*]] <col:10, col:15> 'int'
7443
// CHECK-NEXT: | | `-ImplicitCastExpr [[ADDR_36:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <FunctionToPointerDecay>
7544
// CHECK-NEXT: | | `-DeclRefExpr [[ADDR_37:0x[a-z0-9]*]] <col:10> 'int ({{.*}})' {{.*}}Function [[ADDR_0]] 'OK_1' 'int ({{.*}})'
76-
// CHECK-NEXT: | `-CallExpr [[ADDR_38:0x[a-z0-9]*]] <col:19, col:26> 'int'
77-
// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_39:0x[a-z0-9]*]] <col:19> 'int (*)({{.*}})' <FunctionToPointerDecay>
78-
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] <col:19> 'int ({{.*}})' {{.*}}Function [[ADDR_14]] 'not_OK' 'int ({{.*}})'
45+
// C: | `-CallExpr [[ADDR_38:0x[a-z0-9]*]] <col:19, col:26> 'int'
46+
// C-NEXT: | `-ImplicitCastExpr [[ADDR_39:0x[a-z0-9]*]] <col:19> 'int (*)({{.*}})' <FunctionToPointerDecay>
47+
// C-NEXT: | `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] <col:19> 'int ({{.*}})' {{.*}}Function {{.*}} 'not_OK' 'int ({{.*}})'
48+
// CXX: | `-RecoveryExpr {{.*}} <col:19, col:26> '<dependent type>' contains-errors lvalue
49+
// CXX-NEXT: | `-UnresolvedLookupExpr {{.*}} <col:19> '<overloaded function type>' lvalue (ADL) = 'not_OK' empty
7950
// CHECK-NEXT: `-CallExpr [[ADDR_41:0x[a-z0-9]*]] <col:30, col:35> 'int'
8051
// CHECK-NEXT: `-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <col:30> 'int (*)({{.*}})' <FunctionToPointerDecay>
8152
// CHECK-NEXT: `-DeclRefExpr [[ADDR_43:0x[a-z0-9]*]] <col:30> 'int ({{.*}})' {{.*}}Function [[ADDR_28]] 'OK_3' 'int ({{.*}})'
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
2+
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
3+
4+
// expected-no-diagnostics
5+
6+
#pragma omp begin declare variant match(implementation={vendor(llvm)})
7+
typedef int bar;
8+
void f() {}
9+
#pragma omp end declare variant
10+
11+
#pragma omp begin declare variant match(implementation={vendor(ibm)})
12+
typedef float bar;
13+
void f() {}
14+
#pragma omp end declare variant

llvm/include/llvm/Frontend/OpenMP/OMPContext.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,13 @@ struct OMPContext {
180180
};
181181

182182
/// Return true if \p VMI is applicable in \p Ctx, that is, all traits required
183-
/// by \p VMI are available in the OpenMP context \p Ctx. If \p DeviceSetOnly is
184-
/// true, only the device selector set, if present, are checked. Note that we
185-
/// still honor extension traits provided by the user.
183+
/// by \p VMI are available in the OpenMP context \p Ctx. If
184+
/// \p DeviceOrImplementationSetOnly is true, only the device and implementation
185+
/// selector set, if present, are checked. Note that we still honor extension
186+
/// traits provided by the user.
186187
bool isVariantApplicableInContext(const VariantMatchInfo &VMI,
187188
const OMPContext &Ctx,
188-
bool DeviceSetOnly = false);
189+
bool DeviceOrImplementationSetOnly = false);
189190

190191
/// Return the index (into \p VMIs) of the variant with the highest score
191192
/// from the ones applicable in \p Ctx. See llvm::isVariantApplicableInContext.

llvm/lib/Frontend/OpenMP/OMPContext.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,11 @@ static bool isStrictSubset(const VariantMatchInfo &VMI0,
193193
return true;
194194
}
195195

196-
static int isVariantApplicableInContextHelper(
197-
const VariantMatchInfo &VMI, const OMPContext &Ctx,
198-
SmallVectorImpl<unsigned> *ConstructMatches, bool DeviceSetOnly) {
196+
static int
197+
isVariantApplicableInContextHelper(const VariantMatchInfo &VMI,
198+
const OMPContext &Ctx,
199+
SmallVectorImpl<unsigned> *ConstructMatches,
200+
bool DeviceOrImplementationSetOnly) {
199201

200202
// The match kind determines if we need to match all traits, any of the
201203
// traits, or none of the traits for it to be an applicable context.
@@ -245,8 +247,10 @@ static int isVariantApplicableInContextHelper(
245247

246248
for (unsigned Bit : VMI.RequiredTraits.set_bits()) {
247249
TraitProperty Property = TraitProperty(Bit);
248-
if (DeviceSetOnly &&
249-
getOpenMPContextTraitSetForProperty(Property) != TraitSet::device)
250+
if (DeviceOrImplementationSetOnly &&
251+
getOpenMPContextTraitSetForProperty(Property) != TraitSet::device &&
252+
getOpenMPContextTraitSetForProperty(Property) !=
253+
TraitSet::implementation)
250254
continue;
251255

252256
// So far all extensions are handled elsewhere, we skip them here as they
@@ -272,7 +276,7 @@ static int isVariantApplicableInContextHelper(
272276
return *Result;
273277
}
274278

275-
if (!DeviceSetOnly) {
279+
if (!DeviceOrImplementationSetOnly) {
276280
// We could use isSubset here but we also want to record the match
277281
// locations.
278282
unsigned ConstructIdx = 0, NoConstructTraits = Ctx.ConstructTraits.size();
@@ -315,11 +319,11 @@ static int isVariantApplicableInContextHelper(
315319
return true;
316320
}
317321

318-
bool llvm::omp::isVariantApplicableInContext(const VariantMatchInfo &VMI,
319-
const OMPContext &Ctx,
320-
bool DeviceSetOnly) {
322+
bool llvm::omp::isVariantApplicableInContext(
323+
const VariantMatchInfo &VMI, const OMPContext &Ctx,
324+
bool DeviceOrImplementationSetOnly) {
321325
return isVariantApplicableInContextHelper(
322-
VMI, Ctx, /* ConstructMatches */ nullptr, DeviceSetOnly);
326+
VMI, Ctx, /* ConstructMatches */ nullptr, DeviceOrImplementationSetOnly);
323327
}
324328

325329
static APInt getVariantMatchScore(const VariantMatchInfo &VMI,
@@ -418,8 +422,9 @@ int llvm::omp::getBestVariantMatchForContext(
418422

419423
SmallVector<unsigned, 8> ConstructMatches;
420424
// If the variant is not applicable its not the best.
421-
if (!isVariantApplicableInContextHelper(VMI, Ctx, &ConstructMatches,
422-
/* DeviceSetOnly */ false))
425+
if (!isVariantApplicableInContextHelper(
426+
VMI, Ctx, &ConstructMatches,
427+
/* DeviceOrImplementationSetOnly */ false))
423428
continue;
424429
// Check if its clearly not the best.
425430
APInt Score = getVariantMatchScore(VMI, Ctx, ConstructMatches);

0 commit comments

Comments
 (0)