Index: lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- lib/CodeGen/CGStmtOpenMP.cpp +++ lib/CodeGen/CGStmtOpenMP.cpp @@ -910,13 +910,23 @@ PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address { return GetAddrOfLocalVar(PrivateVD); }); - } else if (auto *ASE = dyn_cast(IRef)) { - auto *Base = ASE->getBase()->IgnoreParenImpCasts(); - while (auto *TempASE = dyn_cast(Base)) - Base = TempASE->getBase()->IgnoreParenImpCasts(); + } else if (isa(IRef) || isa(IRef)) { + const Expr *Array; + const Expr *Base; + if (auto* ASE = dyn_cast(IRef)) { + Array = ASE; + Base = ASE->getBase()->IgnoreParenImpCasts(); + while (auto *TempASE = dyn_cast(Base)) + Base = TempASE->getBase()->IgnoreParenImpCasts(); + } else { + auto* UO = cast(IRef); + assert(UO->getOpcode() == UO_Deref && "should be a dereference"); + Array = UO; + Base = UO->getSubExpr()->IgnoreParenImpCasts(); + } auto *DE = cast(Base); auto *OrigVD = cast(DE->getDecl()); - auto ASELValue = EmitLValue(ASE); + auto ASELValue = EmitLValue(Array); auto OriginalBaseLValue = EmitLValue(DE); LValue BaseLValue = loadToBegin( *this, OrigVD->getType(), ASELValue.getType(), OriginalBaseLValue); Index: lib/Sema/SemaOpenMP.cpp =================================================================== --- lib/Sema/SemaOpenMP.cpp +++ lib/Sema/SemaOpenMP.cpp @@ -7138,6 +7138,11 @@ Base = TempASE->getBase()->IgnoreParenImpCasts(); RefExpr = Base; IsArrayExpr = OMPArraySection; + } else if (auto *UO = dyn_cast_or_null(RefExpr)) { + if (UO->getOpcode() == UO_Deref) { + RefExpr = UO->getSubExpr()->IgnoreParenImpCasts(); + IsArrayExpr = ArraySubscript; + } } } ELoc = RefExpr->getExprLoc(); @@ -8077,6 +8082,7 @@ QualType Type; auto *ASE = dyn_cast(RefExpr->IgnoreParens()); auto *OASE = dyn_cast(RefExpr->IgnoreParens()); + auto *UO = dyn_cast(RefExpr->IgnoreParens()); if (ASE) Type = ASE->getType().getNonReferenceType(); else if (OASE) { @@ -8086,6 +8092,9 @@ else Type = BaseType->getPointeeType(); Type = Type.getNonReferenceType(); + } else if (UO) { + assert(UO->getOpcode() == UO_Deref && "should be a dereference"); + Type = UO->getType().getNonReferenceType(); } else Type = Context.getBaseElementType(D->getType().getNonReferenceType()); auto *VD = dyn_cast(D); Index: test/OpenMP/for_reduction_codegen.cpp =================================================================== --- test/OpenMP/for_reduction_codegen.cpp +++ test/OpenMP/for_reduction_codegen.cpp @@ -217,6 +217,14 @@ #pragma omp for reduction(& : var3) for (int i = 0; i < 10; ++i) ; +#pragma omp parallel +#pragma omp for reduction(& : var3[1]) + for (int i = 0; i < 10; ++i) + ; +#pragma omp parallel +#pragma omp for reduction(& : *var3) + for (int i = 0; i < 10; ++i) + ; return tmain(); #endif } @@ -231,6 +239,8 @@ // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK4:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK5:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK6:@.+]] to void +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK7:@.+]] to void +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK8:@.+]] to void // CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]() // CHECK: call {{.*}} [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]* // CHECK: ret @@ -1002,6 +1012,42 @@ // CHECK: ret void +// CHECK: define internal void [[MAIN_MICROTASK7]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]* dereferenceable(8) %{{.+}}) + +// CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*, +// CHECK: [[VAR3_PRIV:%.+]] = alloca [[S_FLOAT_TY]], + +// Reduction list for runtime. +// CHECK: [[RED_LIST:%.+]] = alloca [1 x i8*], + +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], + +// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], +// CHECK: [[VAR3_ELEM:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 1 + +// CHECK: [[VAR3_PRIV_ELEM:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[VAR3_PRIV]], +// CHECK: [[VAR3_PRIV_ELEM_CASTED:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR3_PRIV_ELEM]] to [2 x [[S_FLOAT_TY]]]* +// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV_ELEM_CASTED]], [2 x [[S_FLOAT_TY]]]** % + +// CHECK: ret void + +// CHECK: define internal void [[MAIN_MICROTASK8]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]* dereferenceable(8) %{{.+}}) + +// CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*, +// CHECK: [[VAR3_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]], + +// Reduction list for runtime. +// CHECK: [[RED_LIST:%.+]] = alloca [1 x i8*], + +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], + +// CHECK: load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], + +// CHECK: [[VAR3_PRIV_ELEM:%.+]] = getelementptr [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], +// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV_ELEM_CASTED]], [2 x [[S_FLOAT_TY]]]** % + +// CHECK: ret void + // CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]() // CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]], // CHECK: call {{.*}} [[S_INT_TY_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]]) Index: test/OpenMP/for_reduction_messages.cpp =================================================================== --- test/OpenMP/for_reduction_messages.cpp +++ test/OpenMP/for_reduction_messages.cpp @@ -147,6 +147,14 @@ for (int i = 0; i < 10; ++i) foo(); #pragma omp parallel +#pragma omp for reduction(max : *qa) + for (int i = 0; i < 10; ++i) + foo(); +#pragma omp parallel +#pragma omp for reduction(max: !qa) // expected-error 2 {{expected variable name, array element or array section}} + for (int i = 0; i < 10; ++i) + foo(); +#pragma omp parallel #pragma omp for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}} for (int i = 0; i < 10; ++i) foo(); @@ -207,6 +215,10 @@ #pragma omp for reduction(+ : qa[1], get()[0]) // expected-error 2 {{reduction variable must be shared}} expected-error {{expected variable name as a base of the array subscript}} for (int i = 0; i < 10; ++i) foo(); +#pragma omp parallel private(qa) // expected-note 2 {{defined as private}} +#pragma omp for reduction(+ : *qa, *(get())) // expected-error 2 {{reduction variable must be shared}} expected-error {{expected variable name as a base of the array subscript}} + for (int i = 0; i < 10; ++i) + foo(); #pragma omp parallel shared(qa) #pragma omp for reduction(+ : qa[1], qa[0]) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}} for (int i = 0; i < 10; ++i) Index: test/OpenMP/parallel_ast_print.cpp =================================================================== --- test/OpenMP/parallel_ast_print.cpp +++ test/OpenMP/parallel_ast_print.cpp @@ -54,6 +54,9 @@ #pragma omp parallel reduction(&& : this->a) reduction(^: b[s.a.a]) for (int k = 0; k < s.a.a; ++k) ++s.a.a; +#pragma omp parallel reduction(^: *b) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; return *this; } }; @@ -70,6 +73,7 @@ // CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a) // CHECK: #pragma omp parallel shared(this->a) shared(this->a) // CHECK: #pragma omp parallel reduction(&&: this->a) reduction(^: this->b[s.a.a]) +// CHECK: #pragma omp parallel reduction(^: *this->b) class S8 : public S7 { S8() {} @@ -145,7 +149,7 @@ a=2; #pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (parallel:argc > 0) num_threads(C) copyin(S::TS) proc_bind(master) reduction(+:c, arr1[argc]) reduction(max:e, arr[:C][0:10]) foo(); -#pragma omp parallel if (C) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:C][:argc]) reduction(&& : g) +#pragma omp parallel if (C) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^:e, f, arr[0:C][:argc]) reduction(&& : g) foo(); return 0; } @@ -159,7 +163,7 @@ // CHECK-NEXT: a = 2; // CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) copyin(S::TS) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10]) // CHECK-NEXT: foo() -// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g) +// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g) // CHECK-NEXT: foo() // CHECK: template long tmain(long argc, long *argv) { // CHECK-NEXT: long b = argc, c, d, e, f, g; @@ -170,7 +174,7 @@ // CHECK-NEXT: a = 2; // CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) copyin(S::TS) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10]) // CHECK-NEXT: foo() -// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g) +// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g) // CHECK-NEXT: foo() // CHECK: template T tmain(T argc, T *argv) { // CHECK-NEXT: T b = argc, c, d, e, f, g; @@ -181,7 +185,7 @@ // CHECK-NEXT: a = 2; // CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) copyin(S::TS) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10]) // CHECK-NEXT: foo() -// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g) +// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g) // CHECK-NEXT: foo() enum Enum { }; @@ -202,9 +206,9 @@ // CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(parallel: argc > 0) num_threads(ee) copyin(a) proc_bind(spread) reduction(|: c,d,arr1[argc]) reduction(*: e,arr[:10][0:argc]) foo(); // CHECK-NEXT: foo(); -// CHECK-NEXT: #pragma omp parallel if(b) num_threads(c) proc_bind(close) reduction(^: e,f) reduction(&&: g,arr[0:argc][:10]) +// CHECK-NEXT: #pragma omp parallel if(b) num_threads(c) proc_bind(close) reduction(+: *arr1) reduction(^: e,f) reduction(&&: g,arr[0:argc][:10]) // CHECK-NEXT: foo() -#pragma omp parallel if (b) num_threads(c) proc_bind(close) reduction(^:e, f) reduction(&& : g, arr[0:argc][:10]) +#pragma omp parallel if (b) num_threads(c) proc_bind(close) reduction(+:*arr1) reduction(^:e, f) reduction(&& : g, arr[0:argc][:10]) foo(); return tmain(b, &b) + tmain(x, &x); } Index: test/OpenMP/target_parallel_ast_print.cpp =================================================================== --- test/OpenMP/target_parallel_ast_print.cpp +++ test/OpenMP/target_parallel_ast_print.cpp @@ -39,7 +39,7 @@ h=2; #pragma omp target parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (parallel:argc > 0) num_threads(C) proc_bind(master) reduction(+:c, arr1[argc]) reduction(max:e, arr[:C][0:10]) foo(); -#pragma omp target parallel if (C) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:C][:argc]) reduction(&& : g) +#pragma omp target parallel if (C) num_threads(s) proc_bind(close) reduction(+:*arr1) reduction(^:e, f, arr[0:C][:argc]) reduction(&& : g) foo(); #pragma omp target parallel if (target:argc > 0) foo(); @@ -74,7 +74,7 @@ // CHECK-NEXT: h = 2; // CHECK-NEXT: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10]) // CHECK-NEXT: foo() -// CHECK-NEXT: #pragma omp target parallel if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g) +// CHECK-NEXT: #pragma omp target parallel if(5) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g) // CHECK-NEXT: foo() // CHECK-NEXT: #pragma omp target parallel if(target: argc > 0) // CHECK-NEXT: foo() @@ -106,7 +106,7 @@ // CHECK-NEXT: h = 2; // CHECK-NEXT: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10]) // CHECK-NEXT: foo() -// CHECK-NEXT: #pragma omp target parallel if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g) +// CHECK-NEXT: #pragma omp target parallel if(1) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g) // CHECK-NEXT: foo() // CHECK-NEXT: #pragma omp target parallel if(target: argc > 0) // CHECK-NEXT: foo() @@ -138,7 +138,7 @@ // CHECK-NEXT: h = 2; // CHECK-NEXT: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10]) // CHECK-NEXT: foo() -// CHECK-NEXT: #pragma omp target parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g) +// CHECK-NEXT: #pragma omp target parallel if(C) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g) // CHECK-NEXT: foo() // CHECK-NEXT: #pragma omp target parallel if(target: argc > 0) // CHECK-NEXT: foo() Index: test/OpenMP/target_parallel_for_ast_print.cpp =================================================================== --- test/OpenMP/target_parallel_for_ast_print.cpp +++ test/OpenMP/target_parallel_for_ast_print.cpp @@ -104,8 +104,8 @@ // CHECK-NEXT: #pragma omp target parallel for default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(N) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:N][0:10]) // CHECK-NEXT: for (int i = 0; i < 2; ++i) { // CHECK-NEXT: } -#pragma omp target parallel for if (N) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:N][:argc]) reduction(&& : h) -// CHECK-NEXT: #pragma omp target parallel for if(N) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:N][:argc]) reduction(&&: h) +#pragma omp target parallel for if (N) num_threads(s) proc_bind(close) reduction(+:*arr1) reduction(^:e, f, arr[0:N][:argc]) reduction(&& : h) +// CHECK-NEXT: #pragma omp target parallel for if(N) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:N][:argc]) reduction(&&: h) for (int i = 0; i < 2; ++i) {} // CHECK-NEXT: for (int i = 0; i < 2; ++i) { // CHECK-NEXT: } @@ -191,8 +191,8 @@ // CHECK-NEXT: #pragma omp target parallel for default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10]) // CHECK-NEXT: for (int i = 0; i < 2; ++i) { // CHECK-NEXT: } -#pragma omp target parallel for if (5) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:5][:argc]) reduction(&& : h) -// CHECK-NEXT: #pragma omp target parallel for if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: h) +#pragma omp target parallel for if (5) num_threads(s) proc_bind(close) reduction(+:*arr1) reduction(^:e, f, arr[0:5][:argc]) reduction(&& : h) +// CHECK-NEXT: #pragma omp target parallel for if(5) num_threads(s) proc_bind(close) reduction(+: *arr1) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: h) for (int i = 0; i < 2; ++i) {} // CHECK-NEXT: for (int i = 0; i < 2; ++i) { // CHECK-NEXT: }