Author: abataev Date: Wed Jul 15 07:14:07 2015 New Revision: 242285 URL: http://llvm.org/viewvc/llvm-project?rev=242285&view=rev Log: [OPENMP] http://llvm.org/PR24121: canonical loop rejected when comparison has implicit conversions or destruction
Allow to use complex iterators expressions in loops for C++. Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp cfe/trunk/test/OpenMP/for_codegen.cpp Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=242285&r1=242284&r2=242285&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original) +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Jul 15 07:14:07 2015 @@ -2262,6 +2262,22 @@ bool OpenMPIterationSpaceChecker::Depend (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::SetVar 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::CheckI 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::CheckC 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::Build 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 DKin 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(); Modified: cfe/trunk/test/OpenMP/for_codegen.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_codegen.cpp?rev=242285&r1=242284&r2=242285&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/for_codegen.cpp (original) +++ cfe/trunk/test/OpenMP/for_codegen.cpp Wed Jul 15 07:14:07 2015 @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits