[clang] 9324cc2 - Change __builtin_sycl_unique_stable_name to just use an Itanium mangling

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 28 06:41:21 PDT 2021


Author: Erich Keane
Date: 2021-09-28T06:41:03-07:00
New Revision: 9324cc2ca951fe5fe11c85470cb08e699c59499c

URL: https://github.com/llvm/llvm-project/commit/9324cc2ca951fe5fe11c85470cb08e699c59499c
DIFF: https://github.com/llvm/llvm-project/commit/9324cc2ca951fe5fe11c85470cb08e699c59499c.diff

LOG: Change __builtin_sycl_unique_stable_name to just use an Itanium mangling

After significant problems in our downstream with the previous
implementation, the SYCL standard has opted to make using macros/etc to
change kernel-naming-lambdas in any way UB (even passively). As a
result, we are able to just emit the itanium mangling.

However, this DOES require a little work in the CXXABI, as the microsoft
and itanium mangler use different numbering schemes for lambdas.  This
patch adds a pair of mangling contexts that use the normal 'itanium'
mangling strategy to fill in the "DeviceManglingNumber" used previously
by CUDA.

Differential Revision: https://reviews.llvm.org/D110281

Added: 
    

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/include/clang/AST/ASTContext.h
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Sema/Sema.h
    clang/lib/AST/ASTContext.cpp
    clang/lib/AST/Expr.cpp
    clang/lib/AST/ExprConstant.cpp
    clang/lib/AST/ItaniumCXXABI.cpp
    clang/lib/AST/ItaniumMangle.cpp
    clang/lib/AST/MicrosoftCXXABI.cpp
    clang/lib/Sema/SemaSYCL.cpp
    clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
    clang/test/CodeGenSYCL/unique_stable_name.cpp
    clang/test/CodeGenSYCL/unique_stable_name_windows_diff.cpp
    clang/test/SemaSYCL/unique_stable_name.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 56e351183899b..5fe47199dcd21 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2521,12 +2521,9 @@ it in an instantiation which changes its value.
 In order to produce the unique name, the current implementation of the bultin
 uses Itanium mangling even if the host compilation uses a 
diff erent name
 mangling scheme at runtime. The mangler marks all the lambdas required to name
-the SYCL kernel and emits a stable local ordering of the respective lambdas,
-starting from ``10000``. The initial value of ``10000`` serves as an obvious
-
diff erentiator from ordinary lambda mangling numbers but does not serve any
-other purpose and may change in the future. The resulting pattern is
-demanglable. When non-lambda types are passed to the builtin, the mangler emits
-their usual pattern without any special treatment.
+the SYCL kernel and emits a stable local ordering of the respective lambdas.
+The resulting pattern is demanglable.  When non-lambda types are passed to the
+builtin, the mangler emits their usual pattern without any special treatment.
 
 **Syntax**:
 

diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index f1b057c8003f8..582134e586e0d 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -3239,31 +3239,10 @@ OPT_LIST(V)
 
   StringRef getCUIDHash() const;
 
-  void AddSYCLKernelNamingDecl(const CXXRecordDecl *RD);
-  bool IsSYCLKernelNamingDecl(const NamedDecl *RD) const;
-  unsigned GetSYCLKernelNamingIndex(const NamedDecl *RD);
-  /// A SourceLocation to store whether we have evaluated a kernel name already,
-  /// and where it happened.  If so, we need to diagnose an illegal use of the
-  /// builtin.
-  llvm::MapVector<const SYCLUniqueStableNameExpr *, std::string>
-      SYCLUniqueStableNameEvaluatedValues;
-
 private:
   /// All OMPTraitInfo objects live in this collection, one per
   /// `pragma omp [begin] declare variant` directive.
   SmallVector<std::unique_ptr<OMPTraitInfo>, 4> OMPTraitInfoVector;
-
-  /// A list of the (right now just lambda decls) declarations required to
-  /// name all the SYCL kernels in the translation unit, so that we can get the
-  /// correct kernel name, as well as implement
-  /// __builtin_sycl_unique_stable_name.
-  llvm::DenseMap<const DeclContext *,
-                 llvm::SmallPtrSet<const CXXRecordDecl *, 4>>
-      SYCLKernelNamingTypes;
-  std::unique_ptr<ItaniumMangleContext> SYCLKernelFilterContext;
-  void FilterSYCLKernelNamingDecls(
-      const CXXRecordDecl *RD,
-      llvm::SmallVectorImpl<const CXXRecordDecl *> &Decls);
 };
 
 /// Insertion operator for diagnostics.

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0e803ee028ce9..5a3eab540d1fe 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6409,11 +6409,6 @@ def warn_gnu_null_ptr_arith : Warning<
 def warn_pointer_sub_null_ptr : Warning<
   "performing pointer subtraction with a null pointer %select{has|may have}0 undefined behavior">,
   InGroup<NullPointerSubtraction>, DefaultIgnore;
-def err_kernel_invalidates_sycl_unique_stable_name
-    : Error<"kernel instantiation changes the result of an evaluated "
-            "'__builtin_sycl_unique_stable_name'">;
-def note_sycl_unique_stable_name_evaluated_here
-    : Note<"'__builtin_sycl_unique_stable_name' evaluated here">;
 
 def warn_floatingpoint_eq : Warning<
   "comparing floating point with == or != is unsafe">,

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 93d5558b8267c..d35f5c520a949 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -914,10 +914,6 @@ class Sema final {
     OpaqueParser = P;
   }
 
-  // Does the work necessary to deal with a SYCL kernel lambda. At the moment,
-  // this just marks the list of lambdas required to name the kernel.
-  void AddSYCLKernelLambda(const FunctionDecl *FD);
-
   class DelayedDiagnostics;
 
   class DelayedDiagnosticsState {

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 42c3dcfd98636..e2ebe737fdfdc 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -11801,86 +11801,3 @@ StringRef ASTContext::getCUIDHash() const {
   CUIDHash = llvm::utohexstr(llvm::MD5Hash(LangOpts.CUID), /*LowerCase=*/true);
   return CUIDHash;
 }
-
-// Get the closest named parent, so we can order the sycl naming decls somewhere
-// that mangling is meaningful.
-static const DeclContext *GetNamedParent(const CXXRecordDecl *RD) {
-  const DeclContext *DC = RD->getDeclContext();
-
-  while (!isa<NamedDecl, TranslationUnitDecl>(DC))
-    DC = DC->getParent();
-  return DC;
-}
-
-void ASTContext::AddSYCLKernelNamingDecl(const CXXRecordDecl *RD) {
-  assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
-  RD = RD->getCanonicalDecl();
-  const DeclContext *DC = GetNamedParent(RD);
-
-  assert(RD->getLocation().isValid() &&
-         "Invalid location on kernel naming decl");
-
-  (void)SYCLKernelNamingTypes[DC].insert(RD);
-}
-
-bool ASTContext::IsSYCLKernelNamingDecl(const NamedDecl *ND) const {
-  assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
-  const auto *RD = dyn_cast<CXXRecordDecl>(ND);
-  if (!RD)
-    return false;
-  RD = RD->getCanonicalDecl();
-  const DeclContext *DC = GetNamedParent(RD);
-
-  auto Itr = SYCLKernelNamingTypes.find(DC);
-
-  if (Itr == SYCLKernelNamingTypes.end())
-    return false;
-
-  return Itr->getSecond().count(RD);
-}
-
-// Filters the Decls list to those that share the lambda mangling with the
-// passed RD.
-void ASTContext::FilterSYCLKernelNamingDecls(
-    const CXXRecordDecl *RD,
-    llvm::SmallVectorImpl<const CXXRecordDecl *> &Decls) {
-
-  if (!SYCLKernelFilterContext)
-    SYCLKernelFilterContext.reset(
-        ItaniumMangleContext::create(*this, getDiagnostics()));
-
-  llvm::SmallString<128> LambdaSig;
-  llvm::raw_svector_ostream Out(LambdaSig);
-  SYCLKernelFilterContext->mangleLambdaSig(RD, Out);
-
-  llvm::erase_if(Decls, [this, &LambdaSig](const CXXRecordDecl *LocalRD) {
-    llvm::SmallString<128> LocalLambdaSig;
-    llvm::raw_svector_ostream LocalOut(LocalLambdaSig);
-    SYCLKernelFilterContext->mangleLambdaSig(LocalRD, LocalOut);
-    return LambdaSig != LocalLambdaSig;
-  });
-}
-
-unsigned ASTContext::GetSYCLKernelNamingIndex(const NamedDecl *ND) {
-  assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
-  assert(IsSYCLKernelNamingDecl(ND) &&
-         "Lambda not involved in mangling asked for a naming index?");
-
-  const CXXRecordDecl *RD = cast<CXXRecordDecl>(ND)->getCanonicalDecl();
-  const DeclContext *DC = GetNamedParent(RD);
-
-  auto Itr = SYCLKernelNamingTypes.find(DC);
-  assert(Itr != SYCLKernelNamingTypes.end() && "Not a valid DeclContext?");
-
-  const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &Set = Itr->getSecond();
-
-  llvm::SmallVector<const CXXRecordDecl *> Decls{Set.begin(), Set.end()};
-
-  FilterSYCLKernelNamingDecls(RD, Decls);
-
-  llvm::sort(Decls, [](const CXXRecordDecl *LHS, const CXXRecordDecl *RHS) {
-    return LHS->getLambdaManglingNumber() < RHS->getLambdaManglingNumber();
-  });
-
-  return llvm::find(Decls, RD) - Decls.begin();
-}

diff  --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9fde21c7ee9e1..7972f9a1aee76 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -545,20 +545,10 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context,
                                                   QualType Ty) {
   auto MangleCallback = [](ASTContext &Ctx,
                            const NamedDecl *ND) -> llvm::Optional<unsigned> {
-    // This replaces the 'lambda number' in the mangling with a unique number
-    // based on its order in the declaration.  To provide some level of visual
-    // notability (actual uniqueness from normal lambdas isn't necessary, as
-    // these are used 
diff erently), we add 10,000 to the number.
-    // For example:
-    // _ZTSZ3foovEUlvE10005_
-    // Demangles to: typeinfo name for foo()::'lambda10005'()
-    // Note that the mangler subtracts 2, since with normal lambdas the lambda
-    // mangling number '0' is an anonymous struct mangle, and '1' is omitted.
-    // So 10,002 results in the first number being 10,000.
-    if (Ctx.IsSYCLKernelNamingDecl(ND))
-      return 10'002 + Ctx.GetSYCLKernelNamingIndex(ND);
-    return llvm::None;
+    if (const auto *RD = dyn_cast<CXXRecordDecl>(ND))
+      return RD->getDeviceLambdaManglingNumber();
   };
