]> granicus.if.org Git - clang/commitdiff
[OPENMP] http://llvm.org/PR24121: canonical loop rejected when comparison has implici...
authorAlexey Bataev <a.bataev@hotmail.com>
Wed, 15 Jul 2015 12:14:07 +0000 (12:14 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Wed, 15 Jul 2015 12:14:07 +0000 (12:14 +0000)
Allow to use complex iterators expressions in loops for C++.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@242285 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOpenMP.cpp
test/OpenMP/for_codegen.cpp

index 4030d9e66e02185e2a339eaaa70a0cecbcb967c7..239ede5bb65bc75be596f4dd011748f05f5fc8b3 100644 (file)
@@ -2262,6 +2262,22 @@ bool OpenMPIterationSpaceChecker::Dependent() const {
          (UB && UB->isValueDependent()) || (Step && Step->isValueDependent());
 }
 
+template <typename T>
+static T *getExprAsWritten(T *E) {
+  if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
+    E = ExprTemp->getSubExpr();
+
+  if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
+    E = MTE->GetTemporaryExpr();
+
+  while (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
+    E = Binder->getSubExpr();
+
+  if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
+    E = ICE->getSubExprAsWritten();
+  return E->IgnoreParens();
+}
+
 bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar,
                                               DeclRefExpr *NewVarRefExpr,
                                               Expr *NewLB) {
@@ -2272,6 +2288,11 @@ bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar,
     return true;
   Var = NewVar;
   VarRef = NewVarRefExpr;
+  if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
+    if (const CXXConstructorDecl *Ctor = CE->getConstructor())
+      if (Ctor->isCopyConstructor() && CE->getNumArgs() == 1 &&
+          CE->getArg(0) != nullptr)
+        NewLB = CE->getArg(0)->IgnoreParenImpCasts();
   LB = NewLB;
   return false;
 }
@@ -2402,7 +2423,7 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
 static const VarDecl *GetInitVarDecl(const Expr *E) {
   if (!E)
     return nullptr;
-  E = E->IgnoreParenImpCasts();
+  E = getExprAsWritten(E);
   if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
     if (const CXXConstructorDecl *Ctor = CE->getConstructor())
       if (Ctor->isCopyConstructor() && CE->getNumArgs() == 1 &&
@@ -2425,7 +2446,7 @@ bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
     SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond) << Var;
     return true;
   }
-  S = S->IgnoreParenImpCasts();
+  S = getExprAsWritten(S);
   SourceLocation CondLoc = S->getLocStart();
   if (auto BO = dyn_cast<BinaryOperator>(S)) {
     if (BO->isRelationalOp()) {
@@ -2646,6 +2667,11 @@ Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const {
       S, DefaultLoc, TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
                                   : (TestIsStrictOp ? BO_GT : BO_GE),
       LB, UB);
+  if (CondExpr.isUsable()) {
+    CondExpr = SemaRef.PerformImplicitConversion(
+        CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
+        /*AllowExplicit=*/true);
+  }
   SemaRef.getDiagnostics().setSuppressAllDiagnostics(Suppress);
   // Otherwise use original loop conditon and evaluate it in runtime.
   return CondExpr.isUsable() ? CondExpr.get() : Cond;
@@ -3231,7 +3257,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
   Built.IterationVarRef = IV.get();
   Built.LastIteration = LastIteration.get();
   Built.NumIterations = NumIterations.get();
-  Built.CalcLastIteration = CalcLastIteration.get();
+  Built.CalcLastIteration =
+      SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get();
   Built.PreCond = PreCond.get();
   Built.Cond = Cond.get();
   Built.Init = Init.get();
index 082a0d4d884195329354272a736b18dca8d57820..539fb7bf02b280d0474c88c14f3da4006fe1a34b 100644 (file)
@@ -389,6 +389,7 @@ void for_with_global_lcv() {
 // CHECK: store i8 [[I_VAL]], i8* [[K]]
 // CHECK-NOT: [[I]]
 // CHECK: call void @__kmpc_for_static_fini(
+// CHECK: call void @__kmpc_barrier(
 #pragma omp for
   for (i = 0; i < 2; ++i) {
     k = i;
@@ -410,5 +411,59 @@ void for_with_global_lcv() {
   }
 }
 
-#endif // HEADER
+struct Bool {
+  Bool(bool b) : b(b) {}
+  operator bool() const { return b; }
+  const bool b;
+};
+
+template <typename T>
+struct It {
+  It() : p(0) {}
+  It(const It &) ;
+  It(It &) ;
+  It &operator=(const It &);
+  It &operator=(It &);
+  ~It() {}
+
+  It(T *p) : p(p) {}
+
+  operator T *&() { return p; }
+  operator T *() const { return p; }
+  T *operator->() const { return p; }
+
+  It &operator++() { ++p; return *this; }
+  It &operator--() { --p; return *this; }
+  It &operator+=(unsigned n) { p += n; return *this; }
+  It &operator-=(unsigned n) { p -= n; return *this; }
+
+  T *p;
+};
+
+template <typename T>
+It<T> operator+(It<T> a, typename It<T>::difference_type n) { return a.p + n; }
+
+template <typename T>
+It<T> operator+(typename It<T>::difference_type n, It<T> a) { return a.p + n; }
+
+template <typename T>
+It<T> operator-(It<T> a, typename It<T>::difference_type n) { return a.p - n; }
 
+typedef Bool BoolType;
+
+template <typename T>
+BoolType operator<(It<T> a, It<T> b) { return a.p < b.p; }
+
+void loop_with_It(It<char> begin, It<char> end) {
+#pragma omp for
+  for (It<char> it = begin; it < end; ++it) {
+    *it = 0;
+  }
+}
+
+// CHECK-LABEL: loop_with_It
+// CHECK: call i32 @__kmpc_global_thread_num(
+// CHECK: call void @__kmpc_for_static_init_8(
+// CHECK: call void @__kmpc_for_static_fini(
+
+#endif // HEADER