InitRVal =
RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
break;
- case TEK_Aggregate:
- InitRVal = RValue::getAggregate(LV.getAddress(CGF));
- break;
+ case TEK_Aggregate: {
+ OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_LValue);
+ CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, LV);
+ CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
+ /*IsInitializer=*/false);
+ return;
+ }
}
OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
}
if (RHSVD->isInvalidDecl())
continue;
- if (!RHSVD->hasInit() &&
- (DeclareReductionRef.isUnset() || !S.LangOpts.CPlusPlus)) {
+ if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
<< Type << ReductionIdRange;
bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
: omp_out = omp_out > omp_in ? omp_in : omp_out) \
initializer(omp_priv = 2147483647)
+#pragma omp declare reduction(mymin \
+ : struct SSS \
+ : omp_out = omp_out.field > omp_in.field ? omp_in : omp_out)
+
int foo(int argc, char **argv) {
int x;
-#pragma omp parallel for reduction(mymin : x)
+ struct SSS ss;
+#pragma omp parallel for reduction(mymin : x, ss)
for (int i = 0; i < 1000; i++)
;
return 0;
}
-// CHECK: #pragma omp parallel for reduction(mymin: x)
+// CHECK: #pragma omp parallel for reduction(mymin: x,ss)
#endif
// CHECK: [[SSS_INT:.+]] = type { i32 }
// CHECK-LOAD: [[SSS_INT:.+]] = type { i32 }
+// CHECK-DAG: [[SSS_INIT:@.+]] = private constant %struct.SSS zeroinitializer
+// CHECK-DAG: [[INT_INIT:@.+]] = private constant i32 0
+
#pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
// CHECK: [[MUL:%.+]] = mul nsw i32
// OMP45-LOAD-NEXT: store i8 [[TRUNC]], i8*
// OMP45-LOAD-NEXT: ret void
// OMP45-LOAD-NEXT: }
+
+// CHECK-LABEL: bar
+struct SSS ss;
+int in;
+void bar() {
+ // CHECK: [[SS_PRIV:%.+]] = alloca %struct.SSS,
+ // CHECK: [[IN_PRIV:%.+]] = alloca i32,
+ // CHECK: [[BC:%.+]] = bitcast %struct.SSS* [[SS_PRIV]] to i8*
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[BC]], i8* align 4 bitcast (%struct.SSS* [[SSS_INIT]] to i8*), i64 4, i1 false)
+ // CHECK: [[IN_VAL:%.+]] = load i32, i32* [[INT_INIT]],
+ // CHECK: store i32 [[IN_VAL]], i32* [[IN_PRIV]],
+ // CHECK: call void @__kmpc_for_static_init_4(
+#pragma omp declare reduction(+ \
+ : struct SSS \
+ : omp_out = omp_in)
+#pragma omp declare reduction(+ \
+ : int \
+ : omp_out = omp_in)
+#pragma omp for reduction(+ \
+ : ss, in)
+ for (int i = 0; i < 10; ++i)
+ ;
+}
#endif
#pragma omp declare reduction(|: struct S: omp_out.s += omp_in.s) initializer(omp_priv = { 0 })
int fun(int arg) {
- struct S s;// expected-note {{'s' defined here}}
+ struct S s;
s.s = 0;
-#pragma omp parallel for reduction(+ : s) // expected-error {{list item of type 'struct S' is not valid for specified reduction operation: unable to provide default initialization value}}
+#pragma omp parallel for reduction(+ : s)
for (arg = 0; arg < 10; ++arg)
s.s += arg;
#pragma omp declare reduction(red : int : omp_out++)