+
   std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
       Context, Context.getDiagnostics(), MangleCallback)};
 

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index ea7818c43e321..0ac36708f0774 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8674,8 +8674,6 @@ class PointerExprEvaluator
   bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E) {
     std::string ResultStr = E->ComputeName(Info.Ctx);
 
-    Info.Ctx.SYCLUniqueStableNameEvaluatedValues[E] = ResultStr;
-
     QualType CharTy = Info.Ctx.CharTy.withConst();
     APInt Size(Info.Ctx.getTypeSize(Info.Ctx.getSizeType()),
                ResultStr.size() + 1);

diff  --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp
index be10258a2d774..e99c21dcff73c 100644
--- a/clang/lib/AST/ItaniumCXXABI.cpp
+++ b/clang/lib/AST/ItaniumCXXABI.cpp
@@ -181,6 +181,37 @@ class ItaniumNumberingContext : public MangleNumberingContext {
   }
 };
 
+// A version of this for SYCL that makes sure that 'device' mangling context
+// matches the lambda mangling number, so that __builtin_sycl_unique_stable_name
+// can be consistently generated between a MS and Itanium host by just referring
+// to the device mangling number.
+class ItaniumSYCLNumberingContext : public ItaniumNumberingContext {
+  llvm::DenseMap<const CXXMethodDecl *, unsigned> ManglingNumbers;
+  using ManglingItr = decltype(ManglingNumbers)::iterator;
+
+public:
+  ItaniumSYCLNumberingContext(ItaniumMangleContext *Mangler)
+      : ItaniumNumberingContext(Mangler) {}
+
+  unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
+    unsigned Number = ItaniumNumberingContext::getManglingNumber(CallOperator);
+    std::pair<ManglingItr, bool> emplace_result =
+        ManglingNumbers.try_emplace(CallOperator, Number);
+    (void)emplace_result;
+    assert(emplace_result.second && "Lambda number set multiple times?");
+    return Number;
+  }
+
+  using ItaniumNumberingContext::getManglingNumber;
+
+  unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
+    ManglingItr Itr = ManglingNumbers.find(CallOperator);
+    assert(Itr != ManglingNumbers.end() && "Lambda not yet mangled?");
+
+    return Itr->second;
+  }
+};
+
 class ItaniumCXXABI : public CXXABI {
 private:
   std::unique_ptr<MangleContext> Mangler;
@@ -249,6 +280,9 @@ class ItaniumCXXABI : public CXXABI {
 
   std::unique_ptr<MangleNumberingContext>
   createMangleNumberingContext() const override {
+    if (Context.getLangOpts().isSYCL())
+      return std::make_unique<ItaniumSYCLNumberingContext>(
+          cast<ItaniumMangleContext>(Mangler.get()));
     return std::make_unique<ItaniumNumberingContext>(
         cast<ItaniumMangleContext>(Mangler.get()));
   }

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index b1ac62b0ac983..34ad2b0b1d043 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -1518,9 +1518,16 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
     // <lambda-sig> ::= <template-param-decl>* <parameter-type>+
     //     # Parameter types or 'v' for 'void'.
     if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
-      if (Record->isLambda() && (Record->getLambdaManglingNumber() ||
-                                 Context.getDiscriminatorOverride()(
-                                     Context.getASTContext(), Record))) {
+      llvm::Optional<unsigned> DeviceNumber =
+          Context.getDiscriminatorOverride()(Context.getASTContext(), Record);
+
+      // If we have a device-number via the discriminator, use that to mangle
+      // the lambda, otherwise use the typical lambda-mangling-number. In either
+      // case, a '0' should be mangled as a normal unnamed class instead of as a
+      // lambda.
+      if (Record->isLambda() &&
+          ((DeviceNumber && *DeviceNumber > 0) ||
+           (!DeviceNumber && Record->getLambdaManglingNumber() > 0))) {
         assert(!AdditionalAbiTags &&
                "Lambda type cannot have additional abi tags");
         mangleLambda(Record);
@@ -1960,8 +1967,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
   // mangling number for this lambda.
   llvm::Optional<unsigned> DeviceNumber =
       Context.getDiscriminatorOverride()(Context.getASTContext(), Lambda);
-  unsigned Number = DeviceNumber.hasValue() ? *DeviceNumber
-                                            : Lambda->getLambdaManglingNumber();
+  unsigned Number =
+      DeviceNumber ? *DeviceNumber : Lambda->getLambdaManglingNumber();
 
   assert(Number > 0 && "Lambda should be mangled as an unnamed class");
   if (Number > 1)

diff  --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp
index 166aa3b3bd603..53d7e0b042ff1 100644
--- a/clang/lib/AST/MicrosoftCXXABI.cpp
+++ b/clang/lib/AST/MicrosoftCXXABI.cpp
@@ -78,6 +78,19 @@ class MSHIPNumberingContext : public MicrosoftNumberingContext {
   }
 };
 
+class MSSYCLNumberingContext : public MicrosoftNumberingContext {
+  std::unique_ptr<MangleNumberingContext> DeviceCtx;
+
+public:
+  MSSYCLNumberingContext(MangleContext *DeviceMangler) {
+    DeviceCtx = createItaniumNumberingContext(DeviceMangler);
+  }
+
+  unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
+    return DeviceCtx->getManglingNumber(CallOperator);
+  }
+};
+
 class MicrosoftCXXABI : public CXXABI {
   ASTContext &Context;
   llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
@@ -100,6 +113,10 @@ class MicrosoftCXXABI : public CXXABI {
       DeviceMangler.reset(
           Context.createMangleContext(Context.getAuxTargetInfo()));
     }
+    else if (Context.getLangOpts().isSYCL()) {
+      DeviceMangler.reset(
+          ItaniumMangleContext::create(Context, Context.getDiagnostics()));
+    }
   }
 
   MemberPointerInfo
@@ -162,7 +179,11 @@ class MicrosoftCXXABI : public CXXABI {
     if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) {
       assert(DeviceMangler && "Missing device mangler");
       return std::make_unique<MSHIPNumberingContext>(DeviceMangler.get());
+    } else if (Context.getLangOpts().isSYCL()) {
+      assert(DeviceMangler && "Missing device mangler");
+      return std::make_unique<MSSYCLNumberingContext>(DeviceMangler.get());
     }
+
     return std::make_unique<MicrosoftNumberingContext>();
   }
 };

