Skip to content

Commit

Permalink
[SYCL][FPGA] Refactor statments attributes to align with community th…
Browse files Browse the repository at this point in the history
…e way we handle conflicting vs duplicate values (intel#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: llvm/llvm-project#70762).

---------

Signed-off-by: Soumi Manna <[email protected]>
  • Loading branch information
smanna12 authored Jan 10, 2024
1 parent 1261e05 commit e29237e
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 17 deletions.
56 changes: 50 additions & 6 deletions clang/lib/Sema/SemaStmtAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename LoopAttrT>
static void CheckForDuplicateAttrs(Sema &S, ArrayRef<const Attr *> Attrs) {
auto FindFunc = [](const Attr *A) { return isa<const LoopAttrT>(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<llvm::APSInt> FirstValue;

const auto *CAFA =
dyn_cast<ConstantExpr>(cast<LoopAttrT>(*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<ConstantExpr>(cast<LoopAttrT>(*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<const Attr *> &Attrs) {
CheckForDuplicationSYCLLoopAttribute<SYCLIntelInitiationIntervalAttr>(
Expand All @@ -977,16 +1021,13 @@ static void CheckForIncompatibleSYCLLoopAttributes(
CheckForDuplicationSYCLLoopAttribute<SYCLIntelLoopCoalesceAttr>(S, Attrs);
CheckForDuplicationSYCLLoopAttribute<SYCLIntelDisableLoopPipeliningAttr>(
S, Attrs);
CheckForDuplicationSYCLLoopAttribute<SYCLIntelMaxInterleavingAttr>(S,
Attrs);
CheckForDuplicationSYCLLoopAttribute<SYCLIntelSpeculatedIterationsAttr>(
S, Attrs);
CheckForDuplicateAttrs<SYCLIntelMaxInterleavingAttr>(S, Attrs);
CheckForDuplicateAttrs<SYCLIntelSpeculatedIterationsAttr>(S, Attrs);
CheckForDuplicateSYCLIntelLoopCountAttrs(S, Attrs);
CheckForDuplicationSYCLLoopAttribute<LoopUnrollHintAttr>(S, Attrs, false);
CheckRedundantSYCLIntelIVDepAttrs(S, Attrs);
CheckForDuplicationSYCLLoopAttribute<SYCLIntelNofusionAttr>(S, Attrs);
CheckForDuplicationSYCLLoopAttribute<SYCLIntelMaxReinvocationDelayAttr>(
S, Attrs);
CheckForDuplicateAttrs<SYCLIntelMaxReinvocationDelayAttr>(S, Attrs);
CheckForDuplicationSYCLLoopAttribute<SYCLIntelEnableLoopPipeliningAttr>(
S, Attrs);
}
Expand Down Expand Up @@ -1169,6 +1210,9 @@ void Sema::ProcessStmtAttributes(Stmt *S, const ParsedAttributes &InAttrs,

bool Sema::CheckRebuiltAttributedStmtAttributes(ArrayRef<const Attr *> Attrs) {
CheckRedundantSYCLIntelIVDepAttrs(*this, Attrs);
CheckForDuplicateAttrs<SYCLIntelSpeculatedIterationsAttr>(*this, Attrs);
CheckForDuplicateAttrs<SYCLIntelMaxInterleavingAttr>(*this, Attrs);
CheckForDuplicateAttrs<SYCLIntelMaxReinvocationDelayAttr>(*this, Attrs);
return false;
}

Expand Down
45 changes: 34 additions & 11 deletions clang/test/SemaSYCL/intel-fpga-loops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 <int A, int B, int C, int D>
Expand All @@ -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 <int A, int B, int C>
Expand Down Expand Up @@ -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() {
Expand Down

0 comments on commit e29237e

Please sign in to comment.