From f0724f0704299b49d42a48099b97c4cf0a55b155 Mon Sep 17 00:00:00 2001
From: Paul Kirth
Date: Fri, 5 Apr 2024 09:41:53 -0700
Subject: [PATCH 001/695] [llvm][NFC] Update URL in comment about Android ABI
The previous URL was stale, and referenced 'master' instead of 'main',
which will never be updated.
Reviewers: topperc, enh-google
Reviewed By: enh-google
Pull Request: https://github.com/llvm/llvm-project/pull/87726
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 8218960406ec..b81688c35713 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -26025,7 +26025,7 @@ static Value *UseTlsOffset(IRBuilderBase &IRB, unsigned Offset) {
Value *AArch64TargetLowering::getIRStackGuard(IRBuilderBase &IRB) const {
// Android provides a fixed TLS slot for the stack cookie. See the definition
// of TLS_SLOT_STACK_GUARD in
- // https://android.googlesource.com/platform/bionic/+/master/libc/private/bionic_tls.h
+ // https://android.googlesource.com/platform/bionic/+/main/libc/platform/bionic/tls_defines.h
if (Subtarget->isTargetAndroid())
return UseTlsOffset(IRB, 0x28);
--
GitLab
From 345c4822e4db2aa734b9f8a0b106308288ddc702 Mon Sep 17 00:00:00 2001
From: Eric Li
Date: Fri, 5 Apr 2024 13:00:01 -0400
Subject: [PATCH 002/695] [libTooling] Fix `getFileRangeForEdit` for inner
nested template types (#87673)
When there is `>>` in source from the right brackets of a nested
template, the end location of the inner template points into a scratch
space with a single `>` token. This prevents the lexer from seeing the
`>>` token in the original source.
However, this causes the range to appear to be partially in a macro, and
is problematic if we are trying to avoid ranges with any macro
expansions.
This change detects these split tokens in token ranges, converting it to the
corresponding character range without the expansion.
---
clang/lib/Tooling/Transformer/SourceCode.cpp | 59 +++++++++++++++++--
clang/unittests/Tooling/SourceCodeTest.cpp | 60 ++++++++++++++++++++
2 files changed, 114 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Tooling/Transformer/SourceCode.cpp b/clang/lib/Tooling/Transformer/SourceCode.cpp
index 6aae834b0db5..ab7184c2c069 100644
--- a/clang/lib/Tooling/Transformer/SourceCode.cpp
+++ b/clang/lib/Tooling/Transformer/SourceCode.cpp
@@ -101,6 +101,54 @@ static bool spelledInMacroDefinition(SourceLocation Loc,
return false;
}
+// Returns the expansion char-range of `Loc` if `Loc` is a split token. For
+// example, `>>` in nested templates needs the first `>` to be split, otherwise
+// the `SourceLocation` of the token would lex as `>>` instead of `>`.
+static std::optional
+getExpansionForSplitToken(SourceLocation Loc, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ if (Loc.isMacroID()) {
+ bool Invalid = false;
+ auto &SLoc = SM.getSLocEntry(SM.getFileID(Loc), &Invalid);
+ if (Invalid)
+ return std::nullopt;
+ if (auto &Expansion = SLoc.getExpansion();
+ !Expansion.isExpansionTokenRange()) {
+ // A char-range expansion is only used where a token-range would be
+ // incorrect, and so identifies this as a split token (and importantly,
+ // not as a macro).
+ return Expansion.getExpansionLocRange();
+ }
+ }
+ return std::nullopt;
+}
+
+// If `Range` covers a split token, returns the expansion range, otherwise
+// returns `Range`.
+static CharSourceRange getRangeForSplitTokens(CharSourceRange Range,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ if (Range.isTokenRange()) {
+ auto BeginToken = getExpansionForSplitToken(Range.getBegin(), SM, LangOpts);
+ auto EndToken = getExpansionForSplitToken(Range.getEnd(), SM, LangOpts);
+ if (EndToken) {
+ SourceLocation BeginLoc =
+ BeginToken ? BeginToken->getBegin() : Range.getBegin();
+ // We can't use the expansion location with a token-range, because that
+ // will incorrectly lex the end token, so use a char-range that ends at
+ // the split.
+ return CharSourceRange::getCharRange(BeginLoc, EndToken->getEnd());
+ } else if (BeginToken) {
+ // Since the end token is not split, the whole range covers the split, so
+ // the only adjustment we make is to use the expansion location of the
+ // begin token.
+ return CharSourceRange::getTokenRange(BeginToken->getBegin(),
+ Range.getEnd());
+ }
+ }
+ return Range;
+}
+
static CharSourceRange getRange(const CharSourceRange &EditRange,
const SourceManager &SM,
const LangOptions &LangOpts,
@@ -109,13 +157,14 @@ static CharSourceRange getRange(const CharSourceRange &EditRange,
if (IncludeMacroExpansion) {
Range = Lexer::makeFileCharRange(EditRange, SM, LangOpts);
} else {
- if (spelledInMacroDefinition(EditRange.getBegin(), SM) ||
- spelledInMacroDefinition(EditRange.getEnd(), SM))
+ auto AdjustedRange = getRangeForSplitTokens(EditRange, SM, LangOpts);
+ if (spelledInMacroDefinition(AdjustedRange.getBegin(), SM) ||
+ spelledInMacroDefinition(AdjustedRange.getEnd(), SM))
return {};
- auto B = SM.getSpellingLoc(EditRange.getBegin());
- auto E = SM.getSpellingLoc(EditRange.getEnd());
- if (EditRange.isTokenRange())
+ auto B = SM.getSpellingLoc(AdjustedRange.getBegin());
+ auto E = SM.getSpellingLoc(AdjustedRange.getEnd());
+ if (AdjustedRange.isTokenRange())
E = Lexer::getLocForEndOfToken(E, 0, SM, LangOpts);
Range = CharSourceRange::getCharRange(B, E);
}
diff --git a/clang/unittests/Tooling/SourceCodeTest.cpp b/clang/unittests/Tooling/SourceCodeTest.cpp
index 3641d2ee453f..3c24b6220a22 100644
--- a/clang/unittests/Tooling/SourceCodeTest.cpp
+++ b/clang/unittests/Tooling/SourceCodeTest.cpp
@@ -8,6 +8,7 @@
#include "clang/Tooling/Transformer/SourceCode.h"
#include "TestVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
@@ -18,10 +19,12 @@
#include
using namespace clang;
+using namespace clang::ast_matchers;
using llvm::Failed;
using llvm::Succeeded;
using llvm::ValueIs;
+using testing::Optional;
using tooling::getAssociatedRange;
using tooling::getExtendedRange;
using tooling::getExtendedText;
@@ -50,6 +53,15 @@ struct CallsVisitor : TestVisitor {
std::function OnCall;
};
+struct TypeLocVisitor : TestVisitor {
+ bool VisitTypeLoc(TypeLoc TL) {
+ OnTypeLoc(TL, Context);
+ return true;
+ }
+
+ std::function OnTypeLoc;
+};
+
// Equality matcher for `clang::CharSourceRange`, which lacks `operator==`.
MATCHER_P(EqualsRange, R, "") {
return arg.isTokenRange() == R.isTokenRange() &&
@@ -510,6 +522,54 @@ int c = M3(3);
Visitor.runOver(Code.code());
}
+TEST(SourceCodeTest, InnerNestedTemplate) {
+ llvm::Annotations Code(R"cpp(
+ template
+ struct A {};
+ template
+ struct B {};
+ template
+ struct C {};
+
+ void f(A$r[[>>]]);
+ )cpp");
+
+ TypeLocVisitor Visitor;
+ Visitor.OnTypeLoc = [&](TypeLoc TL, ASTContext *Context) {
+ if (TL.getSourceRange().isInvalid())
+ return;
+
+ // There are no macros, so every TypeLoc's range should be valid.
+ auto Range = CharSourceRange::getTokenRange(TL.getSourceRange());
+ auto LastTokenRange = CharSourceRange::getTokenRange(TL.getEndLoc());
+ EXPECT_TRUE(getFileRangeForEdit(Range, *Context,
+ /*IncludeMacroExpansion=*/false))
+ << TL.getSourceRange().printToString(Context->getSourceManager());
+ EXPECT_TRUE(getFileRangeForEdit(LastTokenRange, *Context,
+ /*IncludeMacroExpansion=*/false))
+ << TL.getEndLoc().printToString(Context->getSourceManager());
+
+ if (auto matches = match(
+ templateSpecializationTypeLoc(
+ loc(templateSpecializationType(
+ hasDeclaration(cxxRecordDecl(hasName("A"))))),
+ hasTemplateArgumentLoc(
+ 0, templateArgumentLoc(hasTypeLoc(typeLoc().bind("b"))))),
+ TL, *Context);
+ !matches.empty()) {
+ // A range where the start token is split, but the end token is not.
+ auto OuterTL = TL;
+ auto MiddleTL = *matches[0].getNodeAs("b");
+ EXPECT_THAT(
+ getFileRangeForEdit(CharSourceRange::getTokenRange(
+ MiddleTL.getEndLoc(), OuterTL.getEndLoc()),
+ *Context, /*IncludeMacroExpansion=*/false),
+ Optional(EqualsAnnotatedRange(Context, Code.range("r"))));
+ }
+ };
+ Visitor.runOver(Code.code(), TypeLocVisitor::Lang_CXX11);
+}
+
TEST_P(GetFileRangeForEditTest, EditPartialMacroExpansionShouldFail) {
std::string Code = R"cpp(
#define BAR 10+
--
GitLab
From 68b939f9311aaacd4a4fb6e41f86d81857d5c86e Mon Sep 17 00:00:00 2001
From: Cassie Jones
Date: Fri, 5 Apr 2024 13:01:09 -0400
Subject: [PATCH 003/695] [driver] Make --version show if assertions, etc. are
enabled (#87585)
It's useful to have some significant build options visible in the
version when investigating problems with a specific compiler artifact.
This makes it easy to see if assertions, expensive checks, sanitizers,
etc. are enabled when checking a compiler version.
Example config line output:
Build configuration: +unoptimized, +assertions, +asan, +ubsan
---
clang/lib/Driver/Driver.cpp | 6 +++
clang/test/Driver/version-build-config.test | 6 +++
llvm/CMakeLists.txt | 3 ++
llvm/include/llvm/Config/config.h.cmake | 3 ++
llvm/include/llvm/Support/CommandLine.h | 10 +++++
llvm/lib/Support/CommandLine.cpp | 46 +++++++++++++++++++++
6 files changed, 74 insertions(+)
create mode 100644 clang/test/Driver/version-build-config.test
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index e6c1767a0082..e7335a61b10c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2003,6 +2003,12 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
// Print out the install directory.
OS << "InstalledDir: " << Dir << '\n';
+ // Print the build config if it's non-default.
+ // Intended to help LLVM developers understand the configs of compilers
+ // they're investigating.
+ if (!llvm::cl::getCompilerBuildConfig().empty())
+ llvm::cl::printBuildConfig(OS);
+
// If configuration files were used, print their paths.
for (auto ConfigFile : ConfigFiles)
OS << "Configuration file: " << ConfigFile << '\n';
diff --git a/clang/test/Driver/version-build-config.test b/clang/test/Driver/version-build-config.test
new file mode 100644
index 000000000000..4cedf1e63181
--- /dev/null
+++ b/clang/test/Driver/version-build-config.test
@@ -0,0 +1,6 @@
+# REQUIRES: asserts
+# RUN: %clang --version 2>&1 | FileCheck %s
+
+# CHECK: clang version
+# When assertions are enabled, we should have a build configuration line that reflects that
+# CHECK: Build config: {{.*}}+assertions
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 6f5647d70d8b..88cf2d7ff099 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -799,6 +799,9 @@ option (LLVM_BUILD_EXTERNAL_COMPILER_RT
option (LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO
"Show target and host info when tools are invoked with --version." ON)
+option(LLVM_VERSION_PRINTER_SHOW_BUILD_CONFIG
+ "Show the optional build config flags when tools are invoked with --version." ON)
+
# You can configure which libraries from LLVM you want to include in the
# shared library by setting LLVM_DYLIB_COMPONENTS to a semi-colon delimited
# list of LLVM components. All component names handled by llvm-config are valid.
diff --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake
index fc1f9bf342f8..977c182e9d2b 100644
--- a/llvm/include/llvm/Config/config.h.cmake
+++ b/llvm/include/llvm/Config/config.h.cmake
@@ -290,6 +290,9 @@
/* Whether tools show host and target info when invoked with --version */
#cmakedefine01 LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO
+/* Whether tools show optional build config flags when invoked with --version */
+#cmakedefine01 LLVM_VERSION_PRINTER_SHOW_BUILD_CONFIG
+
/* Define if libxml2 is supported on this platform. */
#cmakedefine LLVM_ENABLE_LIBXML2 ${LLVM_ENABLE_LIBXML2}
diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h
index 99dc9aefbd7d..b035209406b6 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -2002,6 +2002,16 @@ void PrintVersionMessage();
/// \param Categorized if true print options in categories
void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
+/// An array of optional enabled settings in the LLVM build configuration,
+/// which may be of interest to compiler developers. For example, includes
+/// "+assertions" if assertions are enabled. Used by printBuildConfig.
+ArrayRef getCompilerBuildConfig();
+
+/// Prints the compiler build configuration.
+/// Designed for compiler developers, not compiler end-users.
+/// Intended to be used in --version output when enabled.
+void printBuildConfig(raw_ostream &OS);
+
//===----------------------------------------------------------------------===//
// Public interface for accessing registered options.
//
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index c076ae8b8431..056340bbab5a 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -2734,6 +2734,52 @@ void cl::PrintHelpMessage(bool Hidden, bool Categorized) {
CommonOptions->CategorizedHiddenPrinter.printHelp();
}
+ArrayRef cl::getCompilerBuildConfig() {
+ static const StringRef Config[] = {
+ // Placeholder to ensure the array always has elements, since it's an
+ // error to have a zero-sized array. Slice this off before returning.
+ "",
+ // Actual compiler build config feature list:
+#if LLVM_IS_DEBUG_BUILD
+ "+unoptimized",
+#endif
+#ifndef NDEBUG
+ "+assertions",
+#endif
+#ifdef EXPENSIVE_CHECKS
+ "+expensive-checks",
+#endif
+#if __has_feature(address_sanitizer)
+ "+asan",
+#endif
+#if __has_feature(dataflow_sanitizer)
+ "+dfsan",
+#endif
+#if __has_feature(hwaddress_sanitizer)
+ "+hwasan",
+#endif
+#if __has_feature(memory_sanitizer)
+ "+msan",
+#endif
+#if __has_feature(thread_sanitizer)
+ "+tsan",
+#endif
+#if __has_feature(undefined_behavior_sanitizer)
+ "+ubsan",
+#endif
+ };
+ return ArrayRef(Config).drop_front(1);
+}
+
+// Utility function for printing the build config.
+void cl::printBuildConfig(raw_ostream &OS) {
+#if LLVM_VERSION_PRINTER_SHOW_BUILD_CONFIG
+ OS << "Build config: ";
+ llvm::interleaveComma(cl::getCompilerBuildConfig(), OS);
+ OS << '\n';
+#endif
+}
+
/// Utility function for printing version number.
void cl::PrintVersionMessage() {
CommonOptions->VersionPrinterInstance.print(CommonOptions->ExtraVersionPrinters);
--
GitLab
From b7593b2e925fc005fc6248cd8e1a3f019e124c6b Mon Sep 17 00:00:00 2001
From: Jakub Chlanda
Date: Fri, 5 Apr 2024 19:05:19 +0200
Subject: [PATCH 004/695] [NFC][Doc] Fix typo in new pass manager snippet
(#87765)
Add missing closing parenthesis and re-flow the snippet to what clang
format would generate.
---
llvm/docs/NewPassManager.rst | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/docs/NewPassManager.rst b/llvm/docs/NewPassManager.rst
index 4554d8004375..b75ab918fda0 100644
--- a/llvm/docs/NewPassManager.rst
+++ b/llvm/docs/NewPassManager.rst
@@ -162,10 +162,10 @@ certain parts of the pipeline. For example,
.. code-block:: c++
PassBuilder PB;
- PB.registerPipelineStartEPCallback([&](ModulePassManager &MPM,
- PassBuilder::OptimizationLevel Level) {
- MPM.addPass(FooPass());
- };
+ PB.registerPipelineStartEPCallback(
+ [&](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
+ MPM.addPass(FooPass());
+ });
will add ``FooPass`` near the very beginning of the pipeline for pass
managers created by that ``PassBuilder``. See the documentation for
--
GitLab
From 30f6eafaa978b4e0211368976fe60f15fa9f0067 Mon Sep 17 00:00:00 2001
From: Erich Keane
Date: Fri, 5 Apr 2024 10:06:44 -0700
Subject: [PATCH 005/695] [OpenACC][NFC] Add OpenACC Clause AST
Nodes/infrastructure (#87675)
As a first step in adding clause support for OpenACC to Semantic
Analysis, this patch adds the 'base' AST nodes required for clauses.
This patch has no functional effect at the moment, but followup patches
will add the semantic analysis of clauses (plus individual clauses).
---
clang/include/clang/AST/ASTNodeTraverser.h | 13 ++
clang/include/clang/AST/JSONNodeDumper.h | 1 +
clang/include/clang/AST/OpenACCClause.h | 135 ++++++++++++++++++
clang/include/clang/AST/RecursiveASTVisitor.h | 13 +-
clang/include/clang/AST/StmtOpenACC.h | 55 +++++--
clang/include/clang/AST/TextNodeDumper.h | 2 +
.../clang/Serialization/ASTRecordReader.h | 7 +
.../clang/Serialization/ASTRecordWriter.h | 7 +
clang/lib/AST/CMakeLists.txt | 1 +
clang/lib/AST/JSONNodeDumper.cpp | 2 +
clang/lib/AST/OpenACCClause.cpp | 17 +++
clang/lib/AST/StmtOpenACC.cpp | 19 +--
clang/lib/AST/StmtPrinter.cpp | 8 +-
clang/lib/AST/StmtProfile.cpp | 21 ++-
clang/lib/AST/TextNodeDumper.cpp | 23 ++-
clang/lib/Sema/SemaOpenACC.cpp | 2 +
clang/lib/Serialization/ASTReader.cpp | 65 +++++++++
clang/lib/Serialization/ASTReaderStmt.cpp | 10 +-
clang/lib/Serialization/ASTWriter.cpp | 62 ++++++++
clang/lib/Serialization/ASTWriterStmt.cpp | 3 +-
20 files changed, 439 insertions(+), 27 deletions(-)
create mode 100644 clang/include/clang/AST/OpenACCClause.h
create mode 100644 clang/lib/AST/OpenACCClause.cpp
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index 06d67e9cba95..94e7dd817809 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -53,6 +53,7 @@ struct {
void Visit(TypeLoc);
void Visit(const Decl *D);
void Visit(const CXXCtorInitializer *Init);
+ void Visit(const OpenACCClause *C);
void Visit(const OMPClause *C);
void Visit(const BlockDecl::Capture &C);
void Visit(const GenericSelectionExpr::ConstAssociation &A);
@@ -239,6 +240,13 @@ public:
});
}
+ void Visit(const OpenACCClause *C) {
+ getNodeDelegate().AddChild([=] {
+ getNodeDelegate().Visit(C);
+ // TODO OpenACC: Switch on clauses that have children, and add them.
+ });
+ }
+
void Visit(const OMPClause *C) {
getNodeDelegate().AddChild([=] {
getNodeDelegate().Visit(C);
@@ -799,6 +807,11 @@ public:
Visit(C);
}
+ void VisitOpenACCConstructStmt(const OpenACCConstructStmt *Node) {
+ for (const auto *C : Node->clauses())
+ Visit(C);
+ }
+
void VisitInitListExpr(const InitListExpr *ILE) {
if (auto *Filler = ILE->getArrayFiller()) {
Visit(Filler, "array_filler");
diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h
index dde70dde2fa2..7a60f362650c 100644
--- a/clang/include/clang/AST/JSONNodeDumper.h
+++ b/clang/include/clang/AST/JSONNodeDumper.h
@@ -203,6 +203,7 @@ public:
void Visit(const TemplateArgument &TA, SourceRange R = {},
const Decl *From = nullptr, StringRef Label = {});
void Visit(const CXXCtorInitializer *Init);
+ void Visit(const OpenACCClause *C);
void Visit(const OMPClause *C);
void Visit(const BlockDecl::Capture &C);
void Visit(const GenericSelectionExpr::ConstAssociation &A);
diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h
new file mode 100644
index 000000000000..06a0098bbda4
--- /dev/null
+++ b/clang/include/clang/AST/OpenACCClause.h
@@ -0,0 +1,135 @@
+//===- OpenACCClause.h - Classes for OpenACC clauses ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// \file
+// This file defines OpenACC AST classes for clauses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H
+#define LLVM_CLANG_AST_OPENACCCLAUSE_H
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/OpenACCKinds.h"
+
+namespace clang {
+/// This is the base type for all OpenACC Clauses.
+class OpenACCClause {
+ OpenACCClauseKind Kind;
+ SourceRange Location;
+
+protected:
+ OpenACCClause(OpenACCClauseKind K, SourceLocation BeginLoc,
+ SourceLocation EndLoc)
+ : Kind(K), Location(BeginLoc, EndLoc) {}
+
+public:
+ OpenACCClauseKind getClauseKind() const { return Kind; }
+ SourceLocation getBeginLoc() const { return Location.getBegin(); }
+ SourceLocation getEndLoc() const { return Location.getEnd(); }
+
+ static bool classof(const OpenACCClause *) { return true; }
+
+ virtual ~OpenACCClause() = default;
+};
+
+/// Represents a clause that has a list of parameters.
+class OpenACCClauseWithParams : public OpenACCClause {
+ /// Location of the '('.
+ SourceLocation LParenLoc;
+
+protected:
+ OpenACCClauseWithParams(OpenACCClauseKind K, SourceLocation BeginLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OpenACCClause(K, BeginLoc, EndLoc), LParenLoc(LParenLoc) {}
+
+public:
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+};
+
+template class OpenACCClauseVisitor {
+ Impl &getDerived() { return static_cast(*this); }
+
+public:
+ void VisitClauseList(ArrayRef List) {
+ for (const OpenACCClause *Clause : List)
+ Visit(Clause);
+ }
+
+ void Visit(const OpenACCClause *C) {
+ if (!C)
+ return;
+
+ switch (C->getClauseKind()) {
+ case OpenACCClauseKind::Default:
+ case OpenACCClauseKind::Finalize:
+ case OpenACCClauseKind::IfPresent:
+ case OpenACCClauseKind::Seq:
+ case OpenACCClauseKind::Independent:
+ case OpenACCClauseKind::Auto:
+ case OpenACCClauseKind::Worker:
+ case OpenACCClauseKind::Vector:
+ case OpenACCClauseKind::NoHost:
+ case OpenACCClauseKind::If:
+ case OpenACCClauseKind::Self:
+ case OpenACCClauseKind::Copy:
+ case OpenACCClauseKind::UseDevice:
+ case OpenACCClauseKind::Attach:
+ case OpenACCClauseKind::Delete:
+ case OpenACCClauseKind::Detach:
+ case OpenACCClauseKind::Device:
+ case OpenACCClauseKind::DevicePtr:
+ case OpenACCClauseKind::DeviceResident:
+ case OpenACCClauseKind::FirstPrivate:
+ case OpenACCClauseKind::Host:
+ case OpenACCClauseKind::Link:
+ case OpenACCClauseKind::NoCreate:
+ case OpenACCClauseKind::Present:
+ case OpenACCClauseKind::Private:
+ case OpenACCClauseKind::CopyOut:
+ case OpenACCClauseKind::CopyIn:
+ case OpenACCClauseKind::Create:
+ case OpenACCClauseKind::Reduction:
+ case OpenACCClauseKind::Collapse:
+ case OpenACCClauseKind::Bind:
+ case OpenACCClauseKind::VectorLength:
+ case OpenACCClauseKind::NumGangs:
+ case OpenACCClauseKind::NumWorkers:
+ case OpenACCClauseKind::DeviceNum:
+ case OpenACCClauseKind::DefaultAsync:
+ case OpenACCClauseKind::DeviceType:
+ case OpenACCClauseKind::DType:
+ case OpenACCClauseKind::Async:
+ case OpenACCClauseKind::Tile:
+ case OpenACCClauseKind::Gang:
+ case OpenACCClauseKind::Wait:
+ case OpenACCClauseKind::Invalid:
+ llvm_unreachable("Clause visitor not yet implemented");
+ }
+ llvm_unreachable("Invalid Clause kind");
+ }
+};
+
+class OpenACCClausePrinter final
+ : public OpenACCClauseVisitor {
+ raw_ostream &OS;
+
+public:
+ void VisitClauseList(ArrayRef List) {
+ for (const OpenACCClause *Clause : List) {
+ Visit(Clause);
+
+ if (Clause != List.back())
+ OS << ' ';
+ }
+ }
+ OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {}
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_OPENACCCLAUSE_H
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 8630317795a9..7eb92e304a38 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -509,6 +509,7 @@ private:
bool TraverseOpenACCConstructStmt(OpenACCConstructStmt *S);
bool
TraverseOpenACCAssociatedStmtConstruct(OpenACCAssociatedStmtConstruct *S);
+ bool VisitOpenACCClauseList(ArrayRef);
};
template
@@ -3936,8 +3937,8 @@ bool RecursiveASTVisitor::VisitOMPXBareClause(OMPXBareClause *C) {
template
bool RecursiveASTVisitor::TraverseOpenACCConstructStmt(
- OpenACCConstructStmt *) {
- // TODO OpenACC: When we implement clauses, ensure we traverse them here.
+ OpenACCConstructStmt *C) {
+ TRY_TO(VisitOpenACCClauseList(C->clauses()));
return true;
}
@@ -3949,6 +3950,14 @@ bool RecursiveASTVisitor::TraverseOpenACCAssociatedStmtConstruct(
return true;
}
+template
+bool RecursiveASTVisitor::VisitOpenACCClauseList(
+ ArrayRef) {
+ // TODO OpenACC: When we have Clauses with expressions, we should visit them
+ // here.
+ return true;
+}
+
DEF_TRAVERSE_STMT(OpenACCComputeConstruct,
{ TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })
diff --git a/clang/include/clang/AST/StmtOpenACC.h b/clang/include/clang/AST/StmtOpenACC.h
index 19da66832c73..419cb6cada0b 100644
--- a/clang/include/clang/AST/StmtOpenACC.h
+++ b/clang/include/clang/AST/StmtOpenACC.h
@@ -13,9 +13,11 @@
#ifndef LLVM_CLANG_AST_STMTOPENACC_H
#define LLVM_CLANG_AST_STMTOPENACC_H
+#include "clang/AST/OpenACCClause.h"
#include "clang/AST/Stmt.h"
#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/SourceLocation.h"
+#include
namespace clang {
/// This is the base class for an OpenACC statement-level construct, other
@@ -30,13 +32,23 @@ class OpenACCConstructStmt : public Stmt {
/// the directive.
SourceRange Range;
- // TODO OPENACC: Clauses should probably be collected in this class.
+ /// The list of clauses. This is stored here as an ArrayRef, as this is the
+ /// most convienient place to access the list, however the list itself should
+ /// be stored in leaf nodes, likely in trailing-storage.
+ MutableArrayRef Clauses;
protected:
OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K,
SourceLocation Start, SourceLocation End)
: Stmt(SC), Kind(K), Range(Start, End) {}
+ // Used only for initialization, the leaf class can initialize this to
+ // trailing storage.
+ void setClauseList(MutableArrayRef NewClauses) {
+ assert(Clauses.empty() && "Cannot change clause list");
+ Clauses = NewClauses;
+ }
+
public:
OpenACCDirectiveKind getDirectiveKind() const { return Kind; }
@@ -47,6 +59,7 @@ public:
SourceLocation getBeginLoc() const { return Range.getBegin(); }
SourceLocation getEndLoc() const { return Range.getEnd(); }
+ ArrayRef clauses() const { return Clauses; }
child_range children() {
return child_range(child_iterator(), child_iterator());
@@ -101,17 +114,32 @@ public:
/// those three, as they are semantically identical, and have only minor
/// differences in the permitted list of clauses, which can be differentiated by
/// the 'Kind'.
-class OpenACCComputeConstruct : public OpenACCAssociatedStmtConstruct {
+class OpenACCComputeConstruct final
+ : public OpenACCAssociatedStmtConstruct,
+ public llvm::TrailingObjects {
friend class ASTStmtWriter;
friend class ASTStmtReader;
friend class ASTContext;
- OpenACCComputeConstruct()
- : OpenACCAssociatedStmtConstruct(
- OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid,
- SourceLocation{}, SourceLocation{}, /*AssociatedStmt=*/nullptr) {}
+ OpenACCComputeConstruct(unsigned NumClauses)
+ : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass,
+ OpenACCDirectiveKind::Invalid,
+ SourceLocation{}, SourceLocation{},
+ /*AssociatedStmt=*/nullptr) {
+ // We cannot send the TrailingObjects storage to the base class (which holds
+ // a reference to the data) until it is constructed, so we have to set it
+ // separately here.
+ std::uninitialized_value_construct(
+ getTrailingObjects(),
+ getTrailingObjects() + NumClauses);
+ setClauseList(MutableArrayRef(getTrailingObjects(),
+ NumClauses));
+ }
OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start,
- SourceLocation End, Stmt *StructuredBlock)
+ SourceLocation End,
+ ArrayRef Clauses,
+ Stmt *StructuredBlock)
: OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start,
End, StructuredBlock) {
assert((K == OpenACCDirectiveKind::Parallel ||
@@ -119,6 +147,13 @@ class OpenACCComputeConstruct : public OpenACCAssociatedStmtConstruct {
K == OpenACCDirectiveKind::Kernels) &&
"Only parallel, serial, and kernels constructs should be "
"represented by this type");
+
+ // Initialize the trailing storage.
+ std::uninitialized_copy(Clauses.begin(), Clauses.end(),
+ getTrailingObjects());
+
+ setClauseList(MutableArrayRef(getTrailingObjects(),
+ Clauses.size()));
}
void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
@@ -128,10 +163,12 @@ public:
return T->getStmtClass() == OpenACCComputeConstructClass;
}
- static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C, EmptyShell);
+ static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses);
static OpenACCComputeConstruct *
Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
- SourceLocation EndLoc, Stmt *StructuredBlock);
+ SourceLocation EndLoc, ArrayRef Clauses,
+ Stmt *StructuredBlock);
Stmt *getStructuredBlock() { return getAssociatedStmt(); }
const Stmt *getStructuredBlock() const {
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index efb5bfe7f83d..1fede6e462e9 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -189,6 +189,8 @@ public:
void Visit(const OMPClause *C);
+ void Visit(const OpenACCClause *C);
+
void Visit(const BlockDecl::Capture &C);
void Visit(const GenericSelectionExpr::ConstAssociation &A);
diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h
index 5d3e95cb5d63..7dd1140106e4 100644
--- a/clang/include/clang/Serialization/ASTRecordReader.h
+++ b/clang/include/clang/Serialization/ASTRecordReader.h
@@ -24,6 +24,7 @@
#include "llvm/ADT/APSInt.h"
namespace clang {
+class OpenACCClause;
class OMPTraitInfo;
class OMPChildren;
@@ -278,6 +279,12 @@ public:
/// Read an OpenMP children, advancing Idx.
void readOMPChildren(OMPChildren *Data);
+ /// Read an OpenACC clause, advancing Idx.
+ OpenACCClause *readOpenACCClause();
+
+ /// Read a list of OpenACC clauses into the passed SmallVector.
+ void readOpenACCClauseList(MutableArrayRef Clauses);
+
/// Read a source location, advancing Idx.
SourceLocation readSourceLocation(LocSeq *Seq = nullptr) {
return Reader->ReadSourceLocation(*F, Record, Idx, Seq);
diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h
index e007d4a70843..1feb8fcbacf7 100644
--- a/clang/include/clang/Serialization/ASTRecordWriter.h
+++ b/clang/include/clang/Serialization/ASTRecordWriter.h
@@ -21,6 +21,7 @@
namespace clang {
+class OpenACCClause;
class TypeLoc;
/// An object for streaming information to a record.
@@ -292,6 +293,12 @@ public:
/// Writes data related to the OpenMP directives.
void writeOMPChildren(OMPChildren *Data);
+ /// Writes out a single OpenACC Clause.
+ void writeOpenACCClause(const OpenACCClause *C);
+
+ /// Writes out a list of OpenACC clauses.
+ void writeOpenACCClauseList(ArrayRef Clauses);
+
/// Emit a string.
void AddString(StringRef Str) {
return Writer->AddString(Str, *Record);
diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index 3fba052d916c..3faefb54f599 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -98,6 +98,7 @@ add_clang_library(clangAST
NSAPI.cpp
ODRDiagsEmitter.cpp
ODRHash.cpp
+ OpenACCClause.cpp
OpenMPClause.cpp
OSLog.cpp
ParentMap.cpp
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 5861d5a7ea0d..fb3494393f75 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -187,6 +187,8 @@ void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
llvm_unreachable("Unknown initializer type");
}
+void JSONNodeDumper::Visit(const OpenACCClause *C) {}
+
void JSONNodeDumper::Visit(const OMPClause *C) {}
void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {
diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp
new file mode 100644
index 000000000000..e1db872f25c3
--- /dev/null
+++ b/clang/lib/AST/OpenACCClause.cpp
@@ -0,0 +1,17 @@
+//===---- OpenACCClause.cpp - Classes for OpenACC Clauses ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the subclasses of the OpenACCClause class declared in
+// OpenACCClause.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/OpenACCClause.h"
+#include "clang/AST/ASTContext.h"
+
+using namespace clang;
diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp
index e6191bc6db70..a381a8dd7b62 100644
--- a/clang/lib/AST/StmtOpenACC.cpp
+++ b/clang/lib/AST/StmtOpenACC.cpp
@@ -15,20 +15,23 @@
using namespace clang;
OpenACCComputeConstruct *
-OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, EmptyShell) {
- void *Mem = C.Allocate(sizeof(OpenACCComputeConstruct),
- alignof(OpenACCComputeConstruct));
- auto *Inst = new (Mem) OpenACCComputeConstruct;
+OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) {
+ void *Mem = C.Allocate(
+ OpenACCComputeConstruct::totalSizeToAlloc(
+ NumClauses));
+ auto *Inst = new (Mem) OpenACCComputeConstruct(NumClauses);
return Inst;
}
OpenACCComputeConstruct *
OpenACCComputeConstruct::Create(const ASTContext &C, OpenACCDirectiveKind K,
SourceLocation BeginLoc, SourceLocation EndLoc,
+ ArrayRef Clauses,
Stmt *StructuredBlock) {
- void *Mem = C.Allocate(sizeof(OpenACCComputeConstruct),
- alignof(OpenACCComputeConstruct));
- auto *Inst =
- new (Mem) OpenACCComputeConstruct(K, BeginLoc, EndLoc, StructuredBlock);
+ void *Mem = C.Allocate(
+ OpenACCComputeConstruct::totalSizeToAlloc(
+ Clauses.size()));
+ auto *Inst = new (Mem)
+ OpenACCComputeConstruct(K, BeginLoc, EndLoc, Clauses, StructuredBlock);
return Inst;
}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index d66c3ccce209..74b18e50bf1f 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1142,7 +1142,13 @@ void StmtPrinter::VisitOMPTargetParallelGenericLoopDirective(
//===----------------------------------------------------------------------===//
void StmtPrinter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) {
Indent() << "#pragma acc " << S->getDirectiveKind();
- // TODO OpenACC: Print Clauses.
+
+ if (!S->clauses().empty()) {
+ OS << ' ';
+ OpenACCClausePrinter Printer(OS);
+ Printer.VisitClauseList(S->clauses());
+ }
+
PrintStmt(S->getStructuredBlock());
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index b545ff472e5a..d68547f444c5 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2441,11 +2441,30 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
}
}
+namespace {
+class OpenACCClauseProfiler
+ : public OpenACCClauseVisitor {
+
+public:
+ OpenACCClauseProfiler() = default;
+
+ void VisitOpenACCClauseList(ArrayRef Clauses) {
+ for (const OpenACCClause *Clause : Clauses) {
+ // TODO OpenACC: When we have clauses with expressions, we should
+ // profile them too.
+ Visit(Clause);
+ }
+ }
+};
+} // namespace
+
void StmtProfiler::VisitOpenACCComputeConstruct(
const OpenACCComputeConstruct *S) {
// VisitStmt handles children, so the AssociatedStmt is handled.
VisitStmt(S);
- // TODO OpenACC: Visit Clauses.
+
+ OpenACCClauseProfiler P;
+ P.VisitOpenACCClauseList(S->clauses());
}
void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 413e452146bd..0ffbf47c9a2f 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -381,6 +381,28 @@ void TextNodeDumper::Visit(const OMPClause *C) {
OS << " ";
}
+void TextNodeDumper::Visit(const OpenACCClause *C) {
+ if (!C) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<>> OpenACCClause";
+ return;
+ }
+ {
+ ColorScope Color(OS, ShowColors, AttrColor);
+ OS << C->getClauseKind();
+
+ // Handle clauses with parens for types that have no children, likely
+ // because there is no sub expression.
+ switch (C->getClauseKind()) {
+ default:
+ // Nothing to do here.
+ break;
+ }
+ }
+ dumpPointer(C);
+ dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
+}
+
void TextNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
const TypeSourceInfo *TSI = A.getTypeSourceInfo();
if (TSI) {
@@ -2684,5 +2706,4 @@ void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
void TextNodeDumper::VisitOpenACCConstructStmt(const OpenACCConstructStmt *S) {
OS << " " << S->getDirectiveKind();
- // TODO OpenACC: Dump clauses as well.
}
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 2ac994cac71e..86ffa5ad74c1 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -94,8 +94,10 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K,
case OpenACCDirectiveKind::Parallel:
case OpenACCDirectiveKind::Serial:
case OpenACCDirectiveKind::Kernels:
+ // TODO OpenACC: Add clauses to the construct here.
return OpenACCComputeConstruct::Create(
getASTContext(), K, StartLoc, EndLoc,
+ /*Clauses=*/std::nullopt,
AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
}
llvm_unreachable("Unhandled case in directive handling?");
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 9a39e7d3826e..9c0364b3934b 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -32,6 +32,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/ODRDiagsEmitter.h"
#include "clang/AST/ODRHash.h"
+#include "clang/AST/OpenACCClause.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/RawCommentList.h"
#include "clang/AST/TemplateBase.h"
@@ -53,6 +54,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PragmaKinds.h"
@@ -11751,3 +11753,66 @@ void ASTRecordReader::readOMPChildren(OMPChildren *Data) {
for (unsigned I = 0, E = Data->getNumChildren(); I < E; ++I)
Data->getChildren()[I] = readStmt();
}
+
+OpenACCClause *ASTRecordReader::readOpenACCClause() {
+ OpenACCClauseKind ClauseKind = readEnum();
+ // TODO OpenACC: We don't have these used anywhere, but eventually we should
+ // be constructing the Clauses with them, so these attributes can go away at
+ // that point.
+ [[maybe_unused]] SourceLocation BeginLoc = readSourceLocation();
+ [[maybe_unused]] SourceLocation EndLoc = readSourceLocation();
+
+ switch (ClauseKind) {
+ case OpenACCClauseKind::Default:
+ case OpenACCClauseKind::Finalize:
+ case OpenACCClauseKind::IfPresent:
+ case OpenACCClauseKind::Seq:
+ case OpenACCClauseKind::Independent:
+ case OpenACCClauseKind::Auto:
+ case OpenACCClauseKind::Worker:
+ case OpenACCClauseKind::Vector:
+ case OpenACCClauseKind::NoHost:
+ case OpenACCClauseKind::If:
+ case OpenACCClauseKind::Self:
+ case OpenACCClauseKind::Copy:
+ case OpenACCClauseKind::UseDevice:
+ case OpenACCClauseKind::Attach:
+ case OpenACCClauseKind::Delete:
+ case OpenACCClauseKind::Detach:
+ case OpenACCClauseKind::Device:
+ case OpenACCClauseKind::DevicePtr:
+ case OpenACCClauseKind::DeviceResident:
+ case OpenACCClauseKind::FirstPrivate:
+ case OpenACCClauseKind::Host:
+ case OpenACCClauseKind::Link:
+ case OpenACCClauseKind::NoCreate:
+ case OpenACCClauseKind::Present:
+ case OpenACCClauseKind::Private:
+ case OpenACCClauseKind::CopyOut:
+ case OpenACCClauseKind::CopyIn:
+ case OpenACCClauseKind::Create:
+ case OpenACCClauseKind::Reduction:
+ case OpenACCClauseKind::Collapse:
+ case OpenACCClauseKind::Bind:
+ case OpenACCClauseKind::VectorLength:
+ case OpenACCClauseKind::NumGangs:
+ case OpenACCClauseKind::NumWorkers:
+ case OpenACCClauseKind::DeviceNum:
+ case OpenACCClauseKind::DefaultAsync:
+ case OpenACCClauseKind::DeviceType:
+ case OpenACCClauseKind::DType:
+ case OpenACCClauseKind::Async:
+ case OpenACCClauseKind::Tile:
+ case OpenACCClauseKind::Gang:
+ case OpenACCClauseKind::Wait:
+ case OpenACCClauseKind::Invalid:
+ llvm_unreachable("Clause serialization not yet implemented");
+ }
+ llvm_unreachable("Invalid Clause Kind");
+}
+
+void ASTRecordReader::readOpenACCClauseList(
+ MutableArrayRef Clauses) {
+ for (unsigned I = 0; I < Clauses.size(); ++I)
+ Clauses[I] = readOpenACCClause();
+}
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index bbeb6db01164..f0984c3e4696 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2784,9 +2784,10 @@ void ASTStmtReader::VisitOMPTargetParallelGenericLoopDirective(
// OpenACC Constructs/Directives.
//===----------------------------------------------------------------------===//
void ASTStmtReader::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) {
+ (void)Record.readInt();
S->Kind = Record.readEnum();
S->Range = Record.readSourceRange();
- // TODO OpenACC: Deserialize Clauses.
+ Record.readOpenACCClauseList(S->Clauses);
}
void ASTStmtReader::VisitOpenACCAssociatedStmtConstruct(
@@ -4218,10 +4219,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = new (Context) ConceptSpecializationExpr(Empty);
break;
}
- case STMT_OPENACC_COMPUTE_CONSTRUCT:
- S = OpenACCComputeConstruct::CreateEmpty(Context, Empty);
+ case STMT_OPENACC_COMPUTE_CONSTRUCT: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ S = OpenACCComputeConstruct::CreateEmpty(Context, NumClauses);
break;
-
+ }
case EXPR_REQUIRES:
unsigned numLocalParameters = Record[ASTStmtReader::NumExprFields];
unsigned numRequirement = Record[ASTStmtReader::NumExprFields + 1];
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index ba6a8a5e16e4..baf03f69d730 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -29,6 +29,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OpenACCClause.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/RawCommentList.h"
#include "clang/AST/TemplateName.h"
@@ -44,6 +45,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/OpenCLOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
@@ -7397,3 +7399,63 @@ void ASTRecordWriter::writeOMPChildren(OMPChildren *Data) {
for (unsigned I = 0, E = Data->getNumChildren(); I < E; ++I)
AddStmt(Data->getChildren()[I]);
}
+
+void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
+ writeEnum(C->getClauseKind());
+ writeSourceLocation(C->getBeginLoc());
+ writeSourceLocation(C->getEndLoc());
+
+ switch (C->getClauseKind()) {
+ case OpenACCClauseKind::Default:
+ case OpenACCClauseKind::Finalize:
+ case OpenACCClauseKind::IfPresent:
+ case OpenACCClauseKind::Seq:
+ case OpenACCClauseKind::Independent:
+ case OpenACCClauseKind::Auto:
+ case OpenACCClauseKind::Worker:
+ case OpenACCClauseKind::Vector:
+ case OpenACCClauseKind::NoHost:
+ case OpenACCClauseKind::If:
+ case OpenACCClauseKind::Self:
+ case OpenACCClauseKind::Copy:
+ case OpenACCClauseKind::UseDevice:
+ case OpenACCClauseKind::Attach:
+ case OpenACCClauseKind::Delete:
+ case OpenACCClauseKind::Detach:
+ case OpenACCClauseKind::Device:
+ case OpenACCClauseKind::DevicePtr:
+ case OpenACCClauseKind::DeviceResident:
+ case OpenACCClauseKind::FirstPrivate:
+ case OpenACCClauseKind::Host:
+ case OpenACCClauseKind::Link:
+ case OpenACCClauseKind::NoCreate:
+ case OpenACCClauseKind::Present:
+ case OpenACCClauseKind::Private:
+ case OpenACCClauseKind::CopyOut:
+ case OpenACCClauseKind::CopyIn:
+ case OpenACCClauseKind::Create:
+ case OpenACCClauseKind::Reduction:
+ case OpenACCClauseKind::Collapse:
+ case OpenACCClauseKind::Bind:
+ case OpenACCClauseKind::VectorLength:
+ case OpenACCClauseKind::NumGangs:
+ case OpenACCClauseKind::NumWorkers:
+ case OpenACCClauseKind::DeviceNum:
+ case OpenACCClauseKind::DefaultAsync:
+ case OpenACCClauseKind::DeviceType:
+ case OpenACCClauseKind::DType:
+ case OpenACCClauseKind::Async:
+ case OpenACCClauseKind::Tile:
+ case OpenACCClauseKind::Gang:
+ case OpenACCClauseKind::Wait:
+ case OpenACCClauseKind::Invalid:
+ llvm_unreachable("Clause serialization not yet implemented");
+ }
+ llvm_unreachable("Invalid Clause Kind");
+}
+
+void ASTRecordWriter::writeOpenACCClauseList(
+ ArrayRef Clauses) {
+ for (const OpenACCClause *Clause : Clauses)
+ writeOpenACCClause(Clause);
+}
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 22e190450d39..0651614e2ce5 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2839,9 +2839,10 @@ void ASTStmtWriter::VisitOMPTargetParallelGenericLoopDirective(
// OpenACC Constructs/Directives.
//===----------------------------------------------------------------------===//
void ASTStmtWriter::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) {
+ Record.push_back(S->clauses().size());
Record.writeEnum(S->Kind);
Record.AddSourceRange(S->Range);
- // TODO OpenACC: Serialize Clauses.
+ Record.writeOpenACCClauseList(S->clauses());
}
void ASTStmtWriter::VisitOpenACCAssociatedStmtConstruct(
--
GitLab
From 0cd0aa029647c8d1dba5c3d62f92325576796fa2 Mon Sep 17 00:00:00 2001
From: Ian Anderson
Date: Fri, 5 Apr 2024 10:13:42 -0700
Subject: [PATCH 006/695] [clang][modules] Headers meant to be included
multiple times can be completely invisible in clang module builds (#83660)
Once a file has been `#import`'ed, it gets stamped as if it was `#pragma
once` and will not be re-entered, even on #include. This means that any
errant #import of a file designed to be included multiple times, such as
, will incorrectly mark it as include-once and break the
multiple include functionality. Normally this isn't a big problem, e.g.
can't have its NDEBUG mode changed after the first #import,
but it is still mostly functional. However, when clang modules are
involved, this can cause the header to be hidden entirely.
Objective-C code most often uses #import for everything, because it's
required for most Objective-C headers to prevent double inclusion and
redeclaration errors. (It's rare for Objective-C headers to use macro
guards or `#pragma once`.) The problem arises when a submodule includes
a multiple-include header. The "already included" state is global across
all modules (which is necessary so that non-modular headers don't get
compiled into multiple translation units and cause redeclaration
errors). If another module or the main file #import's the same header,
it becomes invisible from then on. If the original submodule is not
imported, the include of the header will effectively do nothing and the
header will be invisible. The only way to actually get the header's
declarations is to somehow figure out which submodule consumed the
header, and import that instead. That's basically impossible since it
depends on exactly which modules were built in which order.
#import is a poor indicator of whether a header is actually
include-once, as the #import is external to the header it applies to,
and requires that all inclusions correctly and consistently use #import
vs #include. When modules are enabled, consider a header marked
`textual` in its module as a stronger indicator of multiple-include than
#import's indication of include-once. This will allow headers like
to always be included when modules are enabled, even if
#import is erroneously used somewhere.
---
clang/include/clang/Lex/HeaderSearch.h | 26 ++-
clang/lib/Lex/HeaderSearch.cpp | 183 +++++++++++++------
clang/lib/Serialization/ASTReader.cpp | 2 +-
clang/test/Modules/builtin-import.mm | 2 +
clang/test/Modules/import-textual-noguard.mm | 6 +-
clang/test/Modules/import-textual.mm | 2 +
clang/test/Modules/multiple-import.m | 43 +++++
7 files changed, 201 insertions(+), 63 deletions(-)
create mode 100644 clang/test/Modules/multiple-import.m
diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h
index 705dcfa8aacc..855f81f775f8 100644
--- a/clang/include/clang/Lex/HeaderSearch.h
+++ b/clang/include/clang/Lex/HeaderSearch.h
@@ -78,11 +78,19 @@ struct HeaderFileInfo {
LLVM_PREFERRED_TYPE(bool)
unsigned External : 1;
- /// Whether this header is part of a module.
+ /// Whether this header is part of and built with a module. i.e. it is listed
+ /// in a module map, and is not `excluded` or `textual`. (same meaning as
+ /// `ModuleMap::isModular()`).
LLVM_PREFERRED_TYPE(bool)
unsigned isModuleHeader : 1;
- /// Whether this header is part of the module that we are building.
+ /// Whether this header is a `textual header` in a module.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned isTextualModuleHeader : 1;
+
+ /// Whether this header is part of the module that we are building, even if it
+ /// doesn't build with the module. i.e. this will include `excluded` and
+ /// `textual` headers as well as normal headers.
LLVM_PREFERRED_TYPE(bool)
unsigned isCompilingModuleHeader : 1;
@@ -128,13 +136,20 @@ struct HeaderFileInfo {
HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
- External(false), isModuleHeader(false), isCompilingModuleHeader(false),
- Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {}
+ External(false), isModuleHeader(false), isTextualModuleHeader(false),
+ isCompilingModuleHeader(false), Resolved(false),
+ IndexHeaderMapHeader(false), IsValid(false) {}
/// Retrieve the controlling macro for this header file, if
/// any.
const IdentifierInfo *
getControllingMacro(ExternalPreprocessorSource *External);
+
+ /// Update the module membership bits based on the header role.
+ ///
+ /// isModuleHeader will potentially be set, but not cleared.
+ /// isTextualModuleHeader will be set or cleared based on the role update.
+ void mergeModuleMembership(ModuleMap::ModuleHeaderRole Role);
};
/// An external source of header file information, which may supply
@@ -522,6 +537,9 @@ public:
///
/// \return false if \#including the file will have no effect or true
/// if we should include it.
+ ///
+ /// \param M The module to which `File` belongs (this should usually be the
+ /// SuggestedModule returned by LookupFile/LookupSubframeworkHeader)
bool ShouldEnterIncludeFile(Preprocessor &PP, FileEntryRef File,
bool isImport, bool ModulesEnabled, Module *M,
bool &IsFirstIncludeOfFile);
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index fcc2b56df166..7dffcf0e941e 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -1307,6 +1307,23 @@ OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(
// File Info Management.
//===----------------------------------------------------------------------===//
+static void mergeHeaderFileInfoModuleBits(HeaderFileInfo &HFI,
+ bool isModuleHeader,
+ bool isTextualModuleHeader) {
+ assert((!isModuleHeader || !isTextualModuleHeader) &&
+ "A header can't build with a module and be textual at the same time");
+ HFI.isModuleHeader |= isModuleHeader;
+ if (HFI.isModuleHeader)
+ HFI.isTextualModuleHeader = false;
+ else
+ HFI.isTextualModuleHeader |= isTextualModuleHeader;
+}
+
+void HeaderFileInfo::mergeModuleMembership(ModuleMap::ModuleHeaderRole Role) {
+ mergeHeaderFileInfoModuleBits(*this, ModuleMap::isModular(Role),
+ (Role & ModuleMap::TextualHeader));
+}
+
/// Merge the header file info provided by \p OtherHFI into the current
/// header file info (\p HFI)
static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
@@ -1315,7 +1332,8 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
HFI.isImport |= OtherHFI.isImport;
HFI.isPragmaOnce |= OtherHFI.isPragmaOnce;
- HFI.isModuleHeader |= OtherHFI.isModuleHeader;
+ mergeHeaderFileInfoModuleBits(HFI, OtherHFI.isModuleHeader,
+ OtherHFI.isTextualModuleHeader);
if (!HFI.ControllingMacro && !HFI.ControllingMacroID) {
HFI.ControllingMacro = OtherHFI.ControllingMacro;
@@ -1403,11 +1421,9 @@ bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const {
void HeaderSearch::MarkFileModuleHeader(FileEntryRef FE,
ModuleMap::ModuleHeaderRole Role,
bool isCompilingModuleHeader) {
- bool isModularHeader = ModuleMap::isModular(Role);
-
// Don't mark the file info as non-external if there's nothing to change.
if (!isCompilingModuleHeader) {
- if (!isModularHeader)
+ if ((Role & ModuleMap::ExcludedHeader))
return;
auto *HFI = getExistingFileInfo(FE);
if (HFI && HFI->isModuleHeader)
@@ -1415,7 +1431,7 @@ void HeaderSearch::MarkFileModuleHeader(FileEntryRef FE,
}
auto &HFI = getFileInfo(FE);
- HFI.isModuleHeader |= isModularHeader;
+ HFI.mergeModuleMembership(Role);
HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
}
@@ -1423,74 +1439,128 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
FileEntryRef File, bool isImport,
bool ModulesEnabled, Module *M,
bool &IsFirstIncludeOfFile) {
- ++NumIncluded; // Count # of attempted #includes.
-
+ // An include file should be entered if either:
+ // 1. This is the first include of the file.
+ // 2. This file can be included multiple times, that is it's not an
+ // "include-once" file.
+ //
+ // Include-once is controlled by these preprocessor directives.
+ //
+ // #pragma once
+ // This directive is in the include file, and marks it as an include-once
+ // file.
+ //
+ // #import
+ // This directive is in the includer, and indicates that the include file
+ // should only be entered if this is the first include.
+ ++NumIncluded;
IsFirstIncludeOfFile = false;
-
- // Get information about this file.
HeaderFileInfo &FileInfo = getFileInfo(File);
- // FIXME: this is a workaround for the lack of proper modules-aware support
- // for #import / #pragma once
- auto TryEnterImported = [&]() -> bool {
- if (!ModulesEnabled)
+ auto MaybeReenterImportedFile = [&]() -> bool {
+ // Modules add a wrinkle though: what's included isn't necessarily visible.
+ // Consider this module.
+ // module Example {
+ // module A { header "a.h" export * }
+ // module B { header "b.h" export * }
+ // }
+ // b.h includes c.h. The main file includes a.h, which will trigger a module
+ // build of Example, and c.h will be included. However, c.h isn't visible to
+ // the main file. Normally this is fine, the main file can just include c.h
+ // if it needs it. If c.h is in a module, the include will translate into a
+ // module import, this function will be skipped, and everything will work as
+ // expected. However, if c.h is not in a module (or is `textual`), then this
+ // function will run. If c.h is include-once, it will not be entered from
+ // the main file and it will still not be visible.
+
+ // If modules aren't enabled then there's no visibility issue. Always
+ // respect `#pragma once`.
+ if (!ModulesEnabled || FileInfo.isPragmaOnce)
return false;
+
// Ensure FileInfo bits are up to date.
ModMap.resolveHeaderDirectives(File);
- // Modules with builtins are special; multiple modules use builtins as
- // modular headers, example:
- //
- // module stddef { header "stddef.h" export * }
- //
- // After module map parsing, this expands to:
- //
- // module stddef {
- // header "/path_to_builtin_dirs/stddef.h"
- // textual "stddef.h"
- // }
+
+ // This brings up a subtlety of #import - it's not a very good indicator of
+ // include-once. Developers are often unaware of the difference between
+ // #include and #import, and tend to use one or the other indiscrimiately.
+ // In order to support #include on include-once headers that lack macro
+ // guards and `#pragma once` (which is the vast majority of Objective-C
+ // headers), if a file is ever included with #import, it's marked as
+ // isImport in the HeaderFileInfo and treated as include-once. This allows
+ // #include to work in Objective-C.
+ // #include
+ // #include
+ // Foundation.h has an #import of NSString.h, and so the second #include is
+ // skipped even though NSString.h has no `#pragma once` and no macro guard.
//
- // It's common that libc++ and system modules will both define such
- // submodules. Make sure cached results for a builtin header won't
- // prevent other builtin modules from potentially entering the builtin
- // header. Note that builtins are header guarded and the decision to
- // actually enter them is postponed to the controlling macros logic below.
- bool TryEnterHdr = false;
- if (FileInfo.isCompilingModuleHeader && FileInfo.isModuleHeader)
- TryEnterHdr = ModMap.isBuiltinHeader(File);
-
- // Textual headers can be #imported from different modules. Since ObjC
- // headers find in the wild might rely only on #import and do not contain
- // controlling macros, be conservative and only try to enter textual headers
- // if such macro is present.
- if (!FileInfo.isModuleHeader &&
- FileInfo.getControllingMacro(ExternalLookup))
- TryEnterHdr = true;
- return TryEnterHdr;
+ // However, this helpfulness causes problems with modules. If c.h is not an
+ // include-once file, but something included it with #import anyway (as is
+ // typical in Objective-C code), this include will be skipped and c.h will
+ // not be visible. Consider it not include-once if it is a `textual` header
+ // in a module.
+ if (FileInfo.isTextualModuleHeader)
+ return true;
+
+ if (FileInfo.isCompilingModuleHeader) {
+ // It's safer to re-enter a file whose module is being built because its
+ // declarations will still be scoped to a single module.
+ if (FileInfo.isModuleHeader) {
+ // Headers marked as "builtin" are covered by the system module maps
+ // rather than the builtin ones. Some versions of the Darwin module fail
+ // to mark stdarg.h and stddef.h as textual. Attempt to re-enter these
+ // files while building their module to allow them to function properly.
+ if (ModMap.isBuiltinHeader(File))
+ return true;
+ } else {
+ // Files that are excluded from their module can potentially be
+ // re-entered from their own module. This might cause redeclaration
+ // errors if another module saw this file first, but there's a
+ // reasonable chance that its module will build first. However if
+ // there's no controlling macro, then trust the #import and assume this
+ // really is an include-once file.
+ if (FileInfo.getControllingMacro(ExternalLookup))
+ return true;
+ }
+ }
+ // If the include file has a macro guard, then it might still not be
+ // re-entered if the controlling macro is visibly defined. e.g. another
+ // header in the module being built included this file and local submodule
+ // visibility is not enabled.
+
+ // It might be tempting to re-enter the include-once file if it's not
+ // visible in an attempt to make it visible. However this will still cause
+ // redeclaration errors against the known-but-not-visible declarations. The
+ // include file not being visible will most likely cause "undefined x"
+ // errors, but at least there's a slim chance of compilation succeeding.
+ return false;
};
- // If this is a #import directive, check that we have not already imported
- // this header.
if (isImport) {
- // If this has already been imported, don't import it again.
+ // As discussed above, record that this file was ever `#import`ed, and treat
+ // it as an include-once file from here out.
FileInfo.isImport = true;
-
- // Has this already been #import'ed or #include'd?
- if (PP.alreadyIncluded(File) && !TryEnterImported())
+ if (PP.alreadyIncluded(File) && !MaybeReenterImportedFile())
return false;
} else {
- // Otherwise, if this is a #include of a file that was previously #import'd
- // or if this is the second #include of a #pragma once file, ignore it.
- if ((FileInfo.isPragmaOnce || FileInfo.isImport) && !TryEnterImported())
+ // isPragmaOnce and isImport are only set after the file has been included
+ // at least once. If either are set then this is a repeat #include of an
+ // include-once file.
+ if (FileInfo.isPragmaOnce ||
+ (FileInfo.isImport && !MaybeReenterImportedFile()))
return false;
}
- // Next, check to see if the file is wrapped with #ifndef guards. If so, and
- // if the macro that guards it is defined, we know the #include has no effect.
- if (const IdentifierInfo *ControllingMacro
- = FileInfo.getControllingMacro(ExternalLookup)) {
+ // As a final optimization, check for a macro guard and skip entering the file
+ // if the controlling macro is defined. The macro guard will effectively erase
+ // the file's contents, and the include would have no effect other than to
+ // waste time opening and reading a file.
+ if (const IdentifierInfo *ControllingMacro =
+ FileInfo.getControllingMacro(ExternalLookup)) {
// If the header corresponds to a module, check whether the macro is already
- // defined in that module rather than checking in the current set of visible
- // modules.
+ // defined in that module rather than checking all visible modules. This is
+ // mainly to cover corner cases where the same controlling macro is used in
+ // different files in multiple modules.
if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M)
: PP.isMacroDefined(ControllingMacro)) {
++NumMultiIncludeFileOptzn;
@@ -1499,7 +1569,6 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
}
IsFirstIncludeOfFile = PP.markIncluded(File);
-
return true;
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 9c0364b3934b..fa5bb9f2d543 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -2096,7 +2096,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
Module::Header H = {std::string(key.Filename), "", *FE};
ModMap.addHeader(Mod, H, HeaderRole, /*Imported=*/true);
}
- HFI.isModuleHeader |= ModuleMap::isModular(HeaderRole);
+ HFI.mergeModuleMembership(HeaderRole);
}
// This HeaderFileInfo was externally loaded.
diff --git a/clang/test/Modules/builtin-import.mm b/clang/test/Modules/builtin-import.mm
index 8a27cb358484..52db9c15803c 100644
--- a/clang/test/Modules/builtin-import.mm
+++ b/clang/test/Modules/builtin-import.mm
@@ -1,4 +1,6 @@
// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -nobuiltininc -nostdinc++ -isysroot %S/Inputs/libc-libcxx/sysroot -isystem %S/Inputs/libc-libcxx/sysroot/usr/include/c++/v1 -isystem %S/Inputs/libc-libcxx/sysroot/usr/include -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c++ %s
+// RUN: rm -rf %t
// RUN: %clang_cc1 -fsyntax-only -nobuiltininc -nostdinc++ -isysroot %S/Inputs/libc-libcxx/sysroot -isystem %S/Inputs/libc-libcxx/sysroot/usr/include/c++/v1 -isystem %S/Inputs/libc-libcxx/sysroot/usr/include -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c++ -fmodules-local-submodule-visibility %s
#include
diff --git a/clang/test/Modules/import-textual-noguard.mm b/clang/test/Modules/import-textual-noguard.mm
index dd124b6609d0..ffc506117f51 100644
--- a/clang/test/Modules/import-textual-noguard.mm
+++ b/clang/test/Modules/import-textual-noguard.mm
@@ -1,7 +1,11 @@
// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fmodules -fimplicit-module-maps -I%S/Inputs/import-textual/M2 -fmodules-cache-path=%t -x objective-c++ %s -verify
+// RUN: rm -rf %t
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fmodules -fimplicit-module-maps -I%S/Inputs/import-textual/M2 -fmodules-cache-path=%t -x objective-c++ -fmodules-local-submodule-visibility %s -verify
-#include "A/A.h" // expected-error {{could not build module 'M'}}
+// expected-no-diagnostics
+
+#include "A/A.h"
#include "B/B.h"
typedef aint xxx;
diff --git a/clang/test/Modules/import-textual.mm b/clang/test/Modules/import-textual.mm
index 6593239d7fd7..94a6aa448cdc 100644
--- a/clang/test/Modules/import-textual.mm
+++ b/clang/test/Modules/import-textual.mm
@@ -1,4 +1,6 @@
// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fmodules -fimplicit-module-maps -I%S/Inputs/import-textual/M -fmodules-cache-path=%t -x objective-c++ %s -verify
+// RUN: rm -rf %t
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fmodules -fimplicit-module-maps -I%S/Inputs/import-textual/M -fmodules-cache-path=%t -x objective-c++ -fmodules-local-submodule-visibility %s -verify
// expected-no-diagnostics
diff --git a/clang/test/Modules/multiple-import.m b/clang/test/Modules/multiple-import.m
new file mode 100644
index 000000000000..95ca7dbcd438
--- /dev/null
+++ b/clang/test/Modules/multiple-import.m
@@ -0,0 +1,43 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: %clang_cc1 -std=c17 -fmodules-cache-path=%t/no-lsv -fmodules -fimplicit-module-maps -I%t %t/multiple-imports.m -verify
+// RUN: %clang_cc1 -std=c17 -fmodules-cache-path=%t/lsv -fmodules -fimplicit-module-maps -fmodules-local-submodule-visibility -I%t %t/multiple-imports.m -verify
+
+//--- multiple-imports.m
+// expected-no-diagnostics
+#import
+#import
+void test(void) {
+ assert(0);
+}
+
+//--- module.modulemap
+module Submodules [system] {
+ module one {
+ header "one.h"
+ export *
+ }
+ module two {
+ header "two.h"
+ export *
+ }
+}
+
+module libc [system] {
+ textual header "assert.h"
+}
+
+//--- one.h
+#ifndef one_h
+#define one_h
+#endif
+
+//--- two.h
+#ifndef two_h
+#define two_h
+#include
+#endif
+
+//--- assert.h
+#undef assert
+#define assert(expression) ((void)0)
--
GitLab
From c7eede5d4c1c8e0c20337f3f3c9003f59fe5ccd5 Mon Sep 17 00:00:00 2001
From: Argyrios Kyrtzidis
Date: Fri, 5 Apr 2024 10:31:16 -0700
Subject: [PATCH 007/695] [clang][deps] Remove pgo profile flags from modules
(#87724)
These are not necessary when not performing codegen.
---
clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp | 3 +++
.../test/ClangScanDeps/Inputs/removed-args/cdb.json.template | 2 +-
clang/test/ClangScanDeps/removed-args.c | 4 ++++
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index eb5c50c35428..94ccbd3351b0 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -175,6 +175,9 @@ makeCommonInvocationForModuleBuild(CompilerInvocation CI) {
CI.getCodeGenOpts().CoverageCompilationDir.clear();
CI.getCodeGenOpts().CoverageDataFile.clear();
CI.getCodeGenOpts().CoverageNotesFile.clear();
+ CI.getCodeGenOpts().ProfileInstrumentUsePath.clear();
+ CI.getCodeGenOpts().SampleProfileFile.clear();
+ CI.getCodeGenOpts().ProfileRemappingFile.clear();
}
// Map output paths that affect behaviour to "-" so their existence is in the
diff --git a/clang/test/ClangScanDeps/Inputs/removed-args/cdb.json.template b/clang/test/ClangScanDeps/Inputs/removed-args/cdb.json.template
index 7ae3c88aedd8..ca56799cd08e 100644
--- a/clang/test/ClangScanDeps/Inputs/removed-args/cdb.json.template
+++ b/clang/test/ClangScanDeps/Inputs/removed-args/cdb.json.template
@@ -1,7 +1,7 @@
[
{
"directory": "DIR",
- "command": "clang -fsyntax-only DIR/tu.c -fmodules -fimplicit-module-maps -fmodules-validate-once-per-build-session -fbuild-session-file=DIR/build-session -fmodules-prune-interval=123 -fmodules-prune-after=123 -fmodules-cache-path=DIR/cache -include DIR/header.h -grecord-command-line -fdebug-compilation-dir=DIR/debug -fcoverage-compilation-dir=DIR/coverage -ftest-coverage -o DIR/tu.o -serialize-diagnostics DIR/tu.diag -MT tu -MD -MF DIR/tu.d",
+ "command": "clang -fsyntax-only DIR/tu.c -fmodules -fimplicit-module-maps -fmodules-validate-once-per-build-session -fbuild-session-file=DIR/build-session -fmodules-prune-interval=123 -fmodules-prune-after=123 -fmodules-cache-path=DIR/cache -include DIR/header.h -grecord-command-line -fdebug-compilation-dir=DIR/debug -fcoverage-compilation-dir=DIR/coverage -ftest-coverage -fprofile-instr-use=DIR/tu.profdata -o DIR/tu.o -serialize-diagnostics DIR/tu.diag -MT tu -MD -MF DIR/tu.d",
"file": "DIR/tu.c"
}
]
diff --git a/clang/test/ClangScanDeps/removed-args.c b/clang/test/ClangScanDeps/removed-args.c
index 9a4ef25838e4..f49e4ead82f7 100644
--- a/clang/test/ClangScanDeps/removed-args.c
+++ b/clang/test/ClangScanDeps/removed-args.c
@@ -9,6 +9,8 @@
// RUN: rm -rf %t && mkdir %t
// RUN: cp %S/Inputs/removed-args/* %t
// RUN: touch %t/build-session
+// RUN: touch %t/tu.proftext
+// RUN: llvm-profdata merge %t/tu.proftext -o %t/tu.profdata
// RUN: sed "s|DIR|%/t|g" %S/Inputs/removed-args/cdb.json.template > %t/cdb.json
// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full > %t/result.json
@@ -25,6 +27,7 @@
// CHECK-NOT: "-fcoverage-compilation-dir="
// CHECK-NOT: "-coverage-notes-file
// CHECK-NOT: "-coverage-data-file
+// CHECK-NOT: "-fprofile-instrument-use-path
// CHECK-NOT: "-dwarf-debug-flags"
// CHECK-NOT: "-main-file-name"
// CHECK-NOT: "-include"
@@ -50,6 +53,7 @@
// CHECK-NOT: "-fcoverage-compilation-dir=
// CHECK-NOT: "-coverage-notes-file
// CHECK-NOT: "-coverage-data-file
+// CHECK-NOT: "-fprofile-instrument-use-path
// CHECK-NOT: "-dwarf-debug-flags"
// CHECK-NOT: "-main-file-name"
// CHECK-NOT: "-include"
--
GitLab
From 0e60cf7f4b66312c09df9412be3efd1e9c891e85 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks
Date: Fri, 5 Apr 2024 17:37:01 +0000
Subject: [PATCH 008/695] [gn build] Manually port 68b939f9
---
llvm/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn b/llvm/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn
index e5fb529b455f..80a91507fcc6 100644
--- a/llvm/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn
@@ -122,6 +122,7 @@ write_cmake_config("config") {
"HOST_LINK_VERSION=",
"LIBPFM_HAS_FIELD_CYCLES=",
"LLVM_TARGET_TRIPLE_ENV=",
+ "LLVM_VERSION_PRINTER_SHOW_BUILD_CONFIG=1",
"LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO=1",
"LLVM_WINDOWS_PREFER_FORWARD_SLASH=",
"PACKAGE_BUGREPORT=https://github.com/llvm/llvm-project/issues/",
--
GitLab
From 666fd665e98df1e5c8e8d5be1eb08bf102c0691c Mon Sep 17 00:00:00 2001
From: Arthur Eubanks
Date: Fri, 5 Apr 2024 17:37:44 +0000
Subject: [PATCH 009/695] [gn build] Port 30f6eafaa978
---
llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn
index a405878fecb2..0cf99256c9bd 100644
--- a/llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn
@@ -127,6 +127,7 @@ static_library("AST") {
"ODRDiagsEmitter.cpp",
"ODRHash.cpp",
"OSLog.cpp",
+ "OpenACCClause.cpp",
"OpenMPClause.cpp",
"ParentMap.cpp",
"ParentMapContext.cpp",
--
GitLab
From 6411aaf99cbfddafdeecb73d9fd7388fcae32293 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks
Date: Fri, 5 Apr 2024 17:37:45 +0000
Subject: [PATCH 010/695] [gn build] Port e84a757222aa
---
llvm/utils/gn/secondary/llvm/unittests/ADT/BUILD.gn | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/utils/gn/secondary/llvm/unittests/ADT/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ADT/BUILD.gn
index 15c198c73f94..edf06df4f609 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/ADT/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/ADT/BUILD.gn
@@ -52,6 +52,7 @@ unittest("ADTTests") {
"ImmutableMapTest.cpp",
"ImmutableSetTest.cpp",
"IntEqClassesTest.cpp",
+ "Interleave.cpp",
"IntervalMapTest.cpp",
"IntervalTreeTest.cpp",
"IntrusiveRefCntPtrTest.cpp",
--
GitLab
From 965e053eb3ba336b6174e6753f138cabc0ea92c2 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks
Date: Fri, 5 Apr 2024 17:37:46 +0000
Subject: [PATCH 011/695] [gn build] Port f5960c168dfe
---
llvm/utils/gn/secondary/libcxx/include/BUILD.gn | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
index 78a6e6fda826..66e8084d5808 100644
--- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
+++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
@@ -807,6 +807,7 @@ if (current_toolchain == default_toolchain) {
"__type_traits/datasizeof.h",
"__type_traits/decay.h",
"__type_traits/dependent_type.h",
+ "__type_traits/desugars_to.h",
"__type_traits/disjunction.h",
"__type_traits/enable_if.h",
"__type_traits/extent.h",
@@ -891,7 +892,6 @@ if (current_toolchain == default_toolchain) {
"__type_traits/nat.h",
"__type_traits/negation.h",
"__type_traits/noexcept_move_assign_container.h",
- "__type_traits/operation_traits.h",
"__type_traits/promote.h",
"__type_traits/rank.h",
"__type_traits/remove_all_extents.h",
--
GitLab
From 5772fc890f7ebda04029ba82af32c9072a1c44b6 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks
Date: Fri, 5 Apr 2024 17:42:36 +0000
Subject: [PATCH 012/695] [gn build] Add missing dependency
---
llvm/utils/gn/secondary/llvm/lib/TextAPI/BinaryReader/BUILD.gn | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/utils/gn/secondary/llvm/lib/TextAPI/BinaryReader/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/TextAPI/BinaryReader/BUILD.gn
index 3eeb32aae4e3..24130bc2e08f 100644
--- a/llvm/utils/gn/secondary/llvm/lib/TextAPI/BinaryReader/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/TextAPI/BinaryReader/BUILD.gn
@@ -1,6 +1,7 @@
static_library("BinaryReader") {
output_name = "LLVMTextAPIBinaryReader"
deps = [
+ "//llvm/lib/DebugInfo/DWARF",
"//llvm/lib/Object",
"//llvm/lib/Support",
"//llvm/lib/TargetParser",
--
GitLab
From e915b7d8166a870834868bcf7de85cb5e96a08ec Mon Sep 17 00:00:00 2001
From: Fangrui Song
Date: Fri, 5 Apr 2024 10:52:10 -0700
Subject: [PATCH 013/695] [ELF,test] Add test for R_AARCH64_* implicit addends
to support certain static relocations in the REL format. See #87328 for
the armasm need.
Note: `R_AARCH64_{ABS64,PREL32,PREL64}` have been implemented by https://reviews.llvm.org/D120535
Pull Request: https://github.com/llvm/llvm-project/pull/87733
---
.../ELF/aarch64-reloc-implicit-addend.test | 86 +++++++++++++++++++
1 file changed, 86 insertions(+)
create mode 100644 lld/test/ELF/aarch64-reloc-implicit-addend.test
diff --git a/lld/test/ELF/aarch64-reloc-implicit-addend.test b/lld/test/ELF/aarch64-reloc-implicit-addend.test
new file mode 100644
index 000000000000..15f42c4d87b5
--- /dev/null
+++ b/lld/test/ELF/aarch64-reloc-implicit-addend.test
@@ -0,0 +1,86 @@
+## Test certain REL relocation types generated by legacy armasm.
+# RUN: yaml2obj %s -o %t.o
+# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s
+
+# CHECK-COUNT-17: internal linker error: cannot read addend
+
+---
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_AARCH64
+Sections:
+ - Name: .abs
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Content: fffffefffffffdfffffffffffffffcffffffffffffff
+ - Name: .rel.abs
+ Type: SHT_REL
+ Link: .symtab
+ Info: .abs
+ Relocations:
+ - {Offset: 0, Symbol: abs, Type: R_AARCH64_ABS16}
+ - {Offset: 2, Symbol: abs, Type: R_AARCH64_ABS32}
+ - {Offset: 6, Symbol: abs, Type: R_AARCH64_ABS64}
+ - {Offset: 14, Symbol: abs, Type: R_AARCH64_ADD_ABS_LO12_NC}
+
+ - Name: .uabs
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 4
+ Content: 00ffffff00ffffff00ffffff00ffffff00ffffff00ffffff
+ - Name: .rel.uabs
+ Type: SHT_REL
+ Link: .symtab
+ Info: .uabs
+ Relocations:
+ - {Offset: 0, Symbol: abs, Type: R_AARCH64_MOVW_UABS_G0}
+ - {Offset: 4, Symbol: abs, Type: R_AARCH64_MOVW_UABS_G0_NC}
+ - {Offset: 8, Symbol: abs, Type: R_AARCH64_MOVW_UABS_G1}
+ - {Offset: 12, Symbol: abs, Type: R_AARCH64_MOVW_UABS_G1_NC}
+ - {Offset: 16, Symbol: abs, Type: R_AARCH64_MOVW_UABS_G2}
+ - {Offset: 20, Symbol: abs, Type: R_AARCH64_MOVW_UABS_G2_NC}
+
+ - Name: .prel
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 4
+ Content: 00ffffff00ffffff00ffffff00ffffff00ffffff00ffffff
+ - Name: .rel.prel
+ Type: SHT_REL
+ Link: .symtab
+ Info: .prel
+ Relocations:
+ - {Offset: 0, Symbol: .prel, Type: R_AARCH64_PREL64}
+ - {Offset: 4, Symbol: .prel, Type: R_AARCH64_PREL32}
+ - {Offset: 8, Symbol: .prel, Type: R_AARCH64_PREL16}
+ - {Offset: 12, Symbol: .prel, Type: R_AARCH64_LD_PREL_LO19}
+ - {Offset: 16, Symbol: .prel, Type: R_AARCH64_ADR_PREL_PG_HI21}
+ - {Offset: 20, Symbol: .prel, Type: R_AARCH64_ADR_PREL_PG_HI21_NC}
+
+ - Name: .branch
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 4
+ Content: f0fffffff0fffffff0fffffff0ffffff
+ - Name: .rel.branch
+ Type: SHT_REL
+ Link: .symtab
+ Info: .branch
+ Relocations:
+ - {Offset: 0, Symbol: .branch, Type: R_AARCH64_TSTBR14}
+ - {Offset: 4, Symbol: .branch, Type: R_AARCH64_CONDBR19}
+ - {Offset: 8, Symbol: .branch, Type: R_AARCH64_CALL26}
+ - {Offset: 12, Symbol: .branch, Type: R_AARCH64_JUMP26}
+
+Symbols:
+ - Name: .branch
+ Section: .branch
+ - Name: .prel
+ Section: .prel
+ - Name: abs
+ Index: SHN_ABS
+ Value: 42
+ Binding: STB_GLOBAL
--
GitLab
From 2606c87788153bf33d854fa5c3a03e16d544c5d7 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Fri, 5 Apr 2024 14:04:29 -0400
Subject: [PATCH 014/695] [C99] Claim conformance to WG14 N717 (#87228)
This was the paper that added Universal Character Names to C.
---
clang/test/C/C99/n717.c | 75 +++++++++++++++++++++++++++++++++++++++++
clang/www/c_status.html | 2 +-
2 files changed, 76 insertions(+), 1 deletion(-)
create mode 100644 clang/test/C/C99/n717.c
diff --git a/clang/test/C/C99/n717.c b/clang/test/C/C99/n717.c
new file mode 100644
index 000000000000..25010b413706
--- /dev/null
+++ b/clang/test/C/C99/n717.c
@@ -0,0 +1,75 @@
+// RUN: %clang_cc1 -verify -std=c99 %s
+// RUN: %clang_cc1 -verify -std=c99 -fno-dollars-in-identifiers %s
+
+/* WG14 N717: Clang 17
+ * Extended identifiers
+ */
+
+// Used as a sink for UCNs.
+#define M(arg)
+
+// C99 6.4.3p1 specifies the grammar for UCNs. A \u must be followed by exactly
+// four hex digits, and \U must be followed by exactly eight.
+M(\u1) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}}
+M(\u12) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}}
+M(\u123) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}}
+M(\u1234) // Okay
+M(\u12345)// Okay, two tokens (UCN followed by 5)
+
+M(\U1) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}}
+M(\U12) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}}
+M(\U123) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}}
+M(\U1234) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} \
+ expected-note {{did you mean to use '\u'?}}
+M(\U12345) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}}
+M(\U123456) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}}
+M(\U1234567) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}}
+M(\U12345678) // Okay
+M(\U123456789) // Okay-ish, two tokens (valid-per-spec-but-actually-invalid UCN followed by 9)
+
+// Now test the ones that should work. Note, these work in C17 and earlier but
+// are part of the basic character set in C23 and thus should be diagnosed in
+// that mode. They're valid in a character constant, but not valid in an
+// identifier, except for U+0024 which is allowed if -fdollars-in-identifiers
+// is enabled.
+// FIXME: These three should be handled the same way, and should be accepted
+// when dollar signs are allowed in identifiers, rather than rejected, see
+// GH87106.
+M(\u0024) // expected-error {{character '$' cannot be specified by a universal character name}}
+M(\U00000024) // expected-error {{character '$' cannot be specified by a universal character name}}
+M($)
+
+// These should always be rejected because they're not valid identifier
+// characters.
+// FIXME: the diagnostic could be improved to make it clear this is an issue
+// with forming an identifier rather than a UCN.
+M(\u0040) // expected-error {{character '@' cannot be specified by a universal character name}}
+M(\u0060) // expected-error {{character '`' cannot be specified by a universal character name}}
+M(\U00000040) // expected-error {{character '@' cannot be specified by a universal character name}}
+M(\U00000060) // expected-error {{character '`' cannot be specified by a universal character name}}
+
+// UCNs outside of identifiers are handled in Phase 5 of translation, so we
+// cannot use the macro expansion to test their behavior.
+
+// This is outside of the range of values specified by ISO 10646.
+const char *c1 = "\U00110000"; // expected-error {{invalid universal character}}
+// This does not fall outside of the range
+const char *c2 = "\U0010FFFF";
+
+// These should always be accepted because they're a valid in a character
+// constant.
+int c3 = '\u0024';
+int c4 = '\u0040';
+int c5 = '\u0060';
+
+int c6 = '\U00000024';
+int c7 = '\U00000040';
+int c8 = '\U00000060';
+
+// Valid lone surrogates.
+M(\uD799)
+const char *c9 = "\U0000E000";
+
+// Invalid lone surrogates, which are excluded explicitly by 6.4.3p2.
+M(\uD800) // expected-error {{invalid universal character}}
+const char *c10 = "\U0000DFFF"; // expected-error {{invalid universal character}}
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index bc27b20ce648..7ee1d2b507e8 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -203,7 +203,7 @@ conformance.
| extended identifiers |
N717 |
- Unknown |
+ Clang 17 |
| hexadecimal floating-point constants |
--
GitLab
From 9264c85b47d3866c44f916cfff533c0d9d9d7a8d Mon Sep 17 00:00:00 2001
From: Haojian Wu
Date: Fri, 5 Apr 2024 20:16:54 +0200
Subject: [PATCH 015/695] [Sema] Remove the duplicated
`DeduceTemplateArguments` for partial specialization, NFC (#87782)
We have two identical "DeduceTemplateArguments" implementations for
class and variable partial template specializations, this patch removes
the duplicated code.
---
clang/lib/Sema/SemaTemplateDeduction.cpp | 85 +++++++-----------------
1 file changed, 24 insertions(+), 61 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 716660244537..0b6375001f53 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3140,13 +3140,15 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction(
return TemplateDeductionResult::Success;
}
-/// Perform template argument deduction to determine whether
-/// the given template arguments match the given class template
-/// partial specialization per C++ [temp.class.spec.match].
-TemplateDeductionResult
-Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
- ArrayRef TemplateArgs,
- TemplateDeductionInfo &Info) {
+/// Perform template argument deduction to determine whether the given template
+/// arguments match the given class or variable template partial specialization
+/// per C++ [temp.class.spec.match].
+template
+static std::enable_if_t::value,
+ TemplateDeductionResult>
+DeduceTemplateArguments(Sema &S, T *Partial,
+ ArrayRef TemplateArgs,
+ TemplateDeductionInfo &Info) {
if (Partial->isInvalidDecl())
return TemplateDeductionResult::Invalid;
@@ -3158,25 +3160,25 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
// Unevaluated SFINAE context.
EnterExpressionEvaluationContext Unevaluated(
- *this, Sema::ExpressionEvaluationContext::Unevaluated);
- SFINAETrap Trap(*this);
+ S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Sema::SFINAETrap Trap(S);
// This deduction has no relation to any outer instantiation we might be
// performing.
- LocalInstantiationScope InstantiationScope(*this);
+ LocalInstantiationScope InstantiationScope(S);
SmallVector Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
if (TemplateDeductionResult Result = ::DeduceTemplateArguments(
- *this, Partial->getTemplateParameters(),
+ S, Partial->getTemplateParameters(),
Partial->getTemplateArgs().asArray(), TemplateArgs, Info, Deduced,
/*NumberOfArgumentsMustMatch=*/false);
Result != TemplateDeductionResult::Success)
return Result;
SmallVector DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, Info.getLocation(), Partial, DeducedArgs,
- Info);
+ Sema::InstantiatingTemplate Inst(S, Info.getLocation(), Partial, DeducedArgs,
+ Info);
if (Inst.isInvalid())
return TemplateDeductionResult::InstantiationDepth;
@@ -3184,64 +3186,25 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
return TemplateDeductionResult::SubstitutionFailure;
TemplateDeductionResult Result;
- runWithSufficientStackSpace(Info.getLocation(), [&] {
- Result = ::FinishTemplateArgumentDeduction(*this, Partial,
+ S.runWithSufficientStackSpace(Info.getLocation(), [&] {
+ Result = ::FinishTemplateArgumentDeduction(S, Partial,
/*IsPartialOrdering=*/false,
TemplateArgs, Deduced, Info);
});
return Result;
}
-/// Perform template argument deduction to determine whether
-/// the given template arguments match the given variable template
-/// partial specialization per C++ [temp.class.spec.match].
+TemplateDeductionResult
+Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+ ArrayRef TemplateArgs,
+ TemplateDeductionInfo &Info) {
+ return ::DeduceTemplateArguments(*this, Partial, TemplateArgs, Info);
+}
TemplateDeductionResult
Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
ArrayRef TemplateArgs,
TemplateDeductionInfo &Info) {
- if (Partial->isInvalidDecl())
- return TemplateDeductionResult::Invalid;
-
- // C++ [temp.class.spec.match]p2:
- // A partial specialization matches a given actual template
- // argument list if the template arguments of the partial
- // specialization can be deduced from the actual template argument
- // list (14.8.2).
-
- // Unevaluated SFINAE context.
- EnterExpressionEvaluationContext Unevaluated(
- *this, Sema::ExpressionEvaluationContext::Unevaluated);
- SFINAETrap Trap(*this);
-
- // This deduction has no relation to any outer instantiation we might be
- // performing.
- LocalInstantiationScope InstantiationScope(*this);
-
- SmallVector Deduced;
- Deduced.resize(Partial->getTemplateParameters()->size());
- if (TemplateDeductionResult Result = ::DeduceTemplateArguments(
- *this, Partial->getTemplateParameters(),
- Partial->getTemplateArgs().asArray(), TemplateArgs, Info, Deduced,
- /*NumberOfArgumentsMustMatch=*/false);
- Result != TemplateDeductionResult::Success)
- return Result;
-
- SmallVector DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, Info.getLocation(), Partial, DeducedArgs,
- Info);
- if (Inst.isInvalid())
- return TemplateDeductionResult::InstantiationDepth;
-
- if (Trap.hasErrorOccurred())
- return TemplateDeductionResult::SubstitutionFailure;
-
- TemplateDeductionResult Result;
- runWithSufficientStackSpace(Info.getLocation(), [&] {
- Result = ::FinishTemplateArgumentDeduction(*this, Partial,
- /*IsPartialOrdering=*/false,
- TemplateArgs, Deduced, Info);
- });
- return Result;
+ return ::DeduceTemplateArguments(*this, Partial, TemplateArgs, Info);
}
/// Determine whether the given type T is a simple-template-id type.
--
GitLab
From 66b528078e4852412769375e35d2a672bf36a0ec Mon Sep 17 00:00:00 2001
From: Alexey Bataev
Date: Fri, 5 Apr 2024 14:29:26 -0400
Subject: [PATCH 016/695] [SLP]Improve minbitwidth analysis for
abs/smin/smax/umin/umax intrinsics.
https://alive2.llvm.org/ce/z/ivPZ26 for the abs transformations.
Reviewers: RKSimon
Reviewed By: RKSimon
Pull Request: https://github.com/llvm/llvm-project/pull/86135
---
.../Transforms/Vectorize/SLPVectorizer.cpp | 102 +++++++++++++++---
.../X86/call-arg-reduced-by-minbitwidth.ll | 4 +-
.../cmp-after-intrinsic-call-minbitwidth.ll | 12 ++-
.../X86/store-abs-minbitwidth.ll | 9 +-
4 files changed, 100 insertions(+), 27 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 332877f35081..731d7b4edfa3 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -7056,19 +7056,16 @@ bool BoUpSLP::areAllUsersVectorized(
static std::pair
getVectorCallCosts(CallInst *CI, FixedVectorType *VecTy,
- TargetTransformInfo *TTI, TargetLibraryInfo *TLI) {
+ TargetTransformInfo *TTI, TargetLibraryInfo *TLI,
+ ArrayRef ArgTys) {
Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
// Calculate the cost of the scalar and vector calls.
- SmallVector VecTys;
- for (Use &Arg : CI->args())
- VecTys.push_back(
- FixedVectorType::get(Arg->getType(), VecTy->getNumElements()));
FastMathFlags FMF;
if (auto *FPCI = dyn_cast(CI))
FMF = FPCI->getFastMathFlags();
SmallVector Arguments(CI->args());
- IntrinsicCostAttributes CostAttrs(ID, VecTy, Arguments, VecTys, FMF,
+ IntrinsicCostAttributes CostAttrs(ID, VecTy, Arguments, ArgTys, FMF,
dyn_cast(CI));
auto IntrinsicCost =
TTI->getIntrinsicInstrCost(CostAttrs, TTI::TCK_RecipThroughput);
@@ -7081,8 +7078,8 @@ getVectorCallCosts(CallInst *CI, FixedVectorType *VecTy,
if (!CI->isNoBuiltin() && VecFunc) {
// Calculate the cost of the vector library call.
// If the corresponding vector call is cheaper, return its cost.
- LibCost = TTI->getCallInstrCost(nullptr, VecTy, VecTys,
- TTI::TCK_RecipThroughput);
+ LibCost =
+ TTI->getCallInstrCost(nullptr, VecTy, ArgTys, TTI::TCK_RecipThroughput);
}
return {IntrinsicCost, LibCost};
}
@@ -8508,6 +8505,30 @@ TTI::CastContextHint BoUpSLP::getCastContextHint(const TreeEntry &TE) const {
return TTI::CastContextHint::None;
}
+/// Builds the arguments types vector for the given call instruction with the
+/// given \p ID for the specified vector factor.
+static SmallVector buildIntrinsicArgTypes(const CallInst *CI,
+ const Intrinsic::ID ID,
+ const unsigned VF,
+ unsigned MinBW) {
+ SmallVector ArgTys;
+ for (auto [Idx, Arg] : enumerate(CI->args())) {
+ if (ID != Intrinsic::not_intrinsic) {
+ if (isVectorIntrinsicWithScalarOpAtArg(ID, Idx)) {
+ ArgTys.push_back(Arg->getType());
+ continue;
+ }
+ if (MinBW > 0) {
+ ArgTys.push_back(FixedVectorType::get(
+ IntegerType::get(CI->getContext(), MinBW), VF));
+ continue;
+ }
+ }
+ ArgTys.push_back(FixedVectorType::get(Arg->getType(), VF));
+ }
+ return ArgTys;
+}
+
InstructionCost
BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals,
SmallPtrSetImpl &CheckedExtracts) {
@@ -9074,7 +9095,11 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals,
};
auto GetVectorCost = [=](InstructionCost CommonCost) {
auto *CI = cast(VL0);
- auto VecCallCosts = getVectorCallCosts(CI, VecTy, TTI, TLI);
+ Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
+ SmallVector ArgTys =
+ buildIntrinsicArgTypes(CI, ID, VecTy->getNumElements(),
+ It != MinBWs.end() ? It->second.first : 0);
+ auto VecCallCosts = getVectorCallCosts(CI, VecTy, TTI, TLI, ArgTys);
return std::min(VecCallCosts.first, VecCallCosts.second) + CommonCost;
};
return GetCostDiff(GetScalarCost, GetVectorCost);
@@ -12546,7 +12571,10 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
- auto VecCallCosts = getVectorCallCosts(CI, VecTy, TTI, TLI);
+ SmallVector ArgTys =
+ buildIntrinsicArgTypes(CI, ID, VecTy->getNumElements(),
+ It != MinBWs.end() ? It->second.first : 0);
+ auto VecCallCosts = getVectorCallCosts(CI, VecTy, TTI, TLI, ArgTys);
bool UseIntrinsic = ID != Intrinsic::not_intrinsic &&
VecCallCosts.first <= VecCallCosts.second;
@@ -12555,8 +12583,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
SmallVector TysForDecl;
// Add return type if intrinsic is overloaded on it.
if (UseIntrinsic && isVectorIntrinsicWithOverloadTypeAtArg(ID, -1))
- TysForDecl.push_back(
- FixedVectorType::get(CI->getType(), E->Scalars.size()));
+ TysForDecl.push_back(VecTy);
auto *CEI = cast(VL0);
for (unsigned I : seq(0, CI->arg_size())) {
ValueList OpVL;
@@ -12564,7 +12591,12 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
// vectorized.
if (UseIntrinsic && isVectorIntrinsicWithScalarOpAtArg(ID, I)) {
ScalarArg = CEI->getArgOperand(I);
- OpVecs.push_back(CEI->getArgOperand(I));
+ // if decided to reduce bitwidth of abs intrinsic, it second argument
+ // must be set false (do not return poison, if value issigned min).
+ if (ID == Intrinsic::abs && It != MinBWs.end() &&
+ It->second.first < DL->getTypeSizeInBits(CEI->getType()))
+ ScalarArg = Builder.getFalse();
+ OpVecs.push_back(ScalarArg);
if (isVectorIntrinsicWithOverloadTypeAtArg(ID, I))
TysForDecl.push_back(ScalarArg->getType());
continue;
@@ -12577,10 +12609,13 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
}
ScalarArg = CEI->getArgOperand(I);
if (cast(OpVec->getType())->getElementType() !=
- ScalarArg->getType()) {
+ ScalarArg->getType() &&
+ It == MinBWs.end()) {
auto *CastTy = FixedVectorType::get(ScalarArg->getType(),
VecTy->getNumElements());
OpVec = Builder.CreateIntCast(OpVec, CastTy, GetOperandSignedness(I));
+ } else if (It != MinBWs.end()) {
+ OpVec = Builder.CreateIntCast(OpVec, VecTy, GetOperandSignedness(I));
}
LLVM_DEBUG(dbgs() << "SLP: OpVec[" << I << "]: " << *OpVec << "\n");
OpVecs.push_back(OpVec);
@@ -14324,6 +14359,45 @@ bool BoUpSLP::collectValuesToDemote(
return TryProcessInstruction(I, *ITE, BitWidth, Ops);
}
+ case Instruction::Call: {
+ auto *IC = dyn_cast(I);
+ if (!IC)
+ break;
+ Intrinsic::ID ID = getVectorIntrinsicIDForCall(IC, TLI);
+ if (ID != Intrinsic::abs && ID != Intrinsic::smin &&
+ ID != Intrinsic::smax && ID != Intrinsic::umin && ID != Intrinsic::umax)
+ break;
+ SmallVector Operands(1, I->getOperand(0));
+ End = 1;
+ if (ID != Intrinsic::abs) {
+ Operands.push_back(I->getOperand(1));
+ End = 2;
+ }
+ InstructionCost BestCost =
+ std::numeric_limits::max();
+ unsigned BestBitWidth = BitWidth;
+ unsigned VF = ITE->Scalars.size();
+ // Choose the best bitwidth based on cost estimations.
+ auto Checker = [&](unsigned BitWidth, unsigned) {
+ unsigned MinBW = PowerOf2Ceil(BitWidth);
+ SmallVector ArgTys = buildIntrinsicArgTypes(IC, ID, VF, MinBW);
+ auto VecCallCosts = getVectorCallCosts(
+ IC,
+ FixedVectorType::get(IntegerType::get(IC->getContext(), MinBW), VF),
+ TTI, TLI, ArgTys);
+ InstructionCost Cost = std::min(VecCallCosts.first, VecCallCosts.second);
+ if (Cost < BestCost) {
+ BestCost = Cost;
+ BestBitWidth = BitWidth;
+ }
+ return false;
+ };
+ [[maybe_unused]] bool NeedToExit;
+ (void)AttemptCheckBitwidth(Checker, NeedToExit);
+ BitWidth = BestBitWidth;
+ return TryProcessInstruction(I, *ITE, BitWidth, Operands);
+ }
+
// Otherwise, conservatively give up.
default:
break;
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll
index 27c9655f94d3..82966124d3ba 100644
--- a/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll
+++ b/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll
@@ -11,9 +11,7 @@ define void @test(ptr %0, i8 %1, i1 %cmp12.i) {
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <8 x i8> [[TMP4]], <8 x i8> poison, <8 x i32> zeroinitializer
; CHECK-NEXT: br label [[PRE:%.*]]
; CHECK: pre:
-; CHECK-NEXT: [[TMP6:%.*]] = zext <8 x i8> [[TMP5]] to <8 x i32>
-; CHECK-NEXT: [[TMP7:%.*]] = call <8 x i32> @llvm.umax.v8i32(<8 x i32> [[TMP6]], <8 x i32> )
-; CHECK-NEXT: [[TMP8:%.*]] = trunc <8 x i32> [[TMP7]] to <8 x i8>
+; CHECK-NEXT: [[TMP8:%.*]] = call <8 x i8> @llvm.umax.v8i8(<8 x i8> [[TMP5]], <8 x i8> )
; CHECK-NEXT: [[TMP9:%.*]] = add <8 x i8> [[TMP8]],
; CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP3]], <8 x i8> [[TMP9]], <8 x i8> [[TMP5]]
; CHECK-NEXT: store <8 x i8> [[TMP10]], ptr [[TMP0]], align 1
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll
index a05d4fdd6315..9fa88084aaa0 100644
--- a/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll
+++ b/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll
@@ -5,12 +5,14 @@ define void @test() {
; CHECK-LABEL: define void @test(
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> zeroinitializer, <2 x i32> zeroinitializer)
-; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> zeroinitializer, <2 x i32> zeroinitializer, <2 x i32> [[TMP0]]
-; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i32> [[TMP1]], zeroinitializer
-; CHECK-NEXT: [[ADD:%.*]] = extractelement <2 x i32> [[TMP2]], i32 1
+; CHECK-NEXT: [[TMP0:%.*]] = call <2 x i2> @llvm.smin.v2i2(<2 x i2> zeroinitializer, <2 x i2> zeroinitializer)
+; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> zeroinitializer, <2 x i2> zeroinitializer, <2 x i2> [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i2> [[TMP1]], zeroinitializer
+; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x i2> [[TMP2]], i32 1
+; CHECK-NEXT: [[ADD:%.*]] = zext i2 [[TMP3]] to i32
; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[ADD]], 0
-; CHECK-NEXT: [[ADD45:%.*]] = extractelement <2 x i32> [[TMP2]], i32 0
+; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i2> [[TMP2]], i32 0
+; CHECK-NEXT: [[ADD45:%.*]] = zext i2 [[TMP5]] to i32
; CHECK-NEXT: [[ADD152:%.*]] = or i32 [[ADD45]], [[ADD]]
; CHECK-NEXT: [[IDXPROM153:%.*]] = sext i32 [[ADD152]] to i64
; CHECK-NEXT: [[ARRAYIDX154:%.*]] = getelementptr i8, ptr null, i64 [[IDXPROM153]]
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll
index e8b854b7cea6..df7312e3d2b5 100644
--- a/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll
+++ b/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll
@@ -13,14 +13,13 @@ define i32 @test(ptr noalias %in, ptr noalias %inn, ptr %out) {
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <2 x i8> [[TMP3]], <2 x i8> poison, <4 x i32>
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x i8> [[TMP2]], <2 x i8> poison, <4 x i32>
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <4 x i8> [[TMP5]], <4 x i8> [[TMP6]], <4 x i32>
-; CHECK-NEXT: [[TMP8:%.*]] = sext <4 x i8> [[TMP7]] to <4 x i32>
+; CHECK-NEXT: [[TMP8:%.*]] = sext <4 x i8> [[TMP7]] to <4 x i16>
; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <4 x i32>
; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <2 x i8> [[TMP4]], <2 x i8> poison, <4 x i32>
; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <4 x i8> [[TMP9]], <4 x i8> [[TMP10]], <4 x i32>
-; CHECK-NEXT: [[TMP12:%.*]] = sext <4 x i8> [[TMP11]] to <4 x i32>
-; CHECK-NEXT: [[TMP13:%.*]] = sub <4 x i32> [[TMP12]], [[TMP8]]
-; CHECK-NEXT: [[TMP14:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[TMP13]], i1 true)
-; CHECK-NEXT: [[TMP15:%.*]] = trunc <4 x i32> [[TMP14]] to <4 x i16>
+; CHECK-NEXT: [[TMP12:%.*]] = sext <4 x i8> [[TMP11]] to <4 x i16>
+; CHECK-NEXT: [[TMP13:%.*]] = sub <4 x i16> [[TMP12]], [[TMP8]]
+; CHECK-NEXT: [[TMP15:%.*]] = call <4 x i16> @llvm.abs.v4i16(<4 x i16> [[TMP13]], i1 false)
; CHECK-NEXT: store <4 x i16> [[TMP15]], ptr [[OUT:%.*]], align 2
; CHECK-NEXT: ret i32 undef
;
--
GitLab
From e4169f79ef0f54676c0072e1704c3d02f32925b3 Mon Sep 17 00:00:00 2001
From: David Green
Date: Fri, 5 Apr 2024 19:33:22 +0100
Subject: [PATCH 017/695] [AArch64] Add extra zip and uzp shuffle cost tests.
NFC
---
.../CostModel/AArch64/shuffle-other.ll | 191 ++++++++++++++++++
1 file changed, 191 insertions(+)
diff --git a/llvm/test/Analysis/CostModel/AArch64/shuffle-other.ll b/llvm/test/Analysis/CostModel/AArch64/shuffle-other.ll
index 776c80c4bd1e..90ec92a35a1c 100644
--- a/llvm/test/Analysis/CostModel/AArch64/shuffle-other.ll
+++ b/llvm/test/Analysis/CostModel/AArch64/shuffle-other.ll
@@ -167,6 +167,197 @@ define void @insert_subvec() {
ret void
}
+define void @zip() {
+; CHECK-LABEL: 'zip'
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip1v2i8 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip2v2i8 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %zipv2i8 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %zip1v4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %zip2v4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %zipv4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %zip1v8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %zip2v8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %zipv8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %zip1v16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %zip2v16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 120 for instruction: %zipv16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <32 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip1v2i16 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip2v2i16 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zipv2i16 = shufflevector <2 x i16> undef, <2 x i16> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip1v4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip2v4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %zipv4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %zip1v8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %zip2v8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 56 for instruction: %zipv8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 56 for instruction: %zip1v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 56 for instruction: %zip2v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 112 for instruction: %zipv16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <32 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip1v2i32 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip2v2i32 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zipv2i32 = shufflevector <2 x i32> undef, <2 x i32> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip1v4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip2v4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %zipv4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %zip1v8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %zip2v8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %zipv8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %zip1v16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %zip2v16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %zipv16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <32 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip1v2i64 = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %zip2v2i64 = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %zipv2i64 = shufflevector <2 x i64> undef, <2 x i64> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %zip1v4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %zip2v4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %zipv4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %zip1v8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %zip2v8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %zipv8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %zip1v16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %zip2v16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %zipv16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <32 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
+;
+ %zip1v2i8 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32>
+ %zip2v2i8 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32>
+ %zipv2i8 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32>
+ %zip1v4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32>
+ %zip2v4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32>
+ %zipv4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32>
+ %zip1v8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32>
+ %zip2v8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32>
+ %zipv8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <16 x i32>
+ %zip1v16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32>
+ %zip2v16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32>
+ %zipv16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <32 x i32>
+
+ %zip1v2i16 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32>
+ %zip2v2i16 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32>
+ %zipv2i16 = shufflevector <2 x i16> undef, <2 x i16> undef, <4 x i32>
+ %zip1v4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32>
+ %zip2v4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32>
+ %zipv4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <8 x i32>
+ %zip1v8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32>
+ %zip2v8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32>
+ %zipv8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <16 x i32>
+ %zip1v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32>
+ %zip2v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32>
+ %zipv16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <32 x i32>
+
+ %zip1v2i32 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32>
+ %zip2v2i32 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32>
+ %zipv2i32 = shufflevector <2 x i32> undef, <2 x i32> undef, <4 x i32>
+ %zip1v4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32>
+ %zip2v4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32>
+ %zipv4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <8 x i32>
+ %zip1v8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32>
+ %zip2v8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32>
+ %zipv8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <16 x i32>
+ %zip1v16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32>
+ %zip2v16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32>
+ %zipv16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <32 x i32>
+
+ %zip1v2i64 = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32>
+ %zip2v2i64 = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32>
+ %zipv2i64 = shufflevector <2 x i64> undef, <2 x i64> undef, <4 x i32>
+ %zip1v4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <4 x i32>
+ %zip2v4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <4 x i32>
+ %zipv4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <8 x i32>
+ %zip1v8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <8 x i32>
+ %zip2v8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <8 x i32>
+ %zipv8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <16 x i32>
+ %zip1v16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <16 x i32>
+ %zip2v16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <16 x i32>
+ %zipv16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <32 x i32>
+
+ ret void
+}
+
+define void @uzp() {
+; CHECK-LABEL: 'uzp'
+; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %uzp1v4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %uzp2v4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %uzpv4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %uzp1v8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %uzp2v8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %uzpv8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %uzp1v16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %uzp2v16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 120 for instruction: %uzpv16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <32 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %uzp1v4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %uzp2v4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %uzpv4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %uzp1v8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %uzp2v8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 56 for instruction: %uzpv8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 56 for instruction: %uzp1v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 56 for instruction: %uzp2v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 112 for instruction: %uzpv16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <32 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %uzp1v4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %uzp2v4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %uzpv4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %uzp1v8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %uzp2v8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %uzpv8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %uzp1v16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %uzp2v16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %uzpv16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <32 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %uzp1v4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %uzp2v4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <4 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %uzpv4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %uzp1v8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %uzp2v8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <8 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %uzpv8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %uzp1v16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %uzp2v16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <16 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %uzpv16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <32 x i32>
+; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
+;
+ %uzp1v4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32>
+ %uzp2v4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32>
+ %uzpv4i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32>
+ %uzp1v8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32>
+ %uzp2v8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32>
+ %uzpv8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <16 x i32>
+ %uzp1v16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32>
+ %uzp2v16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32>
+ %uzpv16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <32 x i32>
+
+ %uzp1v4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32>
+ %uzp2v4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32>
+ %uzpv4i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <8 x i32>
+ %uzp1v8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32>
+ %uzp2v8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32>
+ %uzpv8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <16 x i32>
+ %uzp1v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32>
+ %uzp2v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32>
+ %uzpv16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <32 x i32>
+
+ %uzp1v4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32>
+ %uzp2v4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32>
+ %uzpv4i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <8 x i32>
+ %uzp1v8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32>
+ %uzp2v8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32>
+ %uzpv8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <16 x i32>
+ %uzp1v16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32>
+ %uzp2v16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32>
+ %uzpv16i32 = shufflevector <16 x i32> undef, <16 x i32> undef, <32 x i32>
+
+ %uzp1v4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <4 x i32>
+ %uzp2v4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <4 x i32>
+ %uzpv4i64 = shufflevector <4 x i64> undef, <4 x i64> undef, <8 x i32>
+ %uzp1v8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <8 x i32>
+ %uzp2v8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <8 x i32>
+ %uzpv8i64 = shufflevector <8 x i64> undef, <8 x i64> undef, <16 x i32>
+ %uzp1v16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <16 x i32>
+ %uzp2v16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <16 x i32>
+ %uzpv16i64 = shufflevector <16 x i64> undef, <16 x i64> undef, <32 x i32>
+
+ ret void
+}
+
+
define void @multipart() {
; CHECK-LABEL: 'multipart'
; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v16a = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32>
--
GitLab
From 225e14e5b6d64e1f63da39fa7fe31d2ebb08260d Mon Sep 17 00:00:00 2001
From: Dmitry Vasilyev
Date: Fri, 5 Apr 2024 22:40:07 +0400
Subject: [PATCH 018/695] [Support][Windows] Use the original path if
GetFinalPathNameByHandleW() failed (#87749)
The commit f11b056c (#76304) breaks `clang` and other tools if they are
used from a RAMDrive. `GetFinalPathNameByHandleW()` may return 0 and
GetLastError 0x28. This patch fixes that issue. Note `real_path()` uses
`openFileForRead()` but it reports the error only if failed to open a
file. Getting `RealPath` is optional functionality.
BTW, `sys::fs::real_path()` resolves not only symlinks, but also network
drives and virtual drives created by the `subst` tool. It may break an
automation. It is better to detect symlinks and resolve only symlinks.
---
llvm/lib/Support/Windows/Path.inc | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc
index 854d531ab371..4f0336a85daa 100644
--- a/llvm/lib/Support/Windows/Path.inc
+++ b/llvm/lib/Support/Windows/Path.inc
@@ -157,7 +157,9 @@ std::string getMainExecutable(const char *argv0, void *MainExecAddr) {
SmallString<256> RealPath;
sys::fs::real_path(PathNameUTF8, RealPath);
- return std::string(RealPath);
+ if (RealPath.size())
+ return std::string(RealPath);
+ return std::string(PathNameUTF8.data());
}
UniqueID file_status::getUniqueID() const {
--
GitLab
From 0a0fccfc6c0519402a2566e1f63440410e524d17 Mon Sep 17 00:00:00 2001
From: Chris B
Date: Fri, 5 Apr 2024 13:46:14 -0500
Subject: [PATCH 019/695] [HLSL] Implement floating literal suffixes (#87270)
This change implements the HLSL floating literal suffixes for half and
double literals. The PR for the HLSL language specification for this
behavior is https://github.com/microsoft/hlsl-specs/pull/175.
The TL;DR is that the `h` suffix on floating literals means `half`, and
the `l` suffix means `double`.
The expected behavior and diagnostics are different if native half is
supported. When native half is not enabled half is 32-bit so implicit
conversions to float do not lose precision and do not warn.
In all cases `half` and `float` are distinct types.
Resolves #85712
---
clang/lib/Sema/SemaExpr.cpp | 5 +-
clang/test/SemaHLSL/literal_suffixes.hlsl | 59 +++++++++++++++++++
.../SemaHLSL/literal_suffixes_no_16bit.hlsl | 59 +++++++++++++++++++
3 files changed, 121 insertions(+), 2 deletions(-)
create mode 100644 clang/test/SemaHLSL/literal_suffixes.hlsl
create mode 100644 clang/test/SemaHLSL/literal_suffixes_no_16bit.hlsl
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6b2eb245d582..ffe7e44e2387 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4117,7 +4117,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
} else if (Literal.isFloatingLiteral()) {
QualType Ty;
if (Literal.isHalf){
- if (getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()))
+ if (getLangOpts().HLSL ||
+ getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()))
Ty = Context.HalfTy;
else {
Diag(Tok.getLocation(), diag::err_half_const_requires_fp16);
@@ -4126,7 +4127,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
} else if (Literal.isFloat)
Ty = Context.FloatTy;
else if (Literal.isLong)
- Ty = Context.LongDoubleTy;
+ Ty = !getLangOpts().HLSL ? Context.LongDoubleTy : Context.DoubleTy;
else if (Literal.isFloat16)
Ty = Context.Float16Ty;
else if (Literal.isFloat128)
diff --git a/clang/test/SemaHLSL/literal_suffixes.hlsl b/clang/test/SemaHLSL/literal_suffixes.hlsl
new file mode 100644
index 000000000000..25a4d3b5103c
--- /dev/null
+++ b/clang/test/SemaHLSL/literal_suffixes.hlsl
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-library -fnative-half-type -Wconversion -verify %s
+
+void literal_assignments() {
+ half h;
+
+ h = 2.0h; // No conversion, no diagnostic expected.
+
+ // Literal conversions that don't lose precision also don't cause diagnostics.
+ // Conversion from double (no diagnostic expected)
+ h = 2.0l;
+ h = 2.0;
+ h = 2.0f;
+
+ // Literal assignments with conversions that lose precision produce
+ // diagnostics under `-Wconversion`.
+
+ // Lose precision on assignment.
+ h = 3.1415926535897932384626433h; // No diagnostic expected because this isn't a conversion.
+
+ // Lose precision on assignment converting float to half.
+ h = 3.1415926535897932384626433f; // expected-warning {{implicit conversion loses floating-point precision: 'float' to 'half'}}
+
+ // Lose precision on assignment converting float to half.
+ h = 3.1415926535897932384626433f * 2.0f; // expected-warning {{implicit conversion loses floating-point precision: 'float' to 'half'}}
+
+ // Lose precision on assignment converting double to half.
+ h = 3.1415926535897932384626433l; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'half'}}
+
+ // Lose precision on assignment converting double to half.
+ h = 3.1415926535897932384626433l * 2.0l; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'half'}}
+
+ // Literal assinments of values out of the representable range produce
+ // warnings.
+
+ h = 66000.h; // expected-warning {{magnitude of floating-point constant too large for type 'half'; maximum is 65504}}
+ h = -66000.h; // expected-warning {{magnitude of floating-point constant too large for type 'half'; maximum is 65504}}
+
+ // The `h` suffix is invalid on integer literals.
+ h = 66000h; // expected-error {{invalid suffix 'h' on integer constant}}
+}
+
+template
+struct is_same {
+ static const bool value = false;
+};
+
+template
+struct is_same {
+ static const bool value = true;
+};
+
+// The no-suffix behavior is currently wrong. The behavior in DXC is complicated
+// and undocumented. We have a language change planned to address this, and an
+// issue tracking: https://github.com/llvm/llvm-project/issues/85714.
+_Static_assert(is_same::value, "1.0f literal is double (should be float)");
+
+_Static_assert(is_same::value, "1.0h literal is half");
+_Static_assert(is_same::value, "1.0f literal is float");
+_Static_assert(is_same::value, "1.0l literal is double");
diff --git a/clang/test/SemaHLSL/literal_suffixes_no_16bit.hlsl b/clang/test/SemaHLSL/literal_suffixes_no_16bit.hlsl
new file mode 100644
index 000000000000..73e57041329e
--- /dev/null
+++ b/clang/test/SemaHLSL/literal_suffixes_no_16bit.hlsl
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-library -Wconversion -verify %s
+
+void literal_assignments() {
+ half h;
+
+ h = 2.0h; // No conversion, no diagnostic expected.
+
+ // Literal conversions that don't lose precision also don't cause diagnostics.
+ // Conversion from double (no diagnostic expected)
+ h = 2.0l;
+ h = 2.0;
+ h = 2.0f;
+
+ // Literal assignments with conversions that lose precision produce
+ // diagnostics under `-Wconversion`.
+
+ // Lose precision on assignment.
+ h = 3.1415926535897932384626433h; // No diagnostic expected because this isn't a conversion.
+
+ // Lose precision on assignment converting float to half.
+ h = 3.1415926535897932384626433f; // No diagnostic expected because half and float are the same size.
+
+ // Lose precision on assignment converting float to half.
+ h = 3.1415926535897932384626433f * 2.0f; // No diagnostic expected because half and float are the same size.
+
+ // Lose precision on assignment converting double to half.
+ h = 3.1415926535897932384626433l; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'half'}}
+
+ // Lose precision on assignment converting double to half.
+ h = 3.1415926535897932384626433l * 2.0l; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'half'}}
+
+ // Literal assinments of values out of the representable range produce
+ // warnings.
+
+ h = 66000.h; // No diagnostic expected because half is 32-bit.
+ h = -66000.h; // No diagnostic expected because half is 32-bit.
+
+ // The `h` suffix is invalid on integer literals.
+ h = 66000h; // expected-error {{invalid suffix 'h' on integer constant}}
+}
+
+template
+struct is_same {
+ static const bool value = false;
+};
+
+template
+struct is_same {
+ static const bool value = true;
+};
+
+// The no-suffix behavior is currently wrong. The behavior in DXC is complicated
+// and undocumented. We have a language change planned to address this, and an
+// issue tracking: https://github.com/llvm/llvm-project/issues/85714.
+_Static_assert(is_same::value, "1.0f literal is double (should be float)");
+
+_Static_assert(is_same::value, "1.0h literal is half");
+_Static_assert(is_same::value, "1.0f literal is float");
+_Static_assert(is_same::value, "1.0l literal is double");
--
GitLab
From 3989e2245746bbeaae26416a330753b9189cfaeb Mon Sep 17 00:00:00 2001
From: Daniil Kovalev
Date: Fri, 5 Apr 2024 21:50:29 +0300
Subject: [PATCH 020/695] [test][lld][ELF] Enhance pack-dyn-relocs.s test
(#87756)
Use symbol `.data` (STT_SECTION) instead of `__ehdr_start` for some
relocation entries. See discussion in
[72714/#discussion_r1517127619](https://github.com/llvm/llvm-project/pull/72714/#discussion_r1517127619)
---
lld/test/ELF/pack-dyn-relocs.s | 100 ++++++++++++++++-----------------
1 file changed, 50 insertions(+), 50 deletions(-)
diff --git a/lld/test/ELF/pack-dyn-relocs.s b/lld/test/ELF/pack-dyn-relocs.s
index 733ddd4ecad3..dd5d366ae234 100644
--- a/lld/test/ELF/pack-dyn-relocs.s
+++ b/lld/test/ELF/pack-dyn-relocs.s
@@ -198,24 +198,24 @@
// RUN: llvm-readobj -r %t2.a64 | FileCheck --check-prefix=UNPACKED64 %s
// UNPACKED64: Section ({{.+}}) .rela.dyn {
-// UNPACKED64-NEXT: 0x30690 R_AARCH64_RELATIVE - 0x0
-// UNPACKED64-NEXT: 0x30698 R_AARCH64_RELATIVE - 0x1
+// UNPACKED64-NEXT: 0x30690 R_AARCH64_RELATIVE - 0x30690
+// UNPACKED64-NEXT: 0x30698 R_AARCH64_RELATIVE - 0x30691
// UNPACKED64-NEXT: 0x306A0 R_AARCH64_RELATIVE - 0x2
// UNPACKED64-NEXT: 0x306A8 R_AARCH64_RELATIVE - 0xFFFFFFFFFFFFFFFF
// UNPACKED64-NEXT: 0x306B0 R_AARCH64_RELATIVE - 0x80000000
// UNPACKED64-NEXT: 0x306B8 R_AARCH64_RELATIVE - 0x6
// UNPACKED64-NEXT: 0x306C0 R_AARCH64_RELATIVE - 0x7
-// UNPACKED64-NEXT: 0x306C8 R_AARCH64_RELATIVE - 0x8
+// UNPACKED64-NEXT: 0x306C8 R_AARCH64_RELATIVE - 0x30698
-// UNPACKED64-NEXT: 0x306D8 R_AARCH64_RELATIVE - 0x1
+// UNPACKED64-NEXT: 0x306D8 R_AARCH64_RELATIVE - 0x30691
// UNPACKED64-NEXT: 0x306E0 R_AARCH64_RELATIVE - 0x2
// UNPACKED64-NEXT: 0x306E8 R_AARCH64_RELATIVE - 0x3
// UNPACKED64-NEXT: 0x306F0 R_AARCH64_RELATIVE - 0x4
// UNPACKED64-NEXT: 0x306F8 R_AARCH64_RELATIVE - 0x5
// UNPACKED64-NEXT: 0x30700 R_AARCH64_RELATIVE - 0x6
-// UNPACKED64-NEXT: 0x30708 R_AARCH64_RELATIVE - 0x7
+// UNPACKED64-NEXT: 0x30708 R_AARCH64_RELATIVE - 0x30697
-// UNPACKED64-NEXT: 0x30720 R_AARCH64_RELATIVE - 0x1
+// UNPACKED64-NEXT: 0x30720 R_AARCH64_RELATIVE - 0x30691
// UNPACKED64-NEXT: 0x30728 R_AARCH64_RELATIVE - 0x2
// UNPACKED64-NEXT: 0x30730 R_AARCH64_RELATIVE - 0x3
// UNPACKED64-NEXT: 0x30738 R_AARCH64_RELATIVE - 0x4
@@ -223,9 +223,9 @@
// UNPACKED64-NEXT: 0x30748 R_AARCH64_RELATIVE - 0x6
// UNPACKED64-NEXT: 0x30750 R_AARCH64_RELATIVE - 0x7
// UNPACKED64-NEXT: 0x30758 R_AARCH64_RELATIVE - 0x8
-// UNPACKED64-NEXT: 0x30760 R_AARCH64_RELATIVE - 0x9
+// UNPACKED64-NEXT: 0x30760 R_AARCH64_RELATIVE - 0x30699
-// UNPACKED64-NEXT: 0x30769 R_AARCH64_RELATIVE - 0xA
+// UNPACKED64-NEXT: 0x30769 R_AARCH64_RELATIVE - 0x3069A
// UNPACKED64-NEXT: 0x306D0 R_AARCH64_ABS64 bar2 0x1
// UNPACKED64-NEXT: 0x30718 R_AARCH64_ABS64 bar2 0x0
@@ -247,7 +247,7 @@
// ANDROID64: (DEBUG) 0x0
// ANDROID64-NEXT: (ANDROID_RELA) 0x[[#ANDROID]]
-// ANDROID64-NEXT: (ANDROID_RELASZ) 122 (bytes)
+// ANDROID64-NEXT: (ANDROID_RELASZ) 136 (bytes)
// ANDROID64-NEXT: (RELAENT) 24 (bytes)
// ANDROID64-HEADERS: 0x0000000060000011 ANDROID_RELA [[ADDR]]
@@ -255,39 +255,39 @@
// ANDROID64: Relocation section '.rela.dyn' at offset {{.*}} contains 33 entries:
// ANDROID64-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
-// ANDROID64-NEXT: 00000000000303e8 0000000000000403 R_AARCH64_RELATIVE 0
-// ANDROID64-NEXT: 00000000000303f0 0000000000000403 R_AARCH64_RELATIVE 1
-// ANDROID64-NEXT: 00000000000303f8 0000000000000403 R_AARCH64_RELATIVE 2
-// ANDROID64-NEXT: 0000000000030400 0000000000000403 R_AARCH64_RELATIVE ffffffffffffffff
-// ANDROID64-NEXT: 0000000000030408 0000000000000403 R_AARCH64_RELATIVE 80000000
-// ANDROID64-NEXT: 0000000000030410 0000000000000403 R_AARCH64_RELATIVE 6
-// ANDROID64-NEXT: 0000000000030418 0000000000000403 R_AARCH64_RELATIVE 7
-// ANDROID64-NEXT: 0000000000030420 0000000000000403 R_AARCH64_RELATIVE 8
-// ANDROID64-NEXT: 0000000000030478 0000000000000403 R_AARCH64_RELATIVE 1
-// ANDROID64-NEXT: 0000000000030480 0000000000000403 R_AARCH64_RELATIVE 2
-// ANDROID64-NEXT: 0000000000030488 0000000000000403 R_AARCH64_RELATIVE 3
-// ANDROID64-NEXT: 0000000000030490 0000000000000403 R_AARCH64_RELATIVE 4
-// ANDROID64-NEXT: 0000000000030498 0000000000000403 R_AARCH64_RELATIVE 5
-// ANDROID64-NEXT: 00000000000304a0 0000000000000403 R_AARCH64_RELATIVE 6
-// ANDROID64-NEXT: 00000000000304a8 0000000000000403 R_AARCH64_RELATIVE 7
-// ANDROID64-NEXT: 00000000000304b0 0000000000000403 R_AARCH64_RELATIVE 8
-// ANDROID64-NEXT: 00000000000304b8 0000000000000403 R_AARCH64_RELATIVE 9
-// ANDROID64-NEXT: 0000000000030430 0000000000000403 R_AARCH64_RELATIVE 1
-// ANDROID64-NEXT: 0000000000030438 0000000000000403 R_AARCH64_RELATIVE 2
-// ANDROID64-NEXT: 0000000000030440 0000000000000403 R_AARCH64_RELATIVE 3
-// ANDROID64-NEXT: 0000000000030448 0000000000000403 R_AARCH64_RELATIVE 4
-// ANDROID64-NEXT: 0000000000030450 0000000000000403 R_AARCH64_RELATIVE 5
-// ANDROID64-NEXT: 0000000000030458 0000000000000403 R_AARCH64_RELATIVE 6
-// ANDROID64-NEXT: 0000000000030460 0000000000000403 R_AARCH64_RELATIVE 7
-// ANDROID64-NEXT: 00000000000304c1 0000000000000403 R_AARCH64_RELATIVE a
-// ANDROID64-NEXT: 0000000000030470 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0
-// ANDROID64-NEXT: 00000000000304c9 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0
+// ANDROID64-NEXT: 00000000000303f0 0000000000000403 R_AARCH64_RELATIVE 303f0
+// ANDROID64-NEXT: 00000000000303f8 0000000000000403 R_AARCH64_RELATIVE 303f1
+// ANDROID64-NEXT: 0000000000030400 0000000000000403 R_AARCH64_RELATIVE 2
+// ANDROID64-NEXT: 0000000000030408 0000000000000403 R_AARCH64_RELATIVE ffffffffffffffff
+// ANDROID64-NEXT: 0000000000030410 0000000000000403 R_AARCH64_RELATIVE 80000000
+// ANDROID64-NEXT: 0000000000030418 0000000000000403 R_AARCH64_RELATIVE 6
+// ANDROID64-NEXT: 0000000000030420 0000000000000403 R_AARCH64_RELATIVE 7
+// ANDROID64-NEXT: 0000000000030428 0000000000000403 R_AARCH64_RELATIVE 303f8
+// ANDROID64-NEXT: 0000000000030480 0000000000000403 R_AARCH64_RELATIVE 303f1
+// ANDROID64-NEXT: 0000000000030488 0000000000000403 R_AARCH64_RELATIVE 2
+// ANDROID64-NEXT: 0000000000030490 0000000000000403 R_AARCH64_RELATIVE 3
+// ANDROID64-NEXT: 0000000000030498 0000000000000403 R_AARCH64_RELATIVE 4
+// ANDROID64-NEXT: 00000000000304a0 0000000000000403 R_AARCH64_RELATIVE 5
+// ANDROID64-NEXT: 00000000000304a8 0000000000000403 R_AARCH64_RELATIVE 6
+// ANDROID64-NEXT: 00000000000304b0 0000000000000403 R_AARCH64_RELATIVE 7
+// ANDROID64-NEXT: 00000000000304b8 0000000000000403 R_AARCH64_RELATIVE 8
+// ANDROID64-NEXT: 00000000000304c0 0000000000000403 R_AARCH64_RELATIVE 303f9
+// ANDROID64-NEXT: 0000000000030438 0000000000000403 R_AARCH64_RELATIVE 303f1
+// ANDROID64-NEXT: 0000000000030440 0000000000000403 R_AARCH64_RELATIVE 2
+// ANDROID64-NEXT: 0000000000030448 0000000000000403 R_AARCH64_RELATIVE 3
+// ANDROID64-NEXT: 0000000000030450 0000000000000403 R_AARCH64_RELATIVE 4
+// ANDROID64-NEXT: 0000000000030458 0000000000000403 R_AARCH64_RELATIVE 5
+// ANDROID64-NEXT: 0000000000030460 0000000000000403 R_AARCH64_RELATIVE 6
+// ANDROID64-NEXT: 0000000000030468 0000000000000403 R_AARCH64_RELATIVE 303f7
+// ANDROID64-NEXT: 00000000000304c9 0000000000000403 R_AARCH64_RELATIVE 303fa
+// ANDROID64-NEXT: 0000000000030478 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0
// ANDROID64-NEXT: 00000000000304d1 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0
-// ANDROID64-NEXT: 00000000000304e9 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0
-// ANDROID64-NEXT: 0000000000030428 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1
-// ANDROID64-NEXT: 0000000000030468 0000000200000101 R_AARCH64_ABS64 0000000000000000 zed2 + 0
-// ANDROID64-NEXT: 00000000000304d9 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1
+// ANDROID64-NEXT: 00000000000304d9 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0
+// ANDROID64-NEXT: 00000000000304f1 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0
+// ANDROID64-NEXT: 0000000000030430 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1
+// ANDROID64-NEXT: 0000000000030470 0000000200000101 R_AARCH64_ABS64 0000000000000000 zed2 + 0
// ANDROID64-NEXT: 00000000000304e1 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1
+// ANDROID64-NEXT: 00000000000304e9 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1
// ANDROID64-EMPTY:
// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a64.o %t.a64.so -o %t4.a64
@@ -317,7 +317,7 @@
/// Any relative relocations with odd offset stay in SHT_RELA.
// RELR64: Relocation section '.rela.dyn' at offset {{.*}} contains 9 entries:
// RELR64-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
-// RELR64-NEXT: 0000000000030569 0000000000000403 R_AARCH64_RELATIVE a
+// RELR64-NEXT: 0000000000030569 0000000000000403 R_AARCH64_RELATIVE 3049a
// RELR64-NEXT: 00000000000304d0 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1
// RELR64-NEXT: 0000000000030518 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0
// RELR64-NEXT: 0000000000030571 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0
@@ -355,33 +355,33 @@
// RELR64-NEXT: 0000000000030560 0000000000000403 R_AARCH64_RELATIVE
// RELR64-EMPTY:
// RELR64-NEXT: Hex dump of section '.data':
-// RELR64-NEXT: 0x00030490 00000000 00000000 01000000 00000000 .
+// RELR64-NEXT: 0x00030490 90040300 00000000 91040300 00000000 .
// RELR64-NEXT: 0x000304a0 02000000 00000000 ffffffff ffffffff .
// RELR64-NEXT: 0x000304b0 00000080 00000000 06000000 00000000 .
.data
.balign 2
-.dc.a __ehdr_start
-.dc.a __ehdr_start + 1
+.dc.a .data
+.dc.a .data + 1
.dc.a __ehdr_start + 2
.dc.a __ehdr_start - 1
.dc.a __ehdr_start + 0x80000000
.dc.a __ehdr_start + 6
.dc.a __ehdr_start + 7
-.dc.a __ehdr_start + 8
+.dc.a .data + 8
.dc.a bar2 + 1
-.dc.a __ehdr_start + 1
+.dc.a .data + 1
.dc.a __ehdr_start + 2
.dc.a __ehdr_start + 3
.dc.a __ehdr_start + 4
.dc.a __ehdr_start + 5
.dc.a __ehdr_start + 6
-.dc.a __ehdr_start + 7
+.dc.a .data + 7
.dc.a zed2
.dc.a bar2
-.dc.a __ehdr_start + 1
+.dc.a .data + 1
.dc.a __ehdr_start + 2
.dc.a __ehdr_start + 3
.dc.a __ehdr_start + 4
@@ -389,9 +389,9 @@
.dc.a __ehdr_start + 6
.dc.a __ehdr_start + 7
.dc.a __ehdr_start + 8
-.dc.a __ehdr_start + 9
+.dc.a .data + 9
.byte 00
-.dc.a __ehdr_start + 10
+.dc.a .data + 10
.dc.a bar2
.dc.a bar2
.dc.a bar2 + 1
--
GitLab
From 3c37f926a153d38852d593c4a7f9062e72ee4b2f Mon Sep 17 00:00:00 2001
From: Craig Topper
Date: Fri, 5 Apr 2024 11:19:33 -0700
Subject: [PATCH 021/695] [RISCV] Fix comment in compress-opt-branch.ll to
match description. NFC
Test description says constant does not fit in 12 bits, but the constant
used was -2048 which does fit in 12 bits. Update to -2049.
Also remove uses of -NOT in favor of positive checks. One of the -NOT
should have been using RESBROPT instead of "c.beqz" so that it would
check for the absense of the correct instruction based on the sed
replacement on the RUN line.
---
.../test/CodeGen/RISCV/compress-opt-branch.ll | 20 ++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/llvm/test/CodeGen/RISCV/compress-opt-branch.ll b/llvm/test/CodeGen/RISCV/compress-opt-branch.ll
index b6ae6419c4cd..354f180b45a9 100644
--- a/llvm/test/CodeGen/RISCV/compress-opt-branch.ll
+++ b/llvm/test/CodeGen/RISCV/compress-opt-branch.ll
@@ -270,9 +270,14 @@ if.end:
; constant is big and do not fit in 12 bit (imm), fit in i32
; RV32IFDC-LABEL: :
-; RV32IFDC-NOT: RESBROPT
+; RV32IFDC: c.li [[REG:.*]], 0x1
+; RV32IFDC: c.slli [[REG]], 0xb
+; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
; --- no compress extension
-; nothing to check.
+; RV32IFD-LABEL: :
+; RV32IFD: addi [[REG1:.*]], zero, 0x1
+; RV32IFD: slli [[REG2:.*]], [[REG1]], 0xb
+; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG2]], [[PLACE:.*]]
define i32 @f_big_ledge_pos(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, 2048
br i1 %cmp, label %if.then, label %if.else
@@ -290,11 +295,16 @@ if.end:
; constant is big and do not fit in 12 bit (imm), fit in i32
; RV32IFDC-LABEL: :
-; RV32IFDC-NOT: c.beqz
+; RV32IFDC: c.lui [[REG1:.*]], 0xfffff
+; RV32IFDC: addi [[REG2:.*]], [[REG1]], 0x7ff
+; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
; --- no compress extension
-; nothing to check.
+; RV32IFD-LABEL: :
+; RV32IFD: lui [[REG1:.*]], 0xfffff
+; RV32IFD: addi [[REG2:.*]], [[REG1]], 0x7ff
+; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG2]], [[PLACE:.*]]
define i32 @f_big_ledge_neg(i32 %in0) minsize {
- %cmp = icmp CMPCOND i32 %in0, -2048
+ %cmp = icmp CMPCOND i32 %in0, -2049
br i1 %cmp, label %if.then, label %if.else
if.then:
%call = shl i32 %in0, 1
--
GitLab
From a834436099279e458112b8be653f4a597269747b Mon Sep 17 00:00:00 2001
From: Hristo Hristov
Date: Fri, 5 Apr 2024 22:04:07 +0300
Subject: [PATCH 022/695] [libc++] P2872R3: Remove ``wstring_convert`` From
C++26 (#87100)
Implements: https://wg21.link/P2872R3
---
libcxx/docs/ReleaseNotes/19.rst | 4 ++++
libcxx/docs/Status/Cxx2cPapers.csv | 2 +-
libcxx/docs/UsingLibcxx.rst | 8 ++++++--
libcxx/include/locale | 8 ++++++--
libcxx/modules/std/locale.inc | 5 +++++
.../fstreams/fstream.cons/wchar_pointer.pass.cpp | 2 +-
.../fstreams/fstream.members/open_wchar_pointer.pass.cpp | 2 +-
.../fstreams/ofstream.cons/wchar_pointer.pass.cpp | 2 +-
.../fstreams/ofstream.members/open_wchar_pointer.pass.cpp | 2 +-
.../conversions/conversions.string/ctor_move.pass.cpp | 2 +-
.../conversions/conversions.buffer/ctor.pass.cpp | 2 +-
.../conversions/conversions.buffer/overflow.pass.cpp | 2 +-
.../conversions/conversions.buffer/pbackfail.pass.cpp | 2 +-
.../conversions/conversions.buffer/rdbuf.pass.cpp | 2 +-
.../conversions/conversions.buffer/seekoff.pass.cpp | 2 +-
.../conversions/conversions.buffer/state.pass.cpp | 2 +-
.../conversions/conversions.buffer/test.pass.cpp | 2 +-
.../conversions/conversions.buffer/underflow.pass.cpp | 2 +-
.../conversions/conversions.string/converted.pass.cpp | 2 +-
.../conversions/conversions.string/ctor_codecvt.pass.cpp | 2 +-
.../conversions.string/ctor_codecvt_state.pass.cpp | 2 +-
.../conversions/conversions.string/ctor_copy.pass.cpp | 2 +-
.../conversions.string/ctor_err_string.pass.cpp | 2 +-
.../conversions/conversions.string/depr.verify.cpp | 2 ++
.../conversions/conversions.string/from_bytes.pass.cpp | 2 +-
.../conversions/conversions.string/state.pass.cpp | 2 +-
.../conversions/conversions.string/to_bytes.pass.cpp | 2 +-
.../conversions/conversions.string/types.pass.cpp | 2 +-
28 files changed, 46 insertions(+), 27 deletions(-)
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 2da9df54a531..abf1570737df 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -43,6 +43,7 @@ Implemented Papers
- P2819R2 - Add ``tuple`` protocol to ``complex``
- P2495R3 - Interfacing ``stringstream``\s with ``string_view``
- P2867R2 - Remove Deprecated ``strstream``\s From C++26
+- P2872R3 - Remove ``wstring_convert`` From C++26
- P2302R4 - ``std::ranges::contains``
- P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``
@@ -57,6 +58,9 @@ Improvements and New Features
- The ``_LIBCPP_ENABLE_CXX26_REMOVED_STRSTREAM`` macro has been added to make the declarations in ```` available.
+- The ``_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT`` macro has been added to make the declarations in ````
+ available.
+
Deprecations and Removals
-------------------------
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index a34dad581680..af270150fda0 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -49,7 +49,7 @@
"`P2875R4 `__","LWG","Undeprecate ``polymorphic_allocator::destroy`` for C++26","Tokyo March 2024","|Complete|","15.0",""
"`P2867R2 `__","LWG","Remove Deprecated ``strstreams`` From C++26","Tokyo March 2024","|Complete|","19.0",""
"`P2869R4 `__","LWG","Remove Deprecated ``shared_ptr`` Atomic Access APIs from C++26","Tokyo March 2024","","",""
-"`P2872R3 `__","LWG","Remove ``wstring_convert`` From C++26","Tokyo March 2024","","",""
+"`P2872R3 `__","LWG","Remove ``wstring_convert`` From C++26","Tokyo March 2024","|Complete|","19.0",""
"`P3107R5 `__","LWG","Permit an efficient implementation of ``std::print``","Tokyo March 2024","","","|format| |DR|"
"`P3142R0 `__","LWG","Printing Blank Lines with ``println``","Tokyo March 2024","","","|format|"
"`P2845R8 `__","LWG","Formatting of ``std::filesystem::path``","Tokyo March 2024","","","|format|"
diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst
index 8a1c747a2541..bc7817d14d04 100644
--- a/libcxx/docs/UsingLibcxx.rst
+++ b/libcxx/docs/UsingLibcxx.rst
@@ -234,7 +234,7 @@ C++17 Specific Configuration Macros
C++20 Specific Configuration Macros
-----------------------------------
-**_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUE**
+**_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUE**:
This macro is used to re-enable the function
``std::shared_ptr<...>::unique()``.
@@ -267,7 +267,7 @@ C++26 Specific Configuration Macros
**_LIBCPP_ENABLE_CXX26_REMOVED_CODECVT**:
This macro is used to re-enable all named declarations in ````.
-**_LIBCPP_ENABLE_CXX26_REMOVED_STRING_RESERVE**
+**_LIBCPP_ENABLE_CXX26_REMOVED_STRING_RESERVE**:
This macro is used to re-enable the function
``std::basic_string<...>::reserve()``.
@@ -277,6 +277,10 @@ C++26 Specific Configuration Macros
**_LIBCPP_ENABLE_CXX26_REMOVED_STRSTREAM**:
This macro is used to re-enable all named declarations in ````.
+**_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT**:
+ This macro is used to re-enable the ``wstring_convert`` and ``wbuffer_convert``
+ in ````.
+
Libc++ Extensions
=================
diff --git a/libcxx/include/locale b/libcxx/include/locale
index e3c63e3abe13..748b276a8525 100644
--- a/libcxx/include/locale
+++ b/libcxx/include/locale
@@ -84,7 +84,7 @@ template charT tolower(charT c, const locale& loc);
template,
class Byte_alloc = allocator>
-class wstring_convert
+class wstring_convert // Removed in C++26
{
public:
typedef basic_string