14 changes: 0 additions & 14 deletions libcxx/test/libcxx/vendor/clang-cl/experimental-lib-exports.sh.cpp

This file was deleted.

4 changes: 3 additions & 1 deletion libcxx/test/libcxx/vendor/clang-cl/static-lib-exports.sh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

// REQUIRES: msvc

// This file checks that the built static library doesn't contain dllexport
// This file checks that the built static libraries don't contain dllexport
// directives in clang-cl builds.

// RUN: llvm-readobj --coff-directives "%{lib}/libc++.lib" | not grep -i "export:" > /dev/null

// RUN: llvm-readobj --coff-directives "%{lib}/libc++experimental.lib" | not grep -i "export:" > /dev/null
14 changes: 0 additions & 14 deletions libcxx/test/libcxx/vendor/mingw/experimental-lib-exports.sh.cpp

This file was deleted.

4 changes: 3 additions & 1 deletion libcxx/test/libcxx/vendor/mingw/static-lib-exports.sh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

// REQUIRES: target={{.+}}-windows-gnu

// This file checks that the built static library doesn't contain dllexport
// This file checks that the built static libraries don't contain dllexport
// directives in MinGW builds.

// RUN: llvm-readobj --coff-directives "%{lib}/libc++.a" | not grep -i "export:" > /dev/null

// RUN: llvm-readobj --coff-directives "%{lib}/libc++experimental.a" | not grep -i "export:" > /dev/null
Original file line number Diff line number Diff line change
Expand Up @@ -181,16 +181,16 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++20"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down Expand Up @@ -248,16 +248,16 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++2b"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++2b"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,16 +254,16 @@
# error "__cpp_lib_not_fn should have the value 201603L in c++20"
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++20"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down Expand Up @@ -364,16 +364,16 @@
# error "__cpp_lib_not_fn should have the value 201603L in c++2b"
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++2b"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++2b"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,16 @@
# error "__cpp_lib_null_iterators should have the value 201304L in c++20"
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++20"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down Expand Up @@ -231,16 +231,16 @@
# error "__cpp_lib_null_iterators should have the value 201304L in c++2b"
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++2b"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++2b"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,16 +346,16 @@
# error "__cpp_lib_out_ptr should not be defined before c++2b"
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++20"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down Expand Up @@ -485,16 +485,16 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++2b"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++2b"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,16 @@

#elif TEST_STD_VER == 20

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++20"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand All @@ -144,16 +144,16 @@

#elif TEST_STD_VER > 20

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++2b"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++2b"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3194,16 +3194,16 @@
# error "__cpp_lib_quoted_string_io should have the value 201304L in c++20"
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++20"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down Expand Up @@ -4461,16 +4461,16 @@
# error "__cpp_lib_quoted_string_io should have the value 201304L in c++2b"
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++2b"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++2b"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_ranges should not be defined when !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) is not defined!"
# endif
# endif

Expand Down
2 changes: 1 addition & 1 deletion libcxx/test/support/test.support/test_proxy.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ constexpr bool test() {
return true;
}

