| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| // 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| // RUN: %clang_cc1 -emit-llvm -triple i386-linux-gnu %s -o - | FileCheck %s | ||
| // RUN: %clang_cc1 -x c++ -emit-pch -triple i386-linux-gnu -o %t %s | ||
| // RUN: %clang_cc1 -include-pch %t %s -triple i386-linux-gnu -emit-llvm -o - | FileCheck %s | ||
| // expected-no-diagnostics | ||
|
|
||
| #ifndef HEADER | ||
| #define HEADER | ||
|
|
||
| /// foo: declarations only | ||
|
|
||
| __attribute__((assume("foo:before1"))) void foo(); | ||
|
|
||
| __attribute__((assume("foo:before2"))) | ||
| __attribute__((assume("foo:before3"))) void | ||
| foo(); | ||
|
|
||
| /// baz: static function declarations and a definition | ||
|
|
||
| __attribute__((assume("baz:before1"))) static void baz(); | ||
|
|
||
| __attribute__((assume("baz:before2"))) | ||
| __attribute__((assume("baz:before3"))) static void | ||
| baz(); | ||
|
|
||
| // Definition | ||
| __attribute__((assume("baz:def1,baz:def2"))) static void baz() { foo(); } | ||
|
|
||
| __attribute__((assume("baz:after"))) static void baz(); | ||
|
|
||
| /// bar: external function declarations and a definition | ||
|
|
||
| __attribute__((assume("bar:before1"))) void bar(); | ||
|
|
||
| __attribute__((assume("bar:before2"))) | ||
| __attribute__((assume("bar:before3"))) void | ||
| bar(); | ||
|
|
||
| // Definition | ||
| __attribute__((assume("bar:def1,bar:def2"))) void bar() { baz(); } | ||
|
|
||
| __attribute__((assume("bar:after"))) void bar(); | ||
|
|
||
| /// back to foo | ||
|
|
||
| __attribute__((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(); | ||
|
|
||
| public: | ||
| __attribute__((assume("C:public_method1"))) void public_method(); | ||
| __attribute__((assume("C:public_static1"))) static void public_static(); | ||
| }; | ||
|
|
||
| __attribute__((assume("C:public_method2"))) void C::public_method() { | ||
| private_method(); | ||
| } | ||
|
|
||
| __attribute__((assume("C:public_static2"))) void C::public_static() { | ||
| private_static(); | ||
| } | ||
|
|
||
| /// template tests | ||
| template <typename T> | ||
| __attribute__((assume("template_func<T>"))) void template_func() {} | ||
|
|
||
| template <> | ||
| __attribute__((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(); | ||
| }; | ||
|
|
||
| template <> | ||
| __attribute__((assume("S<float>::method"))) void S<float>::method() {} | ||
|
|
||
| template <> | ||
| void S<int>::method() {} | ||
|
|
||
| // CHECK: define{{.*}} void @_Z3barv() #0 | ||
| // CHECK: define{{.*}} void @_ZL3bazv() #1 | ||
| // CHECK: define{{.*}} void @_ZN1C13public_methodEv({{.*}}) #2 | ||
| // CHECK: declare{{.*}} void @_ZN1C14private_methodEv({{.*}}) #3 | ||
| // CHECK: define{{.*}} void @_ZN1C13public_staticEv() #4 | ||
| // CHECK: declare{{.*}} void @_ZN1C14private_staticEv() #5 | ||
| // CHECK: define{{.*}} void @_Z13template_funcIfEvv() #6 | ||
| // CHECK: define{{.*}} void @_Z13template_funcIiEvv() #7 | ||
| // CHECK: define{{.*}} void @_ZN1SIfE6methodEv({{.*}}) #8 | ||
| // CHECK: define{{.*}} void @_ZN1SIiE6methodEv({{.*}}) #9 | ||
| // CHECK: declare{{.*}} void @_Z3foov() #10 | ||
| // 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"="C:public_method1,C:public_method2" | ||
| // CHECK: attributes #3 | ||
| // CHECK-SAME: "llvm.assume"="C:private_method" | ||
| // CHECK: attributes #4 | ||
| // CHECK-SAME: "llvm.assume"="C:public_static1,C:public_static2" | ||
| // CHECK: attributes #5 | ||
| // CHECK-SAME: "llvm.assume"="C:private_static" | ||
| // CHECK: attributes #6 | ||
| // CHECK-SAME: "llvm.assume"="template_func<T>,template_func<float>" | ||
| // CHECK: attributes #7 | ||
| // CHECK-SAME: "llvm.assume"="template_func<T>" | ||
| // CHECK: attributes #8 | ||
| // CHECK-SAME: "llvm.assume"="S<T>::method,S<float>::method" | ||
| // CHECK: attributes #9 | ||
| // CHECK-SAME: "llvm.assume"="S<T>::method" | ||
| // CHECK: attributes #10 | ||
| // CHECK-SAME: "llvm.assume"="foo:before1,foo:before2,foo:before3" | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| // RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s | ||
| // RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s --check-prefix=AST | ||
| // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -verify -o %t %s | ||
| // RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify=pch %s -emit-llvm -o - | FileCheck %s | ||
| // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s | ||
| // RUN: %clang_cc1 -verify -fopenmp -fopenmp-enable-irbuilder -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s | ||
| // RUN: %clang_cc1 -fopenmp -fopenmp-enable-irbuilder -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -verify -o %t %s | ||
| // RUN: %clang_cc1 -fopenmp -fopenmp-enable-irbuilder -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify=pch %s -emit-llvm -o - | FileCheck %s | ||
|
|
||
| // pch-no-diagnostics | ||
|
|
||
| #ifndef HEADER | ||
| #define HEADER | ||
|
|
||
| void foo() { | ||
| } | ||
|
|
||
| #pragma omp assumes no_openmp_routines warning ext_another_warning(1) ext_after_invalid_clauses // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{'ext_another_warning' clause should not be followed by arguments; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} | ||
|
|
||
| #pragma omp assumes no_openmp | ||
|
|
||
| #pragma omp begin assumes ext_range_bar_only | ||
|
|
||
| #pragma omp begin assumes ext_range_bar_only_2 | ||
|
|
||
| class BAR { | ||
| public: | ||
| BAR() {} | ||
|
|
||
| void bar1() { | ||
| } | ||
|
|
||
| static void bar2() { | ||
| } | ||
| }; | ||
|
|
||
| void bar() { BAR b; } | ||
|
|
||
| #pragma omp end assumes | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes ext_not_seen | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes ext_1234 | ||
| void baz(); | ||
|
|
||
| template<typename T> | ||
| class BAZ { | ||
| public: | ||
| BAZ() {} | ||
|
|
||
| void baz1() { | ||
| } | ||
|
|
||
| static void baz2() { | ||
| } | ||
| }; | ||
|
|
||
| void baz() { BAZ<float> b; } | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes ext_lambda_assumption | ||
| int lambda_outer() { | ||
| auto lambda_inner = []() { return 42; }; | ||
| return lambda_inner(); | ||
| } | ||
| #pragma omp end assumes | ||
|
|
||
| // AST: void foo() __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: } | ||
| // AST-NEXT: class BAR { | ||
| // AST-NEXT: public: | ||
| // AST-NEXT: BAR() __attribute__((assume("range_bar_only"))) __attribute__((assume("range_bar_only_2"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: } | ||
| // AST-NEXT: void bar1() __attribute__((assume("range_bar_only"))) __attribute__((assume("range_bar_only_2"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: } | ||
| // AST-NEXT: static void bar2() __attribute__((assume("range_bar_only"))) __attribute__((assume("range_bar_only_2"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: } | ||
| // AST-NEXT: }; | ||
| // AST-NEXT: void bar() __attribute__((assume("range_bar_only"))) __attribute__((assume("range_bar_only_2"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: BAR b; | ||
| // AST-NEXT: } | ||
| // AST-NEXT: void baz() __attribute__((assume("1234"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))); | ||
| // AST-NEXT: template <typename T> class BAZ { | ||
| // AST-NEXT: public: | ||
| // AST-NEXT: BAZ<T>() __attribute__((assume("1234"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: } | ||
| // AST-NEXT: void baz1() __attribute__((assume("1234"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: } | ||
| // AST-NEXT: static void baz2() __attribute__((assume("1234"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: } | ||
| // AST-NEXT: }; | ||
| // AST-NEXT: template<> class BAZ<float> { | ||
| // AST-NEXT: public: | ||
| // AST-NEXT: BAZ() __attribute__((assume("1234"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: } | ||
| // AST-NEXT: void baz1() __attribute__((assume("1234"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))); | ||
| // AST-NEXT: static void baz2() __attribute__((assume("1234"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))); | ||
| // AST-NEXT: }; | ||
| // AST-NEXT: void baz() __attribute__((assume("1234"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: BAZ<float> b; | ||
| // AST-NEXT: } | ||
| // AST-NEXT: int lambda_outer() __attribute__((assume("lambda_assumption"))) __attribute__((assume("no_openmp_routines,another_warning,after_invalid_clauses"))) __attribute__((assume("no_openmp"))) { | ||
| // AST-NEXT: auto lambda_inner = []() { | ||
| // AST-NEXT: return 42; | ||
| // AST-NEXT: }; | ||
| // AST-NEXT: return lambda_inner(); | ||
| // AST-NEXT: } | ||
|
|
||
| #endif | ||
|
|
||
| // CHECK: define{{.*}} void @_Z3foov() | ||
| // CHECK-SAME: [[attr0:#[0-9]]] | ||
| // CHECK: define{{.*}} void @_Z3barv() | ||
| // CHECK-SAME: [[attr1:#[0-9]]] | ||
| // CHECK: call void @_ZN3BARC1Ev(%class.BAR*{{.*}} %b) | ||
| // CHECK-SAME: [[attr9:#[0-9]]] | ||
| // CHECK: define{{.*}} void @_ZN3BARC1Ev(%class.BAR*{{.*}} %this) | ||
| // CHECK-SAME: [[attr2:#[0-9]]] | ||
| // CHECK: call void @_ZN3BARC2Ev(%class.BAR*{{.*}} %this1) | ||
| // CHECK-SAME: [[attr9]] | ||
| // CHECK: define{{.*}} void @_ZN3BARC2Ev(%class.BAR*{{.*}} %this) | ||
| // CHECK-SAME: [[attr3:#[0-9]]] | ||
| // CHECK: define{{.*}} void @_Z3bazv() | ||
| // CHECK-SAME: [[attr4:#[0-9]]] | ||
| // CHECK: call void @_ZN3BAZIfEC1Ev(%class.BAZ*{{.*}} %b) | ||
| // CHECK-SAME: [[attr10:#[0-9]]] | ||
| // CHECK: define{{.*}} void @_ZN3BAZIfEC1Ev(%class.BAZ*{{.*}} %this) | ||
| // CHECK-SAME: [[attr5:#[0-9]]] | ||
| // CHECK: call void @_ZN3BAZIfEC2Ev(%class.BAZ*{{.*}} %this1) | ||
| // CHECK-SAME: [[attr10]] | ||
| // CHECK: define{{.*}} void @_ZN3BAZIfEC2Ev(%class.BAZ*{{.*}} %this) | ||
| // CHECK-SAME: [[attr6:#[0-9]]] | ||
| // CHECK: define{{.*}} i32 @_Z12lambda_outerv() | ||
| // CHECK-SAME: [[attr7:#[0-9]]] | ||
| // CHECK: call i32 @"_ZZ12lambda_outervENK3$_0clEv" | ||
| // CHECK-SAME: [[attr11:#[0-9]]] | ||
| // CHECK: define{{.*}} i32 @"_ZZ12lambda_outervENK3$_0clEv"(%class.anon*{{.*}} %this) | ||
| // CHECK-SAME: [[attr8:#[0-9]]] | ||
|
|
||
| // CHECK: attributes [[attr0]] | ||
| // CHECK-SAME: "llvm.assume"="no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr1]] | ||
| // CHECK-SAME: "llvm.assume"="range_bar_only,range_bar_only_2,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr2]] | ||
| // CHECK-SAME: "llvm.assume"="range_bar_only,range_bar_only_2,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr3]] | ||
| // CHECK-SAME: "llvm.assume"="range_bar_only,range_bar_only_2,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr4]] | ||
| // CHECK-SAME: "llvm.assume"="1234,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp,1234,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr5]] | ||
| // CHECK-SAME: "llvm.assume"="1234,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr6]] | ||
| // CHECK-SAME: "llvm.assume"="1234,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr7]] | ||
| // CHECK-SAME: "llvm.assume"="lambda_assumption,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr8]] | ||
| // CHECK-SAME: "llvm.assume"="lambda_assumption,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr9]] | ||
| // CHECK-SAME: "llvm.assume"="range_bar_only,range_bar_only_2,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr10]] | ||
| // CHECK-SAME: "llvm.assume"="1234,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" | ||
| // CHECK: attributes [[attr11]] | ||
| // CHECK-SAME: "llvm.assume"="lambda_assumption,no_openmp_routines,another_warning,after_invalid_clauses,no_openmp" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| // RUN: %clang_cc1 -x c++ -O1 -disable-llvm-optzns -verify -fopenmp -internal-isystem %S/../Headers/Inputs/include -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc | ||
| // RUN: %clang_cc1 -x c++ -O1 -disable-llvm-optzns -verify -fopenmp -internal-isystem %S/../Headers/Inputs/include -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s | ||
| // RUN: %clang_cc1 -x c++ -O1 -disable-llvm-optzns -verify -fopenmp -internal-isystem %S/../Headers/Inputs/include -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc | ||
| // RUN: %clang_cc1 -x c++ -O1 -disable-llvm-optzns -verify -fopenmp -internal-isystem %S/../Headers/Inputs/include -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s | ||
| // RUN: %clang_cc1 -x c++ -O1 -disable-llvm-optzns -verify -fopenmp -internal-isystem %S/../Headers/Inputs/include -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -fexceptions -fcxx-exceptions -aux-triple powerpc64le-unknown-unknown -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s | ||
| // expected-no-diagnostics | ||
| #ifndef HEADER | ||
| #define HEADER | ||
|
|
||
| #include <cmath> | ||
|
|
||
| // TODO: Think about teaching the OMPIRBuilder about default attributes as well so the __kmpc* declarations are annotated. | ||
|
|
||
| // CHECK: define internal void @__omp_offloading_{{.*}}__Z17complex_reductionIfEvv_{{.*}}_worker() [[attr0:#[0-9]*]] | ||
| // CHECK: define weak void @__omp_offloading_{{.*}}__Z17complex_reductionIfEvv_{{.*}}() [[attr0]] | ||
| // CHECK: %call = call float @_Z3sinf(float 0.000000e+00) [[attr5:#[0-9]*]] | ||
| // CHECK: declare i32 @llvm.nvvm.read.ptx.sreg.warpsize() [[attr1:#[0-9]*]] | ||
| // CHECK: declare i32 @llvm.nvvm.read.ptx.sreg.ntid.x() [[attr1]] | ||
| // CHECK: declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() [[attr1]] | ||
| // CHECK: declare void @__kmpc_kernel_init(i32, i16) | ||
| // CHECK-NOT: # | ||
| // CHECK: declare void @__kmpc_data_sharing_init_stack() | ||
| // CHECK-NOT: # | ||
| // CHECK: declare float @_Z3sinf(float) [[attr2:#[0-9]*]] | ||
| // CHECK: declare void @__kmpc_kernel_deinit(i16) | ||
| // CHECK-NOT: # | ||
| // CHECK: declare void @__kmpc_barrier_simple_spmd(%struct.ident_t*, i32) [[attr3:#[0-9]*]] | ||
| // CHECK: declare i1 @__kmpc_kernel_parallel(i8**) | ||
| // CHECK-NOT: # | ||
| // CHECK: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) [[attr4:#[0-9]*]] | ||
| // CHECK: declare void @__kmpc_kernel_end_parallel() | ||
| // CHECK-NOT: # | ||
| // CHECK: define internal void @__omp_offloading_{{.*}}__Z17complex_reductionIdEvv_{{.*}}_worker() [[attr0]] | ||
| // CHECK: define weak void @__omp_offloading_{{.*}}__Z17complex_reductionIdEvv_{{.*}}() [[attr0]] | ||
| // CHECK: %call = call double @_Z3sind(double 0.000000e+00) [[attr5]] | ||
| // CHECK: declare double @_Z3sind(double) [[attr2]] | ||
|
|
||
| // CHECK: attributes [[attr0]] | ||
| // CHECK-NOT: "llvm.assume" | ||
| // CHECK: attributes [[attr1]] | ||
| // CHECK-NOT: "llvm.assume" | ||
| // CHECK: attributes [[attr2]] | ||
| // CHECK-SAME: "llvm.assume"="check_that_this_is_attached_to_included_functions_and_template_instantiations" | ||
| // CHECK: attributes [[attr3]] | ||
| // CHECK-NOT: "llvm.assume" | ||
| // CHECK: attributes [[attr4]] | ||
| // CHECK-NOT: "llvm.assume" | ||
| // CHECK: attributes [[attr5]] | ||
| // CHECK-SAME: "llvm.assume"="check_that_this_is_attached_to_included_functions_and_template_instantiations" | ||
|
|
||
|
|
||
| template <typename T> | ||
| void foo() { | ||
| cos(T(0)); | ||
| } | ||
|
|
||
| template <typename T> | ||
| void complex_reduction() { | ||
| foo<T>(); | ||
| #pragma omp target | ||
| sin(T(0)); | ||
| } | ||
|
|
||
| #pragma omp assumes ext_check_that_this_is_attached_to_included_functions_and_template_instantiations | ||
|
|
||
| void test() { | ||
| complex_reduction<float>(); | ||
| complex_reduction<double>(); | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| // RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c -std=c99 -fms-extensions -Wno-pragma-pack %s | ||
|
|
||
| // RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c -std=c99 -fms-extensions -Wno-pragma-pack %s | ||
|
|
||
| #pragma omp assumes // expected-error {{expected at least one 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism' clause for '#pragma omp assumes'}} | ||
| #pragma omp begin // expected-error {{expected an OpenMP directive}} | ||
| #pragma omp begin assumes // expected-error {{expected at least one 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism' clause for '#pragma omp begin assumes'}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp assumes foobar // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp begin assumes foobar // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes foobar(foo 2 no_openmp // expected-error {{expected ')'}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note {{to match this '('}} | ||
| #pragma omp assumes foobar(foo 2 no_openmp // expected-error {{expected ')'}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note {{to match this '('}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes foobar(foo 2 baz) // expected-warning {{valid begin assumes 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}} | ||
| #pragma omp assumes foobar(foo 2 baz) // expected-warning {{valid assumes 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}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes foobar foo 2 baz) bar // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp assumes foobar foo 2 baz) bar // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp assumes no_openmp(1) // expected-warning {{'no_openmp' clause should not be followed by arguments; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} | ||
| #pragma omp begin assumes no_openmp(1 2 3) // expected-warning {{'no_openmp' clause should not be followed by arguments; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} | ||
| #pragma omp end assumes no_openmp(1) | ||
|
|
||
| #pragma omp assumes foobar no_openmp bazbaz // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp begin assumes foobar no_openmp bazbaz // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes foobar(foo 2 baz) no_openmp bazbaz(foo 2 baz) // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-warning {{valid begin assumes 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}} expected-note {{the ignored tokens spans until here}} | ||
| #pragma omp assumes foobar(foo 2 baz) no_openmp bazbaz(foo 2 baz) // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-warning {{valid assumes 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}} expected-note {{the ignored tokens spans until here}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes foobar(foo (2) baz) no_openmp bazbaz(foo (2)) baz) // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-note {{the ignored tokens spans until here}} expected-note {{the ignored tokens spans until here}} | ||
| #pragma omp assumes foobar(foo () baz) no_openmp bazbaz(foo ((2) baz) // expected-error {{expected ')'}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-warning {{valid assumes 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}} expected-note {{to match this '('}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp assumes no_openmp foobar no_openmp // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp begin assumes no_openmp foobar no_openmp // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp assumes holds(1, 2 3) | ||
| #pragma omp begin assumes holds(1, 2 3) | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp assumes absent(1, 2 3) | ||
| #pragma omp begin assumes absent(1, 2 3) | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp assumes contains(1, 2 3) | ||
| #pragma omp begin assumes contains(1, 2 3) | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp assumes ext // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp begin assumes ext // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp assumes ext_123(not allowed) // expected-warning {{'ext_123' clause should not be followed by arguments; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} | ||
| #pragma omp begin assumes ext_123(not allowed) // expected-warning {{'ext_123' clause should not be followed by arguments; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp end assumes // expected-error {{'#pragma omp end assumes' with no matching '#pragma omp begin assumes'}} | ||
|
|
||
| // TODO: we should emit a warning at least. | ||
| #pragma omp begin assumes ext_abc |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| // RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s | ||
| // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s | ||
| // RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s | ||
|
|
||
| // RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s | ||
| // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s | ||
| // RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s | ||
| // expected-no-diagnostics | ||
|
|
||
| #ifndef HEADER | ||
| #define HEADER | ||
|
|
||
| void foo() { | ||
| } | ||
|
|
||
| #pragma omp assumes no_openmp_routines | ||
|
|
||
| namespace inner { | ||
| #pragma omp assumes no_openmp | ||
| } // namespace inner | ||
|
|
||
| #pragma omp begin assumes ext_range_bar_only | ||
|
|
||
| #pragma omp begin assumes ext_range_bar_only_2 | ||
|
|
||
| void bar() { | ||
| } | ||
|
|
||
| #pragma omp end assumes | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes ext_not_seen | ||
| #pragma omp end assumes | ||
|
|
||
| #pragma omp begin assumes ext_1234 | ||
| void baz() { | ||
| } | ||
| #pragma omp end assumes | ||
|
|
||
| // CHECK: void foo() __attribute__((assume("no_openmp_routines"))) __attribute__((assume("no_openmp"))) | ||
| // CHECK: void bar() __attribute__((assume("range_bar_only"))) __attribute__((assume("range_bar_only_2"))) __attribute__((assume("no_openmp_routines"))) __attribute__((assume("no_openmp"))) | ||
| // CHECK: void baz() __attribute__((assume("1234"))) __attribute__((assume("no_openmp_routines"))) __attribute__((assume("no_openmp"))) | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| // RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s | ||
| // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s | ||
| // RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s | ||
|
|
||
| // RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s | ||
| // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s | ||
| // RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s | ||
| // expected-no-diagnostics | ||
|
|
||
| // It is unclear if we want to annotate the template instantiations, e.g., S<int>::foo, or not in the two | ||
| // situations shown below. Since it is always fair to drop assumptions, we do that for now. | ||
|
|
||
| #ifndef HEADER | ||
| #define HEADER | ||
|
|
||
| template <typename T> | ||
| struct S { | ||
| int a; | ||
| // CHECK: template <typename T> struct S { | ||
| // CHECK: void foo() __attribute__((assume("global_assumption"))) { | ||
| void foo() { | ||
| #pragma omp parallel | ||
| {} | ||
| } | ||
| }; | ||
|
|
||
| // CHECK: template<> struct S<int> { | ||
| // CHECK: void foo() __attribute__((assume("global_assumption"))) { | ||
|
|
||
| #pragma omp begin assumes no_openmp | ||
| // CHECK: void S_with_assumes_no_call() __attribute__((assume("no_openmp"))) __attribute__((assume("global_assumption"))) { | ||
| void S_with_assumes_no_call() { | ||
| S<int> s; | ||
| s.a = 0; | ||
| } | ||
| // CHECK: void S_with_assumes_call() __attribute__((assume("no_openmp"))) __attribute__((assume("global_assumption"))) { | ||
| void S_with_assumes_call() { | ||
| S<int> s; | ||
| s.a = 0; | ||
| // If this is executed we have UB! | ||
| s.foo(); | ||
| } | ||
| #pragma omp end assumes | ||
|
|
||
| // CHECK: void S_without_assumes() __attribute__((assume("global_assumption"))) { | ||
| void S_without_assumes() { | ||
| S<int> s; | ||
| s.foo(); | ||
| } | ||
|
|
||
| #pragma omp assumes ext_global_assumption | ||
|
|
||
| // Same as the struct S above but the order in which we instantiate P is different, first outside of an assumes. | ||
| template <typename T> | ||
| struct P { | ||
| // CHECK: template <typename T> struct P { | ||
| // CHECK: void foo() __attribute__((assume("global_assumption"))) { | ||
| int a; | ||
| void foo() { | ||
| #pragma omp parallel | ||
| {} | ||
| } | ||
| }; | ||
|
|
||
| // TODO: Avoid the duplication here: | ||
|
|
||
| // CHECK: template<> struct P<int> { | ||
| // CHECK: void foo() __attribute__((assume("global_assumption"))) __attribute__((assume("global_assumption"))) { | ||
|
|
||
| // CHECK: void P_without_assumes() __attribute__((assume("global_assumption"))) { | ||
| void P_without_assumes() { | ||
| P<int> p; | ||
| p.foo(); | ||
| } | ||
|
|
||
| #pragma omp begin assumes no_openmp | ||
| // CHECK: void P_with_assumes_no_call() __attribute__((assume("no_openmp"))) __attribute__((assume("global_assumption"))) { | ||
| void P_with_assumes_no_call() { | ||
| P<int> p; | ||
| p.a = 0; | ||
| } | ||
| // CHECK: void P_with_assumes_call() __attribute__((assume("no_openmp"))) __attribute__((assume("global_assumption"))) { | ||
| void P_with_assumes_call() { | ||
| P<int> p; | ||
| p.a = 0; | ||
| // If this is executed we have UB! | ||
| p.foo(); | ||
| } | ||
| #pragma omp end assumes | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s | ||
|
|
||
| void f1() __attribute__((assume(3))); // expected-error {{'assume' attribute requires a string}} | ||
| void f2() __attribute__((assume(int))); // expected-error {{expected expression}} | ||
| void f3() __attribute__((assume(for))); // expected-error {{expected expression}} | ||
| void f4() __attribute__((assume("QQQQ"))); // expected-warning {{unknown assumption string 'QQQQ'; attribute is potentially ignored}} | ||
| void f5() __attribute__((assume("omp_no_openmp"))); | ||
| void f6() __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() __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() __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() __attribute__((assume("omp_no_openmp", "omp_no_openmp"))); // expected-error {{'assume' attribute takes one argument}} | ||
|
|
||
| int g1 __attribute__((assume(0))); // expected-warning {{'assume' attribute only applies to functions and Objective-C methods}} | ||
| int g2 __attribute__((assume("omp_no_openmp"))); // expected-warning {{'assume' attribute only applies to functions and Objective-C methods}} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| //===--- Assumptions.h - Assumption handling and organization ---*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // String assumptions that are known to optimization passes should be placed in | ||
| // the KnownAssumptionStrings set. This can be done in various ways, i.a., | ||
| // via a static KnownAssumptionString object. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_IR_ASSUMPTIONS_H | ||
| #define LLVM_IR_ASSUMPTIONS_H | ||
|
|
||
| #include "llvm/ADT/StringRef.h" | ||
| #include "llvm/ADT/StringSet.h" | ||
|
|
||
| namespace llvm { | ||
|
|
||
| class Function; | ||
|
|
||
| /// The key we use for assumption attributes. | ||
| constexpr StringRef AssumptionAttrKey = "llvm.assume"; | ||
|
|
||
| /// A set of known assumption strings that are accepted without warning and | ||
| /// which can be recommended as typo correction. | ||
| extern StringSet<> KnownAssumptionStrings; | ||
|
|
||
| /// Helper that allows to insert a new assumption string in the known assumption | ||
| /// set by creating a (static) object. | ||
| struct KnownAssumptionString { | ||
| KnownAssumptionString(StringRef AssumptionStr) | ||
| : AssumptionStr(AssumptionStr) { | ||
| KnownAssumptionStrings.insert(AssumptionStr); | ||
| } | ||
| operator StringRef() const { return AssumptionStr; } | ||
|
|
||
| private: | ||
| StringRef AssumptionStr; | ||
| }; | ||
|
|
||
| /// Return true if \p F has the assumption \p AssumptionStr attached. | ||
| bool hasAssumption(Function &F, const KnownAssumptionString &AssumptionStr); | ||
|
|
||
| } // namespace llvm | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| //===- Assumptions.cpp ------ Collection of helpers for assumptions -------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "llvm/IR/Assumptions.h" | ||
| #include "llvm/IR/Attributes.h" | ||
| #include "llvm/IR/Function.h" | ||
|
|
||
| using namespace llvm; | ||
|
|
||
| bool llvm::hasAssumption(Function &F, | ||
| const KnownAssumptionString &AssumptionStr) { | ||
| const Attribute &A = F.getFnAttribute(AssumptionAttrKey); | ||
| if (!A.isValid()) | ||
| return false; | ||
| assert(A.isStringAttribute() && "Expected a string attribute!"); | ||
|
|
||
| SmallVector<StringRef, 8> Strings; | ||
| A.getValueAsString().split(Strings, ","); | ||
|
|
||
| return llvm::any_of(Strings, [=](StringRef Assumption) { | ||
| return Assumption == AssumptionStr; | ||
| }); | ||
| } | ||
|
|
||
| StringSet<> llvm::KnownAssumptionStrings({ | ||
| "omp_no_openmp", // OpenMP 5.1 | ||
| "omp_no_openmp_routines", // OpenMP 5.1 | ||
| "omp_no_parallelism", // OpenMP 5.1 | ||
| }); |