diff  --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp
index 3b48a53efc0d1..481725eb0924e 100644
--- a/clang/lib/Sema/SemaSYCL.cpp
+++ b/clang/lib/Sema/SemaSYCL.cpp
@@ -48,35 +48,3 @@ bool Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) {
   return DiagKind != SemaDiagnosticBuilder::K_Immediate &&
          DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack;
 }
-
-// The SYCL kernel's 'object type' used for diagnostics and naming/mangling is
-// the first parameter to a sycl_kernel labeled function template. In SYCL1.2.1,
-// this was passed by value, and in SYCL2020, it is passed by reference.
-static QualType GetSYCLKernelObjectType(const FunctionDecl *KernelCaller) {
-  assert(KernelCaller->getNumParams() > 0 && "Insufficient kernel parameters");
-  QualType KernelParamTy = KernelCaller->getParamDecl(0)->getType();
-
-  // SYCL 2020 kernels are passed by reference.
-  if (KernelParamTy->isReferenceType())
-    return KernelParamTy->getPointeeType();
-
-  // SYCL 1.2.1
-  return KernelParamTy;
-}
-
-void Sema::AddSYCLKernelLambda(const FunctionDecl *FD) {
-  auto MangleCallback = [](ASTContext &Ctx,
-                           const NamedDecl *ND) -> llvm::Optional<unsigned> {
-    if (const auto *RD = dyn_cast<CXXRecordDecl>(ND))
-      Ctx.AddSYCLKernelNamingDecl(RD);
-    // We always want to go into the lambda mangling (skipping the unnamed
-    // struct version), so make sure we return a value here.
-    return 1;
-  };
-
-  QualType Ty = GetSYCLKernelObjectType(FD);
-  std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
-      Context, Context.getDiagnostics(), MangleCallback)};
-  llvm::raw_null_ostream Out;
-  Ctx->mangleTypeName(Ty, Out);
-}

