[OPENMP50]Check for lastprivate conditional updates in atomic
authorAlexey Bataev <a.bataev@hotmail.com>
Tue, 28 Jan 2020 16:19:45 +0000 (11:19 -0500)
committerAlexey Bataev <a.bataev@hotmail.com>
Tue, 28 Jan 2020 16:40:31 +0000 (11:40 -0500)
constructs.

Added analysis in atomic constrcuts to support checks for updates of
conditional lastprivate variables.

clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/test/OpenMP/parallel_for_lastprivate_conditional.cpp

index 0e41d52..fcc619d 100644 (file)
@@ -3984,6 +3984,7 @@ static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst,
   if (IsSeqCst)
     CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
   CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc);
+  CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V);
 }
 
 static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst,
@@ -3992,6 +3993,7 @@ static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst,
   // x = expr;
   assert(X->isLValue() && "X of 'omp atomic write' is not lvalue");
   emitSimpleAtomicStore(CGF, IsSeqCst, CGF.EmitLValue(X), CGF.EmitAnyExpr(E));
+  CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
   // OpenMP, 2.12.6, atomic Construct
   // Any atomic construct with a seq_cst clause forces the atomically
   // performed operation to include an implicit flush operation without a
@@ -4148,6 +4150,7 @@ static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst,
   };
   (void)CGF.EmitOMPAtomicSimpleUpdateExpr(
       XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
+  CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
   // OpenMP, 2.12.6, atomic Construct
   // Any atomic construct with a seq_cst clause forces the atomically
   // performed operation to include an implicit flush operation without a
@@ -4214,6 +4217,7 @@ static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
     };
     auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
         XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
+    CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
     if (Res.first) {
       // 'atomicrmw' instruction was generated.
       if (IsPostfixUpdate) {
@@ -4240,6 +4244,7 @@ static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
     auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
         XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO,
         Loc, Gen);
+    CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
     if (Res.first) {
       // 'atomicrmw' instruction was generated.
       NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
@@ -4247,6 +4252,7 @@ static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
   }
   // Emit post-update store to 'v' of old/new 'x' value.
   CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc);
+  CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V);
   // OpenMP, 2.12.6, atomic Construct
   // Any atomic construct with a seq_cst clause forces the atomically
   // performed operation to include an implicit flush operation without a
index e05a5b9..5028235 100644 (file)
@@ -19,6 +19,8 @@ int main() {
       a = 0;
 #pragma omp parallel reduction(+:a) num_threads(10)
       a += i;
+#pragma omp atomic
+      a += i;
     }
   }
   return 0;
@@ -40,6 +42,18 @@ int main() {
 // CHECK: br label %[[DONE]]
 // CHECK: [[DONE]]:
 // CHECK: call void @__kmpc_end_critical(%struct.ident_t* @{{.+}}, i32 %{{.+}}, [8 x i32]* @{{.+}})
+// CHECK: atomicrmw add i32*
+// CHECK: call void @__kmpc_critical(%struct.ident_t* @{{.+}}, i32 %{{.+}}, [8 x i32]* @{{.+}})
+// CHECK: [[LAST_IV_VAL:%.+]] = load i32, i32* [[LAST_IV:@.+]],
+// CHECK: [[RES:%.+]] = icmp sle i32 [[LAST_IV_VAL]], [[IV:%.+]]
+// CHECK: br i1 [[RES]], label %[[THEN:.+]], label %[[DONE:.+]]
+// CHECK: [[THEN]]:
+// CHECK: store i32 [[IV]], i32* [[LAST_IV]],
+// CHECK: [[A_VAL:%.+]] = load i32, i32* [[A_PRIV:%.+]],
+// CHECK: store i32 [[A_VAL]], i32* [[A_GLOB:@.+]],
+// CHECK: br label %[[DONE]]
+// CHECK: [[DONE]]:
+// CHECK: call void @__kmpc_end_critical(%struct.ident_t* @{{.+}}, i32 %{{.+}}, [8 x i32]* @{{.+}})
 // CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @{{.+}}, i32 %{{.+}})
 // CHECK: [[IS_LAST:%.+]] = load i32, i32* %{{.+}},
 // CHECK: [[RES:%.+]] = icmp ne i32 [[IS_LAST]], 0