From e29237e5af37d893d0866e6e0f4793c60e23c411 Mon Sep 17 00:00:00 2001 From: smanna12 Date: Wed, 10 Jan 2024 15:18:34 -0600 Subject: [PATCH] [SYCL][FPGA] Refactor statments attributes to align with community the way we handle conflicting vs duplicate values (#12243) This patch diagnose non-identical duplicates as a 'conflicting' loop attributes and suppress duplicate errors in cases where the two match for FPGA SYCL attributes: 'SYCLIntelMaxInterleavingAttr', 'SYCLIntelSpeculatedIterationsAttr', and 'SYCLIntelMaxReinvocationDelayAttr' to align with clang community change (Ref: https://github.com/llvm/llvm-project/pull/70762). --------- Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaStmtAttr.cpp | 56 +++++++++++++++++++++--- clang/test/SemaSYCL/intel-fpga-loops.cpp | 45 ++++++++++++++----- 2 files changed, 84 insertions(+), 17 deletions(-) diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index a5294b16de8e1..6a746042e324b 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -968,6 +968,50 @@ CheckForDuplicationSYCLLoopAttribute(Sema &S, } } +// Diagnose non-identical duplicates as a 'conflicting' loop attributes +// and suppress duplicate errors in cases where the two match for +// FPGA attributes: 'SYCLIntelMaxInterleavingAttr', +// 'SYCLIntelSpeculatedIterationsAttr', and +// 'SYCLIntelMaxReinvocationDelayAttr'. +template +static void CheckForDuplicateAttrs(Sema &S, ArrayRef Attrs) { + auto FindFunc = [](const Attr *A) { return isa(A); }; + const auto *FirstItr = std::find_if(Attrs.begin(), Attrs.end(), FindFunc); + + if (FirstItr == Attrs.end()) // no attributes found + return; + + const auto *LastFoundItr = FirstItr; + std::optional FirstValue; + + const auto *CAFA = + dyn_cast(cast(*FirstItr)->getNExpr()); + // Return early if first expression is dependent (since we don't + // know what the effective size will be), and skip the loop entirely. + if (!CAFA) + return; + + while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1, + Attrs.end(), FindFunc))) { + const auto *CASA = + dyn_cast(cast(*LastFoundItr)->getNExpr()); + // If the value is dependent, we can not test anything. + if (!CASA) + return; + // Test the attribute values. + llvm::APSInt SecondValue = CASA->getResultAsAPSInt(); + if (!FirstValue) + FirstValue = CAFA->getResultAsAPSInt(); + + if (FirstValue != SecondValue) { + S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_conflict) + << *FirstItr; + S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute); + return; + } + } +} + static void CheckForIncompatibleSYCLLoopAttributes( Sema &S, const SmallVectorImpl &Attrs) { CheckForDuplicationSYCLLoopAttribute( @@ -977,16 +1021,13 @@ static void CheckForIncompatibleSYCLLoopAttributes( CheckForDuplicationSYCLLoopAttribute(S, Attrs); CheckForDuplicationSYCLLoopAttribute( S, Attrs); - CheckForDuplicationSYCLLoopAttribute(S, - Attrs); - CheckForDuplicationSYCLLoopAttribute( - S, Attrs); + CheckForDuplicateAttrs(S, Attrs); + CheckForDuplicateAttrs(S, Attrs); CheckForDuplicateSYCLIntelLoopCountAttrs(S, Attrs); CheckForDuplicationSYCLLoopAttribute(S, Attrs, false); CheckRedundantSYCLIntelIVDepAttrs(S, Attrs); CheckForDuplicationSYCLLoopAttribute(S, Attrs); - CheckForDuplicationSYCLLoopAttribute( - S, Attrs); + CheckForDuplicateAttrs(S, Attrs); CheckForDuplicationSYCLLoopAttribute( S, Attrs); } @@ -1169,6 +1210,9 @@ void Sema::ProcessStmtAttributes(Stmt *S, const ParsedAttributes &InAttrs, bool Sema::CheckRebuiltAttributedStmtAttributes(ArrayRef Attrs) { CheckRedundantSYCLIntelIVDepAttrs(*this, Attrs); + CheckForDuplicateAttrs(*this, Attrs); + CheckForDuplicateAttrs(*this, Attrs); + CheckForDuplicateAttrs(*this, Attrs); return false; } diff --git a/clang/test/SemaSYCL/intel-fpga-loops.cpp b/clang/test/SemaSYCL/intel-fpga-loops.cpp index a293d024491d0..a26f9a0244f07 100644 --- a/clang/test/SemaSYCL/intel-fpga-loops.cpp +++ b/clang/test/SemaSYCL/intel-fpga-loops.cpp @@ -285,17 +285,24 @@ void zoo() { [[intel::max_interleaving(1)]] [[intel::loop_coalesce]] for (int i = 0; i != 10; ++i) a[i] = 0; - [[intel::max_interleaving(1)]] - // expected-error@+2 {{duplicate Intel FPGA loop attribute 'max_interleaving'}} + [[intel::max_interleaving(1)]] // expected-note {{previous attribute is here}} + [[intel::max_interleaving(1)]] // OK. + // expected-error@+2 {{conflicting loop attribute 'max_interleaving'}} [[intel::speculated_iterations(1)]] [[intel::max_interleaving(0)]] for (int i = 0; i != 10; ++i) a[i] = 0; - [[intel::speculated_iterations(1)]] - // expected-error@+2 {{duplicate Intel FPGA loop attribute 'speculated_iterations'}} + [[intel::speculated_iterations(1)]] // expected-note {{previous attribute is here}} + // expected-error@+2 {{conflicting loop attribute 'speculated_iterations'}} [[intel::loop_coalesce]] [[intel::speculated_iterations(2)]] for (int i = 0; i != 10; ++i) a[i] = 0; + [[intel::speculated_iterations(1)]] // expected-note {{previous attribute is here}} + [[intel::speculated_iterations(1)]] // OK + // expected-error@+1 {{conflicting loop attribute 'speculated_iterations'}} + [[intel::speculated_iterations(2)]] for (int i = 0; i != 10; ++i) + a[i] = 0; + [[intel::ivdep]] // expected-warning@+2 {{ignoring redundant Intel FPGA loop attribute 'ivdep': safelen INF >= safelen INF}} // expected-note@-2 {{previous attribute is here}} @@ -359,10 +366,15 @@ void zoo() { a[i] = 0; [[intel::max_reinvocation_delay(1)]] - // expected-error@+1{{duplicate Intel FPGA loop attribute 'max_reinvocation_delay'}} [[intel::max_reinvocation_delay(1)]] for (int i = 0; i != 10; ++i) a[i] = 0; + [[intel::max_reinvocation_delay(10)]] // expected-note {{previous attribute is here}} + [[intel::max_reinvocation_delay(10)]] // OK + // expected-error@+1 {{conflicting loop attribute 'max_reinvocation_delay'}} + [[intel::max_reinvocation_delay(20)]] for (int i = 0; i != 10; ++i) + a[i] = 0; + [[intel::enable_loop_pipelining]] // expected-error@+1 {{duplicate Intel FPGA loop attribute 'enable_loop_pipelining'}} [[intel::enable_loop_pipelining]] for (int i = 0; i != 10; ++i) @@ -501,11 +513,14 @@ void max_interleaving_dependent() { [[intel::max_interleaving(C)]] for (int i = 0; i != 10; ++i) a[i] = 0; - // expected-error@+2 {{duplicate Intel FPGA loop attribute 'max_interleaving'}} - [[intel::max_interleaving(C)]] + // expected-error@+2 {{conflicting loop attribute 'max_interleaving'}} + [[intel::max_interleaving(C)]] // expected-note {{previous attribute is here}} [[intel::max_interleaving(D)]] for (int i = 0; i != 10; ++i) a[i] = 0; + [[intel::max_interleaving(D)]] + [[intel::max_interleaving(D)]] for (int i = 0; i != 10; ++i) + a[i] = 0; } template @@ -515,14 +530,18 @@ void speculated_iterations_dependent() { [[intel::speculated_iterations(C)]] for (int i = 0; i != 10; ++i) a[i] = 0; - // expected-error@+2 {{duplicate Intel FPGA loop attribute 'speculated_iterations'}} - [[intel::speculated_iterations(A)]] + // expected-error@+2 {{conflicting loop attribute 'speculated_iterations'}} + [[intel::speculated_iterations(A)]] // expected-note {{previous attribute is here}} [[intel::speculated_iterations(B)]] for (int i = 0; i != 10; ++i) a[i] = 0; // speculated_iterations attribute accepts value 0. [[intel::speculated_iterations(D)]] for (int i = 0; i != 10; ++i) a[i] = 0; + + [[intel::speculated_iterations(B)]] + [[intel::speculated_iterations(B)]] for (int i = 0; i != 10; ++i) + a[i] = 0; } template @@ -593,10 +612,14 @@ void max_reinvocation_delay_dependent() { [[intel::max_reinvocation_delay(C)]] for (int i = 0; i != 10; ++i) a[i] = 0; - // expected-error@+2 {{duplicate Intel FPGA loop attribute 'max_reinvocation_delay'}} - [[intel::max_reinvocation_delay(A)]] + // expected-error@+2 {{conflicting loop attribute 'max_reinvocation_delay'}} + [[intel::max_reinvocation_delay(A)]] // expected-note {{previous attribute is here}} [[intel::max_reinvocation_delay(B)]] for (int i = 0; i != 10; ++i) a[i] = 0; + + [[intel::max_reinvocation_delay(A)]] + [[intel::max_reinvocation_delay(A)]] for (int i = 0; i != 10; ++i) + a[i] = 0; } void check_max_concurrency_expression() {