From 5a6e060edf3282c6605f084616a14cb4e5d45e05 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Fri, 19 Feb 2021 12:41:41 -0800 Subject: [PATCH 1/4] Add an attr tablegen feature for checking langopts For SYCL, we want some attributes to be ignored in host mode, but without diagnosing the attribute as being ignored. This adds a bit to the tablegen emitter to specify that a given language option opts into this behavior. This allows us to more naturally specify that an attribute is a device-only attribute from Attr.td without adding logic in SemaDeclAttr.cpp to bail out in host mode (which looks like a bug due to the lack of an ignored attribute warning). As a drive-by, this also corrects a think-o with the [[intel::reqd_sub_group_size]] attribute in OpenCL mode, which was always being silently dropped. --- clang/include/clang/Basic/Attr.td | 41 +++++++++++---------- clang/lib/Sema/SemaDeclAttr.cpp | 44 ++++------------------- clang/utils/TableGen/ClangAttrEmitter.cpp | 17 ++++++--- 3 files changed, 41 insertions(+), 61 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 5935897980b2d..80a6b8e331ac4 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -317,10 +317,13 @@ class SubjectList subjects, SubjectDiag diag = WarnDiag, string CustomDiag = customDiag; } -class LangOpt { +class LangOpt { // The language option to test; ignored when custom code is supplied. string Name = name; + // If set to 1, diagnose the attribute as being ignored if the test fails. + bit Warn = warn; + // A custom predicate, written as an expression evaluated in a context with // "LangOpts" bound. code CustomCode = customCode; @@ -329,11 +332,11 @@ def MicrosoftExt : LangOpt<"MicrosoftExt">; def Borland : LangOpt<"Borland">; def CUDA : LangOpt<"CUDA">; def HIP : LangOpt<"HIP">; -def SYCLIsDevice : LangOpt<"SYCLIsDevice">; -def SYCL : LangOpt<"SYCLIsDevice">; -def SYCLIsHost : LangOpt<"SYCLIsHost">; +def SYCL : LangOpt<"SYCL">; +def SYCLIsDevice : LangOpt<"", 0, "(LangOpts.SYCL && LangOpts.SYCLIsDevice)">; +def SYCLIsHost : LangOpt<"", 0, "(LangOpts.SYCL && LangOpts.SYCLIsHost)">; def SYCLExplicitSIMD : LangOpt<"SYCLExplicitSIMD">; -def COnly : LangOpt<"", "!LangOpts.CPlusPlus">; +def COnly : LangOpt<"", 1, "!LangOpts.CPlusPlus">; def CPlusPlus : LangOpt<"CPlusPlus">; def OpenCL : LangOpt<"OpenCL">; def RenderScript : LangOpt<"RenderScript">; @@ -341,7 +344,7 @@ def ObjC : LangOpt<"ObjC">; def BlocksSupported : LangOpt<"Blocks">; def ObjCAutoRefCount : LangOpt<"ObjCAutoRefCount">; def ObjCNonFragileRuntime - : LangOpt<"", "LangOpts.ObjCRuntime.allowsClassStubs()">; + : LangOpt<"", 1, "LangOpts.ObjCRuntime.allowsClassStubs()">; // Language option for CMSE extensions def Cmse : LangOpt<"Cmse">; @@ -1322,7 +1325,7 @@ def SYCLIntelNoGlobalWorkOffset : InheritableAttr { let Spellings = [CXX11<"intelfpga","no_global_work_offset">, CXX11<"intel","no_global_work_offset">]; let Args = [ExprArgument<"Value", /*optional*/1>]; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [SYCLIntelNoGlobalWorkOffsetAttrDocs]; } @@ -1331,7 +1334,7 @@ def SYCLIntelLoopFuse : InheritableAttr { let Spellings = [CXX11<"intel", "loop_fuse">, CXX11<"intel", "loop_fuse_independent">]; let Args = [ExprArgument<"Value", /*optional=*/ 1>]; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Subjects = SubjectList<[Function], ErrorDiag>; let Accessors = [Accessor<"isIndependent", [CXX11<"intel", "loop_fuse_independent">]>]; @@ -1946,7 +1949,7 @@ def IntelFPGADoublePump : Attr { CXX11<"intel", "doublepump">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGADoublePumpAttrDocs]; } @@ -1955,7 +1958,7 @@ def IntelFPGASinglePump : Attr { CXX11<"intel", "singlepump">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGASinglePumpAttrDocs]; } @@ -1976,7 +1979,7 @@ def IntelFPGAMemory : Attr { }]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGAMemoryAttrDocs]; } @@ -1985,7 +1988,7 @@ def IntelFPGARegister : Attr { CXX11<"intel", "fpga_register">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGARegisterAttrDocs]; } @@ -1996,7 +1999,7 @@ def IntelFPGABankWidth : Attr { let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGABankWidthAttrDocs]; } @@ -2006,7 +2009,7 @@ def IntelFPGANumBanks : Attr { let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGANumBanksAttrDocs]; } @@ -2014,7 +2017,7 @@ def IntelFPGAPrivateCopies : InheritableAttr { let Spellings = [CXX11<"intelfpga","private_copies">, CXX11<"intel","private_copies">]; let Args = [ExprArgument<"Value">]; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Subjects = SubjectList<[IntelFPGALocalNonConstVar, Field], ErrorDiag>; let Documentation = [IntelFPGAPrivateCopiesAttrDocs]; } @@ -2026,7 +2029,7 @@ def IntelFPGAMerge : Attr { let Args = [StringArgument<"Name">, StringArgument<"Direction">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGAMergeAttrDocs]; } @@ -2036,7 +2039,7 @@ def IntelFPGAMaxReplicates : Attr { let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGAMaxReplicatesAttrDocs]; } @@ -2045,7 +2048,7 @@ def IntelFPGASimpleDualPort : Attr { CXX11<"intel","simple_dual_port">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGASimpleDualPortAttrDocs]; } @@ -2081,7 +2084,7 @@ def IntelFPGAForcePow2Depth : Attr { let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice]; let Documentation = [IntelFPGAForcePow2DepthAttrDocs]; let AdditionalMembers = [{ static unsigned getMinValue() { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 0558baa1e4ece..8863fded3e3f6 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3211,7 +3211,12 @@ static void handleWorkGroupSizeHint(Sema &S, Decl *D, const ParsedAttr &AL) { // Handles intel_reqd_sub_group_size. static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { - if (S.LangOpts.SYCLIsHost) + // In SYCLIsHost mode, we want to ignore the attribute. In OpenCL or + // SYCLIsDevice mode, we want to process the attribute as normal. This cannot + // be handled in Attr.td unless ClangAttrEmitter.cpp gets smarter logic about + // when to suppress the "ignored attribute" warnings with a list of language + // options. + if (!S.LangOpts.SYCLIsDevice && !S.LangOpts.OpenCL) return; Expr *E = AL.getArgAsExpr(0); @@ -3387,10 +3392,6 @@ void Sema::addSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI, if (checkSYCLIntelLoopFuseArgument(*this, CI, E)) return; - // Attribute should not be added during host compilation. - if (getLangOpts().SYCLIsHost) - return; - SYCLIntelLoopFuseAttr *NewAttr = mergeSYCLIntelLoopFuseAttr(D, CI, E); if (NewAttr) @@ -5634,9 +5635,6 @@ static bool checkForDuplicateAttribute(Sema &S, Decl *D, static void handleNoGlobalWorkOffsetAttr(Sema &S, Decl *D, const ParsedAttr &A) { - if (S.LangOpts.SYCLIsHost) - return; - checkForDuplicateAttribute(S, D, A); S.CheckDeprecatedSYCLAttributeSpelling(A); @@ -5653,9 +5651,6 @@ static void handleNoGlobalWorkOffsetAttr(Sema &S, Decl *D, /// Both are incompatible with the __register__ attribute. template static void handleIntelFPGAPumpAttr(Sema &S, Decl *D, const ParsedAttr &A) { - if (S.LangOpts.SYCLIsHost) - return; - checkForDuplicateAttribute(S, D, A); if (checkAttrMutualExclusion(S, D, A)) return; @@ -5676,10 +5671,6 @@ static void handleIntelFPGAPumpAttr(Sema &S, Decl *D, const ParsedAttr &A) { /// This is incompatible with the [[intelfpga::register]] attribute. static void handleIntelFPGAMemoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - - if (S.LangOpts.SYCLIsHost) - return; - checkForDuplicateAttribute(S, D, AL); if (checkAttrMutualExclusion(S, D, AL)) return; @@ -5749,10 +5740,6 @@ static bool checkIntelFPGARegisterAttrCompatibility(Sema &S, Decl *D, /// Handle the [[intelfpga::register]] attribute. /// This is incompatible with most of the other memory attributes. static void handleIntelFPGARegisterAttr(Sema &S, Decl *D, const ParsedAttr &A) { - - if (S.LangOpts.SYCLIsHost) - return; - checkForDuplicateAttribute(S, D, A); if (checkIntelFPGARegisterAttrCompatibility(S, D, A)) return; @@ -5770,10 +5757,6 @@ static void handleIntelFPGARegisterAttr(Sema &S, Decl *D, const ParsedAttr &A) { template static void handleOneConstantPowerTwoValueAttr(Sema &S, Decl *D, const ParsedAttr &A) { - - if (S.LangOpts.SYCLIsHost) - return; - checkForDuplicateAttribute(S, D, A); if (checkAttrMutualExclusion(S, D, A)) return; @@ -5785,9 +5768,6 @@ static void handleOneConstantPowerTwoValueAttr(Sema &S, Decl *D, static void handleIntelFPGASimpleDualPortAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (S.LangOpts.SYCLIsHost) - return; - checkForDuplicateAttribute(S, D, AL); if (checkAttrMutualExclusion(S, D, AL)) @@ -5805,9 +5785,6 @@ static void handleIntelFPGASimpleDualPortAttr(Sema &S, Decl *D, static void handleIntelFPGAMaxReplicatesAttr(Sema &S, Decl *D, const ParsedAttr &A) { - if (S.LangOpts.SYCLIsHost) - return; - checkForDuplicateAttribute(S, D, A); if (checkAttrMutualExclusion(S, D, A)) @@ -5825,9 +5802,6 @@ static void handleIntelFPGAMaxReplicatesAttr(Sema &S, Decl *D, static void handleIntelFPGAMergeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { checkForDuplicateAttribute(S, D, AL); - if (S.LangOpts.SYCLIsHost) - return; - if (checkAttrMutualExclusion(S, D, AL)) return; @@ -5946,9 +5920,6 @@ void Sema::AddIntelFPGABankBitsAttr(Decl *D, const AttributeCommonInfo &CI, static void handleIntelFPGAPrivateCopiesAttr(Sema &S, Decl *D, const ParsedAttr &A) { - if (S.LangOpts.SYCLIsHost) - return; - checkForDuplicateAttribute(S, D, A); if (checkAttrMutualExclusion(S, D, A)) return; @@ -5960,9 +5931,6 @@ static void handleIntelFPGAPrivateCopiesAttr(Sema &S, Decl *D, static void handleIntelFPGAForcePow2DepthAttr(Sema &S, Decl *D, const ParsedAttr &A) { - if (S.LangOpts.SYCLIsHost) - return; - checkForDuplicateAttribute(S, D, A); if (checkAttrMutualExclusion(S, D, A)) diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index da3f0db3c0183..1d016f7489448 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1992,13 +1992,19 @@ bool PragmaClangAttributeSupport::isAttributedSupported( return true; } -static std::string GenerateTestExpression(ArrayRef LangOpts) { +static std::string GenerateTestExpression(ArrayRef LangOpts, + bool *ShouldDiagnose = nullptr) { std::string Test; for (auto *E : LangOpts) { if (!Test.empty()) Test += " || "; + // If any of the language options say "warn", then warn if any of the + // options fail. + if (ShouldDiagnose && E->getValueAsBit("Warn")) + *ShouldDiagnose = true; + const StringRef Code = E->getValueAsString("CustomCode"); if (!Code.empty()) { Test += "("; @@ -3638,10 +3644,13 @@ static void GenerateLangOptRequirements(const Record &R, OS << "bool diagLangOpts(Sema &S, const ParsedAttr &Attr) "; OS << "const override {\n"; OS << " auto &LangOpts = S.LangOpts;\n"; - OS << " if (" << GenerateTestExpression(LangOpts) << ")\n"; + bool Warn = false; + OS << " if (" << GenerateTestExpression(LangOpts, &Warn) << ")\n"; OS << " return true;\n\n"; - OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) "; - OS << "<< Attr;\n"; + if (Warn) { + OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) "; + OS << "<< Attr;\n"; + } OS << " return false;\n"; OS << "}\n\n"; } From 5110b41ece5fe91029d97683d62ede12791c8e7b Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 22 Feb 2021 06:52:28 -0800 Subject: [PATCH 2/4] Slight redesign of the feature. We still want to list explicitly that the attribute is accepted in host mode, otherwise there's no good way to see that the attribute is silently being accepted there. This complicates the tablegen slightly, but also makes for a more obvious feature. --- clang/include/clang/Basic/Attr.td | 42 +++++++++++---------- clang/lib/Sema/SemaDeclAttr.cpp | 8 ---- clang/test/CodeGenSYCL/loop_fusion_host.cpp | 6 --- clang/utils/TableGen/ClangAttrEmitter.cpp | 28 +++++++------- 4 files changed, 35 insertions(+), 49 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 80a6b8e331ac4..e439175673399 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -317,11 +317,12 @@ class SubjectList subjects, SubjectDiag diag = WarnDiag, string CustomDiag = customDiag; } -class LangOpt { +class LangOpt { // The language option to test; ignored when custom code is supplied. string Name = name; - // If set to 1, diagnose the attribute as being ignored if the test fails. + // If set to 0, the attribute is accepted but is silently ignored. This is + // useful in multi-compilation situations like SYCL. bit Warn = warn; // A custom predicate, written as an expression evaluated in a context with @@ -333,10 +334,11 @@ def Borland : LangOpt<"Borland">; def CUDA : LangOpt<"CUDA">; def HIP : LangOpt<"HIP">; def SYCL : LangOpt<"SYCL">; -def SYCLIsDevice : LangOpt<"", 0, "(LangOpts.SYCL && LangOpts.SYCLIsDevice)">; -def SYCLIsHost : LangOpt<"", 0, "(LangOpts.SYCL && LangOpts.SYCLIsHost)">; +def SYCLIsDevice : LangOpt<"SYCLIsDevice">; +def SYCLIsHost : LangOpt<"SYCLIsHost">; +def SilentlyIgnoreSYCLIsHost : LangOpt<"SYCLIsHost", "", 0>; def SYCLExplicitSIMD : LangOpt<"SYCLExplicitSIMD">; -def COnly : LangOpt<"", 1, "!LangOpts.CPlusPlus">; +def COnly : LangOpt<"", "!LangOpts.CPlusPlus">; def CPlusPlus : LangOpt<"CPlusPlus">; def OpenCL : LangOpt<"OpenCL">; def RenderScript : LangOpt<"RenderScript">; @@ -344,7 +346,7 @@ def ObjC : LangOpt<"ObjC">; def BlocksSupported : LangOpt<"Blocks">; def ObjCAutoRefCount : LangOpt<"ObjCAutoRefCount">; def ObjCNonFragileRuntime - : LangOpt<"", 1, "LangOpts.ObjCRuntime.allowsClassStubs()">; + : LangOpt<"", "LangOpts.ObjCRuntime.allowsClassStubs()">; // Language option for CMSE extensions def Cmse : LangOpt<"Cmse">; @@ -1325,7 +1327,7 @@ def SYCLIntelNoGlobalWorkOffset : InheritableAttr { let Spellings = [CXX11<"intelfpga","no_global_work_offset">, CXX11<"intel","no_global_work_offset">]; let Args = [ExprArgument<"Value", /*optional*/1>]; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [SYCLIntelNoGlobalWorkOffsetAttrDocs]; } @@ -1334,7 +1336,7 @@ def SYCLIntelLoopFuse : InheritableAttr { let Spellings = [CXX11<"intel", "loop_fuse">, CXX11<"intel", "loop_fuse_independent">]; let Args = [ExprArgument<"Value", /*optional=*/ 1>]; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Subjects = SubjectList<[Function], ErrorDiag>; let Accessors = [Accessor<"isIndependent", [CXX11<"intel", "loop_fuse_independent">]>]; @@ -1398,7 +1400,7 @@ def IntelReqdSubGroupSize: InheritableAttr { let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[Function, CXXMethod], ErrorDiag>; let Documentation = [IntelReqdSubGroupSizeDocs]; - let LangOpts = [OpenCL, SYCLIsDevice, SYCLIsHost]; + let LangOpts = [OpenCL, SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; } // This attribute is both a type attribute, and a declaration attribute (for @@ -1949,7 +1951,7 @@ def IntelFPGADoublePump : Attr { CXX11<"intel", "doublepump">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGADoublePumpAttrDocs]; } @@ -1958,7 +1960,7 @@ def IntelFPGASinglePump : Attr { CXX11<"intel", "singlepump">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGASinglePumpAttrDocs]; } @@ -1979,7 +1981,7 @@ def IntelFPGAMemory : Attr { }]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGAMemoryAttrDocs]; } @@ -1988,7 +1990,7 @@ def IntelFPGARegister : Attr { CXX11<"intel", "fpga_register">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGARegisterAttrDocs]; } @@ -1999,7 +2001,7 @@ def IntelFPGABankWidth : Attr { let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGABankWidthAttrDocs]; } @@ -2009,7 +2011,7 @@ def IntelFPGANumBanks : Attr { let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGANumBanksAttrDocs]; } @@ -2017,7 +2019,7 @@ def IntelFPGAPrivateCopies : InheritableAttr { let Spellings = [CXX11<"intelfpga","private_copies">, CXX11<"intel","private_copies">]; let Args = [ExprArgument<"Value">]; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Subjects = SubjectList<[IntelFPGALocalNonConstVar, Field], ErrorDiag>; let Documentation = [IntelFPGAPrivateCopiesAttrDocs]; } @@ -2029,7 +2031,7 @@ def IntelFPGAMerge : Attr { let Args = [StringArgument<"Name">, StringArgument<"Direction">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGAMergeAttrDocs]; } @@ -2039,7 +2041,7 @@ def IntelFPGAMaxReplicates : Attr { let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGAMaxReplicatesAttrDocs]; } @@ -2048,7 +2050,7 @@ def IntelFPGASimpleDualPort : Attr { CXX11<"intel","simple_dual_port">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGASimpleDualPortAttrDocs]; } @@ -2084,7 +2086,7 @@ def IntelFPGAForcePow2Depth : Attr { let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, Field], ErrorDiag>; - let LangOpts = [SYCLIsDevice]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let Documentation = [IntelFPGAForcePow2DepthAttrDocs]; let AdditionalMembers = [{ static unsigned getMinValue() { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8863fded3e3f6..398165f71457d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3211,14 +3211,6 @@ static void handleWorkGroupSizeHint(Sema &S, Decl *D, const ParsedAttr &AL) { // Handles intel_reqd_sub_group_size. static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { - // In SYCLIsHost mode, we want to ignore the attribute. In OpenCL or - // SYCLIsDevice mode, we want to process the attribute as normal. This cannot - // be handled in Attr.td unless ClangAttrEmitter.cpp gets smarter logic about - // when to suppress the "ignored attribute" warnings with a list of language - // options. - if (!S.LangOpts.SYCLIsDevice && !S.LangOpts.OpenCL) - return; - Expr *E = AL.getArgAsExpr(0); if (D->getAttr()) diff --git a/clang/test/CodeGenSYCL/loop_fusion_host.cpp b/clang/test/CodeGenSYCL/loop_fusion_host.cpp index 5245855ebd626..98237d61a6dba 100644 --- a/clang/test/CodeGenSYCL/loop_fusion_host.cpp +++ b/clang/test/CodeGenSYCL/loop_fusion_host.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -fsycl -fsycl-is-host -triple -x86_64-unknown-linux-gnu -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fsycl -fsycl-is-host -triple -x86_64-unknown-linux-gnu -disable-llvm-passes -verify -Wno-sycl-2017-compat -DDIAG %s template __attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) { @@ -30,8 +29,3 @@ void foo() { kernel(f5); } // CHECK-NOT: !loop_fuse - -#if defined(DIAG) -int baz(); -[[intel::loop_fuse(baz())]] void func3(); // expected-error{{'loop_fuse' attribute requires an integer constant}} -#endif diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 1d016f7489448..7492a6271f416 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1993,18 +1993,17 @@ bool PragmaClangAttributeSupport::isAttributedSupported( } static std::string GenerateTestExpression(ArrayRef LangOpts, - bool *ShouldDiagnose = nullptr) { + bool IsAttrAccepted) { std::string Test; for (auto *E : LangOpts) { + bool LangOptWantsWarning = E->getValueAsBit("Warn"); + if (LangOptWantsWarning != IsAttrAccepted) + continue; + if (!Test.empty()) Test += " || "; - // If any of the language options say "warn", then warn if any of the - // options fail. - if (ShouldDiagnose && E->getValueAsBit("Warn")) - *ShouldDiagnose = true; - const StringRef Code = E->getValueAsString("CustomCode"); if (!Code.empty()) { Test += "("; @@ -2016,6 +2015,8 @@ static std::string GenerateTestExpression(ArrayRef LangOpts, "non-empty 'Name' field ignored because 'CustomCode' was supplied"); } } else { + if (!IsAttrAccepted && !LangOptWantsWarning) + Test += "!"; Test += "LangOpts."; Test += E->getValueAsString("Name"); } @@ -2049,7 +2050,7 @@ PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr, // rules if the specific language options are specified. std::vector LangOpts = Rule.getLangOpts(); OS << " MatchRules.push_back(std::make_pair(" << Rule.getEnumValue() - << ", /*IsSupported=*/" << GenerateTestExpression(LangOpts) + << ", /*IsSupported=*/" << GenerateTestExpression(LangOpts, true) << "));\n"; } } @@ -3641,16 +3642,13 @@ static void GenerateLangOptRequirements(const Record &R, if (LangOpts.empty()) return; - OS << "bool diagLangOpts(Sema &S, const ParsedAttr &Attr) "; + OS << "bool diagLangOpts(Sema &S, const ParsedAttr &PA) "; OS << "const override {\n"; - OS << " auto &LangOpts = S.LangOpts;\n"; - bool Warn = false; - OS << " if (" << GenerateTestExpression(LangOpts, &Warn) << ")\n"; + OS << " const auto &LangOpts = S.LangOpts;\n"; + OS << " if (" << GenerateTestExpression(LangOpts, true) << ")\n"; OS << " return true;\n\n"; - if (Warn) { - OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) "; - OS << "<< Attr;\n"; - } + OS << " if (" << GenerateTestExpression(LangOpts, false) << ")\n"; + OS << " S.Diag(PA.getLoc(), diag::warn_attribute_ignored) << PA;\n"; OS << " return false;\n"; OS << "}\n\n"; } From 7572651a4a71123f9926371c8c29c21837201876 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 22 Feb 2021 07:08:32 -0800 Subject: [PATCH 3/4] Update the statement attribute definitions; NFC. (Statement attributes do not currently utilize the tablegen functionality for checking things like language options and subjects.) --- clang/include/clang/Basic/Attr.td | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index e439175673399..1f51fc79e1d56 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1846,7 +1846,7 @@ def SYCLIntelFPGAInitiationInterval : StmtAttr { let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt], ErrorDiag, "'for', 'while', and 'do' statements">; let Args = [ExprArgument<"IntervalExpr">]; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let HasCustomTypeTransform = 1; let Documentation = [SYCLIntelFPGAInitiationIntervalAttrDocs]; } @@ -1857,7 +1857,7 @@ def SYCLIntelFPGAMaxConcurrency : StmtAttr { let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt], ErrorDiag, "'for', 'while', and 'do' statements">; let Args = [ExprArgument<"NThreadsExpr">]; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let HasCustomTypeTransform = 1; let Documentation = [SYCLIntelFPGAMaxConcurrencyAttrDocs]; } @@ -1868,7 +1868,7 @@ def SYCLIntelFPGALoopCoalesce : StmtAttr { let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt], ErrorDiag, "'for', 'while', and 'do' statements">; let Args = [ExprArgument<"NExpr">]; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let HasCustomTypeTransform = 1; let Documentation = [SYCLIntelFPGALoopCoalesceAttrDocs]; } @@ -1878,7 +1878,7 @@ def SYCLIntelFPGADisableLoopPipelining : StmtAttr { CXX11<"intel","disable_loop_pipelining">]; let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt], ErrorDiag, "'for', 'while', and 'do' statements">; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let HasCustomTypeTransform = 1; let Documentation = [SYCLIntelFPGADisableLoopPipeliningAttrDocs]; } @@ -1889,7 +1889,7 @@ def SYCLIntelFPGAMaxInterleaving : StmtAttr { let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt], ErrorDiag, "'for', 'while', and 'do' statements">; let Args = [ExprArgument<"NExpr">]; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let HasCustomTypeTransform = 1; let Documentation = [SYCLIntelFPGAMaxInterleavingAttrDocs]; } @@ -1900,7 +1900,7 @@ def SYCLIntelFPGASpeculatedIterations : StmtAttr { let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt], ErrorDiag, "'for', 'while', and 'do' statements">; let Args = [ExprArgument<"NExpr">]; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let HasCustomTypeTransform = 1; let Documentation = [SYCLIntelFPGASpeculatedIterationsAttrDocs]; } @@ -1909,7 +1909,7 @@ def SYCLIntelFPGANofusion : StmtAttr { let Spellings = [CXX11<"intel","nofusion">]; let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt], ErrorDiag, "'for', 'while', and 'do' statements">; - let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost]; let HasCustomTypeTransform = 1; let Documentation = [SYCLIntelFPGANofusionAttrDocs]; } From d4994cb2e743bb420065640e50f2864282dbe092 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 22 Feb 2021 09:43:46 -0800 Subject: [PATCH 4/4] Renaming the tablegen option based on offline discussion; NFC --- clang/include/clang/Basic/Attr.td | 8 ++++---- clang/utils/TableGen/ClangAttrEmitter.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 1f51fc79e1d56..6160213b07a00 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -317,13 +317,13 @@ class SubjectList subjects, SubjectDiag diag = WarnDiag, string CustomDiag = customDiag; } -class LangOpt { +class LangOpt { // The language option to test; ignored when custom code is supplied. string Name = name; - // If set to 0, the attribute is accepted but is silently ignored. This is + // If set to 1, the attribute is accepted but is silently ignored. This is // useful in multi-compilation situations like SYCL. - bit Warn = warn; + bit SilentlyIgnore = silentlyIgnore; // A custom predicate, written as an expression evaluated in a context with // "LangOpts" bound. @@ -336,7 +336,7 @@ def HIP : LangOpt<"HIP">; def SYCL : LangOpt<"SYCL">; def SYCLIsDevice : LangOpt<"SYCLIsDevice">; def SYCLIsHost : LangOpt<"SYCLIsHost">; -def SilentlyIgnoreSYCLIsHost : LangOpt<"SYCLIsHost", "", 0>; +def SilentlyIgnoreSYCLIsHost : LangOpt<"SYCLIsHost", "", 1>; def SYCLExplicitSIMD : LangOpt<"SYCLExplicitSIMD">; def COnly : LangOpt<"", "!LangOpts.CPlusPlus">; def CPlusPlus : LangOpt<"CPlusPlus">; diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 7492a6271f416..1fefd3c1a6c04 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1997,8 +1997,8 @@ static std::string GenerateTestExpression(ArrayRef LangOpts, std::string Test; for (auto *E : LangOpts) { - bool LangOptWantsWarning = E->getValueAsBit("Warn"); - if (LangOptWantsWarning != IsAttrAccepted) + bool SilentlyIgnore = E->getValueAsBit("SilentlyIgnore"); + if (SilentlyIgnore == IsAttrAccepted) continue; if (!Test.empty()) @@ -2015,7 +2015,7 @@ static std::string GenerateTestExpression(ArrayRef LangOpts, "non-empty 'Name' field ignored because 'CustomCode' was supplied"); } } else { - if (!IsAttrAccepted && !LangOptWantsWarning) + if (!IsAttrAccepted && SilentlyIgnore) Test += "!"; Test += "LangOpts."; Test += E->getValueAsString("Name");