[OPENMP50]Add codegen for update clause in depobj directive.
authorAlexey Bataev <a.bataev@hotmail.com>
Thu, 5 Mar 2020 18:45:28 +0000 (13:45 -0500)
committerAlexey Bataev <a.bataev@hotmail.com>
Thu, 5 Mar 2020 19:31:07 +0000 (14:31 -0500)
Added codegen for update clause in depobj. Reads the number of the
elements from the first element and updates flags for each element in
the loop.
```
omp_depend_t x;
kmp_depend_info *base = (kmp_depend_info *)x;
intptr_t num = x[-1].base_addr;
kmp_depend_info *end = x + num;
kmp_depend_info *el = base;
do {
  el.flags = new_flag;
  el = &el[1];
} while (el != end);
```

clang/lib/CodeGen/CGOpenMPRuntime.cpp
clang/lib/CodeGen/CGOpenMPRuntime.h
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/test/OpenMP/depobj_codegen.cpp

index 6906344..620f6ea 100644 (file)
@@ -5360,6 +5360,67 @@ void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal,
   (void)CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_free), Args);
 }
 
+void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
+                                       OpenMPDependClauseKind NewDepKind,
+                                       SourceLocation Loc) {
+  ASTContext &C = CGM.getContext();
+  QualType FlagsTy;
+  getDependTypes(C, KmpDependInfoTy, FlagsTy);
+  RecordDecl *KmpDependInfoRD =
+      cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
+  llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
+  LValue Base = CGF.EmitLoadOfPointerLValue(
+      DepobjLVal.getAddress(CGF),
+      C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
+  QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
+  Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+          Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy));
+  Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
+                            Base.getTBAAInfo());
+  llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
+      Addr.getPointer(),
+      llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
+  LValue NumDepsBase = CGF.MakeAddrLValue(
+      Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
+      Base.getBaseInfo(), Base.getTBAAInfo());
+  // NumDeps = deps[i].base_addr;
+  LValue BaseAddrLVal = CGF.EmitLValueForField(
+      NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
+  llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc);
+
+  Address Begin = Base.getAddress(CGF);
+  // Cast from pointer to array type to pointer to single element.
+  llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps);
+  // The basic structure here is a while-do loop.
+  llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body");
+  llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done");
+  llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
+  CGF.EmitBlock(BodyBB);
+  llvm::PHINode *ElementPHI =
+      CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast");
+  ElementPHI->addIncoming(Begin.getPointer(), EntryBB);
+  Begin = Address(ElementPHI, Begin.getAlignment());
+  Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(),
+                            Base.getTBAAInfo());
+  // deps[i].flags = NewDepKind;
+  RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind);
+  LValue FlagsLVal = CGF.EmitLValueForField(
+      Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
+  CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
+                        FlagsLVal);
+
+  // Shift the address forward by one element.
+  Address ElementNext =
+      CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext");
+  ElementPHI->addIncoming(ElementNext.getPointer(),
+                          CGF.Builder.GetInsertBlock());
+  llvm::Value *IsEmpty =
+      CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty");
+  CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
+  // Done.
+  CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
+}
+
 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
                                    const OMPExecutableDirective &D,
                                    llvm::Function *TaskFunction,
index fe52646..f176af6 100644 (file)
@@ -1791,6 +1791,12 @@ public:
   /// directive.
   void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal,
                          SourceLocation Loc);
+
+  /// Updates the dependency kind in the specified depobj object.
+  /// \param DepobjLVal LValue for the main depobj object.
+  /// \param NewDepKind New dependency kind.
+  void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
+                        OpenMPDependClauseKind NewDepKind, SourceLocation Loc);
 };
 
 /// Class supports emissionof SIMD-only code.
index 2de1fe6..1ffd594 100644 (file)
@@ -3817,6 +3817,11 @@ void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) {
     CGM.getOpenMPRuntime().emitDestroyClause(*this, DOLVal, DC->getBeginLoc());
     return;
   }