int main(int, const char**) {
int main(int, char**) {
test();
static_assert(test());

Expand Down
3 changes: 2 additions & 1 deletion libcxx/utils/generate_feature_test_macro_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,8 @@ def add_version_header(tc):
"name": "__cpp_lib_ranges",
"values": { "c++20": 201811 },
"headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
"unimplemented": True,
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)",
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)",
}, {
"name": "__cpp_lib_ranges_chunk",
"values": { "c++2b": 202202 },
Expand Down
17 changes: 16 additions & 1 deletion lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,14 @@ void LinkerDriver::parseDirectives(InputFile *file) {
for (StringRef inc : directives.includes)
addUndefined(inc);

// Handle /exclude-symbols: in bulk.
for (StringRef e : directives.excludes) {
SmallVector<StringRef, 2> vec;
e.split(vec, ',');
for (StringRef sym : vec)
excludedSymbols.insert(mangle(sym));
}

// https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-160
for (auto *arg : directives.args) {
switch (arg->getOption().getID()) {
Expand Down Expand Up @@ -1306,12 +1314,19 @@ void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
return;
}

AutoExporter exporter;
AutoExporter exporter(excludedSymbols);

for (auto *arg : args.filtered(OPT_wholearchive_file))
if (Optional<StringRef> path = doFindFile(arg->getValue()))
exporter.addWholeArchive(*path);

for (auto *arg : args.filtered(OPT_exclude_symbols)) {
SmallVector<StringRef, 2> vec;
StringRef(arg->getValue()).split(vec, ',');
for (StringRef sym : vec)
exporter.addExcludedSymbol(mangle(sym));
}

ctx.symtab.forEachSymbol([&](Symbol *s) {
auto *def = dyn_cast<Defined>(s);
if (!exporter.shouldExport(ctx, def))
Expand Down
4 changes: 3 additions & 1 deletion lld/COFF/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ extern COFFOptTable optTable;
struct ParsedDirectives {
std::vector<StringRef> exports;
std::vector<StringRef> includes;
std::vector<StringRef> excludes;
llvm::opt::InputArgList args;
};

Expand Down Expand Up @@ -159,7 +160,8 @@ class LinkerDriver {
std::vector<StringRef> filePaths;
std::vector<MemoryBufferRef> resources;

llvm::StringSet<> directivesExports;
llvm::DenseSet<StringRef> directivesExports;
llvm::DenseSet<StringRef> excludedSymbols;

COFFLinkerContext &ctx;

Expand Down
3 changes: 3 additions & 0 deletions lld/COFF/DriverUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,9 @@ ParsedDirectives ArgParser::parseDirectives(StringRef s) {
else if (tok.startswith_insensitive("/include:") ||
tok.startswith_insensitive("-include:"))
result.includes.push_back(tok.substr(strlen("/include:")));
else if (tok.startswith_insensitive("/exclude-symbols:") ||
tok.startswith_insensitive("-exclude-symbols:"))
result.excludes.push_back(tok.substr(strlen("/exclude-symbols:")));
else {
// Copy substrings that are not valid C strings. The tokenizer may have
// already copied quoted arguments for us, so those do not need to be
Expand Down
10 changes: 8 additions & 2 deletions lld/COFF/MinGW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ using namespace llvm::COFF;
using namespace lld;
using namespace lld::coff;

AutoExporter::AutoExporter() {
AutoExporter::AutoExporter(
const llvm::DenseSet<StringRef> &manualExcludeSymbols)
: manualExcludeSymbols(manualExcludeSymbols) {
excludeLibs = {
"libgcc",
"libgcc_s",
Expand Down Expand Up @@ -122,6 +124,10 @@ void AutoExporter::addWholeArchive(StringRef path) {
excludeLibs.erase(libName);
}

void AutoExporter::addExcludedSymbol(StringRef symbol) {
excludeSymbols.insert(symbol);
}

bool AutoExporter::shouldExport(const COFFLinkerContext &ctx,
Defined *sym) const {
if (!sym || !sym->getChunk())
Expand All @@ -131,7 +137,7 @@ bool AutoExporter::shouldExport(const COFFLinkerContext &ctx,
// disallow import symbols.
if (!isa<DefinedRegular>(sym) && !isa<DefinedCommon>(sym))
return false;
if (excludeSymbols.count(sym->getName()))
if (excludeSymbols.count(sym->getName()) || manualExcludeSymbols.count(sym->getName()))
return false;

for (StringRef prefix : excludeSymbolPrefixes.keys())
Expand Down
6 changes: 5 additions & 1 deletion lld/COFF/MinGW.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "Symbols.h"
#include "lld/Common/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Option/ArgList.h"
#include <vector>
Expand All @@ -25,16 +26,19 @@ class COFFLinkerContext;
// symbols for MinGW.
class AutoExporter {
public:
AutoExporter();
AutoExporter(const llvm::DenseSet<StringRef> &manualExcludeSymbols);

void addWholeArchive(StringRef path);
void addExcludedSymbol(StringRef symbol);

llvm::StringSet<> excludeSymbols;
llvm::StringSet<> excludeSymbolPrefixes;
llvm::StringSet<> excludeSymbolSuffixes;
llvm::StringSet<> excludeLibs;
llvm::StringSet<> excludeObjects;

const llvm::DenseSet<StringRef> &manualExcludeSymbols;

bool shouldExport(const COFFLinkerContext &ctx, Defined *sym) const;
};

Expand Down
2 changes: 2 additions & 0 deletions lld/COFF/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ def diasdkdir : P<"diasdkdir", "Set the location of the DIA SDK">;
def entry : P<"entry", "Name of entry point symbol">;
def errorlimit : P<"errorlimit",
"Maximum number of errors to emit before stopping (0 = no limit)">;
def exclude_symbols : P<"exclude-symbols", "Exclude symbols from automatic export">,
MetaVarName<"<symbol[,symbol,...]>">;
def export : P<"export", "Export a function">;
// No help text because /failifmismatch is not intended to be used by the user.
def failifmismatch : P<"failifmismatch", "">;
Expand Down
2 changes: 2 additions & 0 deletions lld/MinGW/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,8 @@ bool mingw::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
add("-delayload:" + StringRef(a->getValue()));
for (auto *a : args.filtered(OPT_wrap))
add("-wrap:" + StringRef(a->getValue()));
for (auto *a : args.filtered(OPT_exclude_symbols))
add("-exclude-symbols:" + StringRef(a->getValue()));

std::vector<StringRef> searchPaths;
for (auto *a : args.filtered(OPT_L)) {
Expand Down
2 changes: 2 additions & 0 deletions lld/MinGW/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ def enable_stdcall_fixup: F<"enable-stdcall-fixup">,
defm entry: Eq<"entry", "Name of entry point symbol">, MetaVarName<"<entry>">;
def exclude_all_symbols: F<"exclude-all-symbols">,
HelpText<"Don't automatically export any symbols">;
defm exclude_symbols: Eq<"exclude-symbols",
"Exclude symbols from automatic export">, MetaVarName<"<symbol[,symbol,...]>">;
def export_all_symbols: F<"export-all-symbols">,
HelpText<"Export all symbols even if a def file or dllexport attributes are used">;
defm fatal_warnings: B<"fatal-warnings",
Expand Down
5 changes: 5 additions & 0 deletions lld/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ MinGW Improvements

* The ``--disable-reloc-section`` option is now supported.
(`D127478 <https://reviews.llvm.org/D127478>`_)
* The ``--exclude-symbols`` option is now supported.
(`D130118 <https://reviews.llvm.org/D130118>`_)

* Support for an entirely new object file directive, ``-exclude-symbols:``,
has been implemented. (`D130120 <https://reviews.llvm.org/D130120>`_)

MachO Improvements
------------------
Expand Down
24 changes: 24 additions & 0 deletions lld/test/COFF/exclude-symbols-embedded.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=i686-win32-gnu %s -o %t.o

// RUN: lld-link -lldmingw -dll -out:%t.dll %t.o -noentry
// RUN: llvm-readobj --coff-exports %t.dll | FileCheck --implicit-check-not=Name: %s

// CHECK: Name:
// CHECK: Name: sym1

.global _sym1
_sym1:
ret

.global _sym2
_sym2:
ret

.global _sym3
_sym3:
ret

.section .drectve,"yn"
.ascii " -exclude-symbols:sym2,unknownsym"
.ascii " -exclude-symbols:unkonwnsym,sym3"
20 changes: 20 additions & 0 deletions lld/test/COFF/exclude-symbols.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=i686-win32-gnu %s -o %t.o

// RUN: lld-link -lldmingw -dll -out:%t.dll %t.o -noentry -exclude-symbols:sym2,unknownsym -exclude-symbols:unknownsym,sym3
// RUN: llvm-readobj --coff-exports %t.dll | FileCheck --implicit-check-not=Name: %s

// CHECK: Name:
// CHECK: Name: sym1

.global _sym1
_sym1:
ret

.global _sym2
_sym2:
ret

.global _sym3
_sym3:
ret
4 changes: 4 additions & 0 deletions lld/test/MinGW/driver.test
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ RUN: ld.lld -### -m i386pep foo.o -wrap foo1 --wrap foo2 2>&1 | FileCheck -check
RUN: ld.lld -### -m i386pep foo.o -wrap=foo1 --wrap=foo2 2>&1 | FileCheck -check-prefix WRAP %s
WRAP: -wrap:foo1 -wrap:foo2

RUN: ld.lld -### -m i386pep foo.o -exclude-symbols sym1,sym2 --exclude-symbols sym3 2>&1 | FileCheck -check-prefix EXCLUDE_SYMBOLS %s
RUN: ld.lld -### -m i386pep foo.o -exclude-symbols=sym1,sym2 --exclude-symbols=sym3 2>&1 | FileCheck -check-prefix EXCLUDE_SYMBOLS %s
EXCLUDE_SYMBOLS: -exclude-symbols:sym1,sym2 -exclude-symbols:sym3

RUN: ld.lld -### -m i386pep foo.o 2>&1 | FileCheck -check-prefix DEMANGLE %s
RUN: ld.lld -### -m i386pep foo.o -demangle 2>&1 | FileCheck -check-prefix DEMANGLE %s
RUN: ld.lld -### -m i386pep foo.o --demangle 2>&1 | FileCheck -check-prefix DEMANGLE %s
Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/Analysis/TargetTransformInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,10 @@ class TargetTransformInfo {
/// to a stack reload.
unsigned getGISelRematGlobalCost() const;

/// \returns the lower bound of a trip count to decide on vectorization
/// while tail-folding.
unsigned getMinTripCountTailFoldingThreshold() const;

/// \returns True if the target supports scalable vectors.
bool supportsScalableVectors() const;

Expand Down Expand Up @@ -1830,6 +1834,7 @@ class TargetTransformInfo::Concept {
ReductionFlags) const = 0;
virtual bool shouldExpandReduction(const IntrinsicInst *II) const = 0;
virtual unsigned getGISelRematGlobalCost() const = 0;
virtual unsigned getMinTripCountTailFoldingThreshold() const = 0;
virtual bool enableScalableVectorization() const = 0;
virtual bool supportsScalableVectors() const = 0;
virtual bool hasActiveVectorLength(unsigned Opcode, Type *DataType,
Expand Down Expand Up @@ -2453,6 +2458,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
return Impl.getGISelRematGlobalCost();
}

unsigned getMinTripCountTailFoldingThreshold() const override {
return Impl.getMinTripCountTailFoldingThreshold();
}

bool supportsScalableVectors() const override {
return Impl.supportsScalableVectors();
}
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,8 @@ class TargetTransformInfoImplBase {

unsigned getGISelRematGlobalCost() const { return 1; }

unsigned getMinTripCountTailFoldingThreshold() const { return 0; }

bool supportsScalableVectors() const { return false; }

bool enableScalableVectorization() const { return false; }
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Analysis/TargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,10 @@ unsigned TargetTransformInfo::getGISelRematGlobalCost() const {
return TTIImpl->getGISelRematGlobalCost();
}

unsigned TargetTransformInfo::getMinTripCountTailFoldingThreshold() const {
return TTIImpl->getMinTripCountTailFoldingThreshold();
}

bool TargetTransformInfo::supportsScalableVectors() const {
return TTIImpl->supportsScalableVectors();
}
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,10 @@ class AArch64TTIImpl : public BasicTTIImplBase<AArch64TTIImpl> {
return 2;
}

unsigned getMinTripCountTailFoldingThreshold() const {
return ST->hasSVE() ? 5 : 0;
}

PredicationStyle emitGetActiveLaneMask() const {
if (ST->hasSVE())
return PredicationStyle::DataAndControlFlow;
Expand Down
13 changes: 11 additions & 2 deletions llvm/lib/Transforms/IPO/AttributorAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9899,6 +9899,15 @@ struct AAPotentialValuesImpl : AAPotentialValues {
struct ItemInfo {
AA::ValueAndContext I;
AA::ValueScope S;

bool operator==(const ItemInfo &II) const {
return II.I == I && II.S == S;
};
bool operator<(const ItemInfo &II) const {
if (I == II.I)
return S < II.S;
return I < II.I;
};
};

bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
Expand Down Expand Up @@ -10271,7 +10280,7 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl {
SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;

Value *InitialV = &getAssociatedValue();
SmallSet<AA::ValueAndContext, 16> Visited;
SmallSet<ItemInfo, 16> Visited;
SmallVector<ItemInfo, 16> Worklist;
Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});

Expand All @@ -10285,7 +10294,7 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl {

// Check if we should process the current value. To prevent endless
// recursion keep a record of the values we followed!
if (!Visited.insert(II.I).second)
if (!Visited.insert(II).second)
continue;

// Make sure we limit the compile time for complex expressions.
Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,15 @@ static bool shouldConvertToRelLookupTable(Module &M, GlobalVariable &GV) {
return false;

ConstantArray *Array = dyn_cast<ConstantArray>(GV.getInitializer());
// If values are not pointers, do not generate a relative lookup table.
if (!Array || !Array->getType()->getElementType()->isPointerTy())
if (!Array)
return false;

// If values are not 64-bit pointers, do not generate a relative lookup table.
const DataLayout &DL = M.getDataLayout();
Type *ElemType = Array->getType()->getElementType();
if (!ElemType->isPointerTy() || DL.getPointerTypeSizeInBits(ElemType) != 64)
return false;

for (const Use &Op : Array->operands()) {
Constant *ConstOp = cast<Constant>(&Op);
GlobalValue *GVOp;
Expand Down
15 changes: 13 additions & 2 deletions llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10109,8 +10109,19 @@ bool LoopVectorizePass::processLoop(Loop *L) {
if (Hints.getForce() == LoopVectorizeHints::FK_Enabled)
LLVM_DEBUG(dbgs() << " But vectorizing was explicitly forced.\n");
else {
LLVM_DEBUG(dbgs() << "\n");
SEL = CM_ScalarEpilogueNotAllowedLowTripLoop;
if (*ExpectedTC > TTI->getMinTripCountTailFoldingThreshold()) {
LLVM_DEBUG(dbgs() << "\n");
SEL = CM_ScalarEpilogueNotAllowedLowTripLoop;
} else {
LLVM_DEBUG(dbgs() << " But the target considers the trip count too "
"small to consider vectorizing.\n");
reportVectorizationFailure(
"The trip count is below the minial threshold value.",
"loop trip count is too low, avoiding vectorization",
"LowTripCount", ORE, L);
Hints.emitRemarkWithHints();
return false;
}
}
}

Expand Down
262 changes: 175 additions & 87 deletions llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll

Large diffs are not rendered by default.

28 changes: 16 additions & 12 deletions llvm/test/Transforms/LoopVectorize/AArch64/sve-low-trip-count.ll
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,22 @@ for.end: ; preds = %for.body

define void @trip5_i8(i8* noalias nocapture noundef %dst, i8* noalias nocapture noundef readonly %src) #0 {
; CHECK-LABEL: @trip5_i8(
; CHECK: vector.body:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
; CHECK: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 16 x i1> [ {{%.*}}, %vector.ph ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], %vector.body ]
; CHECK: {{%.*}} = call <vscale x 16 x i8> @llvm.masked.load.nxv16i8.p0nxv16i8(<vscale x 16 x i8>* {{%.*}}, i32 1, <vscale x 16 x i1> [[ACTIVE_LANE_MASK]], <vscale x 16 x i8> poison)
; CHECK: {{%.*}} = call <vscale x 16 x i8> @llvm.masked.load.nxv16i8.p0nxv16i8(<vscale x 16 x i8>* {{%.*}}, i32 1, <vscale x 16 x i1> [[ACTIVE_LANE_MASK]], <vscale x 16 x i8> poison)
; CHECK: call void @llvm.masked.store.nxv16i8.p0nxv16i8(<vscale x 16 x i8> {{%.*}}, <vscale x 16 x i8>* {{%.*}}, i32 1, <vscale x 16 x i1> [[ACTIVE_LANE_MASK]])
; CHECK: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
; CHECK-NEXT: [[VF:%.*]] = mul i64 [[VSCALE]], 16
; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[VF]]
; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 16 x i1> @llvm.get.active.lane.mask.nxv16i1.i64(i64 [[INDEX_NEXT]], i64 5)
; CHECK-NEXT: [[ACTIVE_LANE_MASK_NOT:%.*]] = xor <vscale x 16 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 16 x i1> insertelement (<vscale x 16 x i1> poison, i1 true, i32 0), <vscale x 16 x i1> poison, <vscale x 16 x i32> zeroinitializer)
; CHECK-NEXT: br i1 true, label %middle.block, label %vector.body
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i64 [[I_08]]
; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[ARRAYIDX]], align 1
; CHECK-NEXT: [[MUL:%.*]] = shl i8 [[TMP0]], 1
; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[DST:%.*]], i64 [[I_08]]
; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[ARRAYIDX1]], align 1
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[MUL]], [[TMP1]]
; CHECK-NEXT: store i8 [[ADD]], i8* [[ARRAYIDX1]], align 1
; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INC]], 5
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
entry:
br label %for.body
Expand Down
23 changes: 23 additions & 0 deletions llvm/test/Transforms/RelLookupTableConverter/X86/gnux32.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=rel-lookup-table-converter -relocation-model=pic -S | FileCheck %s
; REQUIRES: x86-registered-target

target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnux32"

@a = internal constant i32 0, align 4
@b = internal constant i32 0, align 4
@c = internal constant i32 0, align 4

@table = private unnamed_addr constant [3 x ptr] [ptr @a, ptr @b, ptr @c]

define ptr @test(i32 %cond) {
; CHECK-LABEL: @test(
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x ptr], ptr @table, i32 0, i32 [[COND:%.*]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load ptr, ptr [[SWITCH_GEP]], align 8
; CHECK-NEXT: ret ptr [[SWITCH_LOAD]]
;
%switch.gep = getelementptr inbounds [3 x ptr], ptr @table, i32 0, i32 %cond
%switch.load = load ptr, ptr %switch.gep, align 8
ret ptr %switch.load
}