diff  --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 79fd065a7b69c..e5ccfc27db356 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -556,26 +556,6 @@ static void instantiateDependentAMDGPUWavesPerEUAttr(
 static void instantiateDependentSYCLKernelAttr(
     Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
     const SYCLKernelAttr &Attr, Decl *New) {
-  // Functions cannot be partially specialized, so if we are being instantiated,
-  // we are obviously a complete specialization. Since this attribute is only
-  // valid on function template declarations, we know that this is a full
-  // instantiation of a kernel.
-  S.AddSYCLKernelLambda(cast<FunctionDecl>(New));
-
-  // Evaluate whether this would change any of the already evaluated
-  // __builtin_sycl_unique_stable_name values.
-  for (auto &Itr : S.Context.SYCLUniqueStableNameEvaluatedValues) {
-    const std::string &CurName = Itr.first->ComputeName(S.Context);
-    if (Itr.second != CurName) {
-      S.Diag(New->getLocation(),
-             diag::err_kernel_invalidates_sycl_unique_stable_name);
-      S.Diag(Itr.first->getLocation(),
-             diag::note_sycl_unique_stable_name_evaluated_here);
-      // Update this so future diagnostics work correctly.
-      Itr.second = CurName;
-    }
-  }
-
   New->addAttr(Attr.clone(S.getASTContext()));
 }
 

diff  --git a/clang/test/CodeGenSYCL/unique_stable_name.cpp b/clang/test/CodeGenSYCL/unique_stable_name.cpp
index 380ddaeadc69c..462541a29fc2a 100644
--- a/clang/test/CodeGenSYCL/unique_stable_name.cpp
+++ b/clang/test/CodeGenSYCL/unique_stable_name.cpp
@@ -1,22 +1,22 @@
 // RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
-// CHECK: @[[LAMBDA_KERNEL3:[^\w]+]] = private unnamed_addr constant [[LAMBDA_K3_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ4mainEUlPZ4mainEUlvE10000_E10000_\00"
+// CHECK: @[[LAMBDA_KERNEL3:[^\w]+]] = private unnamed_addr constant [[LAMBDA_K3_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ4mainEUlPZ4mainEUlvE_E_\00"
 // CHECK: @[[INT1:[^\w]+]] = private unnamed_addr constant [[INT_SIZE:\[[0-9]+ x i8\]]] c"_ZTSi\00"
 // CHECK: @[[STRING:[^\w]+]] = private unnamed_addr constant [[STRING_SIZE:\[[0-9]+ x i8\]]] c"_ZTSAppL_ZZ4mainE1jE_i\00",
 // CHECK: @[[INT2:[^\w]+]] = private unnamed_addr constant [[INT_SIZE]] c"_ZTSi\00"
-// CHECK: @[[LAMBDA_X:[^\w]+]] = private unnamed_addr constant [[LAMBDA_X_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE_\00"
-// CHECK: @[[MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE0_\00"
-// CHECK: @[[MACRO_Y:[^\w]+]] =  private unnamed_addr constant [[MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE1_\00"
-// CHECK: @{{.*}} = private unnamed_addr constant [36 x i8] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE2_\00", align 1
-// CHECK: @{{.*}} = private unnamed_addr constant [36 x i8] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE3_\00", align 1
-// CHECK: @[[MACRO_MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE4_\00"
-// CHECK: @[[MACRO_MACRO_Y:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE5_\00"
+// CHECK: @[[LAMBDA_X:[^\w]+]] = private unnamed_addr constant [[LAMBDA_X_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE_\00"
+// CHECK: @[[MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE0_\00"
+// CHECK: @[[MACRO_Y:[^\w]+]] =  private unnamed_addr constant [[MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE1_\00"
+// CHECK: @{{.*}} = private unnamed_addr constant [32 x i8] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE2_\00", align 1
+// CHECK: @{{.*}} = private unnamed_addr constant [32 x i8] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE3_\00", align 1
+// CHECK: @[[MACRO_MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE4_\00"
+// CHECK: @[[MACRO_MACRO_Y:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE5_\00"
 // CHECK: @[[INT3:[^\w]+]] = private unnamed_addr constant [[INT_SIZE]] c"_ZTSi\00"
-// CHECK: @[[LAMBDA:[^\w]+]] = private unnamed_addr constant [[LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE_\00"
+// CHECK: @[[LAMBDA:[^\w]+]] = private unnamed_addr constant [[LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE_\00"
 // CHECK: @[[LAMBDA_IN_DEP_INT:[^\w]+]] = private unnamed_addr constant [[DEP_INT_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIiEvvEUlvE_\00",
-// CHECK: @[[LAMBDA_IN_DEP_X:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIZZ4mainENKUlvE10001_clEvEUlvE_EvvEUlvE_\00",
+// CHECK: @[[LAMBDA_IN_DEP_X:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIZZ4mainENKUlvE0_clEvEUlvE_EvvEUlvE_\00",
 // CHECK: @[[LAMBDA_NO_DEP:[^\w]+]] = private unnamed_addr constant [[NO_DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ13lambda_no_depIidEvT_T0_EUlidE_\00",
-// CHECK: @[[LAMBDA_TWO_DEP:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA1_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE10001_clEvEUliE_ZZ4mainENKS0_clEvEUldE_EvvEUlvE_\00",
-// CHECK: @[[LAMBDA_TWO_DEP2:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA2_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE10001_clEvEUldE_ZZ4mainENKS0_clEvEUliE_EvvEUlvE_\00",
+// CHECK: @[[LAMBDA_TWO_DEP:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA1_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE0_clEvEUliE_ZZ4mainENKS0_clEvEUldE_EvvEUlvE_\00",
+// CHECK: @[[LAMBDA_TWO_DEP2:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA2_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE0_clEvEUldE_ZZ4mainENKS0_clEvEUliE_EvvEUlvE_\00",
 
 extern "C" void puts(const char *) {}
 

diff  --git a/clang/test/CodeGenSYCL/unique_stable_name_windows_
diff .cpp b/clang/test/CodeGenSYCL/unique_stable_name_windows_
diff .cpp
index ecdc1d50abbee..7c7979f712f05 100644
--- a/clang/test/CodeGenSYCL/unique_stable_name_windows_
diff .cpp
+++ b/clang/test/CodeGenSYCL/unique_stable_name_windows_
diff .cpp
@@ -38,7 +38,7 @@ int main() {
   // Make sure the following 3 are the same between the host and device compile.
   // Note that these are NOT the same value as eachother, they 
diff er by the
   // signature.
-  // CHECK: private unnamed_addr constant [22 x i8] c"_ZTSZ4mainEUlvE10000_\00"
-  // CHECK: private unnamed_addr constant [22 x i8] c"_ZTSZ4mainEUliE10000_\00"
-  // CHECK: private unnamed_addr constant [22 x i8] c"_ZTSZ4mainEUldE10000_\00"
+  // CHECK: private unnamed_addr constant [17 x i8] c"_ZTSZ4mainEUlvE_\00"
+  // CHECK: private unnamed_addr constant [17 x i8] c"_ZTSZ4mainEUliE_\00"
+  // CHECK: private unnamed_addr constant [17 x i8] c"_ZTSZ4mainEUldE_\00"
 }

diff  --git a/clang/test/SemaSYCL/unique_stable_name.cpp b/clang/test/SemaSYCL/unique_stable_name.cpp
index f86000fca4e23..2a0230d06137f 100644
--- a/clang/test/SemaSYCL/unique_stable_name.cpp
+++ b/clang/test/SemaSYCL/unique_stable_name.cpp
@@ -15,10 +15,6 @@ template <typename KernelName, typename KernelType>
 template <typename Func>
 void kernel1func(const Func &F1) {
   constexpr const char *F1_output = __builtin_sycl_unique_stable_name(Func); // #USN_F1
-  // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
-  // expected-note@#kernel1func_call{{in instantiation of function template specialization}}
-  // expected-note@#USN_F1{{'__builtin_sycl_unique_stable_name' evaluated here}}
-  // expected-note at +1{{in instantiation of function template specialization}}
   kernel_single_task<class kernel1>(F1); // #kernel1_call
 }
 
@@ -38,10 +34,6 @@ void callkernel1() {
 template <typename Func>
 void kernel2func(const Func &F2) {
   constexpr const char *F2_output = __builtin_sycl_unique_stable_name(Func); // #USN_F2
-  // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
-  // expected-note@#kernel2func_call{{in instantiation of function template specialization}}
-  // expected-note@#USN_F2{{'__builtin_sycl_unique_stable_name' evaluated here}}
-  // expected-note at +1{{in instantiation of function template specialization}}
   kernel_single_task<class kernel2>([]() {});
 }
 
@@ -93,40 +85,34 @@ int main() {
   kernel_single_task<class kernel5>(
       [=]() { l5(); }); // Used in the kernel, but not the kernel name itself
 
-  // kernel6 - expect error
+  // kernel6 - expect no error
   // Test that passing the lambda to the unique stable name builtin and then
-  // using the same lambda in the naming of a kernel causes a diagnostic on the
-  // kernel use due to the change in results to the stable name.
+  // using the same lambda in the naming of a kernel does not cause a diagnostic
+  // on the kernel use due to the change in results to the stable name.
   auto l6 = []() { return 1; };
   constexpr const char *l6_output =
       __builtin_sycl_unique_stable_name(decltype(l6)); // #USN_l6
-  // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
-  // expected-note@#USN_l6{{'__builtin_sycl_unique_stable_name' evaluated here}}
-  // expected-note at +1{{in instantiation of function template specialization}}
   kernel_single_task<class kernel6>(l6); // Used in the kernel name after builtin
 
-  // kernel7 - expect error
+  // kernel7 - expect no error
   // Same as kernel11 (below) except make the lambda part of naming the kernel.
   // Test that passing a lambda to the unique stable name builtin and then
-  // passing a second lambda to the kernel throws an error because the first
-  // lambda is included in the signature of the second lambda, hence it changes
-  // the mangling of the kernel.
+  // passing a second lambda to the kernel does not throw an error because the
+  // first lambda is included in the signature of the second lambda, but does
+  // not change the mangling of the kernel.
   auto l7 = []() { return 1; };
   auto l8 = [](decltype(l7) *derp = nullptr) { return 2; };
   constexpr const char *l7_output =
       __builtin_sycl_unique_stable_name(decltype(l7)); // #USN_l7
-  // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
-  // expected-note@#USN_l7{{'__builtin_sycl_unique_stable_name' evaluated here}}
-  // expected-note at +1{{in instantiation of function template specialization}}
   kernel_single_task<class kernel7>(l8);
 
-  // kernel8 and kernel9 - expect error
-  // Tests that passing a lambda to the unique stable name builtin and passing it
-  // to a kernel called with an if constexpr branch causes a diagnostic on the
-  // kernel9 use due to the change in the results to the stable name. This happens
-  // even though the use of kernel9 happens in the false branch of a constexpr if
-  // because both the true and the false branches cause the instantiation of
-  // kernel_single_task.
+  // kernel8 and kernel9 - expect no error
+  // Tests that passing a lambda to the unique stable name builtin and passing
+  // it to a kernel called with an if constexpr branch does not cause a
+  // diagnostic on the kernel9 as it does not change the result to the stable
+  // name. This is interesting even though the use of kernel9 happens in the
+  // false branch of a constexpr if because both the true and the false branches
+  // cause the instantiation of kernel_single_task.
   auto l9 = []() { return 1; };
   auto l10 = []() { return 2; };
   constexpr const char *l10_output =
@@ -134,9 +120,6 @@ int main() {
   if constexpr (1) {
     kernel_single_task<class kernel8>(l9);
   } else {
-    // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
-    // expected-note@#USN_l10{{'__builtin_sycl_unique_stable_name' evaluated here}}
-    // expected-note at +1{{in instantiation of function template specialization}}
     kernel_single_task<class kernel9>(l10);
   }
 
@@ -151,26 +134,20 @@ int main() {
       __builtin_sycl_unique_stable_name(decltype(l11));
   kernel_single_task<class kernel11>(l12);
 
-  // kernel12 - expect an error
+  // kernel12 - expect no error
   // Test that passing a lambda to the unique stable name builtin and then
-  // passing it to the kernel as a template template parameter causes a
+  // passing it to the kernel as a template template parameter does not cause a
   // diagnostic on the kernel use due to template template parameter being
   // involved in the mangling of the kernel name.
   auto l13 = []() { return 1; };
   constexpr const char *l13_output =
       __builtin_sycl_unique_stable_name(decltype(l13)); // #USN_l13
-  // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
-  // expected-note@#USN_l13{{'__builtin_sycl_unique_stable_name' evaluated here}}
-  // expected-note at +1{{in instantiation of function template specialization}}
   kernel_single_task<class kernel12>(S<Tangerine, decltype(l13)>{});
 
-  // kernel13 - expect an error
+  // kernel13 - expect no error
   // Test that passing a lambda to the unique stable name builtin within a macro
-  // and then calling the macro within the kernel causes an error on the kernel
-  // and diagnoses in all the expected places despite the use of a macro.
-  // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
-  // expected-note@#USN_MACRO{{'__builtin_sycl_unique_stable_name' evaluated here}}
-  // expected-note at +1{{in instantiation of function template specialization}}
+  // and then calling the macro within the kernel does not cause an error on the
+  // kernel.
   kernel_single_task<class kernel13>(
       []() {
         MACRO(); // #USN_MACRO
@@ -213,3 +190,15 @@ void use() {
   // expected-note at +1{{in instantiation of}}
   f2<St>();
 }
+
+// A previous implementation resulted in this being an example of the
+// kernel-ordering and lexical lambda ordering issue.
+void out_of_order_use() {
+  auto x = [](){};
+  auto y = [](){};
+
+  kernel_single_task<decltype(y)>(y);
+  constexpr auto USN =__builtin_sycl_unique_stable_name(decltype(y));
+  (void)USN;
+  kernel_single_task<decltype(x)>(x);
+}


        


More information about the cfe-commits mailing list