+  if (const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
+    CGM.getOpenMPRuntime().emitUpdateClause(
+        *this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
+    return;
+  }
 }
 
 void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
index b777c2b..a4a23ac 100644 (file)
@@ -67,6 +67,21 @@ int main(int argc, char **argv) {
 // CHECK: [[B_REF:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[B_BASE]], i{{.+}} -1
 // CHECK: [[B:%.+]] = bitcast %struct.kmp_depend_info* [[B_REF]] to i8*
 // CHECK: call void @__kmpc_free(i32 [[GTID]], i8* [[B]], i8* null)
+// CHECK: [[B:%.+]] = load i8*, i8** [[B_ADDR]],
+// CHECK: [[B_BASE:%.+]] = bitcast i8* [[B]] to %struct.kmp_depend_info*
+// CHECK: [[NUMDEPS_BASE:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[B_BASE]], i64 -1
+// CHECK: [[NUMDEPS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[NUMDEPS_BASE]], i{{.+}} 0, i{{.+}} 0
+// CHECK: [[NUMDEPS:%.+]] = load i64, i64* [[NUMDEPS_ADDR]],
+// CHECK: [[END:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[B_BASE]], i64 [[NUMDEPS]]
+// CHECK: br label %[[BODY:.+]]
+// CHECK: [[BODY]]:
+// CHECK: [[EL:%.+]] = phi %struct.kmp_depend_info* [ [[B_BASE]], %{{.+}} ], [ [[EL_NEXT:%.+]], %[[BODY]] ]
+// CHECK: [[FLAG_BASE:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[EL]], i{{.+}} 0, i{{.+}} 2
+// CHECK: store i8 4, i8* [[FLAG_BASE]],
+// CHECK: [[EL_NEXT]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[EL]], i{{.+}} 1
+// CHECK: [[IS_DONE:%.+]] = icmp eq %struct.kmp_depend_info* [[EL_NEXT]], [[END]]
+// CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[BODY]]
+// CHECK: [[DONE]]:
 
 // CHECK-LABEL: tmain
 // CHECK: [[ARGC_ADDR:%.+]] = alloca i8*,
@@ -91,5 +106,20 @@ int main(int argc, char **argv) {
 // CHECK: [[ARGC_REF:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[ARGC_BASE]], i{{.+}} -1
 // CHECK: [[ARGC:%.+]] = bitcast %struct.kmp_depend_info* [[ARGC_REF]] to i8*
 // CHECK: call void @__kmpc_free(i32 [[GTID]], i8* [[ARGC]], i8* null)
+// CHECK: [[ARGC:%.+]] = load i8*, i8** [[ARGC_ADDR]],
+// CHECK: [[ARGC_BASE:%.+]] = bitcast i8* [[ARGC]] to %struct.kmp_depend_info*
+// CHECK: [[NUMDEPS_BASE:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[ARGC_BASE]], i64 -1
+// CHECK: [[NUMDEPS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[NUMDEPS_BASE]], i{{.+}} 0, i{{.+}} 0
+// CHECK: [[NUMDEPS:%.+]] = load i64, i64* [[NUMDEPS_ADDR]],
+// CHECK: [[END:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[ARGC_BASE]], i64 [[NUMDEPS]]
+// CHECK: br label %[[BODY:.+]]
+// CHECK: [[BODY]]:
+// CHECK: [[EL:%.+]] = phi %struct.kmp_depend_info* [ [[ARGC_BASE]], %{{.+}} ], [ [[EL_NEXT:%.+]], %[[BODY]] ]
+// CHECK: [[FLAG_BASE:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[EL]], i{{.+}} 0, i{{.+}} 2
+// CHECK: store i8 3, i8* [[FLAG_BASE]],
+// CHECK: [[EL_NEXT]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[EL]], i{{.+}} 1
+// CHECK: [[IS_DONE:%.+]] = icmp eq %struct.kmp_depend_info* [[EL_NEXT]], [[END]]
+// CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[BODY]]
+// CHECK: [[DONE]]:
 
 #endif