diff --git a/contrib/compiler-rt/include/sanitizer/coverage_interface.h b/contrib/compiler-rt/include/sanitizer/coverage_interface.h index bdb113728b95..637379d47c41 100644 --- a/contrib/compiler-rt/include/sanitizer/coverage_interface.h +++ b/contrib/compiler-rt/include/sanitizer/coverage_interface.h @@ -19,8 +19,6 @@ extern "C" { #endif - // Initialize coverage. - void __sanitizer_cov_init(); // Record and dump coverage info. void __sanitizer_cov_dump(); @@ -28,10 +26,6 @@ extern "C" { // .sancov files. void __sanitizer_dump_coverage(const uintptr_t *pcs, uintptr_t len); - // Open .sancov.packed in the coverage directory and return the file - // descriptor. Returns -1 on failure, or if coverage dumping is disabled. - // This is intended for use by sandboxing code. - intptr_t __sanitizer_maybe_open_cov_file(const char *name); #ifdef __cplusplus } // extern "C" #endif diff --git a/contrib/compiler-rt/lib/asan/asan_activation.cc b/contrib/compiler-rt/lib/asan/asan_activation.cc index 7e4e604dc218..66eba9ce2748 100644 --- a/contrib/compiler-rt/lib/asan/asan_activation.cc +++ b/contrib/compiler-rt/lib/asan/asan_activation.cc @@ -106,7 +106,6 @@ void AsanDeactivate() { // Deactivate the runtime. SetCanPoisonMemory(false); SetMallocContextSize(1); - ReInitializeCoverage(false, nullptr); AllocatorOptions disabled = asan_deactivated_flags.allocator_options; disabled.quarantine_size_mb = 0; @@ -130,8 +129,6 @@ void AsanActivate() { SetCanPoisonMemory(asan_deactivated_flags.poison_heap); SetMallocContextSize(asan_deactivated_flags.malloc_context_size); - ReInitializeCoverage(asan_deactivated_flags.coverage, - asan_deactivated_flags.coverage_dir); ReInitializeAllocator(asan_deactivated_flags.allocator_options); asan_is_deactivated = false; diff --git a/contrib/compiler-rt/lib/asan/asan_interceptors.cc b/contrib/compiler-rt/lib/asan/asan_interceptors.cc index e82a5a4a7e96..4682fba3392c 100644 --- a/contrib/compiler-rt/lib/asan/asan_interceptors.cc +++ b/contrib/compiler-rt/lib/asan/asan_interceptors.cc @@ -242,9 +242,8 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) CheckNoDeepBind(filename, flag); \ } while (false) #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() -#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ - CoverageUpdateMapping() -#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping() +#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) +#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ if (AsanThread *t = GetCurrentThread()) { \ @@ -723,9 +722,7 @@ static void AfterFork() { INTERCEPTOR(int, fork, void) { ENSURE_ASAN_INITED(); BeforeFork(); - if (common_flags()->coverage) CovBeforeFork(); int pid = REAL(fork)(); - if (common_flags()->coverage) CovAfterFork(pid); AfterFork(); return pid; } diff --git a/contrib/compiler-rt/lib/asan/asan_thread.cc b/contrib/compiler-rt/lib/asan/asan_thread.cc index f41ee2df2d96..714496d5c606 100644 --- a/contrib/compiler-rt/lib/asan/asan_thread.cc +++ b/contrib/compiler-rt/lib/asan/asan_thread.cc @@ -166,16 +166,19 @@ void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save, } inline AsanThread::StackBounds AsanThread::GetStackBounds() const { - if (!atomic_load(&stack_switching_, memory_order_acquire)) - return StackBounds{stack_bottom_, stack_top_}; // NOLINT + if (!atomic_load(&stack_switching_, memory_order_acquire)) { + // Make sure the stack bounds are fully initialized. + if (stack_bottom_ >= stack_top_) return {0, 0}; + return {stack_bottom_, stack_top_}; + } char local; const uptr cur_stack = (uptr)&local; // Note: need to check next stack first, because FinishSwitchFiber // may be in process of overwriting stack_top_/bottom_. But in such case // we are already on the next stack. if (cur_stack >= next_stack_bottom_ && cur_stack < next_stack_top_) - return StackBounds{next_stack_bottom_, next_stack_top_}; // NOLINT - return StackBounds{stack_bottom_, stack_top_}; // NOLINT + return {next_stack_bottom_, next_stack_top_}; + return {stack_bottom_, stack_top_}; } uptr AsanThread::stack_top() { @@ -197,6 +200,7 @@ FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() { uptr stack_size = this->stack_size(); if (stack_size == 0) // stack_size is not yet available, don't use FakeStack. return nullptr; + CHECK_LE(stack_size, 0x10000000); uptr old_val = 0; // fake_stack_ has 3 states: // 0 -- not initialized diff --git a/contrib/compiler-rt/lib/lsan/lsan_common.cc b/contrib/compiler-rt/lib/lsan/lsan_common.cc index a5ffc6835f5f..d4f670681fa5 100644 --- a/contrib/compiler-rt/lib/lsan/lsan_common.cc +++ b/contrib/compiler-rt/lib/lsan/lsan_common.cc @@ -408,6 +408,9 @@ static void MarkInvalidPCCb(uptr chunk, void *arg) { // On Linux, handles dynamically allocated TLS blocks by treating all chunks // allocated from ld-linux.so as reachable. +// On Linux, treats all chunks allocated from ld-linux.so as reachable, which +// covers dynamically allocated TLS blocks, internal dynamic loader's loaded +// modules accounting etc. // Dynamic TLS blocks contain the TLS variables of dynamically loaded modules. // They are allocated with a __libc_memalign() call in allocate_and_init() // (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those diff --git a/contrib/compiler-rt/lib/lsan/lsan_common_linux.cc b/contrib/compiler-rt/lib/lsan/lsan_common_linux.cc index c903be42d1e7..2e4095b495fe 100644 --- a/contrib/compiler-rt/lib/lsan/lsan_common_linux.cc +++ b/contrib/compiler-rt/lib/lsan/lsan_common_linux.cc @@ -23,6 +23,10 @@ #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_stackdepot.h" +#if SANITIZER_USE_GETAUXVAL +#include +#endif // SANITIZER_USE_GETAUXVAL + namespace __lsan { static const char kLinkerName[] = "ld"; @@ -30,8 +34,12 @@ static const char kLinkerName[] = "ld"; static char linker_placeholder[sizeof(LoadedModule)] ALIGNED(64); static LoadedModule *linker = nullptr; -static bool IsLinker(const char* full_name) { - return LibraryNameIs(full_name, kLinkerName); +static bool IsLinker(const LoadedModule& module) { +#if SANITIZER_USE_GETAUXVAL + return module.base_address() == getauxval(AT_BASE); +#else + return LibraryNameIs(module.full_name(), kLinkerName); +#endif // SANITIZER_USE_GETAUXVAL } __attribute__((tls_model("initial-exec"))) @@ -49,22 +57,25 @@ void InitializePlatformSpecificModules() { ListOfModules modules; modules.init(); for (LoadedModule &module : modules) { - if (!IsLinker(module.full_name())) continue; + if (!IsLinker(module)) + continue; if (linker == nullptr) { linker = reinterpret_cast(linker_placeholder); *linker = module; module = LoadedModule(); } else { VReport(1, "LeakSanitizer: Multiple modules match \"%s\". " - "TLS will not be handled correctly.\n", kLinkerName); + "TLS and other allocations originating from linker might be " + "falsely reported as leaks.\n", kLinkerName); linker->clear(); linker = nullptr; return; } } if (linker == nullptr) { - VReport(1, "LeakSanitizer: Dynamic linker not found. " - "TLS will not be handled correctly.\n"); + VReport(1, "LeakSanitizer: Dynamic linker not found. TLS and other " + "allocations originating from linker might be falsely reported " + "as leaks.\n"); } } diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_common.h index a1c9c5a57a84..79ee6873bcc4 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -317,15 +317,9 @@ bool AddressSpaceIsUnlimited(); void SetAddressSpaceUnlimited(); void AdjustStackSize(void *attr); void PrepareForSandboxing(__sanitizer_sandbox_arguments *args); -void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args); void SetSandboxingCallback(void (*f)()); -void CoverageUpdateMapping(); -void CovBeforeFork(); -void CovAfterFork(int child_pid); - void InitializeCoverage(bool enabled, const char *coverage_dir); -void ReInitializeCoverage(bool enabled, const char *coverage_dir); void InitTlsSize(); uptr GetTlsSize(); diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc index 70c10e04b653..d4749000d80a 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc @@ -11,7 +11,6 @@ INTERFACE_FUNCTION(__sanitizer_cov_dump) INTERFACE_FUNCTION(__sanitizer_dump_coverage) INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage) -INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file) INTERFACE_WEAK_FUNCTION(__sancov_default_options) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp1) diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc deleted file mode 100644 index abfdf3d02088..000000000000 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ /dev/null @@ -1,627 +0,0 @@ -//===-- sanitizer_coverage.cc ---------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Sanitizer Coverage. -// This file implements run-time support for a poor man's coverage tool. -// -// Compiler instrumentation: -// For every interesting basic block the compiler injects the following code: -// if (Guard < 0) { -// __sanitizer_cov(&Guard); -// } -// At the module start up time __sanitizer_cov_module_init sets the guards -// to consecutive negative numbers (-1, -2, -3, ...). -// It's fine to call __sanitizer_cov more than once for a given block. -// -// Run-time: -// - __sanitizer_cov(): record that we've executed the PC (GET_CALLER_PC). -// and atomically set Guard to -Guard. -// - __sanitizer_cov_dump: dump the coverage data to disk. -// For every module of the current process that has coverage data -// this will create a file module_name.PID.sancov. -// -// The file format is simple: the first 8 bytes is the magic, -// one of 0xC0BFFFFFFFFFFF64 and 0xC0BFFFFFFFFFFF32. The last byte of the -// magic defines the size of the following offsets. -// The rest of the data is the offsets in the module. -// -// Eventually, this coverage implementation should be obsoleted by a more -// powerful general purpose Clang/LLVM coverage instrumentation. -// Consider this implementation as prototype. -// -// FIXME: support (or at least test with) dlclose. -//===----------------------------------------------------------------------===// - -#include "sanitizer_allocator_internal.h" -#include "sanitizer_common.h" -#include "sanitizer_libc.h" -#include "sanitizer_mutex.h" -#include "sanitizer_procmaps.h" -#include "sanitizer_stacktrace.h" -#include "sanitizer_symbolizer.h" -#include "sanitizer_flags.h" - -using namespace __sanitizer; - -static const u64 kMagic64 = 0xC0BFFFFFFFFFFF64ULL; -static const u64 kMagic32 = 0xC0BFFFFFFFFFFF32ULL; -static const uptr kNumWordsForMagic = SANITIZER_WORDSIZE == 64 ? 1 : 2; -static const u64 kMagic = SANITIZER_WORDSIZE == 64 ? kMagic64 : kMagic32; - -static atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once. - -static atomic_uintptr_t coverage_counter; - -// pc_array is the array containing the covered PCs. -// To make the pc_array thread- and async-signal-safe it has to be large enough. -// 128M counters "ought to be enough for anybody" (4M on 32-bit). - -// With coverage_direct=1 in ASAN_OPTIONS, pc_array memory is mapped to a file. -// In this mode, __sanitizer_cov_dump does nothing, and CovUpdateMapping() -// dump current memory layout to another file. - -static bool cov_sandboxed = false; -static fd_t cov_fd = kInvalidFd; -static unsigned int cov_max_block_size = 0; -static bool coverage_enabled = false; -static const char *coverage_dir; - -namespace __sanitizer { - -class CoverageData { - public: - void Init(); - void Enable(); - void Disable(); - void ReInit(); - void BeforeFork(); - void AfterFork(int child_pid); - void Extend(uptr npcs); - void Add(uptr pc, u32 *guard); - void DumpOffsets(); - void DumpAll(); - - void InitializeGuardArray(s32 *guards); - void InitializeGuards(s32 *guards, uptr n, const char *module_name, - uptr caller_pc); - void ReinitializeGuards(); - - uptr *data(); - uptr size() const; - - private: - struct NamedPcRange { - const char *copied_module_name; - uptr beg, end; // elements [beg,end) in pc_array. - }; - - void DirectOpen(); - void UpdateModuleNameVec(uptr caller_pc, uptr range_beg, uptr range_end); - void GetRangeOffsets(const NamedPcRange& r, Symbolizer* s, - InternalMmapVector* offsets) const; - - // Maximal size pc array may ever grow. - // We MmapNoReserve this space to ensure that the array is contiguous. - static const uptr kPcArrayMaxSize = - FIRST_32_SECOND_64(1 << (SANITIZER_ANDROID ? 24 : 26), 1 << 27); - // The amount file mapping for the pc array is grown by. - static const uptr kPcArrayMmapSize = 64 * 1024; - - // pc_array is allocated with MmapNoReserveOrDie and so it uses only as - // much RAM as it really needs. - uptr *pc_array; - // Index of the first available pc_array slot. - atomic_uintptr_t pc_array_index; - // Array size. - atomic_uintptr_t pc_array_size; - // Current file mapped size of the pc array. - uptr pc_array_mapped_size; - // Descriptor of the file mapped pc array. - fd_t pc_fd; - - // Vector of coverage guard arrays, protected by mu. - InternalMmapVectorNoCtor guard_array_vec; - - // Vector of module and compilation unit pc ranges. - InternalMmapVectorNoCtor comp_unit_name_vec; - InternalMmapVectorNoCtor module_name_vec; - - StaticSpinMutex mu; -}; - -static CoverageData coverage_data; - -void CovUpdateMapping(const char *path, uptr caller_pc = 0); - -void CoverageData::DirectOpen() { - InternalScopedString path(kMaxPathLength); - internal_snprintf((char *)path.data(), path.size(), "%s/%zd.sancov.raw", - coverage_dir, internal_getpid()); - pc_fd = OpenFile(path.data(), RdWr); - if (pc_fd == kInvalidFd) { - Report("Coverage: failed to open %s for reading/writing\n", path.data()); - Die(); - } - - pc_array_mapped_size = 0; - CovUpdateMapping(coverage_dir); -} - -void CoverageData::Init() { - pc_fd = kInvalidFd; -} - -void CoverageData::Enable() { - if (pc_array) - return; - pc_array = reinterpret_cast( - MmapNoReserveOrDie(sizeof(uptr) * kPcArrayMaxSize, "CovInit")); - atomic_store(&pc_array_index, 0, memory_order_relaxed); - if (common_flags()->coverage_direct) { - Report("coverage_direct=1 is deprecated, don't use it.\n"); - Die(); - atomic_store(&pc_array_size, 0, memory_order_relaxed); - } else { - atomic_store(&pc_array_size, kPcArrayMaxSize, memory_order_relaxed); - } -} - -void CoverageData::InitializeGuardArray(s32 *guards) { - Enable(); // Make sure coverage is enabled at this point. - s32 n = guards[0]; - for (s32 j = 1; j <= n; j++) { - uptr idx = atomic_load_relaxed(&pc_array_index); - atomic_store_relaxed(&pc_array_index, idx + 1); - guards[j] = -static_cast(idx + 1); - } -} - -void CoverageData::Disable() { - if (pc_array) { - UnmapOrDie(pc_array, sizeof(uptr) * kPcArrayMaxSize); - pc_array = nullptr; - } - if (pc_fd != kInvalidFd) { - CloseFile(pc_fd); - pc_fd = kInvalidFd; - } -} - -void CoverageData::ReinitializeGuards() { - // Assuming single thread. - atomic_store(&pc_array_index, 0, memory_order_relaxed); - for (uptr i = 0; i < guard_array_vec.size(); i++) - InitializeGuardArray(guard_array_vec[i]); -} - -void CoverageData::ReInit() { - Disable(); - if (coverage_enabled) { - if (common_flags()->coverage_direct) { - // In memory-mapped mode we must extend the new file to the known array - // size. - uptr size = atomic_load(&pc_array_size, memory_order_relaxed); - uptr npcs = size / sizeof(uptr); - Enable(); - if (size) Extend(npcs); - if (coverage_enabled) CovUpdateMapping(coverage_dir); - } else { - Enable(); - } - } - // Re-initialize the guards. - // We are single-threaded now, no need to grab any lock. - CHECK_EQ(atomic_load(&pc_array_index, memory_order_relaxed), 0); - ReinitializeGuards(); -} - -void CoverageData::BeforeFork() { - mu.Lock(); -} - -void CoverageData::AfterFork(int child_pid) { - // We are single-threaded so it's OK to release the lock early. - mu.Unlock(); - if (child_pid == 0) ReInit(); -} - -// Extend coverage PC array to fit additional npcs elements. -void CoverageData::Extend(uptr npcs) { - if (!common_flags()->coverage_direct) return; - SpinMutexLock l(&mu); - - uptr size = atomic_load(&pc_array_size, memory_order_relaxed); - size += npcs * sizeof(uptr); - - if (coverage_enabled && size > pc_array_mapped_size) { - if (pc_fd == kInvalidFd) DirectOpen(); - CHECK_NE(pc_fd, kInvalidFd); - - uptr new_mapped_size = pc_array_mapped_size; - while (size > new_mapped_size) new_mapped_size += kPcArrayMmapSize; - CHECK_LE(new_mapped_size, sizeof(uptr) * kPcArrayMaxSize); - - // Extend the file and map the new space at the end of pc_array. - uptr res = internal_ftruncate(pc_fd, new_mapped_size); - int err; - if (internal_iserror(res, &err)) { - Printf("failed to extend raw coverage file: %d\n", err); - Die(); - } - - uptr next_map_base = ((uptr)pc_array) + pc_array_mapped_size; - void *p = MapWritableFileToMemory((void *)next_map_base, - new_mapped_size - pc_array_mapped_size, - pc_fd, pc_array_mapped_size); - CHECK_EQ((uptr)p, next_map_base); - pc_array_mapped_size = new_mapped_size; - } - - atomic_store(&pc_array_size, size, memory_order_release); -} - -void CoverageData::UpdateModuleNameVec(uptr caller_pc, uptr range_beg, - uptr range_end) { - auto sym = Symbolizer::GetOrInit(); - if (!sym) - return; - const char *module_name = sym->GetModuleNameForPc(caller_pc); - if (!module_name) return; - if (module_name_vec.empty() || - module_name_vec.back().copied_module_name != module_name) - module_name_vec.push_back({module_name, range_beg, range_end}); - else - module_name_vec.back().end = range_end; -} - -void CoverageData::InitializeGuards(s32 *guards, uptr n, - const char *comp_unit_name, - uptr caller_pc) { - // The array 'guards' has n+1 elements, we use the element zero - // to store 'n'. - CHECK_LT(n, 1 << 30); - guards[0] = static_cast(n); - InitializeGuardArray(guards); - SpinMutexLock l(&mu); - uptr range_end = atomic_load(&pc_array_index, memory_order_relaxed); - uptr range_beg = range_end - n; - comp_unit_name_vec.push_back({comp_unit_name, range_beg, range_end}); - guard_array_vec.push_back(guards); - UpdateModuleNameVec(caller_pc, range_beg, range_end); -} - -static const uptr kBundleCounterBits = 16; - -// When coverage_order_pcs==true and SANITIZER_WORDSIZE==64 -// we insert the global counter into the first 16 bits of the PC. -uptr BundlePcAndCounter(uptr pc, uptr counter) { - if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs) - return pc; - static const uptr kMaxCounter = (1 << kBundleCounterBits) - 1; - if (counter > kMaxCounter) - counter = kMaxCounter; - CHECK_EQ(0, pc >> (SANITIZER_WORDSIZE - kBundleCounterBits)); - return pc | (counter << (SANITIZER_WORDSIZE - kBundleCounterBits)); -} - -uptr UnbundlePc(uptr bundle) { - if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs) - return bundle; - return (bundle << kBundleCounterBits) >> kBundleCounterBits; -} - -uptr UnbundleCounter(uptr bundle) { - if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs) - return 0; - return bundle >> (SANITIZER_WORDSIZE - kBundleCounterBits); -} - -// If guard is negative, atomically set it to -guard and store the PC in -// pc_array. -void CoverageData::Add(uptr pc, u32 *guard) { - atomic_uint32_t *atomic_guard = reinterpret_cast(guard); - s32 guard_value = atomic_load(atomic_guard, memory_order_relaxed); - if (guard_value >= 0) return; - - atomic_store(atomic_guard, -guard_value, memory_order_relaxed); - if (!pc_array) return; - - uptr idx = -guard_value - 1; - if (idx >= atomic_load(&pc_array_index, memory_order_acquire)) - return; // May happen after fork when pc_array_index becomes 0. - CHECK_LT(idx, atomic_load(&pc_array_size, memory_order_acquire)); - uptr counter = atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed); - pc_array[idx] = BundlePcAndCounter(pc, counter); -} - -uptr *CoverageData::data() { - return pc_array; -} - -uptr CoverageData::size() const { - return atomic_load(&pc_array_index, memory_order_relaxed); -} - -// Block layout for packed file format: header, followed by module name (no -// trailing zero), followed by data blob. -struct CovHeader { - int pid; - unsigned int module_name_length; - unsigned int data_length; -}; - -static void CovWritePacked(int pid, const char *module, const void *blob, - unsigned int blob_size) { - if (cov_fd == kInvalidFd) return; - unsigned module_name_length = internal_strlen(module); - CovHeader header = {pid, module_name_length, blob_size}; - - if (cov_max_block_size == 0) { - // Writing to a file. Just go ahead. - WriteToFile(cov_fd, &header, sizeof(header)); - WriteToFile(cov_fd, module, module_name_length); - WriteToFile(cov_fd, blob, blob_size); - } else { - // Writing to a socket. We want to split the data into appropriately sized - // blocks. - InternalScopedBuffer block(cov_max_block_size); - CHECK_EQ((uptr)block.data(), (uptr)(CovHeader *)block.data()); - uptr header_size_with_module = sizeof(header) + module_name_length; - CHECK_LT(header_size_with_module, cov_max_block_size); - unsigned int max_payload_size = - cov_max_block_size - header_size_with_module; - char *block_pos = block.data(); - internal_memcpy(block_pos, &header, sizeof(header)); - block_pos += sizeof(header); - internal_memcpy(block_pos, module, module_name_length); - block_pos += module_name_length; - char *block_data_begin = block_pos; - const char *blob_pos = (const char *)blob; - while (blob_size > 0) { - unsigned int payload_size = Min(blob_size, max_payload_size); - blob_size -= payload_size; - internal_memcpy(block_data_begin, blob_pos, payload_size); - blob_pos += payload_size; - ((CovHeader *)block.data())->data_length = payload_size; - WriteToFile(cov_fd, block.data(), header_size_with_module + payload_size); - } - } -} - -// If packed = false: .. (name = module name). -// If packed = true and name == 0: ... -// If packed = true and name != 0: .. (name is -// user-supplied). -static fd_t CovOpenFile(InternalScopedString *path, bool packed, - const char *name, const char *extension = "sancov") { - path->clear(); - if (!packed) { - CHECK(name); - path->append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(), - extension); - } else { - if (!name) - path->append("%s/%zd.%s.packed", coverage_dir, internal_getpid(), - extension); - else - path->append("%s/%s.%s.packed", coverage_dir, name, extension); - } - error_t err; - fd_t fd = OpenFile(path->data(), WrOnly, &err); - if (fd == kInvalidFd) - Report("SanitizerCoverage: failed to open %s for writing (reason: %d)\n", - path->data(), err); - return fd; -} - -void CoverageData::GetRangeOffsets(const NamedPcRange& r, Symbolizer* sym, - InternalMmapVector* offsets) const { - offsets->clear(); - for (uptr i = 0; i < kNumWordsForMagic; i++) - offsets->push_back(0); - CHECK(r.copied_module_name); - CHECK_LE(r.beg, r.end); - CHECK_LE(r.end, size()); - for (uptr i = r.beg; i < r.end; i++) { - uptr pc = UnbundlePc(pc_array[i]); - uptr counter = UnbundleCounter(pc_array[i]); - if (!pc) continue; // Not visited. - uptr offset = 0; - sym->GetModuleNameAndOffsetForPC(pc, nullptr, &offset); - offsets->push_back(BundlePcAndCounter(offset, counter)); - } - - CHECK_GE(offsets->size(), kNumWordsForMagic); - SortArray(offsets->data(), offsets->size()); - for (uptr i = 0; i < offsets->size(); i++) - (*offsets)[i] = UnbundlePc((*offsets)[i]); -} - -static void GenerateHtmlReport(const InternalMmapVector &cov_files) { - if (!common_flags()->html_cov_report) { - return; - } - char *sancov_path = FindPathToBinary(common_flags()->sancov_path); - if (sancov_path == nullptr) { - return; - } - - InternalMmapVector sancov_argv(cov_files.size() * 2 + 3); - sancov_argv.push_back(sancov_path); - sancov_argv.push_back(internal_strdup("-html-report")); - auto argv_deleter = at_scope_exit([&] { - for (uptr i = 0; i < sancov_argv.size(); ++i) { - InternalFree(sancov_argv[i]); - } - }); - - for (const auto &cov_file : cov_files) { - sancov_argv.push_back(internal_strdup(cov_file)); - } - - { - ListOfModules modules; - modules.init(); - for (const LoadedModule &module : modules) { - sancov_argv.push_back(internal_strdup(module.full_name())); - } - } - - InternalScopedString report_path(kMaxPathLength); - fd_t report_fd = - CovOpenFile(&report_path, false /* packed */, GetProcessName(), "html"); - int pid = StartSubprocess(sancov_argv[0], sancov_argv.data(), - kInvalidFd /* stdin */, report_fd /* std_out */); - if (pid > 0) { - int result = WaitForProcess(pid); - if (result == 0) - Printf("coverage report generated to %s\n", report_path.data()); - } -} - -void CoverageData::DumpOffsets() { - auto sym = Symbolizer::GetOrInit(); - if (!common_flags()->coverage_pcs) return; - Printf("**\n***\n***\n"); - Printf("**WARNING: this implementation of SanitizerCoverage is deprecated\n"); - Printf("**WARNING: and will be removed in future versions\n"); - Printf("**WARNING: See https://clang.llvm.org/docs/SanitizerCoverage.html\n"); - Printf("**\n***\n***\n"); - - CHECK_NE(sym, nullptr); - InternalMmapVector offsets(0); - InternalScopedString path(kMaxPathLength); - - InternalMmapVector cov_files(module_name_vec.size()); - auto cov_files_deleter = at_scope_exit([&] { - for (uptr i = 0; i < cov_files.size(); ++i) { - InternalFree(cov_files[i]); - } - }); - - for (uptr m = 0; m < module_name_vec.size(); m++) { - auto r = module_name_vec[m]; - GetRangeOffsets(r, sym, &offsets); - - uptr num_offsets = offsets.size() - kNumWordsForMagic; - u64 *magic_p = reinterpret_cast(offsets.data()); - CHECK_EQ(*magic_p, 0ULL); - // FIXME: we may want to write 32-bit offsets even in 64-mode - // if all the offsets are small enough. - *magic_p = kMagic; - - const char *module_name = StripModuleName(r.copied_module_name); - if (cov_sandboxed) { - if (cov_fd != kInvalidFd) { - CovWritePacked(internal_getpid(), module_name, offsets.data(), - offsets.size() * sizeof(offsets[0])); - VReport(1, " CovDump: %zd PCs written to packed file\n", num_offsets); - } - } else { - // One file per module per process. - fd_t fd = CovOpenFile(&path, false /* packed */, module_name); - if (fd == kInvalidFd) continue; - WriteToFile(fd, offsets.data(), offsets.size() * sizeof(offsets[0])); - CloseFile(fd); - cov_files.push_back(internal_strdup(path.data())); - VReport(1, " CovDump: %s: %zd PCs written\n", path.data(), num_offsets); - } - } - if (cov_fd != kInvalidFd) - CloseFile(cov_fd); - - GenerateHtmlReport(cov_files); -} - -void CoverageData::DumpAll() { - if (!coverage_enabled || common_flags()->coverage_direct) return; - if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed)) - return; - DumpOffsets(); -} - -void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) { - if (!args) return; - if (!coverage_enabled) return; - cov_sandboxed = args->coverage_sandboxed; - if (!cov_sandboxed) return; - cov_max_block_size = args->coverage_max_block_size; - if (args->coverage_fd >= 0) { - cov_fd = (fd_t)args->coverage_fd; - } else { - InternalScopedString path(kMaxPathLength); - // Pre-open the file now. The sandbox won't allow us to do it later. - cov_fd = CovOpenFile(&path, true /* packed */, nullptr); - } -} - -fd_t MaybeOpenCovFile(const char *name) { - CHECK(name); - if (!coverage_enabled) return kInvalidFd; - InternalScopedString path(kMaxPathLength); - return CovOpenFile(&path, true /* packed */, name); -} - -void CovBeforeFork() { - coverage_data.BeforeFork(); -} - -void CovAfterFork(int child_pid) { - coverage_data.AfterFork(child_pid); -} - -static void MaybeDumpCoverage() { - if (common_flags()->coverage) - __sanitizer_cov_dump(); -} - -void InitializeCoverage(bool enabled, const char *dir) { - if (coverage_enabled) - return; // May happen if two sanitizer enable coverage in the same process. - coverage_enabled = enabled; - coverage_dir = dir; - coverage_data.Init(); - if (enabled) coverage_data.Enable(); - if (!common_flags()->coverage_direct) Atexit(__sanitizer_cov_dump); - AddDieCallback(MaybeDumpCoverage); -} - -void ReInitializeCoverage(bool enabled, const char *dir) { - coverage_enabled = enabled; - coverage_dir = dir; - coverage_data.ReInit(); -} - -void CoverageUpdateMapping() { - if (coverage_enabled) - CovUpdateMapping(coverage_dir); -} - -} // namespace __sanitizer - -extern "C" { -SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { - __sanitizer_dump_trace_pc_guard_coverage(); -} -SANITIZER_INTERFACE_ATTRIBUTE -sptr __sanitizer_maybe_open_cov_file(const char *name) { - return (sptr)MaybeOpenCovFile(name); -} -// Default empty implementations (weak). Users should redefine them. -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp4, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp8, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_switch, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div4, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_gep, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} -} // extern "C" diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc index a98dde76e22a..24433356c63d 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc @@ -146,6 +146,17 @@ static TracePcGuardController pc_guard_controller; } // namespace } // namespace __sancov +namespace __sanitizer { +void InitializeCoverage(bool enabled, const char *dir) { + static bool coverage_enabled = false; + if (coverage_enabled) + return; // May happen if two sanitizer enable coverage in the same process. + coverage_enabled = enabled; + Atexit(__sanitizer_cov_dump); + AddDieCallback(__sanitizer_cov_dump); +} +} // namespace __sanitizer + extern "C" { SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage( // NOLINT const uptr* pcs, uptr len) { @@ -166,4 +177,18 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage() { __sancov::pc_guard_controller.Dump(); } +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { + __sanitizer_dump_trace_pc_guard_coverage(); +} +// Default empty implementations (weak). Users should redefine them. +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp4, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp8, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_switch, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div4, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_gep, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} } // extern "C" diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc deleted file mode 100644 index 3477b065b06a..000000000000 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc +++ /dev/null @@ -1,122 +0,0 @@ -//===-- sanitizer_coverage_mapping.cc -------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Mmap-based implementation of sanitizer coverage. -// -// This is part of the implementation of code coverage that does not require -// __sanitizer_cov_dump() call. Data is stored in 2 files per process. -// -// $pid.sancov.map describes process memory layout in the following text-based -// format: -// // 1 line, 32 or 64 -// // repeated -// ... -// Mapping lines are NOT sorted. This file is updated every time memory layout -// is changed (i.e. in dlopen() and dlclose() interceptors). -// -// $pid.sancov.raw is a binary dump of PC values, sizeof(uptr) each. Again, not -// sorted. This file is extended by 64Kb at a time and mapped into memory. It -// contains one or more 0 words at the end, up to the next 64Kb aligned offset. -// -// To convert these 2 files to the usual .sancov format, run sancov.py rawunpack -// $pid.sancov.raw. -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_allocator_internal.h" -#include "sanitizer_libc.h" -#include "sanitizer_procmaps.h" - -namespace __sanitizer { - -static const uptr kMaxTextSize = 64 * 1024; - -struct CachedMapping { - public: - bool NeedsUpdate(uptr pc) { - int new_pid = internal_getpid(); - if (last_pid == new_pid && pc && pc >= last_range_start && - pc < last_range_end) - return false; - last_pid = new_pid; - return true; - } - - void SetModuleRange(uptr start, uptr end) { - last_range_start = start; - last_range_end = end; - } - - private: - uptr last_range_start, last_range_end; - int last_pid; -}; - -static CachedMapping cached_mapping; -static StaticSpinMutex mapping_mu; - -void CovUpdateMapping(const char *coverage_dir, uptr caller_pc) { - if (!common_flags()->coverage_direct) return; - - SpinMutexLock l(&mapping_mu); - - if (!cached_mapping.NeedsUpdate(caller_pc)) - return; - - InternalScopedString text(kMaxTextSize); - - { - text.append("%d\n", sizeof(uptr) * 8); - ListOfModules modules; - modules.init(); - for (const LoadedModule &module : modules) { - const char *module_name = StripModuleName(module.full_name()); - uptr base = module.base_address(); - for (const auto &range : module.ranges()) { - if (range.executable) { - uptr start = range.beg; - uptr end = range.end; - text.append("%zx %zx %zx %s\n", start, end, base, module_name); - if (caller_pc && caller_pc >= start && caller_pc < end) - cached_mapping.SetModuleRange(start, end); - } - } - } - } - - error_t err; - InternalScopedString tmp_path(64 + internal_strlen(coverage_dir)); - uptr res = internal_snprintf((char *)tmp_path.data(), tmp_path.size(), - "%s/%zd.sancov.map.tmp", coverage_dir, - internal_getpid()); - CHECK_LE(res, tmp_path.size()); - fd_t map_fd = OpenFile(tmp_path.data(), WrOnly, &err); - if (map_fd == kInvalidFd) { - Report("Coverage: failed to open %s for writing: %d\n", tmp_path.data(), - err); - Die(); - } - - if (!WriteToFile(map_fd, text.data(), text.length(), nullptr, &err)) { - Printf("sancov.map write failed: %d\n", err); - Die(); - } - CloseFile(map_fd); - - InternalScopedString path(64 + internal_strlen(coverage_dir)); - res = internal_snprintf((char *)path.data(), path.size(), "%s/%zd.sancov.map", - coverage_dir, internal_getpid()); - CHECK_LE(res, path.size()); - if (!RenameFile(tmp_path.data(), path.data(), &err)) { - Printf("sancov.map rename failed: %d\n", err); - Die(); - } -} - -} // namespace __sanitizer diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc index f87d8b6433ac..8c486b5b1b4d 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -138,16 +138,6 @@ COMMON_FLAG( bool, coverage, false, "If set, coverage information will be dumped at program shutdown (if the " "coverage instrumentation was enabled at compile time).") -COMMON_FLAG(bool, coverage_pcs, true, - "If set (and if 'coverage' is set too), the coverage information " - "will be dumped as a set of PC offsets for every module.") -COMMON_FLAG(bool, coverage_order_pcs, false, - "If true, the PCs will be dumped in the order they've" - " appeared during the execution.") -COMMON_FLAG(bool, coverage_direct, SANITIZER_ANDROID, - "If set, coverage information will be dumped directly to a memory " - "mapped file. This way data is not lost even if the process is " - "suddenly killed.") COMMON_FLAG(const char *, coverage_dir, ".", "Target directory for coverage dumps. Defaults to the current " "directory.") diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index cec2f264cbc4..7bc7682dd962 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -75,16 +75,6 @@ extern char **environ; // provided by crt1 #include #endif -#ifndef __GLIBC_PREREQ -#define __GLIBC_PREREQ(x, y) 0 -#endif - -#if SANITIZER_LINUX && __GLIBC_PREREQ(2, 16) -# define SANITIZER_USE_GETAUXVAL 1 -#else -# define SANITIZER_USE_GETAUXVAL 0 -#endif - #if SANITIZER_USE_GETAUXVAL #include #endif diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index 49732aa32323..8fa3f7ab66fc 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -269,5 +269,14 @@ # define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0 #endif +#ifndef __GLIBC_PREREQ +#define __GLIBC_PREREQ(x, y) 0 +#endif + +#if SANITIZER_LINUX && __GLIBC_PREREQ(2, 16) +# define SANITIZER_USE_GETAUXVAL 1 +#else +# define SANITIZER_USE_GETAUXVAL 0 +#endif #endif // SANITIZER_PLATFORM_H diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index ebf7d221b53b..def2ff56e693 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -23,6 +23,9 @@ // incorporates the map structure. # define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ ((link_map*)((handle) == nullptr ? nullptr : ((char*)(handle) + 544))) +// Get sys/_types.h, because that tells us whether 64-bit inodes are +// used in struct dirent below. +#include #else # define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map*)(handle)) #endif // !SANITIZER_FREEBSD @@ -489,8 +492,12 @@ namespace __sanitizer { }; #elif SANITIZER_FREEBSD struct __sanitizer_dirent { +#if defined(__INO64) unsigned long long d_fileno; unsigned long long d_off; +#else + unsigned int d_fileno; +#endif unsigned short d_reclen; // more fields that we don't care about }; diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc index 791ff4481ca8..5b1d53698707 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -264,7 +264,6 @@ void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { // Same for /proc/self/exe in the symbolizer. #if !SANITIZER_GO Symbolizer::GetOrInit()->PrepareForSandboxing(); - CovPrepareForSandboxing(args); #endif } diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_win.cc index c912e8fa2aa3..afc3bb0ac678 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_win.cc +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_win.cc @@ -400,9 +400,6 @@ void ReExec() { } void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { -#if !SANITIZER_GO - CovPrepareForSandboxing(args); -#endif } bool StackSizeIsUnlimited() { diff --git a/contrib/compiler-rt/lib/ubsan/ubsan_checks.inc b/contrib/compiler-rt/lib/ubsan/ubsan_checks.inc index 6e086414051e..0a87e6e8e3a4 100644 --- a/contrib/compiler-rt/lib/ubsan/ubsan_checks.inc +++ b/contrib/compiler-rt/lib/ubsan/ubsan_checks.inc @@ -19,6 +19,7 @@ UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined") UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null") +UBSAN_CHECK(PointerOverflow, "pointer-overflow", "pointer-overflow") UBSAN_CHECK(MisalignedPointerUse, "misaligned-pointer-use", "alignment") UBSAN_CHECK(InsufficientObjectSize, "insufficient-object-size", "object-size") UBSAN_CHECK(SignedIntegerOverflow, "signed-integer-overflow", diff --git a/contrib/compiler-rt/lib/ubsan/ubsan_handlers.cc b/contrib/compiler-rt/lib/ubsan/ubsan_handlers.cc index d6a8f52a27b4..80cc8ad25790 100644 --- a/contrib/compiler-rt/lib/ubsan/ubsan_handlers.cc +++ b/contrib/compiler-rt/lib/ubsan/ubsan_handlers.cc @@ -554,6 +554,37 @@ void __ubsan::__ubsan_handle_nullability_arg_abort(NonNullArgData *Data) { Die(); } +static void handlePointerOverflowImpl(PointerOverflowData *Data, + ValueHandle Base, + ValueHandle Result, + ReportOptions Opts) { + SourceLocation Loc = Data->Loc.acquire(); + ErrorType ET = ErrorType::PointerOverflow; + + if (ignoreReport(Loc, Opts, ET)) + return; + + ScopedReport R(Opts, Loc, ET); + + Diag(Loc, DL_Error, "pointer index expression with base %0 overflowed to %1") + << (void *)Base << (void*)Result; +} + +void __ubsan::__ubsan_handle_pointer_overflow(PointerOverflowData *Data, + ValueHandle Base, + ValueHandle Result) { + GET_REPORT_OPTIONS(false); + handlePointerOverflowImpl(Data, Base, Result, Opts); +} + +void __ubsan::__ubsan_handle_pointer_overflow_abort(PointerOverflowData *Data, + ValueHandle Base, + ValueHandle Result) { + GET_REPORT_OPTIONS(true); + handlePointerOverflowImpl(Data, Base, Result, Opts); + Die(); +} + static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function, ReportOptions Opts) { if (Data->CheckKind != CFITCK_ICall) diff --git a/contrib/compiler-rt/lib/ubsan/ubsan_handlers.h b/contrib/compiler-rt/lib/ubsan/ubsan_handlers.h index 5857bc2495f5..483c18ced579 100644 --- a/contrib/compiler-rt/lib/ubsan/ubsan_handlers.h +++ b/contrib/compiler-rt/lib/ubsan/ubsan_handlers.h @@ -152,6 +152,13 @@ struct NonNullArgData { RECOVERABLE(nonnull_arg, NonNullArgData *Data) RECOVERABLE(nullability_arg, NonNullArgData *Data) +struct PointerOverflowData { + SourceLocation Loc; +}; + +RECOVERABLE(pointer_overflow, PointerOverflowData *Data, ValueHandle Base, + ValueHandle Result) + /// \brief Known CFI check kinds. /// Keep in sync with the enum of the same name in CodeGenFunction.h enum CFITypeCheckKind : unsigned char { diff --git a/contrib/compiler-rt/lib/ubsan/ubsan_interface.inc b/contrib/compiler-rt/lib/ubsan/ubsan_interface.inc index 0e43ebc68299..681476b3c91d 100644 --- a/contrib/compiler-rt/lib/ubsan/ubsan_interface.inc +++ b/contrib/compiler-rt/lib/ubsan/ubsan_interface.inc @@ -36,6 +36,8 @@ INTERFACE_FUNCTION(__ubsan_handle_nullability_return) INTERFACE_FUNCTION(__ubsan_handle_nullability_return_abort) INTERFACE_FUNCTION(__ubsan_handle_out_of_bounds) INTERFACE_FUNCTION(__ubsan_handle_out_of_bounds_abort) +INTERFACE_FUNCTION(__ubsan_handle_pointer_overflow) +INTERFACE_FUNCTION(__ubsan_handle_pointer_overflow_abort) INTERFACE_FUNCTION(__ubsan_handle_shift_out_of_bounds) INTERFACE_FUNCTION(__ubsan_handle_shift_out_of_bounds_abort) INTERFACE_FUNCTION(__ubsan_handle_sub_overflow) diff --git a/contrib/libc++/include/__hash_table b/contrib/libc++/include/__hash_table index 79336ff793ec..3f430af1283e 100644 --- a/contrib/libc++/include/__hash_table +++ b/contrib/libc++/include/__hash_table @@ -137,7 +137,7 @@ inline _LIBCPP_INLINE_VISIBILITY size_t __next_hash_pow2(size_t __n) { - return size_t(1) << (std::numeric_limits::digits - __clz(__n-1)); + return __n < 2 ? __n : (size_t(1) << (std::numeric_limits::digits - __clz(__n-1))); } diff --git a/contrib/llvm/include/llvm/ADT/SmallVector.h b/contrib/llvm/include/llvm/ADT/SmallVector.h index bd24eab93b50..35c255002001 100644 --- a/contrib/llvm/include/llvm/ADT/SmallVector.h +++ b/contrib/llvm/include/llvm/ADT/SmallVector.h @@ -415,6 +415,9 @@ public: append(IL.begin(), IL.end()); } + // FIXME: Consider assigning over existing elements, rather than clearing & + // re-initializing them - for all assign(...) variants. + void assign(size_type NumElts, const T &Elt) { clear(); if (this->capacity() < NumElts) @@ -423,6 +426,11 @@ public: std::uninitialized_fill(this->begin(), this->end(), Elt); } + template void assign(in_iter in_start, in_iter in_end) { + clear(); + append(in_start, in_end); + } + void assign(std::initializer_list IL) { clear(); append(IL); diff --git a/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h b/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h index 5aa813eb4832..2e716af1f60d 100644 --- a/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h +++ b/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h @@ -58,6 +58,7 @@ public: /// comes before \p B in \p BB. This is a simplification that considers /// cached instruction positions and ignores other basic blocks, being /// only relevant to compare relative instructions positions inside \p BB. + /// Returns false for A == B. bool dominates(const Instruction *A, const Instruction *B); }; diff --git a/contrib/llvm/include/llvm/Analysis/RegionPass.h b/contrib/llvm/include/llvm/Analysis/RegionPass.h index b5f38139abf2..515b362e5407 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionPass.h +++ b/contrib/llvm/include/llvm/Analysis/RegionPass.h @@ -78,6 +78,11 @@ public: return PMT_RegionPassManager; } //@} + +protected: + /// Optional passes call this function to check whether the pass should be + /// skipped. This is the case when optimization bisect is over the limit. + bool skipRegion(Region &R) const; }; /// @brief The pass manager to schedule RegionPasses. diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h index 1d715b590ab7..8ee9712b93d8 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -636,7 +636,7 @@ private: /// @} public: - BackedgeTakenInfo() : MaxAndComplete(nullptr, 0) {} + BackedgeTakenInfo() : MaxAndComplete(nullptr, 0), MaxOrZero(false) {} BackedgeTakenInfo(BackedgeTakenInfo &&) = default; BackedgeTakenInfo &operator=(BackedgeTakenInfo &&) = default; diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegionInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegionInfo.h index 21f847c7e5ba..8394b58d0a16 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRegionInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRegionInfo.h @@ -10,83 +10,77 @@ #ifndef LLVM_CODEGEN_MACHINEREGIONINFO_H #define LLVM_CODEGEN_MACHINEREGIONINFO_H +#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionIterator.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineDominanceFrontier.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineLoopInfo.h" - +#include namespace llvm { -class MachineDominatorTree; struct MachinePostDominatorTree; class MachineRegion; class MachineRegionNode; class MachineRegionInfo; -template<> -struct RegionTraits { - typedef MachineFunction FuncT; - typedef MachineBasicBlock BlockT; - typedef MachineRegion RegionT; - typedef MachineRegionNode RegionNodeT; - typedef MachineRegionInfo RegionInfoT; - typedef MachineDominatorTree DomTreeT; - typedef MachineDomTreeNode DomTreeNodeT; - typedef MachinePostDominatorTree PostDomTreeT; - typedef MachineDominanceFrontier DomFrontierT; - typedef MachineInstr InstT; - typedef MachineLoop LoopT; - typedef MachineLoopInfo LoopInfoT; +template <> struct RegionTraits { + using FuncT = MachineFunction; + using BlockT = MachineBasicBlock; + using RegionT = MachineRegion; + using RegionNodeT = MachineRegionNode; + using RegionInfoT = MachineRegionInfo; + using DomTreeT = MachineDominatorTree; + using DomTreeNodeT = MachineDomTreeNode; + using PostDomTreeT = MachinePostDominatorTree; + using DomFrontierT = MachineDominanceFrontier; + using InstT = MachineInstr; + using LoopT = MachineLoop; + using LoopInfoT = MachineLoopInfo; static unsigned getNumSuccessors(MachineBasicBlock *BB) { return BB->succ_size(); } }; - class MachineRegionNode : public RegionNodeBase> { public: - inline MachineRegionNode(MachineRegion *Parent, - MachineBasicBlock *Entry, + inline MachineRegionNode(MachineRegion *Parent, MachineBasicBlock *Entry, bool isSubRegion = false) - : RegionNodeBase>(Parent, Entry, isSubRegion) { - - } + : RegionNodeBase>(Parent, Entry, + isSubRegion) {} bool operator==(const MachineRegion &RN) const { - return this == reinterpret_cast(&RN); + return this == reinterpret_cast(&RN); } }; class MachineRegion : public RegionBase> { public: MachineRegion(MachineBasicBlock *Entry, MachineBasicBlock *Exit, - MachineRegionInfo* RI, - MachineDominatorTree *DT, MachineRegion *Parent = nullptr); + MachineRegionInfo *RI, MachineDominatorTree *DT, + MachineRegion *Parent = nullptr); ~MachineRegion(); bool operator==(const MachineRegionNode &RN) const { - return &RN == reinterpret_cast(this); + return &RN == reinterpret_cast(this); } }; class MachineRegionInfo : public RegionInfoBase> { public: explicit MachineRegionInfo(); - ~MachineRegionInfo() override; // updateStatistics - Update statistic about created regions. void updateStatistics(MachineRegion *R) final; - void recalculate(MachineFunction &F, - MachineDominatorTree *DT, - MachinePostDominatorTree *PDT, - MachineDominanceFrontier *DF); + void recalculate(MachineFunction &F, MachineDominatorTree *DT, + MachinePostDominatorTree *PDT, MachineDominanceFrontier *DF); }; class MachineRegionInfoPass : public MachineFunctionPass { @@ -94,17 +88,13 @@ class MachineRegionInfoPass : public MachineFunctionPass { public: static char ID; - explicit MachineRegionInfoPass(); + explicit MachineRegionInfoPass(); ~MachineRegionInfoPass() override; - MachineRegionInfo &getRegionInfo() { - return RI; - } + MachineRegionInfo &getRegionInfo() { return RI; } - const MachineRegionInfo &getRegionInfo() const { - return RI; - } + const MachineRegionInfo &getRegionInfo() const { return RI; } /// @name MachineFunctionPass interface //@{ @@ -117,66 +107,76 @@ public: //@} }; - template <> template <> -inline MachineBasicBlock* RegionNodeBase>::getNodeAs() const { +inline MachineBasicBlock * +RegionNodeBase>::getNodeAs() + const { assert(!isSubRegion() && "This is not a MachineBasicBlock RegionNode!"); return getEntry(); } -template<> -template<> -inline MachineRegion* RegionNodeBase>::getNodeAs() const { +template <> +template <> +inline MachineRegion * +RegionNodeBase>::getNodeAs() + const { assert(isSubRegion() && "This is not a subregion RegionNode!"); - auto Unconst = const_cast>*>(this); - return reinterpret_cast(Unconst); + auto Unconst = + const_cast> *>(this); + return reinterpret_cast(Unconst); } - RegionNodeGraphTraits(MachineRegionNode, MachineBasicBlock, MachineRegion); -RegionNodeGraphTraits(const MachineRegionNode, MachineBasicBlock, MachineRegion); +RegionNodeGraphTraits(const MachineRegionNode, MachineBasicBlock, + MachineRegion); RegionGraphTraits(MachineRegion, MachineRegionNode); RegionGraphTraits(const MachineRegion, const MachineRegionNode); -template <> struct GraphTraits - : public GraphTraits > { - typedef df_iterator, false, - GraphTraits>> - nodes_iterator; +template <> +struct GraphTraits + : public GraphTraits> { + using nodes_iterator = df_iterator, + false, GraphTraits>>; static NodeRef getEntryNode(MachineRegionInfo *RI) { - return GraphTraits >::getEntryNode(RI->getTopLevelRegion()); + return GraphTraits>::getEntryNode( + RI->getTopLevelRegion()); } - static nodes_iterator nodes_begin(MachineRegionInfo* RI) { + + static nodes_iterator nodes_begin(MachineRegionInfo *RI) { return nodes_iterator::begin(getEntryNode(RI)); } + static nodes_iterator nodes_end(MachineRegionInfo *RI) { return nodes_iterator::end(getEntryNode(RI)); } }; -template <> struct GraphTraits - : public GraphTraits { - typedef df_iterator, false, - GraphTraits>> - nodes_iterator; +template <> +struct GraphTraits + : public GraphTraits { + using nodes_iterator = df_iterator, + false, GraphTraits>>; static NodeRef getEntryNode(MachineRegionInfoPass *RI) { - return GraphTraits::getEntryNode(&RI->getRegionInfo()); + return GraphTraits::getEntryNode(&RI->getRegionInfo()); } - static nodes_iterator nodes_begin(MachineRegionInfoPass* RI) { - return GraphTraits::nodes_begin(&RI->getRegionInfo()); + + static nodes_iterator nodes_begin(MachineRegionInfoPass *RI) { + return GraphTraits::nodes_begin(&RI->getRegionInfo()); } + static nodes_iterator nodes_end(MachineRegionInfoPass *RI) { - return GraphTraits::nodes_end(&RI->getRegionInfo()); + return GraphTraits::nodes_end(&RI->getRegionInfo()); } }; extern template class RegionBase>; extern template class RegionNodeBase>; extern template class RegionInfoBase>; -} -#endif +} // end namespace llvm + +#endif // LLVM_CODEGEN_MACHINEREGIONINFO_H diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 1026654da3d7..c027783aae55 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -14,11 +14,13 @@ #ifndef LLVM_CODEGEN_MACHINEREGISTERINFO_H #define LLVM_CODEGEN_MACHINEREGISTERINFO_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/iterator_range.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -41,8 +43,8 @@ namespace llvm { class PSetIterator; /// Convenient type to represent either a register class or a register bank. -typedef PointerUnion - RegClassOrRegBank; +using RegClassOrRegBank = + PointerUnion; /// MachineRegisterInfo - Keep track of information for virtual and physical /// registers, including vreg register classes, use/def chains for registers, @@ -125,7 +127,7 @@ private: /// started. BitVector ReservedRegs; - typedef DenseMap VRegToTypeMap; + using VRegToTypeMap = DenseMap; /// Map generic virtual registers to their actual size. mutable std::unique_ptr VRegToType; @@ -266,8 +268,8 @@ public: /// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified /// register. - typedef defusechain_iterator - reg_iterator; + using reg_iterator = + defusechain_iterator; reg_iterator reg_begin(unsigned RegNo) const { return reg_iterator(getRegUseDefListHead(RegNo)); } @@ -279,8 +281,8 @@ public: /// reg_instr_iterator/reg_instr_begin/reg_instr_end - Walk all defs and uses /// of the specified register, stepping by MachineInstr. - typedef defusechain_instr_iterator - reg_instr_iterator; + using reg_instr_iterator = + defusechain_instr_iterator; reg_instr_iterator reg_instr_begin(unsigned RegNo) const { return reg_instr_iterator(getRegUseDefListHead(RegNo)); } @@ -295,8 +297,8 @@ public: /// reg_bundle_iterator/reg_bundle_begin/reg_bundle_end - Walk all defs and uses /// of the specified register, stepping by bundle. - typedef defusechain_instr_iterator - reg_bundle_iterator; + using reg_bundle_iterator = + defusechain_instr_iterator; reg_bundle_iterator reg_bundle_begin(unsigned RegNo) const { return reg_bundle_iterator(getRegUseDefListHead(RegNo)); } @@ -314,8 +316,8 @@ public: /// reg_nodbg_iterator/reg_nodbg_begin/reg_nodbg_end - Walk all defs and uses /// of the specified register, skipping those marked as Debug. - typedef defusechain_iterator - reg_nodbg_iterator; + using reg_nodbg_iterator = + defusechain_iterator; reg_nodbg_iterator reg_nodbg_begin(unsigned RegNo) const { return reg_nodbg_iterator(getRegUseDefListHead(RegNo)); } @@ -331,8 +333,8 @@ public: /// reg_instr_nodbg_iterator/reg_instr_nodbg_begin/reg_instr_nodbg_end - Walk /// all defs and uses of the specified register, stepping by MachineInstr, /// skipping those marked as Debug. - typedef defusechain_instr_iterator - reg_instr_nodbg_iterator; + using reg_instr_nodbg_iterator = + defusechain_instr_iterator; reg_instr_nodbg_iterator reg_instr_nodbg_begin(unsigned RegNo) const { return reg_instr_nodbg_iterator(getRegUseDefListHead(RegNo)); } @@ -348,8 +350,8 @@ public: /// reg_bundle_nodbg_iterator/reg_bundle_nodbg_begin/reg_bundle_nodbg_end - Walk /// all defs and uses of the specified register, stepping by bundle, /// skipping those marked as Debug. - typedef defusechain_instr_iterator - reg_bundle_nodbg_iterator; + using reg_bundle_nodbg_iterator = + defusechain_instr_iterator; reg_bundle_nodbg_iterator reg_bundle_nodbg_begin(unsigned RegNo) const { return reg_bundle_nodbg_iterator(getRegUseDefListHead(RegNo)); } @@ -369,8 +371,8 @@ public: } /// def_iterator/def_begin/def_end - Walk all defs of the specified register. - typedef defusechain_iterator - def_iterator; + using def_iterator = + defusechain_iterator; def_iterator def_begin(unsigned RegNo) const { return def_iterator(getRegUseDefListHead(RegNo)); } @@ -382,8 +384,8 @@ public: /// def_instr_iterator/def_instr_begin/def_instr_end - Walk all defs of the /// specified register, stepping by MachineInst. - typedef defusechain_instr_iterator - def_instr_iterator; + using def_instr_iterator = + defusechain_instr_iterator; def_instr_iterator def_instr_begin(unsigned RegNo) const { return def_instr_iterator(getRegUseDefListHead(RegNo)); } @@ -398,8 +400,8 @@ public: /// def_bundle_iterator/def_bundle_begin/def_bundle_end - Walk all defs of the /// specified register, stepping by bundle. - typedef defusechain_instr_iterator - def_bundle_iterator; + using def_bundle_iterator = + defusechain_instr_iterator; def_bundle_iterator def_bundle_begin(unsigned RegNo) const { return def_bundle_iterator(getRegUseDefListHead(RegNo)); } @@ -425,8 +427,8 @@ public: } /// use_iterator/use_begin/use_end - Walk all uses of the specified register. - typedef defusechain_iterator - use_iterator; + using use_iterator = + defusechain_iterator; use_iterator use_begin(unsigned RegNo) const { return use_iterator(getRegUseDefListHead(RegNo)); } @@ -438,8 +440,8 @@ public: /// use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the /// specified register, stepping by MachineInstr. - typedef defusechain_instr_iterator - use_instr_iterator; + using use_instr_iterator = + defusechain_instr_iterator; use_instr_iterator use_instr_begin(unsigned RegNo) const { return use_instr_iterator(getRegUseDefListHead(RegNo)); } @@ -454,8 +456,8 @@ public: /// use_bundle_iterator/use_bundle_begin/use_bundle_end - Walk all uses of the /// specified register, stepping by bundle. - typedef defusechain_instr_iterator - use_bundle_iterator; + using use_bundle_iterator = + defusechain_instr_iterator; use_bundle_iterator use_bundle_begin(unsigned RegNo) const { return use_bundle_iterator(getRegUseDefListHead(RegNo)); } @@ -482,8 +484,8 @@ public: /// use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the /// specified register, skipping those marked as Debug. - typedef defusechain_iterator - use_nodbg_iterator; + using use_nodbg_iterator = + defusechain_iterator; use_nodbg_iterator use_nodbg_begin(unsigned RegNo) const { return use_nodbg_iterator(getRegUseDefListHead(RegNo)); } @@ -499,8 +501,8 @@ public: /// use_instr_nodbg_iterator/use_instr_nodbg_begin/use_instr_nodbg_end - Walk /// all uses of the specified register, stepping by MachineInstr, skipping /// those marked as Debug. - typedef defusechain_instr_iterator - use_instr_nodbg_iterator; + using use_instr_nodbg_iterator = + defusechain_instr_iterator; use_instr_nodbg_iterator use_instr_nodbg_begin(unsigned RegNo) const { return use_instr_nodbg_iterator(getRegUseDefListHead(RegNo)); } @@ -516,8 +518,8 @@ public: /// use_bundle_nodbg_iterator/use_bundle_nodbg_begin/use_bundle_nodbg_end - Walk /// all uses of the specified register, stepping by bundle, skipping /// those marked as Debug. - typedef defusechain_instr_iterator - use_bundle_nodbg_iterator; + using use_bundle_nodbg_iterator = + defusechain_instr_iterator; use_bundle_nodbg_iterator use_bundle_nodbg_begin(unsigned RegNo) const { return use_bundle_nodbg_iterator(getRegUseDefListHead(RegNo)); } @@ -593,7 +595,6 @@ public: /// Return the register class of the specified virtual register. /// This shouldn't be used directly unless \p Reg has a register class. /// \see getRegClassOrNull when this might happen. - /// const TargetRegisterClass *getRegClass(unsigned Reg) const { assert(VRegInfo[Reg].first.is() && "Register class not set, wrong accessor"); @@ -620,7 +621,6 @@ public: /// a register bank or has been assigned a register class. /// \note It is possible to get the register bank from the register class via /// RegisterBankInfo::getRegBankFromRegClass. - /// const RegisterBank *getRegBankOrNull(unsigned Reg) const { const RegClassOrRegBank &Val = VRegInfo[Reg].first; return Val.dyn_cast(); @@ -629,17 +629,14 @@ public: /// Return the register bank or register class of \p Reg. /// \note Before the register bank gets assigned (i.e., before the /// RegBankSelect pass) \p Reg may not have either. - /// const RegClassOrRegBank &getRegClassOrRegBank(unsigned Reg) const { return VRegInfo[Reg].first; } /// setRegClass - Set the register class of the specified virtual register. - /// void setRegClass(unsigned Reg, const TargetRegisterClass *RC); /// Set the register bank to \p RegBank for \p Reg. - /// void setRegBank(unsigned Reg, const RegisterBank &RegBank); void setRegClassOrRegBank(unsigned Reg, @@ -653,7 +650,6 @@ public: /// new register class, or NULL if no such class exists. /// This should only be used when the constraint is known to be trivial, like /// GR32 -> GR32_NOSP. Beware of increasing register pressure. - /// const TargetRegisterClass *constrainRegClass(unsigned Reg, const TargetRegisterClass *RC, unsigned MinNumRegs = 0); @@ -665,12 +661,10 @@ public: /// This method can be used after constraints have been removed from a /// virtual register, for example after removing instructions or splitting /// the live range. - /// bool recomputeRegClass(unsigned Reg); /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. - /// unsigned createVirtualRegister(const TargetRegisterClass *RegClass); /// Accessor for VRegToType. This accessor should only be used @@ -704,7 +698,6 @@ public: unsigned createIncompleteVirtualRegister(); /// getNumVirtRegs - Return the number of virtual registers created. - /// unsigned getNumVirtRegs() const { return VRegInfo.size(); } /// clearVirtRegs - Remove all virtual registers (after physreg assignment). @@ -810,7 +803,6 @@ public: /// /// Reserved registers may belong to an allocatable register class, but the /// target has explicitly requested that they are not used. - /// bool isReserved(unsigned PhysReg) const { return getReservedRegs().test(PhysReg); } @@ -838,8 +830,8 @@ public: // Iteration support for the live-ins set. It's kept in sorted order // by register number. - typedef std::vector>::const_iterator - livein_iterator; + using livein_iterator = + std::vector>::const_iterator; livein_iterator livein_begin() const { return LiveIns.begin(); } livein_iterator livein_end() const { return LiveIns.end(); } bool livein_empty() const { return LiveIns.empty(); } @@ -910,10 +902,10 @@ public: } public: - typedef std::iterator::reference reference; - typedef std::iterator::pointer pointer; + using reference = std::iterator::reference; + using pointer = std::iterator::pointer; defusechain_iterator() = default; @@ -1016,10 +1008,10 @@ public: } public: - typedef std::iterator::reference reference; - typedef std::iterator::pointer pointer; + using reference = std::iterator::reference; + using pointer = std::iterator::pointer; defusechain_instr_iterator() = default; diff --git a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h index 6b2a16e1d36e..3b02ec400aba 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h @@ -104,10 +104,15 @@ extern cl::opt ForceBottomUp; class LiveIntervals; class MachineDominatorTree; +class MachineFunction; +class MachineInstr; class MachineLoopInfo; class RegisterClassInfo; class SchedDFSResult; class ScheduleHazardRecognizer; +class TargetInstrInfo; +class TargetPassConfig; +class TargetRegisterInfo; /// MachineSchedContext provides enough context from the MachineScheduler pass /// for the target to instantiate a scheduler. @@ -129,10 +134,10 @@ struct MachineSchedContext { /// schedulers. class MachineSchedRegistry : public MachinePassRegistryNode { public: - typedef ScheduleDAGInstrs *(*ScheduleDAGCtor)(MachineSchedContext *); + using ScheduleDAGCtor = ScheduleDAGInstrs *(*)(MachineSchedContext *); // RegisterPassParser requires a (misnamed) FunctionPassCtor type. - typedef ScheduleDAGCtor FunctionPassCtor; + using FunctionPassCtor = ScheduleDAGCtor; static MachinePassRegistry Registry; @@ -527,7 +532,7 @@ public: unsigned size() const { return Queue.size(); } - typedef std::vector::iterator iterator; + using iterator = std::vector::iterator; iterator begin() { return Queue.begin(); } diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/CostAllocator.h b/contrib/llvm/include/llvm/CodeGen/PBQP/CostAllocator.h index 02d39fe383f1..bde451ae1fcc 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/CostAllocator.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/CostAllocator.h @@ -1,4 +1,4 @@ -//===---------- CostAllocator.h - PBQP Cost Allocator -----------*- C++ -*-===// +//===- CostAllocator.h - PBQP Cost Allocator --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,26 +19,28 @@ #define LLVM_CODEGEN_PBQP_COSTALLOCATOR_H #include "llvm/ADT/DenseSet.h" +#include +#include #include -#include namespace llvm { namespace PBQP { -template -class ValuePool { +template class ValuePool { public: - typedef std::shared_ptr PoolRef; + using PoolRef = std::shared_ptr; private: - class PoolEntry : public std::enable_shared_from_this { public: template PoolEntry(ValuePool &Pool, ValueKeyT Value) : Pool(Pool), Value(std::move(Value)) {} + ~PoolEntry() { Pool.removeEntry(this); } - const ValueT& getValue() const { return Value; } + + const ValueT &getValue() const { return Value; } + private: ValuePool &Pool; ValueT Value; @@ -46,10 +48,10 @@ private: class PoolEntryDSInfo { public: - static inline PoolEntry* getEmptyKey() { return nullptr; } + static inline PoolEntry *getEmptyKey() { return nullptr; } - static inline PoolEntry* getTombstoneKey() { - return reinterpret_cast(static_cast(1)); + static inline PoolEntry *getTombstoneKey() { + return reinterpret_cast(static_cast(1)); } template @@ -66,8 +68,7 @@ private: } template - static - bool isEqual(const ValueKeyT1 &C1, const ValueKeyT2 &C2) { + static bool isEqual(const ValueKeyT1 &C1, const ValueKeyT2 &C2) { return C1 == C2; } @@ -83,10 +84,9 @@ private: return P1 == P2; return isEqual(P1->getValue(), P2); } - }; - typedef DenseSet EntrySetT; + using EntrySetT = DenseSet; EntrySetT EntrySet; @@ -105,28 +105,31 @@ public: } }; -template -class PoolCostAllocator { +template class PoolCostAllocator { private: - typedef ValuePool VectorCostPool; - typedef ValuePool MatrixCostPool; + using VectorCostPool = ValuePool; + using MatrixCostPool = ValuePool; + public: - typedef VectorT Vector; - typedef MatrixT Matrix; - typedef typename VectorCostPool::PoolRef VectorPtr; - typedef typename MatrixCostPool::PoolRef MatrixPtr; + using Vector = VectorT; + using Matrix = MatrixT; + using VectorPtr = typename VectorCostPool::PoolRef; + using MatrixPtr = typename MatrixCostPool::PoolRef; - template - VectorPtr getVector(VectorKeyT v) { return VectorPool.getValue(std::move(v)); } + template VectorPtr getVector(VectorKeyT v) { + return VectorPool.getValue(std::move(v)); + } + + template MatrixPtr getMatrix(MatrixKeyT m) { + return MatrixPool.getValue(std::move(m)); + } - template - MatrixPtr getMatrix(MatrixKeyT m) { return MatrixPool.getValue(std::move(m)); } private: VectorCostPool VectorPool; MatrixCostPool MatrixPool; }; -} // namespace PBQP -} // namespace llvm +} // end namespace PBQP +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_PBQP_COSTALLOCATOR_H diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h index 83487e6a808a..e94878ced10d 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h @@ -1,4 +1,4 @@ -//===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===// +//===- Graph.h - PBQP Graph -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,16 +11,14 @@ // //===----------------------------------------------------------------------===// - #ifndef LLVM_CODEGEN_PBQP_GRAPH_H #define LLVM_CODEGEN_PBQP_GRAPH_H #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Debug.h" #include #include +#include #include -#include #include namespace llvm { @@ -28,8 +26,8 @@ namespace PBQP { class GraphBase { public: - typedef unsigned NodeId; - typedef unsigned EdgeId; + using NodeId = unsigned; + using EdgeId = unsigned; /// @brief Returns a value representing an invalid (non-existent) node. static NodeId invalidNodeId() { @@ -48,32 +46,32 @@ namespace PBQP { template class Graph : public GraphBase { private: - typedef typename SolverT::CostAllocator CostAllocator; + using CostAllocator = typename SolverT::CostAllocator; + public: - typedef typename SolverT::RawVector RawVector; - typedef typename SolverT::RawMatrix RawMatrix; - typedef typename SolverT::Vector Vector; - typedef typename SolverT::Matrix Matrix; - typedef typename CostAllocator::VectorPtr VectorPtr; - typedef typename CostAllocator::MatrixPtr MatrixPtr; - typedef typename SolverT::NodeMetadata NodeMetadata; - typedef typename SolverT::EdgeMetadata EdgeMetadata; - typedef typename SolverT::GraphMetadata GraphMetadata; + using RawVector = typename SolverT::RawVector; + using RawMatrix = typename SolverT::RawMatrix; + using Vector = typename SolverT::Vector; + using Matrix = typename SolverT::Matrix; + using VectorPtr = typename CostAllocator::VectorPtr; + using MatrixPtr = typename CostAllocator::MatrixPtr; + using NodeMetadata = typename SolverT::NodeMetadata; + using EdgeMetadata = typename SolverT::EdgeMetadata; + using GraphMetadata = typename SolverT::GraphMetadata; private: - class NodeEntry { public: - typedef std::vector AdjEdgeList; - typedef AdjEdgeList::size_type AdjEdgeIdx; - typedef AdjEdgeList::const_iterator AdjEdgeItr; + using AdjEdgeList = std::vector; + using AdjEdgeIdx = AdjEdgeList::size_type; + using AdjEdgeItr = AdjEdgeList::const_iterator; + + NodeEntry(VectorPtr Costs) : Costs(std::move(Costs)) {} static AdjEdgeIdx getInvalidAdjEdgeIdx() { return std::numeric_limits::max(); } - NodeEntry(VectorPtr Costs) : Costs(std::move(Costs)) {} - AdjEdgeIdx addAdjEdgeId(EdgeId EId) { AdjEdgeIdx Idx = AdjEdgeIds.size(); AdjEdgeIds.push_back(EId); @@ -96,6 +94,7 @@ namespace PBQP { VectorPtr Costs; NodeMetadata Metadata; + private: AdjEdgeList AdjEdgeIds; }; @@ -150,8 +149,10 @@ namespace PBQP { NodeId getN1Id() const { return NIds[0]; } NodeId getN2Id() const { return NIds[1]; } + MatrixPtr Costs; EdgeMetadata Metadata; + private: NodeId NIds[2]; typename NodeEntry::AdjEdgeIdx ThisEdgeAdjIdxs[2]; @@ -161,18 +162,20 @@ namespace PBQP { GraphMetadata Metadata; CostAllocator CostAlloc; - SolverT *Solver; + SolverT *Solver = nullptr; - typedef std::vector NodeVector; - typedef std::vector FreeNodeVector; + using NodeVector = std::vector; + using FreeNodeVector = std::vector; NodeVector Nodes; FreeNodeVector FreeNodeIds; - typedef std::vector EdgeVector; - typedef std::vector FreeEdgeVector; + using EdgeVector = std::vector; + using FreeEdgeVector = std::vector; EdgeVector Edges; FreeEdgeVector FreeEdgeIds; + Graph(const Graph &Other) {} + // ----- INTERNAL METHODS ----- NodeEntry &getNode(NodeId NId) { @@ -220,20 +223,18 @@ namespace PBQP { return EId; } - Graph(const Graph &Other) {} void operator=(const Graph &Other) {} public: - - typedef typename NodeEntry::AdjEdgeItr AdjEdgeItr; + using AdjEdgeItr = typename NodeEntry::AdjEdgeItr; class NodeItr { public: - typedef std::forward_iterator_tag iterator_category; - typedef NodeId value_type; - typedef int difference_type; - typedef NodeId* pointer; - typedef NodeId& reference; + using iterator_category = std::forward_iterator_tag; + using value_type = NodeId; + using difference_type = int; + using pointer = NodeId *; + using reference = NodeId &; NodeItr(NodeId CurNId, const Graph &G) : CurNId(CurNId), EndNId(G.Nodes.size()), FreeNodeIds(G.FreeNodeIds) { @@ -283,53 +284,65 @@ namespace PBQP { class NodeIdSet { public: - NodeIdSet(const Graph &G) : G(G) { } + NodeIdSet(const Graph &G) : G(G) {} + NodeItr begin() const { return NodeItr(0, G); } NodeItr end() const { return NodeItr(G.Nodes.size(), G); } + bool empty() const { return G.Nodes.empty(); } + typename NodeVector::size_type size() const { return G.Nodes.size() - G.FreeNodeIds.size(); } + private: const Graph& G; }; class EdgeIdSet { public: - EdgeIdSet(const Graph &G) : G(G) { } + EdgeIdSet(const Graph &G) : G(G) {} + EdgeItr begin() const { return EdgeItr(0, G); } EdgeItr end() const { return EdgeItr(G.Edges.size(), G); } + bool empty() const { return G.Edges.empty(); } + typename NodeVector::size_type size() const { return G.Edges.size() - G.FreeEdgeIds.size(); } + private: const Graph& G; }; class AdjEdgeIdSet { public: - AdjEdgeIdSet(const NodeEntry &NE) : NE(NE) { } + AdjEdgeIdSet(const NodeEntry &NE) : NE(NE) {} + typename NodeEntry::AdjEdgeItr begin() const { return NE.getAdjEdgeIds().begin(); } + typename NodeEntry::AdjEdgeItr end() const { return NE.getAdjEdgeIds().end(); } + bool empty() const { return NE.getAdjEdgeIds().empty(); } + typename NodeEntry::AdjEdgeList::size_type size() const { return NE.getAdjEdgeIds().size(); } + private: const NodeEntry &NE; }; /// @brief Construct an empty PBQP graph. - Graph() : Solver(nullptr) {} + Graph() = default; /// @brief Construct an empty PBQP graph with the given graph metadata. - Graph(GraphMetadata Metadata) - : Metadata(std::move(Metadata)), Solver(nullptr) {} + Graph(GraphMetadata Metadata) : Metadata(std::move(Metadata)) {} /// @brief Get a reference to the graph metadata. GraphMetadata& getMetadata() { return Metadata; } @@ -656,7 +669,7 @@ namespace PBQP { } }; -} // namespace PBQP -} // namespace llvm +} // end namespace PBQP +} // end namespace llvm #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h index 278787550a43..ba405e816d10 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h @@ -1,4 +1,4 @@ -//===------ Math.h - PBQP Vector and Matrix classes -------------*- C++ -*-===// +//===- Math.h - PBQP Vector and Matrix classes ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,20 +11,22 @@ #define LLVM_CODEGEN_PBQP_MATH_H #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/STLExtras.h" #include #include #include +#include namespace llvm { namespace PBQP { -typedef float PBQPNum; +using PBQPNum = float; /// \brief PBQP Vector class. class Vector { friend hash_code hash_value(const Vector &); -public: +public: /// \brief Construct a PBQP vector of the given size. explicit Vector(unsigned Length) : Length(Length), Data(llvm::make_unique(Length)) {} @@ -120,8 +122,8 @@ OStream& operator<<(OStream &OS, const Vector &V) { class Matrix { private: friend hash_code hash_value(const Matrix &); -public: +public: /// \brief Construct a PBQP Matrix with the given dimensions. Matrix(unsigned Rows, unsigned Cols) : Rows(Rows), Cols(Cols), Data(llvm::make_unique(Rows * Cols)) { @@ -253,9 +255,11 @@ OStream& operator<<(OStream &OS, const Matrix &M) { template class MDVector : public Vector { public: - MDVector(const Vector &v) : Vector(v), md(*this) { } + MDVector(const Vector &v) : Vector(v), md(*this) {} MDVector(Vector &&v) : Vector(std::move(v)), md(*this) { } + const Metadata& getMetadata() const { return md; } + private: Metadata md; }; @@ -268,9 +272,11 @@ inline hash_code hash_value(const MDVector &V) { template class MDMatrix : public Matrix { public: - MDMatrix(const Matrix &m) : Matrix(m), md(*this) { } + MDMatrix(const Matrix &m) : Matrix(m), md(*this) {} MDMatrix(Matrix &&m) : Matrix(std::move(m)), md(*this) { } + const Metadata& getMetadata() const { return md; } + private: Metadata md; }; @@ -280,7 +286,7 @@ inline hash_code hash_value(const MDMatrix &M) { return hash_value(static_cast(M)); } -} // namespace PBQP -} // namespace llvm +} // end namespace PBQP +} // end namespace llvm #endif // LLVM_CODEGEN_PBQP_MATH_H diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h b/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h index d4a544bfe721..8aeb51936760 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -1,4 +1,4 @@ -//===----------- ReductionRules.h - Reduction Rules -------------*- C++ -*-===// +//===- ReductionRules.h - Reduction Rules -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,6 +17,8 @@ #include "Graph.h" #include "Math.h" #include "Solution.h" +#include +#include namespace llvm { namespace PBQP { @@ -27,11 +29,11 @@ namespace PBQP { /// neighbor. Notify the problem domain. template void applyR1(GraphT &G, typename GraphT::NodeId NId) { - typedef typename GraphT::NodeId NodeId; - typedef typename GraphT::EdgeId EdgeId; - typedef typename GraphT::Vector Vector; - typedef typename GraphT::Matrix Matrix; - typedef typename GraphT::RawVector RawVector; + using NodeId = typename GraphT::NodeId; + using EdgeId = typename GraphT::EdgeId; + using Vector = typename GraphT::Vector; + using Matrix = typename GraphT::Matrix; + using RawVector = typename GraphT::RawVector; assert(G.getNodeDegree(NId) == 1 && "R1 applied to node with degree != 1."); @@ -71,11 +73,11 @@ namespace PBQP { template void applyR2(GraphT &G, typename GraphT::NodeId NId) { - typedef typename GraphT::NodeId NodeId; - typedef typename GraphT::EdgeId EdgeId; - typedef typename GraphT::Vector Vector; - typedef typename GraphT::Matrix Matrix; - typedef typename GraphT::RawMatrix RawMatrix; + using NodeId = typename GraphT::NodeId; + using EdgeId = typename GraphT::EdgeId; + using Vector = typename GraphT::Vector; + using Matrix = typename GraphT::Matrix; + using RawMatrix = typename GraphT::RawMatrix; assert(G.getNodeDegree(NId) == 2 && "R2 applied to node with degree != 2."); @@ -177,9 +179,9 @@ namespace PBQP { // state. template Solution backpropagate(GraphT& G, StackT stack) { - typedef GraphBase::NodeId NodeId; - typedef typename GraphT::Matrix Matrix; - typedef typename GraphT::RawVector RawVector; + using NodeId = GraphBase::NodeId; + using Matrix = typename GraphT::Matrix; + using RawVector = typename GraphT::RawVector; Solution s; @@ -215,7 +217,7 @@ namespace PBQP { return s; } -} // namespace PBQP -} // namespace llvm +} // end namespace PBQP +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_PBQP_REDUCTIONRULES_H diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h index d96b5eac4520..8d5d2374679d 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h @@ -26,7 +26,7 @@ namespace PBQP { /// To get the selection for each node in the problem use the getSelection method. class Solution { private: - typedef std::map SelectionsMap; + using SelectionsMap = std::map; SelectionsMap selections; unsigned r0Reductions = 0; diff --git a/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h b/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h index 833b9bad613f..269b7a7b3a35 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h @@ -1,4 +1,4 @@ -//===-- RegAllocPBQP.h ------------------------------------------*- C++ -*-===// +//===- RegAllocPBQP.h -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,23 +16,22 @@ #ifndef LLVM_CODEGEN_PBQPRACONSTRAINT_H #define LLVM_CODEGEN_PBQPRACONSTRAINT_H +#include #include #include namespace llvm { + namespace PBQP { namespace RegAlloc { + // Forward declare PBQP graph class. class PBQPRAGraph; -} -} -class LiveIntervals; -class MachineBlockFrequencyInfo; -class MachineFunction; -class TargetRegisterInfo; +} // end namespace RegAlloc +} // end namespace PBQP -typedef PBQP::RegAlloc::PBQPRAGraph PBQPRAGraph; +using PBQPRAGraph = PBQP::RegAlloc::PBQPRAGraph; /// @brief Abstract base for classes implementing PBQP register allocation /// constraints (e.g. Spill-costs, interference, coalescing). @@ -40,6 +39,7 @@ class PBQPRAConstraint { public: virtual ~PBQPRAConstraint() = 0; virtual void apply(PBQPRAGraph &G) = 0; + private: virtual void anchor(); }; @@ -59,11 +59,13 @@ public: if (C) Constraints.push_back(std::move(C)); } + private: std::vector> Constraints; + void anchor() override; }; -} +} // end namespace llvm -#endif /* LLVM_CODEGEN_PBQPRACONSTRAINT_H */ +#endif // LLVM_CODEGEN_PBQPRACONSTRAINT_H diff --git a/contrib/llvm/include/llvm/CodeGen/Passes.h b/contrib/llvm/include/llvm/CodeGen/Passes.h index 3bcfc1c4254b..96cfce5b84df 100644 --- a/contrib/llvm/include/llvm/CodeGen/Passes.h +++ b/contrib/llvm/include/llvm/CodeGen/Passes.h @@ -140,6 +140,9 @@ namespace llvm { /// Greedy register allocator. extern char &RAGreedyID; + /// Basic register allocator. + extern char &RABasicID; + /// VirtRegRewriter pass. Rewrite virtual registers to physical registers as /// assigned in VirtRegMap. extern char &VirtRegRewriterID; diff --git a/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h index 8872a5dc54a1..5b342863eb50 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h +++ b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h @@ -130,10 +130,10 @@ inline hash_code hash_value(const AllowedRegVector &OptRegs) { /// \brief Holds graph-level metadata relevant to PBQP RA problems. class GraphMetadata { private: - typedef ValuePool AllowedRegVecPool; + using AllowedRegVecPool = ValuePool; public: - typedef AllowedRegVecPool::PoolRef AllowedRegVecRef; + using AllowedRegVecRef = AllowedRegVecPool::PoolRef; GraphMetadata(MachineFunction &MF, LiveIntervals &LIS, @@ -167,17 +167,17 @@ private: /// \brief Holds solver state and other metadata relevant to each PBQP RA node. class NodeMetadata { public: - typedef RegAlloc::AllowedRegVector AllowedRegVector; + using AllowedRegVector = RegAlloc::AllowedRegVector; // The node's reduction state. The order in this enum is important, // as it is assumed nodes can only progress up (i.e. towards being // optimally reducible) when reducing the graph. - typedef enum { + using ReductionState = enum { Unprocessed, NotProvablyAllocatable, ConservativelyAllocatable, OptimallyReducible - } ReductionState; + }; NodeMetadata() = default; @@ -267,23 +267,23 @@ private: class RegAllocSolverImpl { private: - typedef MDMatrix RAMatrix; + using RAMatrix = MDMatrix; public: - typedef PBQP::Vector RawVector; - typedef PBQP::Matrix RawMatrix; - typedef PBQP::Vector Vector; - typedef RAMatrix Matrix; - typedef PBQP::PoolCostAllocator CostAllocator; + using RawVector = PBQP::Vector; + using RawMatrix = PBQP::Matrix; + using Vector = PBQP::Vector; + using Matrix = RAMatrix; + using CostAllocator = PBQP::PoolCostAllocator; - typedef GraphBase::NodeId NodeId; - typedef GraphBase::EdgeId EdgeId; + using NodeId = GraphBase::NodeId; + using EdgeId = GraphBase::EdgeId; - typedef RegAlloc::NodeMetadata NodeMetadata; - struct EdgeMetadata { }; - typedef RegAlloc::GraphMetadata GraphMetadata; + using NodeMetadata = RegAlloc::NodeMetadata; + struct EdgeMetadata {}; + using GraphMetadata = RegAlloc::GraphMetadata; - typedef PBQP::Graph Graph; + using Graph = PBQP::Graph; RegAllocSolverImpl(Graph &G) : G(G) {} @@ -426,7 +426,7 @@ private: std::vector reduce() { assert(!G.empty() && "Cannot reduce empty graph."); - typedef GraphBase::NodeId NodeId; + using NodeId = GraphBase::NodeId; std::vector NodeStack; // Consume worklists. @@ -459,7 +459,6 @@ private: ConservativelyAllocatableNodes.erase(NItr); NodeStack.push_back(NId); G.disconnectAllNeighborsFromNode(NId); - } else if (!NotProvablyAllocatableNodes.empty()) { NodeSet::iterator NItr = std::min_element(NotProvablyAllocatableNodes.begin(), @@ -493,7 +492,7 @@ private: }; Graph& G; - typedef std::set NodeSet; + using NodeSet = std::set; NodeSet OptimallyReducibleNodes; NodeSet ConservativelyAllocatableNodes; NodeSet NotProvablyAllocatableNodes; @@ -501,7 +500,7 @@ private: class PBQPRAGraph : public PBQP::Graph { private: - typedef PBQP::Graph BaseT; + using BaseT = PBQP::Graph; public: PBQPRAGraph(GraphMetadata Metadata) : BaseT(std::move(Metadata)) {} diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h index 1f939e72e139..ad1efe18c72d 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h @@ -204,6 +204,10 @@ private: void setLiveInsUsed(const MachineBasicBlock &MBB); }; +/// Replaces all frame index virtual registers with physical registers. Uses the +/// register scavenger to find an appropriate register to use. +void scavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger &RS); + } // end namespace llvm #endif // LLVM_CODEGEN_REGISTERSCAVENGING_H diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h index f5f5bfd45e79..d62bb9bf0b75 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -1,4 +1,4 @@ -//==- ScheduleDAGInstrs.h - MachineInstr Scheduling --------------*- C++ -*-==// +//===- ScheduleDAGInstrs.h - MachineInstr Scheduling ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,22 +15,38 @@ #ifndef LLVM_CODEGEN_SCHEDULEDAGINSTRS_H #define LLVM_CODEGEN_SCHEDULEDAGINSTRS_H -#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SparseMultiSet.h" #include "llvm/ADT/SparseSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/LivePhysRegs.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/CodeGen/TargetSchedule.h" -#include "llvm/Support/Compiler.h" +#include "llvm/MC/LaneBitmask.h" #include "llvm/Target/TargetRegisterInfo.h" +#include +#include #include +#include +#include namespace llvm { + + class LiveIntervals; class MachineFrameInfo; + class MachineFunction; + class MachineInstr; class MachineLoopInfo; - class MachineDominatorTree; - class RegPressureTracker; + class MachineOperand; + struct MCSchedClassDesc; class PressureDiffs; + class PseudoSourceValue; + class RegPressureTracker; + class UndefValue; + class Value; /// An individual mapping from virtual register number to SUnit. struct VReg2SUnit { @@ -70,31 +86,34 @@ namespace llvm { /// Use a SparseMultiSet to track physical registers. Storage is only /// allocated once for the pass. It can be cleared in constant time and reused /// without any frees. - typedef SparseMultiSet, uint16_t> - Reg2SUnitsMap; + using Reg2SUnitsMap = + SparseMultiSet, uint16_t>; /// Use SparseSet as a SparseMap by relying on the fact that it never /// compares ValueT's, only unsigned keys. This allows the set to be cleared /// between scheduling regions in constant time as long as ValueT does not /// require a destructor. - typedef SparseSet VReg2SUnitMap; + using VReg2SUnitMap = SparseSet; /// Track local uses of virtual registers. These uses are gathered by the DAG /// builder and may be consulted by the scheduler to avoid iterating an entire /// vreg use list. - typedef SparseMultiSet VReg2SUnitMultiMap; + using VReg2SUnitMultiMap = SparseMultiSet; - typedef SparseMultiSet - VReg2SUnitOperIdxMultiMap; + using VReg2SUnitOperIdxMultiMap = + SparseMultiSet; + + using ValueType = PointerUnion; - typedef PointerUnion ValueType; struct UnderlyingObject : PointerIntPair { UnderlyingObject(ValueType V, bool MayAlias) : PointerIntPair(V, MayAlias) {} + ValueType getValue() const { return getPointer(); } bool mayAlias() const { return getInt(); } }; - typedef SmallVector UnderlyingObjectsVector; + + using UnderlyingObjectsVector = SmallVector; /// A ScheduleDAG for scheduling lists of MachineInstr. class ScheduleDAGInstrs : public ScheduleDAG { @@ -114,10 +133,10 @@ namespace llvm { /// reordering. A specialized scheduler can override /// TargetInstrInfo::isSchedulingBoundary then enable this flag to indicate /// it has taken responsibility for scheduling the terminator correctly. - bool CanHandleTerminators; + bool CanHandleTerminators = false; /// Whether lane masks should get tracked. - bool TrackLaneMasks; + bool TrackLaneMasks = false; // State specific to the current scheduling region. // ------------------------------------------------ @@ -155,12 +174,12 @@ namespace llvm { /// Tracks the last instructions in this region using each virtual register. VReg2SUnitOperIdxMultiMap CurrentVRegUses; - AliasAnalysis *AAForDep; + AliasAnalysis *AAForDep = nullptr; /// Remember a generic side-effecting instruction as we proceed. /// No other SU ever gets scheduled around it (except in the special /// case of a huge region that gets reduced). - SUnit *BarrierChain; + SUnit *BarrierChain = nullptr; public: /// A list of SUnits, used in Value2SUsMap, during DAG construction. @@ -168,7 +187,7 @@ namespace llvm { /// implementation of this data structure, such as a singly linked list /// with a memory pool (SmallVector was tried but slow and SparseSet is not /// applicable). - typedef std::list SUList; + using SUList = std::list; protected: /// \brief A map from ValueType to SUList, used during DAG construction, as @@ -216,13 +235,13 @@ namespace llvm { /// For an unanalyzable memory access, this Value is used in maps. UndefValue *UnknownValue; - typedef std::vector> - DbgValueVector; + using DbgValueVector = + std::vector>; /// Remember instruction that precedes DBG_VALUE. /// These are generated by buildSchedGraph but persist so they can be /// referenced when emitting the final schedule. DbgValueVector DbgValues; - MachineInstr *FirstDbgValue; + MachineInstr *FirstDbgValue = nullptr; /// Set of live physical registers for updating kill flags. LivePhysRegs LiveRegs; @@ -232,7 +251,7 @@ namespace llvm { const MachineLoopInfo *mli, bool RemoveKillFlags = false); - ~ScheduleDAGInstrs() override {} + ~ScheduleDAGInstrs() override = default; /// Gets the machine model for instruction scheduling. const TargetSchedModel *getSchedModel() const { return &SchedModel; } @@ -354,6 +373,7 @@ namespace llvm { return nullptr; return I->second; } + } // end namespace llvm -#endif +#endif // LLVM_CODEGEN_SCHEDULEDAGINSTRS_H diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h index 493122b15704..4b1a375abd57 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ---------*- C++ -*-===// +//===- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,35 +15,72 @@ #ifndef LLVM_CODEGEN_SELECTIONDAG_H #define LLVM_CODEGEN_SELECTIONDAG_H +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/DAGCombine.h" +#include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Metadata.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/ArrayRecycler.h" +#include "llvm/Support/AtomicOrdering.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/RecyclingAllocator.h" -#include "llvm/Target/TargetMachine.h" +#include #include +#include +#include #include #include +#include +#include #include namespace llvm { +class BlockAddress; +class Constant; +class ConstantFP; +class ConstantInt; +class DataLayout; +struct fltSemantics; +class GlobalValue; struct KnownBits; +class LLVMContext; +class MachineBasicBlock; class MachineConstantPoolValue; -class MachineFunction; -class MDNode; +class MCSymbol; class OptimizationRemarkEmitter; class SDDbgValue; -class TargetLowering; +class SelectionDAG; class SelectionDAGTargetInfo; +class TargetLowering; +class TargetMachine; +class TargetSubtargetInfo; +class Value; class SDVTListNode : public FoldingSetNode { friend struct FoldingSetTrait; + /// A reference to an Interned FoldingSetNodeID for this node. /// The Allocator in SelectionDAG holds the data. /// SDVTList contains all types which are frequently accessed in SelectionDAG. @@ -55,11 +92,13 @@ class SDVTListNode : public FoldingSetNode { /// The hash value for SDVTList is fixed, so cache it to avoid /// hash calculation. unsigned HashValue; + public: SDVTListNode(const FoldingSetNodeIDRef ID, const EVT *VT, unsigned int Num) : FastID(ID), VTs(VT), NumVTs(Num) { HashValue = ID.ComputeHash(); } + SDVTList getSDVTList() { SDVTList result = {VTs, NumVTs}; return result; @@ -72,12 +111,14 @@ template<> struct FoldingSetTrait : DefaultFoldingSetTrait DbgValues; SmallVector ByvalParmDbgValues; - typedef DenseMap > DbgValMapType; + using DbgValMapType = DenseMap>; DbgValMapType DbgValMap; - void operator=(const SDDbgInfo&) = delete; - SDDbgInfo(const SDDbgInfo&) = delete; public: - SDDbgInfo() {} + SDDbgInfo() = default; + SDDbgInfo(const SDDbgInfo &) = delete; + SDDbgInfo &operator=(const SDDbgInfo &) = delete; void add(SDDbgValue *V, const SDNode *Node, bool isParameter) { if (isParameter) { @@ -144,14 +185,14 @@ public: return ArrayRef(); } - typedef SmallVectorImpl::iterator DbgIterator; + using DbgIterator = SmallVectorImpl::iterator; + DbgIterator DbgBegin() { return DbgValues.begin(); } DbgIterator DbgEnd() { return DbgValues.end(); } DbgIterator ByvalParmDbgBegin() { return ByvalParmDbgValues.begin(); } DbgIterator ByvalParmDbgEnd() { return ByvalParmDbgValues.end(); } }; -class SelectionDAG; void checkForCycles(const SelectionDAG *DAG, bool force = false); /// This is used to represent a portion of an LLVM function in a low-level @@ -167,8 +208,8 @@ void checkForCycles(const SelectionDAG *DAG, bool force = false); /// class SelectionDAG { const TargetMachine &TM; - const SelectionDAGTargetInfo *TSI; - const TargetLowering *TLI; + const SelectionDAGTargetInfo *TSI = nullptr; + const TargetLowering *TLI = nullptr; MachineFunction *MF; LLVMContext *Context; CodeGenOpt::Level OptLevel; @@ -188,9 +229,9 @@ class SelectionDAG { /// The AllocatorType for allocating SDNodes. We use /// pool allocation with recycling. - typedef RecyclingAllocator - NodeAllocatorType; + using NodeAllocatorType = RecyclingAllocator; /// Pool allocation for nodes. NodeAllocatorType NodeAllocator; @@ -243,9 +284,11 @@ public: struct DAGNodeDeletedListener : public DAGUpdateListener { std::function Callback; + DAGNodeDeletedListener(SelectionDAG &DAG, std::function Callback) : DAGUpdateListener(DAG), Callback(std::move(Callback)) {} + void NodeDeleted(SDNode *N, SDNode *E) override { Callback(N, E); } }; @@ -254,7 +297,7 @@ public: /// have legal types. This is important after type legalization since /// any illegally typed nodes generated after this point will not experience /// type legalization. - bool NewNodesMustHaveLegalTypes; + bool NewNodesMustHaveLegalTypes = false; private: /// DAGUpdateListener is a friend so it can manipulate the listener stack. @@ -262,7 +305,7 @@ private: /// Linked list of registered DAGUpdateListener instances. /// This stack is maintained by DAGUpdateListener RAII. - DAGUpdateListener *UpdateListeners; + DAGUpdateListener *UpdateListeners = nullptr; /// Implementation of setSubgraphColor. /// Return whether we had to truncate the search. @@ -316,11 +359,10 @@ private: Node->OperandList = nullptr; } - void operator=(const SelectionDAG&) = delete; - SelectionDAG(const SelectionDAG&) = delete; - public: - explicit SelectionDAG(const TargetMachine &TM, llvm::CodeGenOpt::Level); + explicit SelectionDAG(const TargetMachine &TM, CodeGenOpt::Level); + SelectionDAG(const SelectionDAG &) = delete; + SelectionDAG &operator=(const SelectionDAG &) = delete; ~SelectionDAG(); /// Prepare this SelectionDAG to process code in the given MachineFunction. @@ -364,12 +406,16 @@ public: /// Convenience for setting subgraph color attribute. void setSubgraphColor(SDNode *N, const char *Color); - typedef ilist::const_iterator allnodes_const_iterator; + using allnodes_const_iterator = ilist::const_iterator; + allnodes_const_iterator allnodes_begin() const { return AllNodes.begin(); } allnodes_const_iterator allnodes_end() const { return AllNodes.end(); } - typedef ilist::iterator allnodes_iterator; + + using allnodes_iterator = ilist::iterator; + allnodes_iterator allnodes_begin() { return AllNodes.begin(); } allnodes_iterator allnodes_end() { return AllNodes.end(); } + ilist::size_type allnodes_size() const { return AllNodes.size(); } @@ -475,7 +521,6 @@ public: //===--------------------------------------------------------------------===// // Node creation methods. - // /// \brief Create a ConstantSDNode wrapping a constant value. /// If VT is a vector type, the constant is splatted into a BUILD_VECTOR. @@ -1251,9 +1296,11 @@ public: SDDbgInfo::DbgIterator DbgBegin() { return DbgInfo->DbgBegin(); } SDDbgInfo::DbgIterator DbgEnd() { return DbgInfo->DbgEnd(); } + SDDbgInfo::DbgIterator ByvalParmDbgBegin() { return DbgInfo->ByvalParmDbgBegin(); } + SDDbgInfo::DbgIterator ByvalParmDbgEnd() { return DbgInfo->ByvalParmDbgEnd(); } @@ -1479,10 +1526,12 @@ private: }; template <> struct GraphTraits : public GraphTraits { - typedef pointer_iterator nodes_iterator; + using nodes_iterator = pointer_iterator; + static nodes_iterator nodes_begin(SelectionDAG *G) { return nodes_iterator(G->allnodes_begin()); } + static nodes_iterator nodes_end(SelectionDAG *G) { return nodes_iterator(G->allnodes_end()); } @@ -1493,7 +1542,6 @@ SDValue SelectionDAG::getTargetMemSDNode(SDVTList VTs, ArrayRef Ops, const SDLoc &dl, EVT MemVT, MachineMemOperand *MMO) { - /// Compose node ID and try to find an existing node. FoldingSetNodeID ID; unsigned Opcode = @@ -1524,6 +1572,6 @@ SDValue SelectionDAG::getTargetMemSDNode(SDVTList VTs, return SDValue(N, 0); } -} // end namespace llvm +} // end namespace llvm -#endif +#endif // LLVM_CODEGEN_SELECTIONDAG_H diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 973c5aac5281..3a4feb322092 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -37,6 +37,7 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Casting.h" @@ -53,14 +54,18 @@ namespace llvm { -class SelectionDAG; +class APInt; +class Constant; +template struct DenseMapInfo; class GlobalValue; class MachineBasicBlock; class MachineConstantPoolValue; -class SDNode; -class Value; class MCSymbol; -template struct DenseMapInfo; +class raw_ostream; +class SDNode; +class SelectionDAG; +class Type; +class Value; void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr, bool force = false); @@ -229,13 +234,15 @@ template <> struct isPodLike { static const bool value = true; }; /// Allow casting operators to work directly on /// SDValues as if they were SDNode*'s. template<> struct simplify_type { - typedef SDNode* SimpleType; + using SimpleType = SDNode *; + static SimpleType getSimplifiedValue(SDValue &Val) { return Val.getNode(); } }; template<> struct simplify_type { - typedef /*const*/ SDNode* SimpleType; + using SimpleType = /*const*/ SDNode *; + static SimpleType getSimplifiedValue(const SDValue &Val) { return Val.getNode(); } @@ -330,7 +337,8 @@ private: /// simplify_type specializations - Allow casting operators to work directly on /// SDValues as if they were SDNode*'s. template<> struct simplify_type { - typedef SDNode* SimpleType; + using SimpleType = SDNode *; + static SimpleType getSimplifiedValue(SDUse &Val) { return Val.getNode(); } @@ -695,10 +703,10 @@ public: explicit use_iterator(SDUse *op) : Op(op) {} public: - typedef std::iterator::reference reference; - typedef std::iterator::pointer pointer; + using reference = std::iterator::reference; + using pointer = std::iterator::pointer; use_iterator() = default; use_iterator(const use_iterator &I) : Op(I.Op) {} @@ -824,7 +832,7 @@ public: return OperandList[Num]; } - typedef SDUse* op_iterator; + using op_iterator = SDUse *; op_iterator op_begin() const { return OperandList; } op_iterator op_end() const { return OperandList+NumOperands; } @@ -896,7 +904,8 @@ public: return getValueType(ResNo).getSizeInBits(); } - typedef const EVT* value_iterator; + using value_iterator = const EVT *; + value_iterator value_begin() const { return ValueList; } value_iterator value_end() const { return ValueList+NumValues; } @@ -1822,8 +1831,7 @@ class BlockAddressSDNode : public SDNode { BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, int64_t o, unsigned char Flags) : SDNode(NodeTy, 0, DebugLoc(), getSDVTList(VT)), - BA(ba), Offset(o), TargetFlags(Flags) { - } + BA(ba), Offset(o), TargetFlags(Flags) {} public: const BlockAddress *getBlockAddress() const { return BA; } @@ -2154,7 +2162,7 @@ public: /// instruction selection proper phase. class MachineSDNode : public SDNode { public: - typedef MachineMemOperand **mmo_iterator; + using mmo_iterator = MachineMemOperand **; private: friend class SelectionDAG; @@ -2226,8 +2234,8 @@ public: }; template <> struct GraphTraits { - typedef SDNode *NodeRef; - typedef SDNodeIterator ChildIteratorType; + using NodeRef = SDNode *; + using ChildIteratorType = SDNodeIterator; static NodeRef getEntryNode(SDNode *N) { return N; } @@ -2244,12 +2252,12 @@ template <> struct GraphTraits { /// /// This needs to be a union because the largest node differs on 32 bit systems /// with 4 and 8 byte pointer alignment, respectively. -typedef AlignedCharArrayUnion - LargestSDNode; +using LargestSDNode = AlignedCharArrayUnion; /// The SDNode class with the greatest alignment requirement. -typedef GlobalAddressSDNode MostAlignedSDNode; +using MostAlignedSDNode = GlobalAddressSDNode; namespace ISD { diff --git a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h index 14fc3a499a08..a275b2721b44 100644 --- a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h +++ b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h @@ -20,17 +20,26 @@ #define LLVM_CODEGEN_SLOTINDEXES_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ilist.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/ilist.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/Pass.h" #include "llvm/Support/Allocator.h" +#include +#include +#include +#include namespace llvm { +class raw_ostream; + /// This class represents an entry in the slot index list held in the /// SlotIndexes pass. It should not be used directly. See the /// SlotIndex & SlotIndexes classes for the public interface to this @@ -40,7 +49,6 @@ namespace llvm { unsigned index; public: - IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) {} MachineInstr* getInstr() const { return mi; } @@ -301,7 +309,7 @@ namespace llvm { return os; } - typedef std::pair IdxMBBPair; + using IdxMBBPair = std::pair; inline bool operator<(SlotIndex V, const IdxMBBPair &IM) { return V < IM.first; @@ -325,7 +333,7 @@ namespace llvm { // IndexListEntry allocator. BumpPtrAllocator ileAllocator; - typedef ilist IndexList; + using IndexList = ilist; IndexList indexList; #ifdef EXPENSIVE_CHECKS @@ -334,7 +342,7 @@ namespace llvm { MachineFunction *mf; - typedef DenseMap Mi2IndexMap; + using Mi2IndexMap = DenseMap; Mi2IndexMap mi2iMap; /// MBBRanges - Map MBB number to (start, stop) indexes. @@ -436,7 +444,7 @@ namespace llvm { const MachineBasicBlock *MBB = MI.getParent(); assert(MBB && "MI must be inserted inna basic block"); MachineBasicBlock::const_iterator I = MI, B = MBB->begin(); - for (;;) { + while (true) { if (I == B) return getMBBStartIdx(MBB); --I; @@ -453,7 +461,7 @@ namespace llvm { const MachineBasicBlock *MBB = MI.getParent(); assert(MBB && "MI must be inserted inna basic block"); MachineBasicBlock::const_iterator I = MI, E = MBB->end(); - for (;;) { + while (true) { ++I; if (I == E) return getMBBEndIdx(MBB); @@ -497,21 +505,25 @@ namespace llvm { /// Iterator over the idx2MBBMap (sorted pairs of slot index of basic block /// begin and basic block) - typedef SmallVectorImpl::const_iterator MBBIndexIterator; + using MBBIndexIterator = SmallVectorImpl::const_iterator; + /// Move iterator to the next IdxMBBPair where the SlotIndex is greater or /// equal to \p To. MBBIndexIterator advanceMBBIndex(MBBIndexIterator I, SlotIndex To) const { return std::lower_bound(I, idx2MBBMap.end(), To); } + /// Get an iterator pointing to the IdxMBBPair with the biggest SlotIndex /// that is greater or equal to \p Idx. MBBIndexIterator findMBBIndex(SlotIndex Idx) const { return advanceMBBIndex(idx2MBBMap.begin(), Idx); } + /// Returns an iterator for the begin of the idx2MBBMap. MBBIndexIterator MBBIndexBegin() const { return idx2MBBMap.begin(); } + /// Return an iterator for the end of the idx2MBBMap. MBBIndexIterator MBBIndexEnd() const { return idx2MBBMap.end(); diff --git a/contrib/llvm/include/llvm/CodeGen/StackMaps.h b/contrib/llvm/include/llvm/CodeGen/StackMaps.h index a18936feea7b..8263946ed928 100644 --- a/contrib/llvm/include/llvm/CodeGen/StackMaps.h +++ b/contrib/llvm/include/llvm/CodeGen/StackMaps.h @@ -145,21 +145,27 @@ public: /// /// Statepoint operands take the form: /// , , , , -/// [call arguments], , , +/// [call arguments...], +/// , , /// , , -/// , , [other args], -/// [gc values] +/// , , [deopt args...], +/// +/// Note that the last two sets of arguments are not currently length +/// prefixed. class StatepointOpers { -private: + // TODO:: we should change the STATEPOINT representation so that CC and + // Flags should be part of meta operands, with args and deopt operands, and + // gc operands all prefixed by their length and a type code. This would be + // much more consistent. +public: // These values are aboolute offsets into the operands of the statepoint // instruction. enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd }; // These values are relative offests from the start of the statepoint meta // arguments (i.e. the end of the call arguments). - enum { CCOffset = 1, FlagsOffset = 3, NumVMSArgsOffset = 5 }; + enum { CCOffset = 1, FlagsOffset = 3, NumDeoptOperandsOffset = 5 }; -public: explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {} /// Get starting index of non call related arguments @@ -220,7 +226,7 @@ public: // OpTypes are used to encode information about the following logical // operand (which may consist of several MachineOperands) for the // OpParser. - typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType; + using OpType = enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp }; StackMaps(AsmPrinter &AP); @@ -248,9 +254,10 @@ public: private: static const char *WSMP; - typedef SmallVector LocationVec; - typedef SmallVector LiveOutVec; - typedef MapVector ConstantPool; + + using LocationVec = SmallVector; + using LiveOutVec = SmallVector; + using ConstantPool = MapVector; struct FunctionInfo { uint64_t StackSize = 0; @@ -273,8 +280,8 @@ private: LiveOuts(std::move(LiveOuts)) {} }; - typedef MapVector FnInfoMap; - typedef std::vector CallsiteInfoList; + using FnInfoMap = MapVector; + using CallsiteInfoList = std::vector; AsmPrinter &AP; CallsiteInfoList CSInfos; diff --git a/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h b/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h index 1992412120aa..4365fca74bf1 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h @@ -55,6 +55,9 @@ public: /// Return the MCSchedClassDesc for this instruction. const MCSchedClassDesc *resolveSchedClass(const MachineInstr *MI) const; + /// \brief TargetSubtargetInfo getter. + const TargetSubtargetInfo *getSubtargetInfo() const { return STI; } + /// \brief TargetInstrInfo getter. const TargetInstrInfo *getInstrInfo() const { return TII; } diff --git a/contrib/llvm/include/llvm/CodeGen/WinEHFuncInfo.h b/contrib/llvm/include/llvm/CodeGen/WinEHFuncInfo.h index dd730495a5f6..8043024626a0 100644 --- a/contrib/llvm/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/WinEHFuncInfo.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/WinEHFuncInfo.h ----------------------------*- C++ -*-===// +//===- llvm/CodeGen/WinEHFuncInfo.h -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,28 +17,26 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/TinyPtrVector.h" -#include "llvm/IR/Instructions.h" +#include +#include +#include namespace llvm { + class AllocaInst; class BasicBlock; -class CatchReturnInst; -class Constant; +class FuncletPadInst; class Function; class GlobalVariable; +class Instruction; class InvokeInst; -class IntrinsicInst; -class LandingPadInst; -class MCExpr; -class MCSymbol; class MachineBasicBlock; -class Value; +class MCSymbol; // The following structs respresent the .xdata tables for various // Windows-related EH personalities. -typedef PointerUnion MBBOrBasicBlock; +using MBBOrBasicBlock = PointerUnion; struct CxxUnwindMapEntry { int ToState; @@ -99,18 +97,18 @@ struct WinEHFuncInfo { SmallVector TryBlockMap; SmallVector SEHUnwindMap; SmallVector ClrEHUnwindMap; - int UnwindHelpFrameIdx = INT_MAX; - int PSPSymFrameIdx = INT_MAX; + int UnwindHelpFrameIdx = std::numeric_limits::max(); + int PSPSymFrameIdx = std::numeric_limits::max(); int getLastStateNumber() const { return CxxUnwindMap.size() - 1; } void addIPToStateRange(const InvokeInst *II, MCSymbol *InvokeBegin, MCSymbol *InvokeEnd); - int EHRegNodeFrameIndex = INT_MAX; - int EHRegNodeEndOffset = INT_MAX; - int EHGuardFrameIndex = INT_MAX; - int SEHSetFrameOffset = INT_MAX; + int EHRegNodeFrameIndex = std::numeric_limits::max(); + int EHRegNodeEndOffset = std::numeric_limits::max(); + int EHGuardFrameIndex = std::numeric_limits::max(); + int SEHSetFrameOffset = std::numeric_limits::max(); WinEHFuncInfo(); }; @@ -125,5 +123,7 @@ void calculateSEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo); void calculateClrEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo); -} + +} // end namespace llvm + #endif // LLVM_CODEGEN_WINEHFUNCINFO_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index 4e8c8feb7a12..9890263ae2d2 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -574,6 +574,14 @@ struct FrameData { IsFunctionStart = 1 << 2, }; }; + +enum class CodeViewContainer { ObjectFile, Pdb }; + +inline uint32_t alignOf(CodeViewContainer Container) { + if (Container == CodeViewContainer::ObjectFile) + return 1; + return 4; +} } } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h index b3976826a316..db944c7057f7 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -136,6 +136,7 @@ public: Error mapByteVectorTail(ArrayRef &Bytes); Error mapByteVectorTail(std::vector &Bytes); + Error padToAlignment(uint32_t Align); Error skipPadding(); private: diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h index e7036033d2d9..c958a95ee6de 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h @@ -60,8 +60,8 @@ public: Error initialize(BinaryStreamReader Reader); Error initialize(BinaryStreamRef Stream); - Iterator begin() { return Checksums.begin(); } - Iterator end() { return Checksums.end(); } + Iterator begin() const { return Checksums.begin(); } + Iterator end() const { return Checksums.end(); } const FileChecksumArray &getArray() const { return Checksums; } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h index e2cfc3c99233..60440700c265 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h @@ -74,8 +74,13 @@ private: class DebugInlineeLinesSubsection final : public DebugSubsection { public: + struct Entry { + std::vector ExtraFiles; + InlineeSourceLineHeader Header; + }; + DebugInlineeLinesSubsection(DebugChecksumsSubsection &Checksums, - bool HasExtraFiles); + bool HasExtraFiles = false); static bool classof(const DebugSubsection *S) { return S->kind() == DebugSubsectionKind::InlineeLines; @@ -87,16 +92,18 @@ public: void addInlineSite(TypeIndex FuncId, StringRef FileName, uint32_t SourceLine); void addExtraFile(StringRef FileName); + bool hasExtraFiles() const { return HasExtraFiles; } + void setHasExtraFiles(bool Has) { HasExtraFiles = Has; } + + std::vector::const_iterator begin() const { return Entries.begin(); } + std::vector::const_iterator end() const { return Entries.end(); } + private: DebugChecksumsSubsection &Checksums; bool HasExtraFiles = false; uint32_t ExtraFileCount = 0; - struct Entry { - std::vector ExtraFiles; - InlineeSourceLineHeader Header; - }; std::vector Entries; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h index b2e1131e5968..847259c5ceac 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h @@ -31,28 +31,32 @@ struct DebugSubsectionHeader { class DebugSubsectionRecord { public: DebugSubsectionRecord(); - DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data); + DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data, + CodeViewContainer Container); - static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info); + static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info, + CodeViewContainer Container); uint32_t getRecordLength() const; DebugSubsectionKind kind() const; BinaryStreamRef getRecordData() const; private: + CodeViewContainer Container; DebugSubsectionKind Kind; BinaryStreamRef Data; }; class DebugSubsectionRecordBuilder { public: - DebugSubsectionRecordBuilder(DebugSubsectionKind Kind, DebugSubsection &Frag); + DebugSubsectionRecordBuilder(std::unique_ptr Subsection, + CodeViewContainer Container); uint32_t calculateSerializedLength(); Error commit(BinaryStreamWriter &Writer); private: - DebugSubsectionKind Kind; - DebugSubsection &Frag; + std::unique_ptr Subsection; + CodeViewContainer Container; }; } // namespace codeview @@ -62,7 +66,12 @@ template <> struct VarStreamArrayExtractor { static Error extract(BinaryStreamRef Stream, uint32_t &Length, codeview::DebugSubsectionRecord &Info) { - if (auto EC = codeview::DebugSubsectionRecord::initialize(Stream, Info)) + // FIXME: We need to pass the container type through to this function, but + // VarStreamArray doesn't easily support stateful contexts. In practice + // this isn't super important since the subsection header describes its + // length and we can just skip it. It's more important when writing. + if (auto EC = codeview::DebugSubsectionRecord::initialize( + Stream, Info, codeview::CodeViewContainer::Pdb)) return EC; Length = Info.getRecordLength(); return Error::success(); diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h index 428ff153d5d1..7080b0480757 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h @@ -24,9 +24,9 @@ namespace codeview { class SymbolVisitorDelegate; class SymbolDeserializer : public SymbolVisitorCallbacks { struct MappingInfo { - explicit MappingInfo(ArrayRef RecordData) + MappingInfo(ArrayRef RecordData, CodeViewContainer Container) : Stream(RecordData, llvm::support::little), Reader(Stream), - Mapping(Reader) {} + Mapping(Reader, Container) {} BinaryByteStream Stream; BinaryStreamReader Reader; @@ -35,7 +35,9 @@ class SymbolDeserializer : public SymbolVisitorCallbacks { public: template static Error deserializeAs(CVSymbol Symbol, T &Record) { - SymbolDeserializer S(nullptr); + // If we're just deserializing one record, then don't worry about alignment + // as there's nothing that comes after. + SymbolDeserializer S(nullptr, CodeViewContainer::ObjectFile); if (auto EC = S.visitSymbolBegin(Symbol)) return EC; if (auto EC = S.visitKnownRecord(Symbol, Record)) @@ -45,12 +47,13 @@ public: return Error::success(); } - explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate) - : Delegate(Delegate) {} + explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate, + CodeViewContainer Container) + : Delegate(Delegate), Container(Container) {} Error visitSymbolBegin(CVSymbol &Record) override { assert(!Mapping && "Already in a symbol mapping!"); - Mapping = llvm::make_unique(Record.content()); + Mapping = llvm::make_unique(Record.content(), Container); return Mapping->Mapping.visitSymbolBegin(Record); } Error visitSymbolEnd(CVSymbol &Record) override { @@ -78,6 +81,7 @@ private: } SymbolVisitorDelegate *Delegate; + CodeViewContainer Container; std::unique_ptr Mapping; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h index e91065dcf87e..293daa851bdd 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -26,9 +26,11 @@ class TypeCollection; class CVSymbolDumper { public: CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types, + CodeViewContainer Container, std::unique_ptr ObjDelegate, bool PrintRecordBytes) - : W(W), Types(Types), ObjDelegate(std::move(ObjDelegate)), + : W(W), Types(Types), Container(Container), + ObjDelegate(std::move(ObjDelegate)), PrintRecordBytes(PrintRecordBytes) {} /// Dumps one type record. Returns false if there was a type parsing error, @@ -44,6 +46,7 @@ public: private: ScopedPrinter &W; TypeCollection &Types; + CodeViewContainer Container; std::unique_ptr ObjDelegate; bool PrintRecordBytes; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h index 5d072a3b2723..391e8f127665 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h @@ -20,8 +20,12 @@ class BinaryStreamWriter; namespace codeview { class SymbolRecordMapping : public SymbolVisitorCallbacks { public: - explicit SymbolRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {} - explicit SymbolRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {} + explicit SymbolRecordMapping(BinaryStreamReader &Reader, + CodeViewContainer Container) + : IO(Reader), Container(Container) {} + explicit SymbolRecordMapping(BinaryStreamWriter &Writer, + CodeViewContainer Container) + : IO(Writer), Container(Container) {} Error visitSymbolBegin(CVSymbol &Record) override; Error visitSymbolEnd(CVSymbol &Record) override; @@ -35,6 +39,7 @@ private: Optional Kind; CodeViewRecordIO IO; + CodeViewContainer Container; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h index a8fe1a3ae1d0..42adbdb4e20f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h @@ -46,17 +46,18 @@ class SymbolSerializer : public SymbolVisitorCallbacks { public: template - static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage) { + static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage, + CodeViewContainer Container) { CVSymbol Result; Result.Type = static_cast(Sym.Kind); - SymbolSerializer Serializer(Storage); + SymbolSerializer Serializer(Storage, Container); consumeError(Serializer.visitSymbolBegin(Result)); consumeError(Serializer.visitKnownRecord(Result, Sym)); consumeError(Serializer.visitSymbolEnd(Result)); return Result; } - explicit SymbolSerializer(BumpPtrAllocator &Storage); + SymbolSerializer(BumpPtrAllocator &Storage, CodeViewContainer Container); virtual Error visitSymbolBegin(CVSymbol &Record) override; virtual Error visitSymbolEnd(CVSymbol &Record) override; diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h index d68f5f70c83e..36dce393fc66 100644 --- a/contrib/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h @@ -44,17 +44,19 @@ class MappedBlockStream : public BinaryStream { public: static std::unique_ptr createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, - BinaryStreamRef MsfData); + BinaryStreamRef MsfData, BumpPtrAllocator &Allocator); static std::unique_ptr createIndexedStream(const MSFLayout &Layout, BinaryStreamRef MsfData, - uint32_t StreamIndex); + uint32_t StreamIndex, BumpPtrAllocator &Allocator); static std::unique_ptr - createFpmStream(const MSFLayout &Layout, BinaryStreamRef MsfData); + createFpmStream(const MSFLayout &Layout, BinaryStreamRef MsfData, + BumpPtrAllocator &Allocator); static std::unique_ptr - createDirectoryStream(const MSFLayout &Layout, BinaryStreamRef MsfData); + createDirectoryStream(const MSFLayout &Layout, BinaryStreamRef MsfData, + BumpPtrAllocator &Allocator); llvm::support::endianness getEndian() const override { return llvm::support::little; @@ -67,9 +69,7 @@ public: uint32_t getLength() override; - uint32_t getNumBytesCopied() const; - - llvm::BumpPtrAllocator &getAllocator() { return Pool; } + llvm::BumpPtrAllocator &getAllocator() { return Allocator; } void invalidateCache(); @@ -79,7 +79,7 @@ public: protected: MappedBlockStream(uint32_t BlockSize, const MSFStreamLayout &StreamLayout, - BinaryStreamRef MsfData); + BinaryStreamRef MsfData, BumpPtrAllocator &Allocator); private: const MSFStreamLayout &getStreamLayout() const { return StreamLayout; } @@ -94,7 +94,15 @@ private: BinaryStreamRef MsfData; typedef MutableArrayRef CacheEntry; - llvm::BumpPtrAllocator Pool; + + // We just store the allocator by reference. We use this to allocate + // contiguous memory for things like arrays or strings that cross a block + // boundary, and this memory is expected to outlive the stream. For example, + // someone could create a stream, read some stuff, then close the stream, and + // we would like outstanding references to fields to remain valid since the + // entire file is mapped anyway. Because of that, the user must supply the + // allocator to allocate broken records from. + BumpPtrAllocator &Allocator; DenseMap> CacheMap; }; @@ -102,18 +110,20 @@ class WritableMappedBlockStream : public WritableBinaryStream { public: static std::unique_ptr createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, - WritableBinaryStreamRef MsfData); + WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator); static std::unique_ptr createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, - uint32_t StreamIndex); + uint32_t StreamIndex, BumpPtrAllocator &Allocator); static std::unique_ptr createDirectoryStream(const MSFLayout &Layout, - WritableBinaryStreamRef MsfData); + WritableBinaryStreamRef MsfData, + BumpPtrAllocator &Allocator); static std::unique_ptr - createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData); + createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, + BumpPtrAllocator &Allocator); llvm::support::endianness getEndian() const override { return llvm::support::little; @@ -139,7 +149,8 @@ public: protected: WritableMappedBlockStream(uint32_t BlockSize, const MSFStreamLayout &StreamLayout, - WritableBinaryStreamRef MsfData); + WritableBinaryStreamRef MsfData, + BumpPtrAllocator &Allocator); private: MappedBlockStream ReadInterface; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h index e5858d0f45e3..2ff166b24e68 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -49,11 +49,8 @@ public: void setObjFileName(StringRef Name); void addSymbol(codeview::CVSymbol Symbol); - void addC13Fragment(std::unique_ptr Lines); - void addC13Fragment( - std::unique_ptr Inlinees); - void setC13FileChecksums( - std::unique_ptr Checksums); + void + addDebugSubsection(std::unique_ptr Subsection); uint16_t getStreamIndex() const; StringRef getModuleName() const { return ModuleName; } @@ -83,10 +80,6 @@ private: std::vector SourceFiles; std::vector Symbols; - std::unique_ptr ChecksumInfo; - std::vector> LineInfo; - std::vector> Inlinees; - std::vector> C13Builders; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h index 822ce3ce13d3..a8121978d882 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h @@ -12,6 +12,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" @@ -25,7 +26,7 @@ class PDBFile; class DbiModuleDescriptor; class ModuleDebugStreamRef { - typedef codeview::DebugSubsectionArray::Iterator LinesAndChecksumsIterator; + typedef codeview::DebugSubsectionArray::Iterator DebugSubsectionIterator; public: ModuleDebugStreamRef(const DbiModuleDescriptor &Module, @@ -39,12 +40,15 @@ public: iterator_range symbols(bool *HadError) const; - llvm::iterator_range linesAndChecksums() const; + llvm::iterator_range subsections() const; - bool hasLineInfo() const; + bool hasDebugSubsections() const; Error commit(); + Expected + findChecksumsSubsection() const; + private: const DbiModuleDescriptor &Mod; @@ -57,7 +61,7 @@ private: BinaryStreamRef C13LinesSubstream; BinaryStreamRef GlobalRefsSubstream; - codeview::DebugSubsectionArray LinesAndChecksums; + codeview::DebugSubsectionArray Subsections; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h index 6aeb0a5479cb..28a14d7356d2 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h @@ -45,6 +45,8 @@ public: FixedStreamArray name_ids() const; + codeview::DebugStringTableSubsectionRef getStringTable() const; + private: Error readHeader(BinaryStreamReader &Reader); Error readStrings(BinaryStreamReader &Reader); diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h index 17fba9991c2e..0ee697696ca5 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h @@ -34,8 +34,7 @@ class TpiStream { friend class TpiStreamBuilder; public: - TpiStream(const PDBFile &File, - std::unique_ptr Stream); + TpiStream(PDBFile &File, std::unique_ptr Stream); ~TpiStream(); Error reload(); @@ -61,7 +60,7 @@ public: Error commit(); private: - const PDBFile &Pdb; + PDBFile &Pdb; std::unique_ptr Stream; std::unique_ptr Types; diff --git a/contrib/llvm/include/llvm/IR/DIBuilder.h b/contrib/llvm/include/llvm/IR/DIBuilder.h index 4afb5d9d63b2..8e6bb4baccaf 100644 --- a/contrib/llvm/include/llvm/IR/DIBuilder.h +++ b/contrib/llvm/include/llvm/IR/DIBuilder.h @@ -86,6 +86,10 @@ namespace llvm { /// Construct any deferred debug info descriptors. void finalize(); + /// Finalize a specific subprogram - no new variables may be added to this + /// subprogram afterwards. + void finalizeSubprogram(DISubprogram *SP); + /// A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. /// \param Lang Source programming language, eg. dwarf::DW_LANG_C99 diff --git a/contrib/llvm/include/llvm/IR/DebugLoc.h b/contrib/llvm/include/llvm/IR/DebugLoc.h index aa74f361cda2..eef1212abc4b 100644 --- a/contrib/llvm/include/llvm/IR/DebugLoc.h +++ b/contrib/llvm/include/llvm/IR/DebugLoc.h @@ -90,12 +90,6 @@ namespace llvm { DenseMap &Cache, bool ReplaceLast = false); - /// Reparent all debug locations referenced by \c I that belong to \c OrigSP - /// to become (possibly indirect) children of \c NewSP. - static void reparentDebugInfo(Instruction &I, DISubprogram *OrigSP, - DISubprogram *NewSP, - DenseMap &Cache); - unsigned getLine() const; unsigned getCol() const; MDNode *getScope() const; diff --git a/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h b/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h index c46c609609e2..757ddf6cf46b 100644 --- a/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -134,16 +134,18 @@ public: /// be renamed or references something that can't be renamed). unsigned NotEligibleToImport : 1; - /// Indicate that the global value must be considered a live root for - /// index-based liveness analysis. Used for special LLVM values such as - /// llvm.global_ctors that the linker does not know about. - unsigned LiveRoot : 1; + /// In per-module summary, indicate that the global value must be considered + /// a live root for index-based liveness analysis. Used for special LLVM + /// values such as llvm.global_ctors that the linker does not know about. + /// + /// In combined summary, indicate that the global value is live. + unsigned Live : 1; /// Convenience Constructors explicit GVFlags(GlobalValue::LinkageTypes Linkage, - bool NotEligibleToImport, bool LiveRoot) + bool NotEligibleToImport, bool Live) : Linkage(Linkage), NotEligibleToImport(NotEligibleToImport), - LiveRoot(LiveRoot) {} + Live(Live) {} }; private: @@ -172,6 +174,8 @@ private: /// are listed in the derived FunctionSummary object. std::vector RefEdgeList; + bool isLive() const { return Flags.Live; } + protected: GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector Refs) : Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) {} @@ -213,19 +217,17 @@ public: /// Return true if this global value can't be imported. bool notEligibleToImport() const { return Flags.NotEligibleToImport; } - /// Return true if this global value must be considered a root for live - /// value analysis on the index. - bool liveRoot() const { return Flags.LiveRoot; } - - /// Flag that this global value must be considered a root for live - /// value analysis on the index. - void setLiveRoot() { Flags.LiveRoot = true; } + void setLive(bool Live) { Flags.Live = Live; } /// Flag that this global value cannot be imported. void setNotEligibleToImport() { Flags.NotEligibleToImport = true; } /// Return the list of values referenced by this global value definition. ArrayRef refs() const { return RefEdgeList; } + + friend class ModuleSummaryIndex; + friend void computeDeadSymbols(class ModuleSummaryIndex &, + const DenseSet &); }; /// \brief Alias summary information. @@ -535,6 +537,11 @@ private: /// GUIDs, it will be mapped to 0. std::map OidGuidMap; + /// Indicates that summary-based GlobalValue GC has run, and values with + /// GVFlags::Live==false are really dead. Otherwise, all values must be + /// considered live. + bool WithGlobalValueDeadStripping = false; + // YAML I/O support. friend yaml::MappingTraits; @@ -550,6 +557,17 @@ public: const_gvsummary_iterator end() const { return GlobalValueMap.end(); } size_t size() const { return GlobalValueMap.size(); } + bool withGlobalValueDeadStripping() const { + return WithGlobalValueDeadStripping; + } + void setWithGlobalValueDeadStripping() { + WithGlobalValueDeadStripping = true; + } + + bool isGlobalValueLive(const GlobalValueSummary *GVS) const { + return !WithGlobalValueDeadStripping || GVS->isLive(); + } + /// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo(). ValueInfo getValueInfo(GlobalValue::GUID GUID) const { auto I = GlobalValueMap.find(GUID); diff --git a/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h b/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h index 78fdb602027d..891d84c2dbca 100644 --- a/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h +++ b/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h @@ -128,6 +128,8 @@ template <> struct MappingTraits { }; struct FunctionSummaryYaml { + unsigned Linkage; + bool NotEligibleToImport, Live; std::vector TypeTests; std::vector TypeTestAssumeVCalls, TypeCheckedLoadVCalls; @@ -168,6 +170,9 @@ namespace yaml { template <> struct MappingTraits { static void mapping(IO &io, FunctionSummaryYaml& summary) { + io.mapOptional("Linkage", summary.Linkage); + io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport); + io.mapOptional("Live", summary.Live); io.mapOptional("TypeTests", summary.TypeTests); io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls); io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls); @@ -199,12 +204,12 @@ template <> struct CustomMappingTraits { } auto &Elem = V[KeyInt]; for (auto &FSum : FSums) { - GlobalValueSummary::GVFlags GVFlags(GlobalValue::ExternalLinkage, false, - false); Elem.SummaryList.push_back(llvm::make_unique( - GVFlags, 0, ArrayRef{}, - ArrayRef{}, std::move(FSum.TypeTests), - std::move(FSum.TypeTestAssumeVCalls), + GlobalValueSummary::GVFlags( + static_cast(FSum.Linkage), + FSum.NotEligibleToImport, FSum.Live), + 0, ArrayRef{}, ArrayRef{}, + std::move(FSum.TypeTests), std::move(FSum.TypeTestAssumeVCalls), std::move(FSum.TypeCheckedLoadVCalls), std::move(FSum.TypeTestAssumeConstVCalls), std::move(FSum.TypeCheckedLoadConstVCalls))); @@ -216,8 +221,10 @@ template <> struct CustomMappingTraits { for (auto &Sum : P.second.SummaryList) { if (auto *FSum = dyn_cast(Sum.get())) FSums.push_back(FunctionSummaryYaml{ - FSum->type_tests(), FSum->type_test_assume_vcalls(), - FSum->type_checked_load_vcalls(), + FSum->flags().Linkage, + static_cast(FSum->flags().NotEligibleToImport), + static_cast(FSum->flags().Live), FSum->type_tests(), + FSum->type_test_assume_vcalls(), FSum->type_checked_load_vcalls(), FSum->type_test_assume_const_vcalls(), FSum->type_checked_load_const_vcalls()}); } @@ -231,6 +238,8 @@ template <> struct MappingTraits { static void mapping(IO &io, ModuleSummaryIndex& index) { io.mapOptional("GlobalValueMap", index.GlobalValueMap); io.mapOptional("TypeIdMap", index.TypeIdMap); + io.mapOptional("WithGlobalValueDeadStripping", + index.WithGlobalValueDeadStripping); } }; diff --git a/contrib/llvm/include/llvm/IR/Statepoint.h b/contrib/llvm/include/llvm/IR/Statepoint.h index f01607614a0c..a5f0130f79f4 100644 --- a/contrib/llvm/include/llvm/IR/Statepoint.h +++ b/contrib/llvm/include/llvm/IR/Statepoint.h @@ -228,24 +228,24 @@ public: return cast(NumVMSArgs)->getZExtValue(); } - typename CallSiteTy::arg_iterator vm_state_begin() const { + typename CallSiteTy::arg_iterator deopt_begin() const { auto I = gc_transition_args_end() + 1; assert((getCallSite().arg_end() - I) >= 0); return I; } - typename CallSiteTy::arg_iterator vm_state_end() const { - auto I = vm_state_begin() + getNumTotalVMSArgs(); + typename CallSiteTy::arg_iterator deopt_end() const { + auto I = deopt_begin() + getNumTotalVMSArgs(); assert((getCallSite().arg_end() - I) >= 0); return I; } /// range adapter for vm state arguments - iterator_range vm_state_args() const { - return make_range(vm_state_begin(), vm_state_end()); + iterator_range deopt_operands() const { + return make_range(deopt_begin(), deopt_end()); } typename CallSiteTy::arg_iterator gc_args_begin() const { - return vm_state_end(); + return deopt_end(); } typename CallSiteTy::arg_iterator gc_args_end() const { return getCallSite().arg_end(); @@ -289,8 +289,8 @@ public: (void)arg_end(); (void)gc_transition_args_begin(); (void)gc_transition_args_end(); - (void)vm_state_begin(); - (void)vm_state_end(); + (void)deopt_begin(); + (void)deopt_end(); (void)gc_args_begin(); (void)gc_args_end(); } diff --git a/contrib/llvm/include/llvm/InitializePasses.h b/contrib/llvm/include/llvm/InitializePasses.h index 5b9796d4fba6..abb0aa3e3caf 100644 --- a/contrib/llvm/include/llvm/InitializePasses.h +++ b/contrib/llvm/include/llvm/InitializePasses.h @@ -86,7 +86,6 @@ void initializeCFGOnlyPrinterLegacyPassPass(PassRegistry&); void initializeCFGOnlyViewerLegacyPassPass(PassRegistry&); void initializeCFGPrinterLegacyPassPass(PassRegistry&); void initializeCFGSimplifyPassPass(PassRegistry&); -void initializeLateCFGSimplifyPassPass(PassRegistry&); void initializeCFGViewerLegacyPassPass(PassRegistry&); void initializeCFLAndersAAWrapperPassPass(PassRegistry&); void initializeCFLSteensAAWrapperPassPass(PassRegistry&); @@ -144,8 +143,8 @@ void initializeGCMachineCodeAnalysisPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); void initializeGCOVProfilerLegacyPassPass(PassRegistry&); void initializeGVNHoistLegacyPassPass(PassRegistry&); -void initializeGVNSinkLegacyPassPass(PassRegistry&); void initializeGVNLegacyPassPass(PassRegistry&); +void initializeGVNSinkLegacyPassPass(PassRegistry&); void initializeGlobalDCELegacyPassPass(PassRegistry&); void initializeGlobalMergePass(PassRegistry&); void initializeGlobalOptLegacyPassPass(PassRegistry&); @@ -175,13 +174,14 @@ void initializeIntervalPartitionPass(PassRegistry&); void initializeJumpThreadingPass(PassRegistry&); void initializeLCSSAVerificationPassPass(PassRegistry&); void initializeLCSSAWrapperPassPass(PassRegistry&); +void initializeLateCFGSimplifyPassPass(PassRegistry&); void initializeLazyBlockFrequencyInfoPassPass(PassRegistry&); void initializeLazyBranchProbabilityInfoPassPass(PassRegistry&); void initializeLazyMachineBlockFrequencyInfoPassPass(PassRegistry&); +void initializeLazyValueInfoPrinterPass(PassRegistry&); void initializeLazyValueInfoWrapperPassPass(PassRegistry&); void initializeLegacyLICMPassPass(PassRegistry&); void initializeLegacyLoopSinkPassPass(PassRegistry&); -void initializeLazyValueInfoPrinterPass(PassRegistry&); void initializeLegalizerPass(PassRegistry&); void initializeLibCallsShrinkWrapLegacyPassPass(PassRegistry&); void initializeLintPass(PassRegistry&); @@ -195,8 +195,8 @@ void initializeLiveVariablesPass(PassRegistry&); void initializeLoadCombinePass(PassRegistry&); void initializeLoadStoreVectorizerPass(PassRegistry&); void initializeLoaderPassPass(PassRegistry&); -void initializeLocalizerPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); +void initializeLocalizerPass(PassRegistry&); void initializeLoopAccessLegacyAnalysisPass(PassRegistry&); void initializeLoopDataPrefetchLegacyPassPass(PassRegistry&); void initializeLoopDeletionLegacyPassPass(PassRegistry&); @@ -304,6 +304,7 @@ void initializeProcessImplicitDefsPass(PassRegistry&); void initializeProfileSummaryInfoWrapperPassPass(PassRegistry&); void initializePromoteLegacyPassPass(PassRegistry&); void initializePruneEHPass(PassRegistry&); +void initializeRABasicPass(PassRegistry&); void initializeRAGreedyPass(PassRegistry&); void initializeReassociateLegacyPassPass(PassRegistry&); void initializeRegBankSelectPass(PassRegistry&); @@ -327,8 +328,9 @@ void initializeSafeStackLegacyPassPass(PassRegistry&); void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&); void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeScalarEvolutionWrapperPassPass(PassRegistry&); -void initializeScalarizerPass(PassRegistry&); void initializeScalarizeMaskedMemIntrinPass(PassRegistry&); +void initializeScalarizerPass(PassRegistry&); +void initializeScavengerTestPass(PassRegistry&); void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&); void initializeSeparateConstOffsetFromGEPPass(PassRegistry&); void initializeShadowStackGCLoweringPass(PassRegistry&); diff --git a/contrib/llvm/include/llvm/LTO/Config.h b/contrib/llvm/include/llvm/LTO/Config.h index 5ba8492db8f5..73106f77ca55 100644 --- a/contrib/llvm/include/llvm/LTO/Config.h +++ b/contrib/llvm/include/llvm/LTO/Config.h @@ -46,6 +46,9 @@ struct Config { unsigned OptLevel = 2; bool DisableVerify = false; + /// Use the new pass manager + bool UseNewPM = false; + /// Disable entirely the optimizer, including importing for ThinLTO bool CodeGenOnly = false; diff --git a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h index 6ddae2e2b41c..a6d4d404415f 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h +++ b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h @@ -17,12 +17,20 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/ObjectYAML/YAML.h" namespace llvm { + +namespace codeview { +class DebugStringTableSubsection; +class DebugStringTableSubsectionRef; +class DebugChecksumsSubsectionRef; +} namespace CodeViewYAML { + namespace detail { -struct C13FragmentBase; +struct YAMLSubsectionBase; } struct SourceLineEntry { @@ -74,18 +82,24 @@ struct InlineeInfo { std::vector Sites; }; -struct SourceFileInfo { - std::vector FileChecksums; - std::vector LineFragments; - std::vector Inlinees; +struct YAMLDebugSubsection { + static Expected + fromCodeViewSubection(const codeview::DebugStringTableSubsectionRef &Strings, + const codeview::DebugChecksumsSubsectionRef &Checksums, + const codeview::DebugSubsectionRecord &SS); + + std::shared_ptr Subsection; }; -struct C13DebugSection { - std::vector Fragments; -}; +Expected>> +convertSubsectionList(ArrayRef Subsections, + codeview::DebugStringTableSubsection &Strings); + } // namespace CodeViewYAML } // namespace llvm -LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceFileInfo) +LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::YAMLDebugSubsection) + +LLVM_YAML_IS_SEQUENCE_VECTOR(CodeViewYAML::YAMLDebugSubsection) #endif diff --git a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h index ee4e2ac9d404..9b411e8b074f 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h +++ b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h @@ -28,7 +28,9 @@ struct SymbolRecordBase; struct SymbolRecord { std::shared_ptr Symbol; - codeview::CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator) const; + codeview::CVSymbol + toCodeViewSymbol(BumpPtrAllocator &Allocator, + codeview::CodeViewContainer Container) const; static Expected fromCodeViewSymbol(codeview::CVSymbol Symbol); }; diff --git a/contrib/llvm/include/llvm/TableGen/Record.h b/contrib/llvm/include/llvm/TableGen/Record.h index 3c181f0e511b..5c3bf88fbbfa 100644 --- a/contrib/llvm/include/llvm/TableGen/Record.h +++ b/contrib/llvm/include/llvm/TableGen/Record.h @@ -1361,10 +1361,6 @@ public: return false; } - bool isTemplateArg(StringRef Name) const { - return isTemplateArg(StringInit::get(Name)); - } - const RecordVal *getValue(const Init *Name) const { for (const RecordVal &Val : Values) if (Val.Name == Name) return &Val; @@ -1388,10 +1384,6 @@ public: TemplateArgs.push_back(Name); } - void addTemplateArg(StringRef Name) { - addTemplateArg(StringInit::get(Name)); - } - void addValue(const RecordVal &RV) { assert(getValue(RV.getNameInit()) == nullptr && "Value already added!"); Values.push_back(RV); diff --git a/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h b/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h index d66b6edc7a4f..de35cdf052e1 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h +++ b/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h @@ -81,15 +81,11 @@ public: /// \p ExportLists contains for each Module the set of globals (GUID) that will /// be imported by another module, or referenced by such a function. I.e. this /// is the set of globals that need to be promoted/renamed appropriately. -/// -/// \p DeadSymbols (optional) contains a list of GUID that are deemed "dead" and -/// will be ignored for the purpose of importing. void ComputeCrossModuleImport( const ModuleSummaryIndex &Index, const StringMap &ModuleToDefinedGVSummaries, StringMap &ImportLists, - StringMap &ExportLists, - const DenseSet *DeadSymbols = nullptr); + StringMap &ExportLists); /// Compute all the imports for the given module using the Index. /// @@ -102,9 +98,9 @@ void ComputeCrossModuleImportForModule( /// Compute all the symbols that are "dead": i.e these that can't be reached /// in the graph from any of the given symbols listed in /// \p GUIDPreservedSymbols. -DenseSet -computeDeadSymbols(const ModuleSummaryIndex &Index, - const DenseSet &GUIDPreservedSymbols); +void computeDeadSymbols( + ModuleSummaryIndex &Index, + const DenseSet &GUIDPreservedSymbols); /// Compute the set of summaries needed for a ThinLTO backend compilation of /// \p ModulePath. diff --git a/contrib/llvm/include/llvm/Transforms/Instrumentation.h b/contrib/llvm/include/llvm/Transforms/Instrumentation.h index 023d7af7f729..b6c6c091631d 100644 --- a/contrib/llvm/include/llvm/Transforms/Instrumentation.h +++ b/contrib/llvm/include/llvm/Transforms/Instrumentation.h @@ -177,6 +177,7 @@ struct SanitizerCoverageOptions { bool Use8bitCounters = false; bool TracePC = false; bool TracePCGuard = false; + bool Inline8bitCounters = false; bool NoPrune = false; SanitizerCoverageOptions() = default; diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h index 91c9d255302f..2a8b89d86282 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h @@ -36,6 +36,7 @@ class BasicBlock; class BlockFrequencyInfo; class CallInst; class CallGraph; +class DebugInfoFinder; class DominatorTree; class Function; class Instruction; @@ -110,7 +111,8 @@ struct ClonedCodeInfo { /// BasicBlock *CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix = "", Function *F = nullptr, - ClonedCodeInfo *CodeInfo = nullptr); + ClonedCodeInfo *CodeInfo = nullptr, + DebugInfoFinder *DIFinder = nullptr); /// CloneFunction - Return a copy of the specified function and add it to that /// function's module. Also, any references specified in the VMap are changed diff --git a/contrib/llvm/lib/Analysis/ConstantFolding.cpp b/contrib/llvm/lib/Analysis/ConstantFolding.cpp index 6a1af87450c9..a906770dbb34 100644 --- a/contrib/llvm/lib/Analysis/ConstantFolding.cpp +++ b/contrib/llvm/lib/Analysis/ConstantFolding.cpp @@ -1170,7 +1170,9 @@ Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate, const DataLayout &DL, const TargetLibraryInfo *TLI) { // fold: icmp (inttoptr x), null -> icmp x, 0 + // fold: icmp null, (inttoptr x) -> icmp 0, x // fold: icmp (ptrtoint x), 0 -> icmp x, null + // fold: icmp 0, (ptrtoint x) -> icmp null, x // fold: icmp (inttoptr x), (inttoptr y) -> icmp trunc/zext x, trunc/zext y // fold: icmp (ptrtoint x), (ptrtoint y) -> icmp x, y // @@ -1240,6 +1242,11 @@ Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate, Predicate == ICmpInst::ICMP_EQ ? Instruction::And : Instruction::Or; return ConstantFoldBinaryOpOperands(OpC, LHS, RHS, DL); } + } else if (isa(Ops1)) { + // If RHS is a constant expression, but the left side isn't, swap the + // operands and try again. + Predicate = ICmpInst::getSwappedPredicate((ICmpInst::Predicate)Predicate); + return ConstantFoldCompareInstOperands(Predicate, Ops1, Ops0, DL, TLI); } return ConstantExpr::getCompare(Predicate, Ops0, Ops1); diff --git a/contrib/llvm/lib/Analysis/IndirectCallPromotionAnalysis.cpp b/contrib/llvm/lib/Analysis/IndirectCallPromotionAnalysis.cpp index 3da33ac71421..ed233d201537 100644 --- a/contrib/llvm/lib/Analysis/IndirectCallPromotionAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/IndirectCallPromotionAnalysis.cpp @@ -43,7 +43,7 @@ static cl::opt // The percent threshold for the direct-call target (this call site vs the // total call count) for it to be considered as the promotion target. static cl::opt - ICPPercentThreshold("icp-percent-threshold", cl::init(33), cl::Hidden, + ICPPercentThreshold("icp-percent-threshold", cl::init(30), cl::Hidden, cl::ZeroOrMore, cl::desc("The percentage threshold for the promotion")); diff --git a/contrib/llvm/lib/Analysis/InlineCost.cpp b/contrib/llvm/lib/Analysis/InlineCost.cpp index 4702569126c6..77c87928728a 100644 --- a/contrib/llvm/lib/Analysis/InlineCost.cpp +++ b/contrib/llvm/lib/Analysis/InlineCost.cpp @@ -54,11 +54,6 @@ static cl::opt cl::init(45), cl::desc("Threshold for inlining cold callsites")); -static cl::opt - EnableGenericSwitchCost("inline-generic-switch-cost", cl::Hidden, - cl::init(false), - cl::desc("Enable generic switch cost model")); - // We introduce this threshold to help performance of instrumentation based // PGO before we actually hook up inliner with analysis passes such as BPI and // BFI. @@ -1015,83 +1010,68 @@ bool CallAnalyzer::visitSwitchInst(SwitchInst &SI) { if (isa(V)) return true; - if (EnableGenericSwitchCost) { - // Assume the most general case where the swith is lowered into - // either a jump table, bit test, or a balanced binary tree consisting of - // case clusters without merging adjacent clusters with the same - // destination. We do not consider the switches that are lowered with a mix - // of jump table/bit test/binary search tree. The cost of the switch is - // proportional to the size of the tree or the size of jump table range. - - // Exit early for a large switch, assuming one case needs at least one - // instruction. - // FIXME: This is not true for a bit test, but ignore such case for now to - // save compile-time. - int64_t CostLowerBound = - std::min((int64_t)INT_MAX, - (int64_t)SI.getNumCases() * InlineConstants::InstrCost + Cost); - - if (CostLowerBound > Threshold) { - Cost = CostLowerBound; - return false; - } - - unsigned JumpTableSize = 0; - unsigned NumCaseCluster = - TTI.getEstimatedNumberOfCaseClusters(SI, JumpTableSize); - - // If suitable for a jump table, consider the cost for the table size and - // branch to destination. - if (JumpTableSize) { - int64_t JTCost = (int64_t)JumpTableSize * InlineConstants::InstrCost + - 4 * InlineConstants::InstrCost; - Cost = std::min((int64_t)INT_MAX, JTCost + Cost); - return false; - } - - // Considering forming a binary search, we should find the number of nodes - // which is same as the number of comparisons when lowered. For a given - // number of clusters, n, we can define a recursive function, f(n), to find - // the number of nodes in the tree. The recursion is : - // f(n) = 1 + f(n/2) + f (n - n/2), when n > 3, - // and f(n) = n, when n <= 3. - // This will lead a binary tree where the leaf should be either f(2) or f(3) - // when n > 3. So, the number of comparisons from leaves should be n, while - // the number of non-leaf should be : - // 2^(log2(n) - 1) - 1 - // = 2^log2(n) * 2^-1 - 1 - // = n / 2 - 1. - // Considering comparisons from leaf and non-leaf nodes, we can estimate the - // number of comparisons in a simple closed form : - // n + n / 2 - 1 = n * 3 / 2 - 1 - if (NumCaseCluster <= 3) { - // Suppose a comparison includes one compare and one conditional branch. - Cost += NumCaseCluster * 2 * InlineConstants::InstrCost; - return false; - } - int64_t ExpectedNumberOfCompare = 3 * (uint64_t)NumCaseCluster / 2 - 1; - uint64_t SwitchCost = - ExpectedNumberOfCompare * 2 * InlineConstants::InstrCost; - Cost = std::min((uint64_t)INT_MAX, SwitchCost + Cost); - return false; - } - - // Use a simple switch cost model where we accumulate a cost proportional to - // the number of distinct successor blocks. This fan-out in the CFG cannot - // be represented for free even if we can represent the core switch as a - // jumptable that takes a single instruction. - /// + // Assume the most general case where the swith is lowered into + // either a jump table, bit test, or a balanced binary tree consisting of + // case clusters without merging adjacent clusters with the same + // destination. We do not consider the switches that are lowered with a mix + // of jump table/bit test/binary search tree. The cost of the switch is + // proportional to the size of the tree or the size of jump table range. + // // NB: We convert large switches which are just used to initialize large phi // nodes to lookup tables instead in simplify-cfg, so this shouldn't prevent // inlining those. It will prevent inlining in cases where the optimization // does not (yet) fire. - SmallPtrSet SuccessorBlocks; - SuccessorBlocks.insert(SI.getDefaultDest()); - for (auto Case : SI.cases()) - SuccessorBlocks.insert(Case.getCaseSuccessor()); - // Add cost corresponding to the number of distinct destinations. The first - // we model as free because of fallthrough. - Cost += (SuccessorBlocks.size() - 1) * InlineConstants::InstrCost; + + // Exit early for a large switch, assuming one case needs at least one + // instruction. + // FIXME: This is not true for a bit test, but ignore such case for now to + // save compile-time. + int64_t CostLowerBound = + std::min((int64_t)INT_MAX, + (int64_t)SI.getNumCases() * InlineConstants::InstrCost + Cost); + + if (CostLowerBound > Threshold) { + Cost = CostLowerBound; + return false; + } + + unsigned JumpTableSize = 0; + unsigned NumCaseCluster = + TTI.getEstimatedNumberOfCaseClusters(SI, JumpTableSize); + + // If suitable for a jump table, consider the cost for the table size and + // branch to destination. + if (JumpTableSize) { + int64_t JTCost = (int64_t)JumpTableSize * InlineConstants::InstrCost + + 4 * InlineConstants::InstrCost; + Cost = std::min((int64_t)INT_MAX, JTCost + Cost); + return false; + } + + // Considering forming a binary search, we should find the number of nodes + // which is same as the number of comparisons when lowered. For a given + // number of clusters, n, we can define a recursive function, f(n), to find + // the number of nodes in the tree. The recursion is : + // f(n) = 1 + f(n/2) + f (n - n/2), when n > 3, + // and f(n) = n, when n <= 3. + // This will lead a binary tree where the leaf should be either f(2) or f(3) + // when n > 3. So, the number of comparisons from leaves should be n, while + // the number of non-leaf should be : + // 2^(log2(n) - 1) - 1 + // = 2^log2(n) * 2^-1 - 1 + // = n / 2 - 1. + // Considering comparisons from leaf and non-leaf nodes, we can estimate the + // number of comparisons in a simple closed form : + // n + n / 2 - 1 = n * 3 / 2 - 1 + if (NumCaseCluster <= 3) { + // Suppose a comparison includes one compare and one conditional branch. + Cost += NumCaseCluster * 2 * InlineConstants::InstrCost; + return false; + } + int64_t ExpectedNumberOfCompare = 3 * (uint64_t)NumCaseCluster / 2 - 1; + uint64_t SwitchCost = + ExpectedNumberOfCompare * 2 * InlineConstants::InstrCost; + Cost = std::min((uint64_t)INT_MAX, SwitchCost + Cost); return false; } diff --git a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp b/contrib/llvm/lib/Analysis/LazyValueInfo.cpp index a2b9015a8a1d..6a9ae6440ace 100644 --- a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/contrib/llvm/lib/Analysis/LazyValueInfo.cpp @@ -662,13 +662,13 @@ namespace { bool solveBlockValuePHINode(LVILatticeVal &BBLV, PHINode *PN, BasicBlock *BB); bool solveBlockValueSelect(LVILatticeVal &BBLV, SelectInst *S, BasicBlock *BB); - bool solveBlockValueBinaryOp(LVILatticeVal &BBLV, Instruction *BBI, + bool solveBlockValueBinaryOp(LVILatticeVal &BBLV, BinaryOperator *BBI, BasicBlock *BB); - bool solveBlockValueCast(LVILatticeVal &BBLV, Instruction *BBI, + bool solveBlockValueCast(LVILatticeVal &BBLV, CastInst *CI, BasicBlock *BB); void intersectAssumeOrGuardBlockValueConstantRange(Value *Val, LVILatticeVal &BBLV, - Instruction *BBI); + Instruction *BBI); void solve(); @@ -849,12 +849,12 @@ bool LazyValueInfoImpl::solveBlockValueImpl(LVILatticeVal &Res, return true; } if (BBI->getType()->isIntegerTy()) { - if (isa(BBI)) - return solveBlockValueCast(Res, BBI, BB); - + if (auto *CI = dyn_cast(BBI)) + return solveBlockValueCast(Res, CI, BB); + BinaryOperator *BO = dyn_cast(BBI); if (BO && isa(BO->getOperand(1))) - return solveBlockValueBinaryOp(Res, BBI, BB); + return solveBlockValueBinaryOp(Res, BO, BB); } DEBUG(dbgs() << " compute BB '" << BB->getName() @@ -1168,9 +1168,9 @@ bool LazyValueInfoImpl::solveBlockValueSelect(LVILatticeVal &BBLV, } bool LazyValueInfoImpl::solveBlockValueCast(LVILatticeVal &BBLV, - Instruction *BBI, - BasicBlock *BB) { - if (!BBI->getOperand(0)->getType()->isSized()) { + CastInst *CI, + BasicBlock *BB) { + if (!CI->getOperand(0)->getType()->isSized()) { // Without knowing how wide the input is, we can't analyze it in any useful // way. BBLV = LVILatticeVal::getOverdefined(); @@ -1180,7 +1180,7 @@ bool LazyValueInfoImpl::solveBlockValueCast(LVILatticeVal &BBLV, // Filter out casts we don't know how to reason about before attempting to // recurse on our operand. This can cut a long search short if we know we're // not going to be able to get any useful information anways. - switch (BBI->getOpcode()) { + switch (CI->getOpcode()) { case Instruction::Trunc: case Instruction::SExt: case Instruction::ZExt: @@ -1197,44 +1197,43 @@ bool LazyValueInfoImpl::solveBlockValueCast(LVILatticeVal &BBLV, // Figure out the range of the LHS. If that fails, we still apply the // transfer rule on the full set since we may be able to locally infer // interesting facts. - if (!hasBlockValue(BBI->getOperand(0), BB)) - if (pushBlockValue(std::make_pair(BB, BBI->getOperand(0)))) + if (!hasBlockValue(CI->getOperand(0), BB)) + if (pushBlockValue(std::make_pair(BB, CI->getOperand(0)))) // More work to do before applying this transfer rule. return false; const unsigned OperandBitWidth = - DL.getTypeSizeInBits(BBI->getOperand(0)->getType()); + DL.getTypeSizeInBits(CI->getOperand(0)->getType()); ConstantRange LHSRange = ConstantRange(OperandBitWidth); - if (hasBlockValue(BBI->getOperand(0), BB)) { - LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB); - intersectAssumeOrGuardBlockValueConstantRange(BBI->getOperand(0), LHSVal, - BBI); + if (hasBlockValue(CI->getOperand(0), BB)) { + LVILatticeVal LHSVal = getBlockValue(CI->getOperand(0), BB); + intersectAssumeOrGuardBlockValueConstantRange(CI->getOperand(0), LHSVal, + CI); if (LHSVal.isConstantRange()) LHSRange = LHSVal.getConstantRange(); } - const unsigned ResultBitWidth = - cast(BBI->getType())->getBitWidth(); + const unsigned ResultBitWidth = CI->getType()->getIntegerBitWidth(); // NOTE: We're currently limited by the set of operations that ConstantRange // can evaluate symbolically. Enhancing that set will allows us to analyze // more definitions. - auto CastOp = (Instruction::CastOps) BBI->getOpcode(); - BBLV = LVILatticeVal::getRange(LHSRange.castOp(CastOp, ResultBitWidth)); + BBLV = LVILatticeVal::getRange(LHSRange.castOp(CI->getOpcode(), + ResultBitWidth)); return true; } bool LazyValueInfoImpl::solveBlockValueBinaryOp(LVILatticeVal &BBLV, - Instruction *BBI, + BinaryOperator *BO, BasicBlock *BB) { - assert(BBI->getOperand(0)->getType()->isSized() && + assert(BO->getOperand(0)->getType()->isSized() && "all operands to binary operators are sized"); // Filter out operators we don't know how to reason about before attempting to // recurse on our operand(s). This can cut a long search short if we know - // we're not going to be able to get any useful information anways. - switch (BBI->getOpcode()) { + // we're not going to be able to get any useful information anyways. + switch (BO->getOpcode()) { case Instruction::Add: case Instruction::Sub: case Instruction::Mul: @@ -1256,29 +1255,29 @@ bool LazyValueInfoImpl::solveBlockValueBinaryOp(LVILatticeVal &BBLV, // Figure out the range of the LHS. If that fails, use a conservative range, // but apply the transfer rule anyways. This lets us pick up facts from // expressions like "and i32 (call i32 @foo()), 32" - if (!hasBlockValue(BBI->getOperand(0), BB)) - if (pushBlockValue(std::make_pair(BB, BBI->getOperand(0)))) + if (!hasBlockValue(BO->getOperand(0), BB)) + if (pushBlockValue(std::make_pair(BB, BO->getOperand(0)))) // More work to do before applying this transfer rule. return false; const unsigned OperandBitWidth = - DL.getTypeSizeInBits(BBI->getOperand(0)->getType()); + DL.getTypeSizeInBits(BO->getOperand(0)->getType()); ConstantRange LHSRange = ConstantRange(OperandBitWidth); - if (hasBlockValue(BBI->getOperand(0), BB)) { - LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB); - intersectAssumeOrGuardBlockValueConstantRange(BBI->getOperand(0), LHSVal, - BBI); + if (hasBlockValue(BO->getOperand(0), BB)) { + LVILatticeVal LHSVal = getBlockValue(BO->getOperand(0), BB); + intersectAssumeOrGuardBlockValueConstantRange(BO->getOperand(0), LHSVal, + BO); if (LHSVal.isConstantRange()) LHSRange = LHSVal.getConstantRange(); } - ConstantInt *RHS = cast(BBI->getOperand(1)); + ConstantInt *RHS = cast(BO->getOperand(1)); ConstantRange RHSRange = ConstantRange(RHS->getValue()); // NOTE: We're currently limited by the set of operations that ConstantRange // can evaluate symbolically. Enhancing that set will allows us to analyze // more definitions. - auto BinOp = (Instruction::BinaryOps) BBI->getOpcode(); + Instruction::BinaryOps BinOp = BO->getOpcode(); BBLV = LVILatticeVal::getRange(LHSRange.binaryOp(BinOp, RHSRange)); return true; } diff --git a/contrib/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/contrib/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index 26706f5509ba..3253f27c010d 100644 --- a/contrib/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -275,7 +275,7 @@ computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M, // FIXME: refactor this to use the same code that inliner is using. F.isVarArg(); GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport, - /* LiveRoot = */ false); + /* Live = */ false); auto FuncSummary = llvm::make_unique( Flags, NumInsts, RefEdges.takeVector(), CallGraphEdges.takeVector(), TypeTests.takeVector(), TypeTestAssumeVCalls.takeVector(), @@ -295,7 +295,7 @@ computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V, findRefEdges(Index, &V, RefEdges, Visited); bool NonRenamableLocal = isNonRenamableLocal(V); GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal, - /* LiveRoot = */ false); + /* Live = */ false); auto GVarSummary = llvm::make_unique(Flags, RefEdges.takeVector()); if (NonRenamableLocal) @@ -308,7 +308,7 @@ computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A, DenseSet &CantBePromoted) { bool NonRenamableLocal = isNonRenamableLocal(A); GlobalValueSummary::GVFlags Flags(A.getLinkage(), NonRenamableLocal, - /* LiveRoot = */ false); + /* Live = */ false); auto AS = llvm::make_unique(Flags, ArrayRef{}); auto *Aliasee = A.getBaseObject(); auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee); @@ -323,7 +323,7 @@ computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A, static void setLiveRoot(ModuleSummaryIndex &Index, StringRef Name) { if (ValueInfo VI = Index.getValueInfo(GlobalValue::getGUID(Name))) for (auto &Summary : VI.getSummaryList()) - Summary->setLiveRoot(); + Summary->setLive(true); } ModuleSummaryIndex llvm::buildModuleSummaryIndex( @@ -423,8 +423,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex( return; assert(GV->isDeclaration() && "Def in module asm already has definition"); GlobalValueSummary::GVFlags GVFlags(GlobalValue::InternalLinkage, - /* NotEligibleToImport */ true, - /* LiveRoot */ true); + /* NotEligibleToImport = */ true, + /* Live = */ true); CantBePromoted.insert(GlobalValue::getGUID(Name)); // Create the appropriate summary type. if (isa(GV)) { diff --git a/contrib/llvm/lib/Analysis/OrderedBasicBlock.cpp b/contrib/llvm/lib/Analysis/OrderedBasicBlock.cpp index 0f0016f22cc0..a04c0aef04be 100644 --- a/contrib/llvm/lib/Analysis/OrderedBasicBlock.cpp +++ b/contrib/llvm/lib/Analysis/OrderedBasicBlock.cpp @@ -55,7 +55,7 @@ bool OrderedBasicBlock::comesBefore(const Instruction *A, assert(II != IE && "Instruction not found?"); assert((Inst == A || Inst == B) && "Should find A or B"); LastInstFound = II; - return Inst == A; + return Inst != B; } /// \brief Find out whether \p A dominates \p B, meaning whether \p A diff --git a/contrib/llvm/lib/Analysis/RegionPass.cpp b/contrib/llvm/lib/Analysis/RegionPass.cpp index 82107cb18025..b38e6225c840 100644 --- a/contrib/llvm/lib/Analysis/RegionPass.cpp +++ b/contrib/llvm/lib/Analysis/RegionPass.cpp @@ -15,6 +15,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/RegionPass.h" #include "llvm/Analysis/RegionIterator.h" +#include "llvm/IR/OptBisect.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" @@ -280,3 +281,18 @@ Pass *RegionPass::createPrinterPass(raw_ostream &O, const std::string &Banner) const { return new PrintRegionPass(Banner, O); } + +bool RegionPass::skipRegion(Region &R) const { + Function &F = *R.getEntry()->getParent(); + if (!F.getContext().getOptBisect().shouldRunPass(this, R)) + return true; + + if (F.hasFnAttribute(Attribute::OptimizeNone)) { + // Report this only once per function. + if (R.getEntry() == &F.getEntryBlock()) + DEBUG(dbgs() << "Skipping pass '" << getPassName() + << "' on function " << F.getName() << "\n"); + return true; + } + return false; +} diff --git a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 686c94687669..fffa9045b2fd 100644 --- a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -865,11 +865,11 @@ static GlobalValueSummary::GVFlags getDecodedGVSummaryFlags(uint64_t RawFlags, auto Linkage = GlobalValue::LinkageTypes(RawFlags & 0xF); // 4 bits RawFlags = RawFlags >> 4; bool NotEligibleToImport = (RawFlags & 0x1) || Version < 3; - // The LiveRoot flag wasn't introduced until version 3. For dead stripping + // The Live flag wasn't introduced until version 3. For dead stripping // to work correctly on earlier versions, we must conservatively treat all // values as live. - bool LiveRoot = (RawFlags & 0x2) || Version < 3; - return GlobalValueSummary::GVFlags(Linkage, NotEligibleToImport, LiveRoot); + bool Live = (RawFlags & 0x2) || Version < 3; + return GlobalValueSummary::GVFlags(Linkage, NotEligibleToImport, Live); } static GlobalValue::VisibilityTypes getDecodedVisibility(unsigned Val) { diff --git a/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index a402b4ddd462..9043b8c12d25 100644 --- a/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -351,7 +351,8 @@ public: /// Calls the callback for each value GUID and summary to be written to /// bitcode. This hides the details of whether they are being pulled from the /// entire index or just those in a provided ModuleToSummariesForIndex map. - void forEachSummary(std::function Callback) { + template + void forEachSummary(Functor Callback) { if (ModuleToSummariesForIndex) { for (auto &M : *ModuleToSummariesForIndex) for (auto &Summary : M.second) @@ -363,6 +364,29 @@ public: } } + /// Calls the callback for each entry in the modulePaths StringMap that + /// should be written to the module path string table. This hides the details + /// of whether they are being pulled from the entire index or just those in a + /// provided ModuleToSummariesForIndex map. + template void forEachModule(Functor Callback) { + if (ModuleToSummariesForIndex) { + for (const auto &M : *ModuleToSummariesForIndex) { + const auto &MPI = Index.modulePaths().find(M.first); + if (MPI == Index.modulePaths().end()) { + // This should only happen if the bitcode file was empty, in which + // case we shouldn't be importing (the ModuleToSummariesForIndex + // would only include the module we are writing and index for). + assert(ModuleToSummariesForIndex->size() == 1); + continue; + } + Callback(*MPI); + } + } else { + for (const auto &MPSE : Index.modulePaths()) + Callback(MPSE); + } + } + /// Main entry point for writing a combined index to bitcode. void write(); @@ -370,14 +394,6 @@ private: void writeModStrings(); void writeCombinedGlobalValueSummary(); - /// Indicates whether the provided \p ModulePath should be written into - /// the module string table, e.g. if full index written or if it is in - /// the provided subset. - bool doIncludeModule(StringRef ModulePath) { - return !ModuleToSummariesForIndex || - ModuleToSummariesForIndex->count(ModulePath); - } - Optional getValueId(GlobalValue::GUID ValGUID) { auto VMI = GUIDToValueIdMap.find(ValGUID); if (VMI == GUIDToValueIdMap.end()) @@ -864,7 +880,7 @@ static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags) { uint64_t RawFlags = 0; RawFlags |= Flags.NotEligibleToImport; // bool - RawFlags |= (Flags.LiveRoot << 1); + RawFlags |= (Flags.Live << 1); // Linkage don't need to be remapped at that time for the summary. Any future // change to the getEncodedLinkage() function will need to be taken into // account here as well. @@ -968,19 +984,18 @@ void ModuleBitcodeWriter::writeValueSymbolTableForwardDecl() { enum StringEncoding { SE_Char6, SE_Fixed7, SE_Fixed8 }; /// Determine the encoding to use for the given string name and length. -static StringEncoding getStringEncoding(const char *Str, unsigned StrLen) { +static StringEncoding getStringEncoding(StringRef Str) { bool isChar6 = true; - for (const char *C = Str, *E = C + StrLen; C != E; ++C) { + for (char C : Str) { if (isChar6) - isChar6 = BitCodeAbbrevOp::isChar6(*C); - if ((unsigned char)*C & 128) + isChar6 = BitCodeAbbrevOp::isChar6(C); + if ((unsigned char)C & 128) // don't bother scanning the rest. return SE_Fixed8; } if (isChar6) return SE_Char6; - else - return SE_Fixed7; + return SE_Fixed7; } /// Emit top-level description of module, including target triple, inline asm, @@ -1073,8 +1088,7 @@ void ModuleBitcodeWriter::writeModuleInfo() { SmallVector Vals; // Emit the module's source file name. { - StringEncoding Bits = getStringEncoding(M.getSourceFileName().data(), - M.getSourceFileName().size()); + StringEncoding Bits = getStringEncoding(M.getSourceFileName()); BitCodeAbbrevOp AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8); if (Bits == SE_Char6) AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Char6); @@ -2790,8 +2804,7 @@ void ModuleBitcodeWriter::writeFunctionLevelValueSymbolTable( for (const ValueName &Name : VST) { // Figure out the encoding to use for the name. - StringEncoding Bits = - getStringEncoding(Name.getKeyData(), Name.getKeyLength()); + StringEncoding Bits = getStringEncoding(Name.getKey()); unsigned AbbrevToUse = VST_ENTRY_8_ABBREV; NameVals.push_back(VE.getValueID(Name.getValue())); @@ -3149,41 +3162,33 @@ void IndexBitcodeWriter::writeModStrings() { unsigned AbbrevHash = Stream.EmitAbbrev(std::move(Abbv)); SmallVector Vals; - for (const auto &MPSE : Index.modulePaths()) { - if (!doIncludeModule(MPSE.getKey())) - continue; - StringEncoding Bits = - getStringEncoding(MPSE.getKey().data(), MPSE.getKey().size()); - unsigned AbbrevToUse = Abbrev8Bit; - if (Bits == SE_Char6) - AbbrevToUse = Abbrev6Bit; - else if (Bits == SE_Fixed7) - AbbrevToUse = Abbrev7Bit; + forEachModule( + [&](const StringMapEntry> &MPSE) { + StringRef Key = MPSE.getKey(); + const auto &Value = MPSE.getValue(); + StringEncoding Bits = getStringEncoding(Key); + unsigned AbbrevToUse = Abbrev8Bit; + if (Bits == SE_Char6) + AbbrevToUse = Abbrev6Bit; + else if (Bits == SE_Fixed7) + AbbrevToUse = Abbrev7Bit; - Vals.push_back(MPSE.getValue().first); + Vals.push_back(Value.first); + Vals.append(Key.begin(), Key.end()); - for (const auto P : MPSE.getKey()) - Vals.push_back((unsigned char)P); + // Emit the finished record. + Stream.EmitRecord(bitc::MST_CODE_ENTRY, Vals, AbbrevToUse); - // Emit the finished record. - Stream.EmitRecord(bitc::MST_CODE_ENTRY, Vals, AbbrevToUse); + // Emit an optional hash for the module now + const auto &Hash = Value.second; + if (llvm::any_of(Hash, [](uint32_t H) { return H; })) { + Vals.assign(Hash.begin(), Hash.end()); + // Emit the hash record. + Stream.EmitRecord(bitc::MST_CODE_HASH, Vals, AbbrevHash); + } - Vals.clear(); - // Emit an optional hash for the module now - auto &Hash = MPSE.getValue().second; - bool AllZero = true; // Detect if the hash is empty, and do not generate it - for (auto Val : Hash) { - if (Val) - AllZero = false; - Vals.push_back(Val); - } - if (!AllZero) { - // Emit the hash record. - Stream.EmitRecord(bitc::MST_CODE_HASH, Vals, AbbrevHash); - } - - Vals.clear(); - } + Vals.clear(); + }); Stream.ExitBlock(); } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp index 20e1467b30c3..c2ad9db81cfd 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp @@ -194,6 +194,10 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF, // some variables. for (const MachineOperand &MO : MI.operands()) { if (MO.isReg() && MO.isDef() && MO.getReg()) { + // Ignore call instructions that claim to clobber SP. The AArch64 + // backend does this for aggregate function arguments. + if (MI.isCall() && MO.getReg() == SP) + continue; // If this is a virtual register, only clobber it since it doesn't // have aliases. if (TRI->isVirtualRegister(MO.getReg())) diff --git a/contrib/llvm/lib/CodeGen/CodeGen.cpp b/contrib/llvm/lib/CodeGen/CodeGen.cpp index 4d30c6574b12..256a0c95d365 100644 --- a/contrib/llvm/lib/CodeGen/CodeGen.cpp +++ b/contrib/llvm/lib/CodeGen/CodeGen.cpp @@ -77,6 +77,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializePostRASchedulerPass(Registry); initializePreISelIntrinsicLoweringLegacyPassPass(Registry); initializeProcessImplicitDefsPass(Registry); + initializeRABasicPass(Registry); initializeRAGreedyPass(Registry); initializeRegisterCoalescerPass(Registry); initializeRenameIndependentSubregsPass(Registry); diff --git a/contrib/llvm/lib/CodeGen/GlobalMerge.cpp b/contrib/llvm/lib/CodeGen/GlobalMerge.cpp index 23812a2a2344..3603f9b7ed93 100644 --- a/contrib/llvm/lib/CodeGen/GlobalMerge.cpp +++ b/contrib/llvm/lib/CodeGen/GlobalMerge.cpp @@ -556,6 +556,10 @@ bool GlobalMerge::doInitialization(Module &M) { if (GV.isDeclaration() || GV.isThreadLocal() || GV.hasSection()) continue; + // It's not safe to merge globals that may be preempted + if (TM && !TM->shouldAssumeDSOLocal(M, &GV)) + continue; + if (!(MergeExternalGlobals && GV.hasExternalLinkage()) && !GV.hasInternalLinkage()) continue; diff --git a/contrib/llvm/lib/CodeGen/LivePhysRegs.cpp b/contrib/llvm/lib/CodeGen/LivePhysRegs.cpp index 0dc1079b2ad4..cde6ccd29dfd 100644 --- a/contrib/llvm/lib/CodeGen/LivePhysRegs.cpp +++ b/contrib/llvm/lib/CodeGen/LivePhysRegs.cpp @@ -198,13 +198,12 @@ void LivePhysRegs::addLiveOutsNoPristines(const MachineBasicBlock &MBB) { } void LivePhysRegs::addLiveOuts(const MachineBasicBlock &MBB) { + const MachineFunction &MF = *MBB.getParent(); if (!MBB.succ_empty()) { - const MachineFunction &MF = *MBB.getParent(); addPristines(*this, MF); addLiveOutsNoPristines(MBB); } else if (MBB.isReturnBlock()) { // For the return block: Add all callee saved registers. - const MachineFunction &MF = *MBB.getParent(); const MachineFrameInfo &MFI = MF.getFrameInfo(); if (MFI.isCalleeSavedInfoValid()) addCalleeSavedRegs(*this, MF); diff --git a/contrib/llvm/lib/CodeGen/LiveRegUnits.cpp b/contrib/llvm/lib/CodeGen/LiveRegUnits.cpp index dff555f49565..3746b74e0528 100644 --- a/contrib/llvm/lib/CodeGen/LiveRegUnits.cpp +++ b/contrib/llvm/lib/CodeGen/LiveRegUnits.cpp @@ -12,11 +12,13 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/LiveRegUnits.h" + #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBundle.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Target/TargetRegisterInfo.h" @@ -81,46 +83,50 @@ void LiveRegUnits::accumulateBackward(const MachineInstr &MI) { } /// Add live-in registers of basic block \p MBB to \p LiveUnits. -static void addLiveIns(LiveRegUnits &LiveUnits, const MachineBasicBlock &MBB) { +static void addBlockLiveIns(LiveRegUnits &LiveUnits, + const MachineBasicBlock &MBB) { for (const auto &LI : MBB.liveins()) LiveUnits.addRegMasked(LI.PhysReg, LI.LaneMask); } -static void addLiveOuts(LiveRegUnits &LiveUnits, const MachineBasicBlock &MBB) { - // To get the live-outs we simply merge the live-ins of all successors. - for (const MachineBasicBlock *Succ : MBB.successors()) - addLiveIns(LiveUnits, *Succ); +/// Adds all callee saved registers to \p LiveUnits. +static void addCalleeSavedRegs(LiveRegUnits &LiveUnits, + const MachineFunction &MF) { + const MachineRegisterInfo &MRI = MF.getRegInfo(); + for (const MCPhysReg *CSR = MRI.getCalleeSavedRegs(); CSR && *CSR; ++CSR) + LiveUnits.addReg(*CSR); } -/// Add pristine registers to the given \p LiveUnits. This function removes -/// actually saved callee save registers when \p InPrologueEpilogue is false. -static void removeSavedRegs(LiveRegUnits &LiveUnits, const MachineFunction &MF, - const MachineFrameInfo &MFI, - const TargetRegisterInfo &TRI) { +/// Adds pristine registers to the given \p LiveUnits. Pristine registers are +/// callee saved registers that are unused in the function. +static void addPristines(LiveRegUnits &LiveUnits, const MachineFunction &MF) { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + if (!MFI.isCalleeSavedInfoValid()) + return; + /// Add all callee saved regs, then remove the ones that are saved+restored. + addCalleeSavedRegs(LiveUnits, MF); + /// Remove the ones that are not saved/restored; they are pristine. for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) LiveUnits.removeReg(Info.getReg()); } void LiveRegUnits::addLiveOuts(const MachineBasicBlock &MBB) { const MachineFunction &MF = *MBB.getParent(); - const MachineFrameInfo &MFI = MF.getFrameInfo(); - if (MFI.isCalleeSavedInfoValid()) { - for (const MCPhysReg *I = TRI->getCalleeSavedRegs(&MF); *I; ++I) - addReg(*I); - if (!MBB.isReturnBlock()) - removeSavedRegs(*this, MF, MFI, *TRI); + if (!MBB.succ_empty()) { + addPristines(*this, MF); + // To get the live-outs we simply merge the live-ins of all successors. + for (const MachineBasicBlock *Succ : MBB.successors()) + addBlockLiveIns(*this, *Succ); + } else if (MBB.isReturnBlock()) { + // For the return block: Add all callee saved registers. + const MachineFrameInfo &MFI = MF.getFrameInfo(); + if (MFI.isCalleeSavedInfoValid()) + addCalleeSavedRegs(*this, MF); } - ::addLiveOuts(*this, MBB); } void LiveRegUnits::addLiveIns(const MachineBasicBlock &MBB) { const MachineFunction &MF = *MBB.getParent(); - const MachineFrameInfo &MFI = MF.getFrameInfo(); - if (MFI.isCalleeSavedInfoValid()) { - for (const MCPhysReg *I = TRI->getCalleeSavedRegs(&MF); *I; ++I) - addReg(*I); - if (&MBB != &MF.front()) - removeSavedRegs(*this, MF, MFI, *TRI); - } - ::addLiveIns(*this, MBB); + addPristines(*this, MF); + addBlockLiveIns(*this, MBB); } diff --git a/contrib/llvm/lib/CodeGen/MachineRegionInfo.cpp b/contrib/llvm/lib/CodeGen/MachineRegionInfo.cpp index 71ad4e6aa7f5..2402ffdbbcb1 100644 --- a/contrib/llvm/lib/CodeGen/MachineRegionInfo.cpp +++ b/contrib/llvm/lib/CodeGen/MachineRegionInfo.cpp @@ -1,7 +1,19 @@ -#include "llvm/CodeGen/MachineRegionInfo.h" +//===- lib/Codegen/MachineRegionInfo.cpp ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/RegionInfoImpl.h" #include "llvm/CodeGen/MachinePostDominators.h" +#include "llvm/CodeGen/MachineRegionInfo.h" +#include "llvm/Pass.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" #define DEBUG_TYPE "machine-region-info" @@ -11,36 +23,29 @@ STATISTIC(numMachineRegions, "The # of machine regions"); STATISTIC(numMachineSimpleRegions, "The # of simple machine regions"); namespace llvm { + template class RegionBase>; template class RegionNodeBase>; template class RegionInfoBase>; -} + +} // end namespace llvm //===----------------------------------------------------------------------===// // MachineRegion implementation -// MachineRegion::MachineRegion(MachineBasicBlock *Entry, MachineBasicBlock *Exit, MachineRegionInfo* RI, MachineDominatorTree *DT, MachineRegion *Parent) : - RegionBase>(Entry, Exit, RI, DT, Parent) { + RegionBase>(Entry, Exit, RI, DT, Parent) {} -} - -MachineRegion::~MachineRegion() { } +MachineRegion::~MachineRegion() = default; //===----------------------------------------------------------------------===// // MachineRegionInfo implementation -// -MachineRegionInfo::MachineRegionInfo() : - RegionInfoBase>() { +MachineRegionInfo::MachineRegionInfo() = default; -} - -MachineRegionInfo::~MachineRegionInfo() { - -} +MachineRegionInfo::~MachineRegionInfo() = default; void MachineRegionInfo::updateStatistics(MachineRegion *R) { ++numMachineRegions; @@ -73,9 +78,7 @@ MachineRegionInfoPass::MachineRegionInfoPass() : MachineFunctionPass(ID) { initializeMachineRegionInfoPassPass(*PassRegistry::getPassRegistry()); } -MachineRegionInfoPass::~MachineRegionInfoPass() { - -} +MachineRegionInfoPass::~MachineRegionInfoPass() = default; bool MachineRegionInfoPass::runOnMachineFunction(MachineFunction &F) { releaseMemory(); @@ -137,8 +140,9 @@ INITIALIZE_PASS_END(MachineRegionInfoPass, DEBUG_TYPE, // the link time optimization. namespace llvm { - FunctionPass *createMachineRegionInfoPass() { - return new MachineRegionInfoPass(); - } + +FunctionPass *createMachineRegionInfoPass() { + return new MachineRegionInfoPass(); } +} // end namespace llvm diff --git a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp index 265f93c363ca..f6dbf667cf02 100644 --- a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp @@ -36,6 +36,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/StackMaps.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" @@ -909,17 +910,43 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { } } - // Generic loads and stores must have a single MachineMemOperand - // describing that access. - if ((MI->getOpcode() == TargetOpcode::G_LOAD || - MI->getOpcode() == TargetOpcode::G_STORE) && - !MI->hasOneMemOperand()) - report("Generic instruction accessing memory must have one mem operand", - MI); - StringRef ErrorInfo; if (!TII->verifyInstruction(*MI, ErrorInfo)) report(ErrorInfo.data(), MI); + + // Verify properties of various specific instruction types + switch(MI->getOpcode()) { + default: + break; + case TargetOpcode::G_LOAD: + case TargetOpcode::G_STORE: + // Generic loads and stores must have a single MachineMemOperand + // describing that access. + if (!MI->hasOneMemOperand()) + report("Generic instruction accessing memory must have one mem operand", + MI); + break; + case TargetOpcode::STATEPOINT: + if (!MI->getOperand(StatepointOpers::IDPos).isImm() || + !MI->getOperand(StatepointOpers::NBytesPos).isImm() || + !MI->getOperand(StatepointOpers::NCallArgsPos).isImm()) + report("meta operands to STATEPOINT not constant!", MI); + break; + + auto VerifyStackMapConstant = [&](unsigned Offset) { + if (!MI->getOperand(Offset).isImm() || + MI->getOperand(Offset).getImm() != StackMaps::ConstantOp || + !MI->getOperand(Offset + 1).isImm()) + report("stack map constant to STATEPOINT not well formed!", MI); + }; + const unsigned VarStart = StatepointOpers(MI).getVarIdx(); + VerifyStackMapConstant(VarStart + StatepointOpers::CCOffset); + VerifyStackMapConstant(VarStart + StatepointOpers::FlagsOffset); + VerifyStackMapConstant(VarStart + StatepointOpers::NumDeoptOperandsOffset); + + // TODO: verify we have properly encoded deopt arguments + + }; } void diff --git a/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp index a9813e534c5f..e9f8d43fe643 100644 --- a/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -54,8 +54,6 @@ static void doSpillCalleeSavedRegs(MachineFunction &MF, RegScavenger *RS, const MBBVector &SaveBlocks, const MBBVector &RestoreBlocks); -static void doScavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger *RS); - namespace { class PEI : public MachineFunctionPass { public: @@ -84,7 +82,7 @@ private: const MBBVector &SaveBlocks, const MBBVector &RestoreBlocks)> SpillCalleeSavedRegisters; - std::function + std::function ScavengeFrameVirtualRegs; bool UsesCalleeSaves = false; @@ -142,7 +140,6 @@ MachineFunctionPass *llvm::createPrologEpilogInserterPass() { return new PEI(); } -STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged"); STATISTIC(NumBytesStackSpace, "Number of bytes used for stack in all functions"); @@ -168,10 +165,10 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { SpillCalleeSavedRegisters = [](MachineFunction &, RegScavenger *, unsigned &, unsigned &, const MBBVector &, const MBBVector &) {}; - ScavengeFrameVirtualRegs = [](MachineFunction &, RegScavenger *) {}; + ScavengeFrameVirtualRegs = [](MachineFunction &, RegScavenger &) {}; } else { SpillCalleeSavedRegisters = doSpillCalleeSavedRegs; - ScavengeFrameVirtualRegs = doScavengeFrameVirtualRegs; + ScavengeFrameVirtualRegs = scavengeFrameVirtualRegs; UsesCalleeSaves = true; } } @@ -222,7 +219,7 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { // post-pass, scavenge the virtual registers that frame index elimination // inserted. if (TRI->requiresRegisterScavenging(Fn) && FrameIndexVirtualScavenging) { - ScavengeFrameVirtualRegs(Fn, RS); + ScavengeFrameVirtualRegs(Fn, *RS); // Clear any vregs created by virtual scavenging. Fn.getRegInfo().clearVirtRegs(); @@ -1153,92 +1150,3 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, RS->forward(MI); } } - -/// doScavengeFrameVirtualRegs - Replace all frame index virtual registers -/// with physical registers. Use the register scavenger to find an -/// appropriate register to use. -/// -/// FIXME: Iterating over the instruction stream is unnecessary. We can simply -/// iterate over the vreg use list, which at this point only contains machine -/// operands for which eliminateFrameIndex need a new scratch reg. -static void -doScavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger *RS) { - // Run through the instructions and find any virtual registers. - MachineRegisterInfo &MRI = MF.getRegInfo(); - for (MachineBasicBlock &MBB : MF) { - RS->enterBasicBlock(MBB); - - int SPAdj = 0; - - // The instruction stream may change in the loop, so check MBB.end() - // directly. - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { - // We might end up here again with a NULL iterator if we scavenged a - // register for which we inserted spill code for definition by what was - // originally the first instruction in MBB. - if (I == MachineBasicBlock::iterator(nullptr)) - I = MBB.begin(); - - const MachineInstr &MI = *I; - MachineBasicBlock::iterator J = std::next(I); - MachineBasicBlock::iterator P = - I == MBB.begin() ? MachineBasicBlock::iterator(nullptr) - : std::prev(I); - - // RS should process this instruction before we might scavenge at this - // location. This is because we might be replacing a virtual register - // defined by this instruction, and if so, registers killed by this - // instruction are available, and defined registers are not. - RS->forward(I); - - for (const MachineOperand &MO : MI.operands()) { - if (!MO.isReg()) - continue; - unsigned Reg = MO.getReg(); - if (!TargetRegisterInfo::isVirtualRegister(Reg)) - continue; - - // When we first encounter a new virtual register, it - // must be a definition. - assert(MO.isDef() && "frame index virtual missing def!"); - // Scavenge a new scratch register - const TargetRegisterClass *RC = MRI.getRegClass(Reg); - unsigned ScratchReg = RS->scavengeRegister(RC, J, SPAdj); - - ++NumScavengedRegs; - - // Replace this reference to the virtual register with the - // scratch register. - assert(ScratchReg && "Missing scratch register!"); - MRI.replaceRegWith(Reg, ScratchReg); - - // Because this instruction was processed by the RS before this - // register was allocated, make sure that the RS now records the - // register as being used. - RS->setRegUsed(ScratchReg); - } - - // If the scavenger needed to use one of its spill slots, the - // spill code will have been inserted in between I and J. This is a - // problem because we need the spill code before I: Move I to just - // prior to J. - if (I != std::prev(J)) { - MBB.splice(J, &MBB, I); - - // Before we move I, we need to prepare the RS to visit I again. - // Specifically, RS will assert if it sees uses of registers that - // it believes are undefined. Because we have already processed - // register kills in I, when it visits I again, it will believe that - // those registers are undefined. To avoid this situation, unprocess - // the instruction I. - assert(RS->getCurrentPosition() == I && - "The register scavenger has an unexpected position"); - I = P; - RS->unprocess(P); - } else - ++I; - } - } - - MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs); -} diff --git a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp index a87fed3a687e..24be7ea98d82 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp @@ -58,8 +58,9 @@ namespace { /// whenever a register is unavailable. This is not practical in production but /// provides a useful baseline both for measuring other allocators and comparing /// the speed of the basic algorithm against other styles of allocators. -class RABasic : public MachineFunctionPass, public RegAllocBase -{ +class RABasic : public MachineFunctionPass, + public RegAllocBase, + private LiveRangeEdit::Delegate { // context MachineFunction *MF; @@ -72,6 +73,9 @@ class RABasic : public MachineFunctionPass, public RegAllocBase // selectOrSplit(). BitVector UsableRegs; + bool LRE_CanEraseVirtReg(unsigned) override; + void LRE_WillShrinkVirtReg(unsigned) override; + public: RABasic(); @@ -121,17 +125,46 @@ char RABasic::ID = 0; } // end anonymous namespace +char &llvm::RABasicID = RABasic::ID; + +INITIALIZE_PASS_BEGIN(RABasic, "regallocbasic", "Basic Register Allocator", + false, false) +INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_DEPENDENCY(RegisterCoalescer) +INITIALIZE_PASS_DEPENDENCY(MachineScheduler) +INITIALIZE_PASS_DEPENDENCY(LiveStacks) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(VirtRegMap) +INITIALIZE_PASS_DEPENDENCY(LiveRegMatrix) +INITIALIZE_PASS_END(RABasic, "regallocbasic", "Basic Register Allocator", false, + false) + +bool RABasic::LRE_CanEraseVirtReg(unsigned VirtReg) { + if (VRM->hasPhys(VirtReg)) { + LiveInterval &LI = LIS->getInterval(VirtReg); + Matrix->unassign(LI); + aboutToRemoveInterval(LI); + return true; + } + // Unassigned virtreg is probably in the priority queue. + // RegAllocBase will erase it after dequeueing. + return false; +} + +void RABasic::LRE_WillShrinkVirtReg(unsigned VirtReg) { + if (!VRM->hasPhys(VirtReg)) + return; + + // Register is assigned, put it back on the queue for reassignment. + LiveInterval &LI = LIS->getInterval(VirtReg); + Matrix->unassign(LI); + enqueue(&LI); +} + RABasic::RABasic(): MachineFunctionPass(ID) { - initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry()); - initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); - initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); - initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); - initializeMachineSchedulerPass(*PassRegistry::getPassRegistry()); - initializeLiveStacksPass(*PassRegistry::getPassRegistry()); - initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry()); - initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); - initializeVirtRegMapPass(*PassRegistry::getPassRegistry()); - initializeLiveRegMatrixPass(*PassRegistry::getPassRegistry()); } void RABasic::getAnalysisUsage(AnalysisUsage &AU) const { @@ -200,7 +233,7 @@ bool RABasic::spillInterferences(LiveInterval &VirtReg, unsigned PhysReg, Matrix->unassign(Spill); // Spill the extracted interval. - LiveRangeEdit LRE(&Spill, SplitVRegs, *MF, *LIS, VRM, nullptr, &DeadRemats); + LiveRangeEdit LRE(&Spill, SplitVRegs, *MF, *LIS, VRM, this, &DeadRemats); spiller().spill(LRE); } return true; @@ -259,7 +292,7 @@ unsigned RABasic::selectOrSplit(LiveInterval &VirtReg, DEBUG(dbgs() << "spilling: " << VirtReg << '\n'); if (!VirtReg.isSpillable()) return ~0u; - LiveRangeEdit LRE(&VirtReg, SplitVRegs, *MF, *LIS, VRM, nullptr, &DeadRemats); + LiveRangeEdit LRE(&VirtReg, SplitVRegs, *MF, *LIS, VRM, this, &DeadRemats); spiller().spill(LRE); // The live virtual register requesting allocation was spilled, so tell diff --git a/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp b/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp index 3b5964eef55e..b2dfef91add5 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp @@ -49,9 +49,11 @@ #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PBQP/Graph.h" +#include "llvm/CodeGen/PBQP/Math.h" #include "llvm/CodeGen/PBQP/Solution.h" #include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/CodeGen/RegAllocPBQP.h" @@ -139,13 +141,13 @@ public: } private: - typedef std::map LI2NodeMap; - typedef std::vector Node2LIMap; - typedef std::vector AllowedSet; - typedef std::vector AllowedSetMap; - typedef std::pair RegPair; - typedef std::map CoalesceMap; - typedef std::set RegSet; + using LI2NodeMap = std::map; + using Node2LIMap = std::vector; + using AllowedSet = std::vector; + using AllowedSetMap = std::vector; + using RegPair = std::pair; + using CoalesceMap = std::map; + using RegSet = std::set; char *customPassID; @@ -212,12 +214,12 @@ public: /// @brief Add interference edges between overlapping vregs. class Interference : public PBQPRAConstraint { private: - typedef const PBQP::RegAlloc::AllowedRegVector* AllowedRegVecPtr; - typedef std::pair IKey; - typedef DenseMap IMatrixCache; - typedef DenseSet DisjointAllowedRegsCache; - typedef std::pair IEdgeKey; - typedef DenseSet IEdgeCache; + using AllowedRegVecPtr = const PBQP::RegAlloc::AllowedRegVector *; + using IKey = std::pair; + using IMatrixCache = DenseMap; + using DisjointAllowedRegsCache = DenseSet; + using IEdgeKey = std::pair; + using IEdgeCache = DenseSet; bool haveDisjointAllowedRegs(const PBQPRAGraph &G, PBQPRAGraph::NodeId NId, PBQPRAGraph::NodeId MId, @@ -252,8 +254,8 @@ private: // for the fast interference graph construction algorithm. The last is there // to save us from looking up node ids via the VRegToNode map in the graph // metadata. - typedef std::tuple - IntervalInfo; + using IntervalInfo = + std::tuple; static SlotIndex getStartPoint(const IntervalInfo &I) { return std::get<0>(I)->segments[std::get<1>(I)].start; @@ -320,9 +322,10 @@ public: // Cache known disjoint allowed registers pairs DisjointAllowedRegsCache D; - typedef std::set IntervalSet; - typedef std::priority_queue, - decltype(&lowestStartPoint)> IntervalQueue; + using IntervalSet = std::set; + using IntervalQueue = + std::priority_queue, + decltype(&lowestStartPoint)>; IntervalSet Active(lowestEndPoint); IntervalQueue Inactive(lowestStartPoint); @@ -658,7 +661,6 @@ void RegAllocPBQP::spillVReg(unsigned VReg, SmallVectorImpl &NewIntervals, MachineFunction &MF, LiveIntervals &LIS, VirtRegMap &VRM, Spiller &VRegSpiller) { - VRegsToAlloc.erase(VReg); LiveRangeEdit LRE(&LIS.getInterval(VReg), NewIntervals, MF, LIS, &VRM, nullptr, &DeadRemats); diff --git a/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp b/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp index 0635e5c0a63c..1aed58c36e17 100644 --- a/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp +++ b/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp @@ -15,18 +15,23 @@ // //===----------------------------------------------------------------------===// +#include "llvm/CodeGen/RegisterScavenging.h" + #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/PassSupport.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" @@ -39,6 +44,8 @@ using namespace llvm; #define DEBUG_TYPE "reg-scavenging" +STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged"); + void RegScavenger::setRegUsed(unsigned Reg, LaneBitmask LaneMask) { LiveUnits.addRegMasked(Reg, LaneMask); } @@ -469,3 +476,120 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, return SReg; } + +void llvm::scavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger &RS) { + // FIXME: Iterating over the instruction stream is unnecessary. We can simply + // iterate over the vreg use list, which at this point only contains machine + // operands for which eliminateFrameIndex need a new scratch reg. + + // Run through the instructions and find any virtual registers. + MachineRegisterInfo &MRI = MF.getRegInfo(); + for (MachineBasicBlock &MBB : MF) { + RS.enterBasicBlock(MBB); + + int SPAdj = 0; + + // The instruction stream may change in the loop, so check MBB.end() + // directly. + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { + // We might end up here again with a NULL iterator if we scavenged a + // register for which we inserted spill code for definition by what was + // originally the first instruction in MBB. + if (I == MachineBasicBlock::iterator(nullptr)) + I = MBB.begin(); + + const MachineInstr &MI = *I; + MachineBasicBlock::iterator J = std::next(I); + MachineBasicBlock::iterator P = + I == MBB.begin() ? MachineBasicBlock::iterator(nullptr) + : std::prev(I); + + // RS should process this instruction before we might scavenge at this + // location. This is because we might be replacing a virtual register + // defined by this instruction, and if so, registers killed by this + // instruction are available, and defined registers are not. + RS.forward(I); + + for (const MachineOperand &MO : MI.operands()) { + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + + // When we first encounter a new virtual register, it + // must be a definition. + assert(MO.isDef() && "frame index virtual missing def!"); + // Scavenge a new scratch register + const TargetRegisterClass *RC = MRI.getRegClass(Reg); + unsigned ScratchReg = RS.scavengeRegister(RC, J, SPAdj); + + ++NumScavengedRegs; + + // Replace this reference to the virtual register with the + // scratch register. + assert(ScratchReg && "Missing scratch register!"); + MRI.replaceRegWith(Reg, ScratchReg); + + // Because this instruction was processed by the RS before this + // register was allocated, make sure that the RS now records the + // register as being used. + RS.setRegUsed(ScratchReg); + } + + // If the scavenger needed to use one of its spill slots, the + // spill code will have been inserted in between I and J. This is a + // problem because we need the spill code before I: Move I to just + // prior to J. + if (I != std::prev(J)) { + MBB.splice(J, &MBB, I); + + // Before we move I, we need to prepare the RS to visit I again. + // Specifically, RS will assert if it sees uses of registers that + // it believes are undefined. Because we have already processed + // register kills in I, when it visits I again, it will believe that + // those registers are undefined. To avoid this situation, unprocess + // the instruction I. + assert(RS.getCurrentPosition() == I && + "The register scavenger has an unexpected position"); + I = P; + RS.unprocess(P); + } else + ++I; + } + } + + MRI.clearVirtRegs(); + MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs); +} + +namespace { +/// This class runs register scavenging independ of the PrologEpilogInserter. +/// This is used in for testing. +class ScavengerTest : public MachineFunctionPass { +public: + static char ID; + ScavengerTest() : MachineFunctionPass(ID) {} + bool runOnMachineFunction(MachineFunction &MF) { + const TargetSubtargetInfo &STI = MF.getSubtarget(); + const TargetFrameLowering &TFL = *STI.getFrameLowering(); + + RegScavenger RS; + // Let's hope that calling those outside of PrologEpilogueInserter works + // well enough to initialize the scavenger with some emergency spillslots + // for the target. + BitVector SavedRegs; + TFL.determineCalleeSaves(MF, SavedRegs, &RS); + TFL.processFunctionBeforeFrameFinalized(MF, &RS); + + // Let's scavenge the current function + scavengeFrameVirtualRegs(MF, RS); + return true; + } +}; +char ScavengerTest::ID; + +} // end anonymous namespace + +INITIALIZE_PASS(ScavengerTest, "scavenger-test", + "Scavenge virtual registers inside basic blocks", false, false) diff --git a/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp index 8035ea80364b..3fdbd2459361 100644 --- a/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -12,32 +12,54 @@ // //===----------------------------------------------------------------------===// -#include "llvm/CodeGen/ScheduleDAGInstrs.h" #include "llvm/ADT/IntEqClasses.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SparseSet.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LivePhysRegs.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBundle.h" #include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/RegisterPressure.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/ScheduleDAGInstrs.h" #include "llvm/CodeGen/ScheduleDFS.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" -#include "llvm/IR/Type.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Value.h" +#include "llvm/MC/LaneBitmask.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" +#include +#include +#include +#include +#include +#include using namespace llvm; @@ -90,11 +112,9 @@ ScheduleDAGInstrs::ScheduleDAGInstrs(MachineFunction &mf, const MachineLoopInfo *mli, bool RemoveKillFlags) : ScheduleDAG(mf), MLI(mli), MFI(mf.getFrameInfo()), - RemoveKillFlags(RemoveKillFlags), CanHandleTerminators(false), - TrackLaneMasks(false), AAForDep(nullptr), BarrierChain(nullptr), + RemoveKillFlags(RemoveKillFlags), UnknownValue(UndefValue::get( - Type::getVoidTy(mf.getFunction()->getContext()))), - FirstDbgValue(nullptr) { + Type::getVoidTy(mf.getFunction()->getContext()))) { DbgValues.clear(); const TargetSubtargetInfo &ST = mf.getSubtarget(); @@ -126,7 +146,7 @@ static const Value *getUnderlyingObjectFromInt(const Value *V) { return V; } assert(V->getType()->isIntegerTy() && "Unexpected operand type!"); - } while (1); + } while (true); } /// This is a wrapper around GetUnderlyingObjects and adds support for basic @@ -563,7 +583,7 @@ void ScheduleDAGInstrs::initSUnits() { // which is contained within a basic block. SUnits.reserve(NumRegionInstrs); - for (MachineInstr &MI : llvm::make_range(RegionBegin, RegionEnd)) { + for (MachineInstr &MI : make_range(RegionBegin, RegionEnd)) { if (MI.isDebugValue()) continue; @@ -606,13 +626,13 @@ void ScheduleDAGInstrs::initSUnits() { class ScheduleDAGInstrs::Value2SUsMap : public MapVector { /// Current total number of SUs in map. - unsigned NumNodes; + unsigned NumNodes = 0; /// 1 for loads, 0 for stores. (see comment in SUList) unsigned TrueMemOrderLatency; public: - Value2SUsMap(unsigned lat = 0) : NumNodes(0), TrueMemOrderLatency(lat) {} + Value2SUsMap(unsigned lat = 0) : TrueMemOrderLatency(lat) {} /// To keep NumNodes up to date, insert() is used instead of /// this operator w/ push_back(). @@ -630,7 +650,7 @@ public: void inline clearList(ValueType V) { iterator Itr = find(V); if (Itr != end()) { - assert (NumNodes >= Itr->second.size()); + assert(NumNodes >= Itr->second.size()); NumNodes -= Itr->second.size(); Itr->second.clear(); @@ -646,7 +666,7 @@ public: unsigned inline size() const { return NumNodes; } /// Counts the number of SUs in this map after a reduction. - void reComputeSize(void) { + void reComputeSize() { NumNodes = 0; for (auto &I : *this) NumNodes += I.second.size(); @@ -676,7 +696,7 @@ void ScheduleDAGInstrs::addChainDependencies(SUnit *SU, } void ScheduleDAGInstrs::addBarrierChain(Value2SUsMap &map) { - assert (BarrierChain != nullptr); + assert(BarrierChain != nullptr); for (auto &I : map) { SUList &sus = I.second; @@ -687,7 +707,7 @@ void ScheduleDAGInstrs::addBarrierChain(Value2SUsMap &map) { } void ScheduleDAGInstrs::insertBarrierChain(Value2SUsMap &map) { - assert (BarrierChain != nullptr); + assert(BarrierChain != nullptr); // Go through all lists of SUs. for (Value2SUsMap::iterator I = map.begin(), EE = map.end(); I != EE;) { @@ -1028,7 +1048,7 @@ void ScheduleDAGInstrs::reduceHugeMemNodeMaps(Value2SUsMap &stores, // The N last elements in NodeNums will be removed, and the SU with // the lowest NodeNum of them will become the new BarrierChain to // let the not yet seen SUs have a dependency to the removed SUs. - assert (N <= NodeNums.size()); + assert(N <= NodeNums.size()); SUnit *newBarrierChain = &SUnits[*(NodeNums.end() - N)]; if (BarrierChain) { // The aliasing and non-aliasing maps reduce independently of each @@ -1156,6 +1176,7 @@ std::string ScheduleDAGInstrs::getDAGName() const { //===----------------------------------------------------------------------===// namespace llvm { + /// Internal state used to compute SchedDFSResult. class SchedDFSImpl { SchedDFSResult &R; @@ -1163,16 +1184,16 @@ class SchedDFSImpl { /// Join DAG nodes into equivalence classes by their subtree. IntEqClasses SubtreeClasses; /// List PredSU, SuccSU pairs that represent data edges between subtrees. - std::vector > ConnectionPairs; + std::vector> ConnectionPairs; struct RootData { unsigned NodeID; unsigned ParentNodeID; ///< Parent node (member of the parent subtree). - unsigned SubInstrCount; ///< Instr count in this tree only, not children. + unsigned SubInstrCount = 0; ///< Instr count in this tree only, not + /// children. RootData(unsigned id): NodeID(id), - ParentNodeID(SchedDFSResult::InvalidSubtreeID), - SubInstrCount(0) {} + ParentNodeID(SchedDFSResult::InvalidSubtreeID) {} unsigned getSparseSetIndex() const { return NodeID; } }; @@ -1340,12 +1361,15 @@ protected: } while (FromTree != SchedDFSResult::InvalidSubtreeID); } }; + } // end namespace llvm namespace { + /// Manage the stack used by a reverse depth-first search over the DAG. class SchedDAGReverseDFS { - std::vector > DFSStack; + std::vector> DFSStack; + public: bool isComplete() const { return DFSStack.empty(); } @@ -1367,7 +1391,8 @@ public: return getCurr()->Preds.end(); } }; -} // anonymous + +} // end anonymous namespace static bool hasDataSucc(const SUnit *SU) { for (const SDep &SuccDep : SU->Succs) { @@ -1392,7 +1417,7 @@ void SchedDFSResult::compute(ArrayRef SUnits) { SchedDAGReverseDFS DFS; Impl.visitPreorder(&SU); DFS.follow(&SU); - for (;;) { + while (true) { // Traverse the leftmost path as far as possible. while (DFS.getPred() != DFS.getPredEnd()) { const SDep &PredDep = *DFS.getPred(); @@ -1457,4 +1482,5 @@ raw_ostream &operator<<(raw_ostream &OS, const ILPValue &Val) { } } // end namespace llvm + #endif diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp index 5f167f8de1cf..9355dbe77f94 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -225,6 +225,7 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) { } return TranslateLegalizeResults(Op, Lowered); } + LLVM_FALLTHROUGH; case TargetLowering::Expand: Changed = true; return LegalizeOp(ExpandLoad(Op)); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 177898e1e950..80a03ea4eea0 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1,4 +1,4 @@ -//===-- SelectionDAG.cpp - Implement the SelectionDAG data structures -----===// +//===- SelectionDAG.cpp - Implement the SelectionDAG data structures ------===// // // The LLVM Compiler Infrastructure // @@ -11,29 +11,46 @@ // //===----------------------------------------------------------------------===// -#include "llvm/CodeGen/SelectionDAG.h" #include "SDNodeDbgValue.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/Twine.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineValueType.h" +#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" -#include "llvm/IR/CallingConv.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" -#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" -#include "llvm/IR/GlobalAlias.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/KnownBits.h" @@ -41,16 +58,20 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetIntrinsicInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" #include -#include +#include +#include +#include +#include +#include +#include #include +#include using namespace llvm; @@ -269,7 +290,6 @@ ISD::CondCode ISD::getSetCCInverse(ISD::CondCode Op, bool isInteger) { return ISD::CondCode(Operation); } - /// For an integer comparison, return 1 if the comparison is a signed operation /// and 2 if the result is an unsigned comparison. Return zero if the operation /// does not depend on the sign of the input (setne and seteq). @@ -338,7 +358,6 @@ ISD::CondCode ISD::getSetCCAndOperation(ISD::CondCode Op1, ISD::CondCode Op2, //===----------------------------------------------------------------------===// /// AddNodeIDOpcode - Add the node opcode to the NodeID data. -/// static void AddNodeIDOpcode(FoldingSetNodeID &ID, unsigned OpC) { ID.AddInteger(OpC); } @@ -350,7 +369,6 @@ static void AddNodeIDValueTypes(FoldingSetNodeID &ID, SDVTList VTList) { } /// AddNodeIDOperands - Various routines for adding operands to the NodeID data. -/// static void AddNodeIDOperands(FoldingSetNodeID &ID, ArrayRef Ops) { for (auto& Op : Ops) { @@ -360,7 +378,6 @@ static void AddNodeIDOperands(FoldingSetNodeID &ID, } /// AddNodeIDOperands - Various routines for adding operands to the NodeID data. -/// static void AddNodeIDOperands(FoldingSetNodeID &ID, ArrayRef Ops) { for (auto& Op : Ops) { @@ -392,10 +409,9 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { break; } case ISD::TargetConstantFP: - case ISD::ConstantFP: { + case ISD::ConstantFP: ID.AddPointer(cast(N)->getConstantFPValue()); break; - } case ISD::TargetGlobalAddress: case ISD::GlobalAddress: case ISD::TargetGlobalTLSAddress: @@ -770,7 +786,6 @@ bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) { /// maps and modified in place. Add it back to the CSE maps, unless an identical /// node already exists, in which case transfer all its users to the existing /// node. This transfer can potentially trigger recursive merging. -/// void SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N) { // For node types that aren't CSE'd, just act as if no identical node @@ -835,7 +850,6 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, return Node; } - /// FindModifiedNodeSlot - Find a slot for the specified node if its operands /// were replaced with those specified. If this node is never memoized, /// return null, otherwise return a pointer to the slot it would take. If a @@ -864,10 +878,9 @@ unsigned SelectionDAG::getEVTAlignment(EVT VT) const { // EntryNode could meaningfully have debug info if we can find it... SelectionDAG::SelectionDAG(const TargetMachine &tm, CodeGenOpt::Level OL) - : TM(tm), TSI(nullptr), TLI(nullptr), OptLevel(OL), + : TM(tm), OptLevel(OL), EntryNode(ISD::EntryToken, 0, DebugLoc(), getVTList(MVT::Other)), - Root(getEntryNode()), NewNodesMustHaveLegalTypes(false), - UpdateListeners(nullptr) { + Root(getEntryNode()) { InsertNode(&EntryNode); DbgInfo = new SDDbgInfo(); } @@ -1038,7 +1051,6 @@ SDValue SelectionDAG::getZeroExtendVectorInReg(SDValue Op, const SDLoc &DL, } /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). -/// SDValue SelectionDAG::getNOT(const SDLoc &DL, SDValue Val, EVT VT) { EVT EltVT = VT.getScalarType(); SDValue NegOne = @@ -1317,7 +1329,6 @@ SDValue SelectionDAG::getConstantPool(const Constant *C, EVT VT, return SDValue(N, 0); } - SDValue SelectionDAG::getConstantPool(MachineConstantPoolValue *C, EVT VT, unsigned Alignment, int Offset, bool isTarget, @@ -1451,7 +1462,7 @@ SDValue SelectionDAG::getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, // Validate that all indices in Mask are within the range of the elements // input to the shuffle. int NElts = Mask.size(); - assert(all_of(Mask, [&](int M) { return M < (NElts * 2); }) && + assert(llvm::all_of(Mask, [&](int M) { return M < (NElts * 2); }) && "Index out of range"); // Copy the mask so we can do any needed cleanup. @@ -2918,7 +2929,7 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts, else DemandedRHS.setBit((unsigned)M % NumElts); } - Tmp = UINT_MAX; + Tmp = std::numeric_limits::max(); if (!!DemandedLHS) Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedLHS, Depth + 1); if (!!DemandedRHS) { @@ -3122,7 +3133,7 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts, unsigned EltIdx = CEltNo->getZExtValue(); // If we demand the inserted element then get its sign bits. - Tmp = UINT_MAX; + Tmp = std::numeric_limits::max(); if (DemandedElts[EltIdx]) { // TODO - handle implicit truncation of inserted elements. if (InVal.getScalarValueSizeInBits() != VTBits) @@ -3188,7 +3199,7 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts, case ISD::CONCAT_VECTORS: // Determine the minimum number of sign bits across all demanded // elts of the input vectors. Early out if the result is already 1. - Tmp = UINT_MAX; + Tmp = std::numeric_limits::max(); EVT SubVectorVT = Op.getOperand(0).getValueType(); unsigned NumSubVectorElts = SubVectorVT.getVectorNumElements(); unsigned NumSubVectors = Op.getNumOperands(); @@ -3327,7 +3338,7 @@ bool SelectionDAG::haveNoCommonBitsSet(SDValue A, SDValue B) const { static SDValue FoldCONCAT_VECTORS(const SDLoc &DL, EVT VT, ArrayRef Ops, - llvm::SelectionDAG &DAG) { + SelectionDAG &DAG) { assert(!Ops.empty() && "Can't concatenate an empty list of vectors!"); assert(llvm::all_of(Ops, [Ops](SDValue Op) { @@ -3836,8 +3847,9 @@ bool SelectionDAG::isUndef(unsigned Opcode, ArrayRef Ops) { return true; return ISD::isBuildVectorOfConstantSDNodes(Divisor.getNode()) && - any_of(Divisor->op_values(), - [](SDValue V) { return V.isUndef() || isNullConstant(V); }); + llvm::any_of(Divisor->op_values(), + [](SDValue V) { return V.isUndef() || + isNullConstant(V); }); // TODO: Handle signed overflow. } // TODO: Handle oversized shifts. @@ -3948,8 +3960,8 @@ SDValue SelectionDAG::FoldConstantVectorArithmetic(unsigned Opcode, // All operands must be vector types with the same number of elements as // the result type and must be either UNDEF or a build vector of constant // or UNDEF scalars. - if (!all_of(Ops, IsConstantBuildVectorOrUndef) || - !all_of(Ops, IsScalarOrSameVectorSize)) + if (!llvm::all_of(Ops, IsConstantBuildVectorOrUndef) || + !llvm::all_of(Ops, IsScalarOrSameVectorSize)) return SDValue(); // If we are comparing vectors, then the result needs to be a i1 boolean @@ -5550,7 +5562,7 @@ SDValue SelectionDAG::getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, Opcode == ISD::PREFETCH || Opcode == ISD::LIFETIME_START || Opcode == ISD::LIFETIME_END || - (Opcode <= INT_MAX && + ((int)Opcode <= std::numeric_limits::max() && (int)Opcode >= ISD::FIRST_TARGET_MEMORY_OPCODE)) && "Opcode is not a memory-accessing opcode!"); @@ -5884,7 +5896,6 @@ SDValue SelectionDAG::getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::LoadExtType ExtTy, bool isExpanding) { - SDVTList VTs = getVTList(VT, MVT::Other); SDValue Ops[] = { Chain, Ptr, Mask, Src0 }; FoldingSetNodeID ID; @@ -6038,13 +6049,12 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, switch (Opcode) { default: break; - case ISD::CONCAT_VECTORS: { + case ISD::CONCAT_VECTORS: // Attempt to fold CONCAT_VECTORS into BUILD_VECTOR or UNDEF. if (SDValue V = FoldCONCAT_VECTORS(DL, VT, Ops, *this)) return V; break; - } - case ISD::SELECT_CC: { + case ISD::SELECT_CC: assert(NumOps == 5 && "SELECT_CC takes 5 operands!"); assert(Ops[0].getValueType() == Ops[1].getValueType() && "LHS and RHS of condition must have same type!"); @@ -6053,14 +6063,12 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, assert(Ops[2].getValueType() == VT && "select_cc node must be of same type as true and false value!"); break; - } - case ISD::BR_CC: { + case ISD::BR_CC: assert(NumOps == 5 && "BR_CC takes 5 operands!"); assert(Ops[2].getValueType() == Ops[3].getValueType() && "LHS/RHS of comparison should match types!"); break; } - } // Memoize nodes. SDNode *N; @@ -6599,7 +6607,6 @@ SDNode* SelectionDAG::mutateStrictFPToFP(SDNode *Node) { return Res; } - /// getMachineNode - These are used for target selectors to create a new node /// with specified return type(s), MachineInstr opcode, and operands. /// @@ -6812,7 +6819,7 @@ public: : SelectionDAG::DAGUpdateListener(d), UI(ui), UE(ue) {} }; -} +} // end anonymous namespace /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. /// This can cause recursive merging of nodes in the DAG. @@ -6858,7 +6865,6 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To) { AddModifiedNodeToCSEMaps(User); } - // If we just RAUW'd the root, take note. if (FromN == getRoot()) setRoot(To); @@ -7028,6 +7034,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){ } namespace { + /// UseMemo - This class is used by SelectionDAG::ReplaceAllUsesOfValuesWith /// to record information about a use. struct UseMemo { @@ -7040,7 +7047,8 @@ namespace { bool operator<(const UseMemo &L, const UseMemo &R) { return (intptr_t)L.User < (intptr_t)R.User; } -} + +} // end anonymous namespace /// ReplaceAllUsesOfValuesWith - Replace any uses of From with To, leaving /// uses of other values produced by From.getNode() alone. The same value @@ -7106,7 +7114,6 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From, /// based on their topological order. It returns the maximum id and a vector /// of the SDNodes* in assigned order by reference. unsigned SelectionDAG::AssignTopologicalOrder() { - unsigned DAGSize = 0; // SortedPos tracks the progress of the algorithm. Nodes before it are @@ -7333,6 +7340,7 @@ void SDNode::Profile(FoldingSetNodeID &ID) const { } namespace { + struct EVTArray { std::vector VTs; @@ -7342,11 +7350,12 @@ namespace { VTs.push_back(MVT((MVT::SimpleValueType)i)); } }; -} -static ManagedStatic > EVTs; +} // end anonymous namespace + +static ManagedStatic> EVTs; static ManagedStatic SimpleVTArray; -static ManagedStatic > VTMutex; +static ManagedStatic> VTMutex; /// getValueTypeList - Return a pointer to the specified value type. /// @@ -7380,7 +7389,6 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const { return NUses == 0; } - /// hasAnyUseOfValue - Return true if there are any use of the indicated /// value. This method ignores uses of other values defined by this operation. bool SDNode::hasAnyUseOfValue(unsigned Value) const { @@ -7393,9 +7401,7 @@ bool SDNode::hasAnyUseOfValue(unsigned Value) const { return false; } - /// isOnlyUserOf - Return true if this node is the only use of N. -/// bool SDNode::isOnlyUserOf(const SDNode *N) const { bool Seen = false; for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { @@ -7425,7 +7431,6 @@ bool SDNode::areOnlyUsersOf(ArrayRef Nodes, const SDNode *N) { } /// isOperand - Return true if this node is an operand of N. -/// bool SDValue::isOperandOf(const SDNode *N) const { for (const SDValue &Op : N->op_values()) if (*this == Op) @@ -7475,7 +7480,7 @@ bool SDValue::reachesChainWithoutSideEffects(SDValue Dest, } // Next, try a deep search: check whether every operand of the TokenFactor // reaches Dest. - return all_of((*this)->ops(), [=](SDValue Op) { + return llvm::all_of((*this)->ops(), [=](SDValue Op) { return Op.reachesChainWithoutSideEffects(Dest, Depth - 1); }); } @@ -7627,7 +7632,6 @@ bool SelectionDAG::areNonVolatileConsecutiveLoads(LoadSDNode *LD, return false; } - /// InferPtrAlignment - Infer alignment of a load / store address. Return 0 if /// it cannot be inferred. unsigned SelectionDAG::InferPtrAlignment(SDValue Ptr) const { @@ -7718,7 +7722,6 @@ unsigned GlobalAddressSDNode::getAddressSpace() const { return getGlobal()->getType()->getAddressSpace(); } - Type *ConstantPoolSDNode::getType() const { if (isMachineConstantPoolEntry()) return Val.MachineCPVal->getType(); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 687b882c5e4d..b5ccd64ee76c 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2022,7 +2022,7 @@ static SDNode *findGlueUse(SDNode *N) { } /// findNonImmUse - Return true if "Use" is a non-immediate use of "Def". -/// This function recursively traverses up the operand chain, ignoring +/// This function iteratively traverses up the operand chain, ignoring /// certain nodes. static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse, SDNode *Root, SmallPtrSetImpl &Visited, @@ -2035,30 +2035,36 @@ static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse, // The Use may be -1 (unassigned) if it is a newly allocated node. This can // happen because we scan down to newly selected nodes in the case of glue // uses. - if ((Use->getNodeId() < Def->getNodeId() && Use->getNodeId() != -1)) - return false; + std::vector WorkList; + WorkList.push_back(Use); - // Don't revisit nodes if we already scanned it and didn't fail, we know we - // won't fail if we scan it again. - if (!Visited.insert(Use).second) - return false; - - for (const SDValue &Op : Use->op_values()) { - // Ignore chain uses, they are validated by HandleMergeInputChains. - if (Op.getValueType() == MVT::Other && IgnoreChains) + while (!WorkList.empty()) { + Use = WorkList.back(); + WorkList.pop_back(); + if (Use->getNodeId() < Def->getNodeId() && Use->getNodeId() != -1) continue; - SDNode *N = Op.getNode(); - if (N == Def) { - if (Use == ImmedUse || Use == Root) - continue; // We are not looking for immediate use. - assert(N != Root); - return true; - } + // Don't revisit nodes if we already scanned it and didn't fail, we know we + // won't fail if we scan it again. + if (!Visited.insert(Use).second) + continue; - // Traverse up the operand chain. - if (findNonImmUse(N, Def, ImmedUse, Root, Visited, IgnoreChains)) - return true; + for (const SDValue &Op : Use->op_values()) { + // Ignore chain uses, they are validated by HandleMergeInputChains. + if (Op.getValueType() == MVT::Other && IgnoreChains) + continue; + + SDNode *N = Op.getNode(); + if (N == Def) { + if (Use == ImmedUse || Use == Root) + continue; // We are not looking for immediate use. + assert(N != Root); + return true; + } + + // Traverse up the operand chain. + WorkList.push_back(N); + } } return false; } diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index 1c66649cae01..eed667dbe7e0 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -818,7 +818,7 @@ SelectionDAGBuilder::LowerStatepoint(ImmutableStatepoint ISP, SI.GCTransitionArgs = ArrayRef(ISP.gc_args_begin(), ISP.gc_args_end()); SI.ID = ISP.getID(); - SI.DeoptState = ArrayRef(ISP.vm_state_begin(), ISP.vm_state_end()); + SI.DeoptState = ArrayRef(ISP.deopt_begin(), ISP.deopt_end()); SI.StatepointFlags = ISP.getFlags(); SI.NumPatchBytes = ISP.getNumPatchBytes(); SI.EHPadBB = EHPadBB; diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 0dffffee9976..adb2b188265b 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1493,8 +1493,7 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, } } - // Ensure that the constant occurs on the RHS, and fold constant - // comparisons. + // Ensure that the constant occurs on the RHS and fold constant comparisons. ISD::CondCode SwappedCC = ISD::getSetCCSwappedOperands(Cond); if (isa(N0.getNode()) && (DCI.isBeforeLegalizeOps() || @@ -1638,14 +1637,13 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, return DAG.getSetCC(dl, VT, TopSetCC.getOperand(0), TopSetCC.getOperand(1), InvCond); - } } } - // If the LHS is '(and load, const)', the RHS is 0, - // the test is for equality or unsigned, and all 1 bits of the const are - // in the same partial word, see if we can shorten the load. + // If the LHS is '(and load, const)', the RHS is 0, the test is for + // equality or unsigned, and all 1 bits of the const are in the same + // partial word, see if we can shorten the load. if (DCI.isBeforeLegalize() && !ISD::isSignedIntSetCC(Cond) && N0.getOpcode() == ISD::AND && C1 == 0 && @@ -1669,10 +1667,10 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, APInt newMask = APInt::getLowBitsSet(maskWidth, width); for (unsigned offset=0; offset X & 1 @@ -1883,7 +1883,10 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, // Canonicalize GE/LE comparisons to use GT/LT comparisons. if (Cond == ISD::SETGE || Cond == ISD::SETUGE) { - if (C1 == MinVal) return DAG.getConstant(1, dl, VT); // X >= MIN --> true + // X >= MIN --> true + if (C1 == MinVal) + return DAG.getConstant(1, dl, VT); + // X >= C0 --> X > (C0 - 1) APInt C = C1 - 1; ISD::CondCode NewCC = (Cond == ISD::SETGE) ? ISD::SETGT : ISD::SETUGT; @@ -1898,7 +1901,10 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, } if (Cond == ISD::SETLE || Cond == ISD::SETULE) { - if (C1 == MaxVal) return DAG.getConstant(1, dl, VT); // X <= MAX --> true + // X <= MAX --> true + if (C1 == MaxVal) + return DAG.getConstant(1, dl, VT); + // X <= C0 --> X < (C0 + 1) APInt C = C1 + 1; ISD::CondCode NewCC = (Cond == ISD::SETLE) ? ISD::SETLT : ISD::SETULT; diff --git a/contrib/llvm/lib/CodeGen/TargetLoweringBase.cpp b/contrib/llvm/lib/CodeGen/TargetLoweringBase.cpp index 900c0318b179..c43a5e18ad23 100644 --- a/contrib/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/contrib/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -1456,6 +1456,7 @@ void TargetLoweringBase::computeRegisterProperties( } if (IsLegalWiderType) break; + LLVM_FALLTHROUGH; } case TypeWidenVector: { // Try to widen the vector. @@ -1473,6 +1474,7 @@ void TargetLoweringBase::computeRegisterProperties( } if (IsLegalWiderType) break; + LLVM_FALLTHROUGH; } case TypeSplitVector: case TypeScalarizeVector: { diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp index 282e3103adc9..711144fc2faa 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp @@ -27,6 +27,14 @@ Error CodeViewRecordIO::beginRecord(Optional MaxLength) { Error CodeViewRecordIO::endRecord() { assert(!Limits.empty() && "Not in a record!"); Limits.pop_back(); + // We would like to assert that we actually read / wrote all the bytes that we + // expected to for this record, but unfortunately we can't do this. Some + // producers such as MASM over-allocate for certain types of records and + // commit the extraneous data, so when reading we can't be sure every byte + // will have been read. And when writing we over-allocate temporarily since + // we don't know how big the record is until we're finished writing it, so + // even though we don't commit the extraneous data, we still can't guarantee + // we're at the end of the allocated data. return Error::success(); } @@ -49,6 +57,12 @@ uint32_t CodeViewRecordIO::maxFieldLength() const { return *Min; } +Error CodeViewRecordIO::padToAlignment(uint32_t Align) { + if (isReading()) + return Reader->padToAlignment(Align); + return Writer->padToAlignment(Align); +} + Error CodeViewRecordIO::skipPadding() { assert(!isWriting() && "Cannot skip padding while writing!"); diff --git a/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp index b8741eb0b675..2e72242181b0 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp @@ -72,7 +72,7 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { uint32_t DebugStringTableSubsection::size() const { return Strings.size(); } uint32_t DebugStringTableSubsection::getStringId(StringRef S) const { - auto P = Strings.find(S); - assert(P != Strings.end()); - return P->second; + auto Iter = Strings.find(S); + assert(Iter != Strings.end()); + return Iter->second; } diff --git a/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index 511f36d0020a..cfd1c5d3ab0c 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -16,14 +16,17 @@ using namespace llvm; using namespace llvm::codeview; DebugSubsectionRecord::DebugSubsectionRecord() - : Kind(DebugSubsectionKind::None) {} + : Container(CodeViewContainer::ObjectFile), + Kind(DebugSubsectionKind::None) {} DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind, - BinaryStreamRef Data) - : Kind(Kind), Data(Data) {} + BinaryStreamRef Data, + CodeViewContainer Container) + : Container(Container), Kind(Kind), Data(Data) {} Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream, - DebugSubsectionRecord &Info) { + DebugSubsectionRecord &Info, + CodeViewContainer Container) { const DebugSubsectionHeader *Header; BinaryStreamReader Reader(Stream); if (auto EC = Reader.readObject(Header)) @@ -41,13 +44,14 @@ Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream, } if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) return EC; + Info.Container = Container; Info.Kind = Kind; return Error::success(); } uint32_t DebugSubsectionRecord::getRecordLength() const { uint32_t Result = sizeof(DebugSubsectionHeader) + Data.getLength(); - assert(Result % 4 == 0); + assert(Result % alignOf(Container) == 0); return Result; } @@ -56,25 +60,29 @@ DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; } BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; } DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( - DebugSubsectionKind Kind, DebugSubsection &Frag) - : Kind(Kind), Frag(Frag) {} + std::unique_ptr Subsection, CodeViewContainer Container) + : Subsection(std::move(Subsection)), Container(Container) {} uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { - uint32_t Size = sizeof(DebugSubsectionHeader) + - alignTo(Frag.calculateSerializedSize(), 4); + uint32_t Size = + sizeof(DebugSubsectionHeader) + + alignTo(Subsection->calculateSerializedSize(), alignOf(Container)); return Size; } Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) { + assert(Writer.getOffset() % alignOf(Container) == 0 && + "Debug Subsection not properly aligned"); + DebugSubsectionHeader Header; - Header.Kind = uint32_t(Kind); + Header.Kind = uint32_t(Subsection->kind()); Header.Length = calculateSerializedLength() - sizeof(DebugSubsectionHeader); if (auto EC = Writer.writeObject(Header)) return EC; - if (auto EC = Frag.commit(Writer)) + if (auto EC = Subsection->commit(Writer)) return EC; - if (auto EC = Writer.padToAlignment(4)) + if (auto EC = Writer.padToAlignment(alignOf(Container))) return EC; return Error::success(); diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index 3d49a7198d1a..66045933ce9b 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -668,7 +668,7 @@ Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { Error CVSymbolDumper::dump(CVRecord &Record) { SymbolVisitorCallbackPipeline Pipeline; - SymbolDeserializer Deserializer(ObjDelegate.get()); + SymbolDeserializer Deserializer(ObjDelegate.get(), Container); CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); @@ -679,7 +679,7 @@ Error CVSymbolDumper::dump(CVRecord &Record) { Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) { SymbolVisitorCallbackPipeline Pipeline; - SymbolDeserializer Deserializer(ObjDelegate.get()); + SymbolDeserializer Deserializer(ObjDelegate.get(), Container); CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index bb1731465495..ea46841a70f6 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -40,6 +40,7 @@ Error SymbolRecordMapping::visitSymbolBegin(CVSymbol &Record) { } Error SymbolRecordMapping::visitSymbolEnd(CVSymbol &Record) { + error(IO.padToAlignment(alignOf(Container))); error(IO.endRecord()); return Error::success(); } diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp index 251cc431f52b..9f2d619d1a1c 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp @@ -12,9 +12,11 @@ using namespace llvm; using namespace llvm::codeview; -SymbolSerializer::SymbolSerializer(BumpPtrAllocator &Allocator) - : Storage(Allocator), RecordBuffer(MaxRecordLength), Stream(RecordBuffer, llvm::support::little), - Writer(Stream), Mapping(Writer) { } +SymbolSerializer::SymbolSerializer(BumpPtrAllocator &Allocator, + CodeViewContainer Container) + : Storage(Allocator), RecordBuffer(MaxRecordLength), + Stream(RecordBuffer, llvm::support::little), Writer(Stream), + Mapping(Writer, Container) {} Error SymbolSerializer::visitSymbolBegin(CVSymbol &Record) { assert(!CurrentSymbol.hasValue() && "Already in a symbol mapping!"); diff --git a/contrib/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp b/contrib/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp index dfdeb8414212..faf2442bc94b 100644 --- a/contrib/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp +++ b/contrib/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp @@ -47,42 +47,46 @@ static Interval intersect(const Interval &I1, const Interval &I2) { MappedBlockStream::MappedBlockStream(uint32_t BlockSize, const MSFStreamLayout &Layout, - BinaryStreamRef MsfData) - : BlockSize(BlockSize), StreamLayout(Layout), MsfData(MsfData) {} + BinaryStreamRef MsfData, + BumpPtrAllocator &Allocator) + : BlockSize(BlockSize), StreamLayout(Layout), MsfData(MsfData), + Allocator(Allocator) {} -std::unique_ptr -MappedBlockStream::createStream(uint32_t BlockSize, - const MSFStreamLayout &Layout, - BinaryStreamRef MsfData) { +std::unique_ptr MappedBlockStream::createStream( + uint32_t BlockSize, const MSFStreamLayout &Layout, BinaryStreamRef MsfData, + BumpPtrAllocator &Allocator) { return llvm::make_unique>( - BlockSize, Layout, MsfData); + BlockSize, Layout, MsfData, Allocator); } std::unique_ptr MappedBlockStream::createIndexedStream( - const MSFLayout &Layout, BinaryStreamRef MsfData, uint32_t StreamIndex) { + const MSFLayout &Layout, BinaryStreamRef MsfData, uint32_t StreamIndex, + BumpPtrAllocator &Allocator) { assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index"); MSFStreamLayout SL; SL.Blocks = Layout.StreamMap[StreamIndex]; SL.Length = Layout.StreamSizes[StreamIndex]; return llvm::make_unique>( - Layout.SB->BlockSize, SL, MsfData); + Layout.SB->BlockSize, SL, MsfData, Allocator); } std::unique_ptr MappedBlockStream::createDirectoryStream(const MSFLayout &Layout, - BinaryStreamRef MsfData) { + BinaryStreamRef MsfData, + BumpPtrAllocator &Allocator) { MSFStreamLayout SL; SL.Blocks = Layout.DirectoryBlocks; SL.Length = Layout.SB->NumDirectoryBytes; - return createStream(Layout.SB->BlockSize, SL, MsfData); + return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator); } std::unique_ptr MappedBlockStream::createFpmStream(const MSFLayout &Layout, - BinaryStreamRef MsfData) { + BinaryStreamRef MsfData, + BumpPtrAllocator &Allocator) { MSFStreamLayout SL; initializeFpmStreamLayout(Layout, SL); - return createStream(Layout.SB->BlockSize, SL, MsfData); + return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator); } Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size, @@ -148,7 +152,7 @@ Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size, // into it, and return an ArrayRef to that. Do not touch existing pool // allocations, as existing clients may be holding a pointer which must // not be invalidated. - uint8_t *WriteBuffer = static_cast(Pool.Allocate(Size, 8)); + uint8_t *WriteBuffer = static_cast(Allocator.Allocate(Size, 8)); if (auto EC = readBytes(Offset, MutableArrayRef(WriteBuffer, Size))) return EC; @@ -269,10 +273,6 @@ Error MappedBlockStream::readBytes(uint32_t Offset, return Error::success(); } -uint32_t MappedBlockStream::getNumBytesCopied() const { - return static_cast(Pool.getBytesAllocated()); -} - void MappedBlockStream::invalidateCache() { CacheMap.shrink_and_clear(); } void MappedBlockStream::fixCacheAfterWrite(uint32_t Offset, @@ -313,43 +313,48 @@ void MappedBlockStream::fixCacheAfterWrite(uint32_t Offset, WritableMappedBlockStream::WritableMappedBlockStream( uint32_t BlockSize, const MSFStreamLayout &Layout, - WritableBinaryStreamRef MsfData) - : ReadInterface(BlockSize, Layout, MsfData), WriteInterface(MsfData) {} + WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator) + : ReadInterface(BlockSize, Layout, MsfData, Allocator), + WriteInterface(MsfData) {} std::unique_ptr WritableMappedBlockStream::createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, - WritableBinaryStreamRef MsfData) { + WritableBinaryStreamRef MsfData, + BumpPtrAllocator &Allocator) { return llvm::make_unique>( - BlockSize, Layout, MsfData); + BlockSize, Layout, MsfData, Allocator); } std::unique_ptr WritableMappedBlockStream::createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, - uint32_t StreamIndex) { + uint32_t StreamIndex, + BumpPtrAllocator &Allocator) { assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index"); MSFStreamLayout SL; SL.Blocks = Layout.StreamMap[StreamIndex]; SL.Length = Layout.StreamSizes[StreamIndex]; - return createStream(Layout.SB->BlockSize, SL, MsfData); + return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator); } std::unique_ptr WritableMappedBlockStream::createDirectoryStream( - const MSFLayout &Layout, WritableBinaryStreamRef MsfData) { + const MSFLayout &Layout, WritableBinaryStreamRef MsfData, + BumpPtrAllocator &Allocator) { MSFStreamLayout SL; SL.Blocks = Layout.DirectoryBlocks; SL.Length = Layout.SB->NumDirectoryBytes; - return createStream(Layout.SB->BlockSize, SL, MsfData); + return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator); } std::unique_ptr WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout, - WritableBinaryStreamRef MsfData) { + WritableBinaryStreamRef MsfData, + BumpPtrAllocator &Allocator) { MSFStreamLayout SL; initializeFpmStreamLayout(Layout, SL); - return createStream(Layout.SB->BlockSize, SL, MsfData); + return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator); } Error WritableMappedBlockStream::readBytes(uint32_t Offset, uint32_t Size, diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index b28ec2ff33ac..22c2ef31bd71 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -66,7 +66,11 @@ void DbiModuleDescriptorBuilder::setObjFileName(StringRef Name) { void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) { Symbols.push_back(Symbol); - SymbolByteSize += Symbol.data().size(); + // Symbols written to a PDB file are required to be 4 byte aligned. The same + // is not true of object files. + assert(Symbol.length() % alignOf(CodeViewContainer::Pdb) == 0 && + "Invalid Symbol alignment!"); + SymbolByteSize += Symbol.length(); } void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) { @@ -140,7 +144,7 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, if (Layout.ModDiStream != kInvalidStreamIndex) { auto NS = WritableMappedBlockStream::createIndexedStream( - MsfLayout, MsfBuffer, Layout.ModDiStream); + MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator()); WritableBinaryStreamRef Ref(*NS); BinaryStreamWriter SymbolWriter(Ref); // Write the symbols. @@ -153,7 +157,8 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, if (auto EC = SymbolWriter.writeStreamRef(RecordsRef)) return EC; // TODO: Write C11 Line data - + assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 && + "Invalid debug section alignment!"); for (const auto &Builder : C13Builders) { assert(Builder && "Empty C13 Fragment Builder!"); if (auto EC = Builder->commit(SymbolWriter)) @@ -169,42 +174,9 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, return Error::success(); } -void DbiModuleDescriptorBuilder::addC13Fragment( - std::unique_ptr Lines) { - DebugLinesSubsection &Frag = *Lines; - - // File Checksums have to come first, so push an empty entry on if this - // is the first. - if (C13Builders.empty()) - C13Builders.push_back(nullptr); - - this->LineInfo.push_back(std::move(Lines)); - C13Builders.push_back( - llvm::make_unique(Frag.kind(), Frag)); -} - -void DbiModuleDescriptorBuilder::addC13Fragment( - std::unique_ptr Inlinees) { - DebugInlineeLinesSubsection &Frag = *Inlinees; - - // File Checksums have to come first, so push an empty entry on if this - // is the first. - if (C13Builders.empty()) - C13Builders.push_back(nullptr); - - this->Inlinees.push_back(std::move(Inlinees)); - C13Builders.push_back( - llvm::make_unique(Frag.kind(), Frag)); -} - -void DbiModuleDescriptorBuilder::setC13FileChecksums( - std::unique_ptr Checksums) { - assert(!ChecksumInfo && "Can't have more than one checksum info!"); - - if (C13Builders.empty()) - C13Builders.push_back(nullptr); - - ChecksumInfo = std::move(Checksums); - C13Builders[0] = llvm::make_unique( - ChecksumInfo->kind(), *ChecksumInfo); +void DbiModuleDescriptorBuilder::addDebugSubsection( + std::unique_ptr Subsection) { + assert(Subsection); + C13Builders.push_back(llvm::make_unique( + std::move(Subsection), CodeViewContainer::Pdb)); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp index 2f4fb6cc295d..320b11dc5cab 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp @@ -252,7 +252,7 @@ Error DbiStream::initializeSectionHeadersData() { return make_error(raw_error_code::no_stream); auto SHS = MappedBlockStream::createIndexedStream( - Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum); + Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator()); size_t StreamLen = SHS->getLength(); if (StreamLen % sizeof(object::coff_section)) @@ -284,7 +284,7 @@ Error DbiStream::initializeFpoRecords() { return make_error(raw_error_code::no_stream); auto FS = MappedBlockStream::createIndexedStream( - Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum); + Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator()); size_t StreamLen = FS->getLength(); if (StreamLen % sizeof(object::FpoData)) diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index 23c7456d7772..55c20fdb9af6 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -357,8 +357,8 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, if (auto EC = finalize()) return EC; - auto DbiS = WritableMappedBlockStream::createIndexedStream(Layout, MsfBuffer, - StreamDBI); + auto DbiS = WritableMappedBlockStream::createIndexedStream( + Layout, MsfBuffer, StreamDBI, Allocator); BinaryStreamWriter Writer(*DbiS); if (auto EC = Writer.writeObject(*Header)) @@ -396,7 +396,7 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, if (Stream.StreamNumber == kInvalidStreamIndex) continue; auto WritableStream = WritableMappedBlockStream::createIndexedStream( - Layout, MsfBuffer, Stream.StreamNumber); + Layout, MsfBuffer, Stream.StreamNumber, Allocator); BinaryStreamWriter DbgStreamWriter(*WritableStream); if (auto EC = DbgStreamWriter.writeArray(Stream.Data)) return EC; diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp index f019d410328a..707128f7efd4 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp @@ -50,8 +50,8 @@ Error InfoStreamBuilder::finalizeMsfLayout() { Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer) const { - auto InfoS = - WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamPDB); + auto InfoS = WritableMappedBlockStream::createIndexedStream( + Layout, Buffer, StreamPDB, Msf.getAllocator()); BinaryStreamWriter Writer(*InfoS); InfoStreamHeader H; diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp index d7a203746a0d..c4ff30011a17 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -55,9 +55,9 @@ Error ModuleDebugStreamRef::reload() { if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size)) return EC; - BinaryStreamReader LineReader(C13LinesSubstream); - if (auto EC = - LineReader.readArray(LinesAndChecksums, LineReader.bytesRemaining())) + BinaryStreamReader SubsectionsReader(C13LinesSubstream); + if (auto EC = SubsectionsReader.readArray(Subsections, + SubsectionsReader.bytesRemaining())) return EC; uint32_t GlobalRefsSize; @@ -77,13 +77,27 @@ ModuleDebugStreamRef::symbols(bool *HadError) const { return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end()); } -llvm::iterator_range -ModuleDebugStreamRef::linesAndChecksums() const { - return make_range(LinesAndChecksums.begin(), LinesAndChecksums.end()); +llvm::iterator_range +ModuleDebugStreamRef::subsections() const { + return make_range(Subsections.begin(), Subsections.end()); } -bool ModuleDebugStreamRef::hasLineInfo() const { +bool ModuleDebugStreamRef::hasDebugSubsections() const { return C13LinesSubstream.getLength() > 0; } Error ModuleDebugStreamRef::commit() { return Error::success(); } + +Expected +ModuleDebugStreamRef::findChecksumsSubsection() const { + for (const auto &SS : subsections()) { + if (SS.kind() != DebugSubsectionKind::FileChecksums) + continue; + + codeview::DebugChecksumsSubsectionRef Result; + if (auto EC = Result.initialize(SS.getRecordData())) + return std::move(EC); + return Result; + } + return make_error(raw_error_code::no_entry); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp index 859295d2c7d3..1254e23c73eb 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -146,7 +146,8 @@ Error PDBFile::parseFileHeaders() { // at getBlockSize() intervals, so we have to be compatible. // See the function fpmPn() for more information: // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489 - auto FpmStream = MappedBlockStream::createFpmStream(ContainerLayout, *Buffer); + auto FpmStream = + MappedBlockStream::createFpmStream(ContainerLayout, *Buffer, Allocator); BinaryStreamReader FpmReader(*FpmStream); ArrayRef FpmBytes; if (auto EC = FpmReader.readBytes(FpmBytes, @@ -184,7 +185,8 @@ Error PDBFile::parseStreamData() { // is exactly what we are attempting to parse. By specifying a custom // subclass of IPDBStreamData which only accesses the fields that have already // been parsed, we can avoid this and reuse MappedBlockStream. - auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer); + auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer, + Allocator); BinaryStreamReader Reader(*DS); if (auto EC = Reader.readInteger(NumStreams)) return EC; @@ -407,5 +409,6 @@ PDBFile::safelyCreateIndexedStream(const MSFLayout &Layout, uint32_t StreamIndex) const { if (StreamIndex >= getNumStreams()) return make_error(raw_error_code::no_stream); - return MappedBlockStream::createIndexedStream(Layout, MsfData, StreamIndex); + return MappedBlockStream::createIndexedStream(Layout, MsfData, StreamIndex, + Allocator); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index c6568029ec55..2c6465e6fb2a 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -140,8 +140,8 @@ Error PDBFileBuilder::commit(StringRef Filename) { if (auto EC = Writer.writeArray(Layout.DirectoryBlocks)) return EC; - auto DirStream = - WritableMappedBlockStream::createDirectoryStream(Layout, Buffer); + auto DirStream = WritableMappedBlockStream::createDirectoryStream( + Layout, Buffer, Allocator); BinaryStreamWriter DW(*DirStream); if (auto EC = DW.writeInteger(Layout.StreamSizes.size())) return EC; @@ -158,8 +158,8 @@ Error PDBFileBuilder::commit(StringRef Filename) { if (!ExpectedSN) return ExpectedSN.takeError(); - auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, - *ExpectedSN); + auto NS = WritableMappedBlockStream::createIndexedStream( + Layout, Buffer, *ExpectedSN, Allocator); BinaryStreamWriter NSWriter(*NS); if (auto EC = Strings.commit(NSWriter)) return EC; diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp index e84573fe07b8..6013c342cf02 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp @@ -56,6 +56,10 @@ Error PDBStringTable::readStrings(BinaryStreamReader &Reader) { return Error::success(); } +codeview::DebugStringTableSubsectionRef PDBStringTable::getStringTable() const { + return Strings; +} + Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) { const support::ulittle32_t *HashCount; if (auto EC = Reader.readObject(HashCount)) diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp index 623afb371b50..67c803d3124e 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -32,8 +32,7 @@ using namespace llvm::support; using namespace llvm::msf; using namespace llvm::pdb; -TpiStream::TpiStream(const PDBFile &File, - std::unique_ptr Stream) +TpiStream::TpiStream(PDBFile &File, std::unique_ptr Stream) : Pdb(File), Stream(std::move(Stream)) {} TpiStream::~TpiStream() = default; @@ -77,7 +76,8 @@ Error TpiStream::reload() { "Invalid TPI hash stream index."); auto HS = MappedBlockStream::createIndexedStream( - Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex); + Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex, + Pdb.getAllocator()); BinaryStreamReader HSR(*HS); // There should be a hash value for every type record, or no hashes at all. diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp index 20456cc97823..9e943c7f114d 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp @@ -147,8 +147,8 @@ Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout, if (auto EC = finalize()) return EC; - auto InfoS = - WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx); + auto InfoS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, + Idx, Allocator); BinaryStreamWriter Writer(*InfoS); if (auto EC = Writer.writeObject(*Header)) @@ -159,8 +159,8 @@ Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout, return EC; if (HashStreamIndex != kInvalidStreamIndex) { - auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, - HashStreamIndex); + auto HVS = WritableMappedBlockStream::createIndexedStream( + Layout, Buffer, HashStreamIndex, Allocator); BinaryStreamWriter HW(*HVS); if (HashValueStream) { if (auto EC = HW.writeStreamRef(*HashValueStream)) diff --git a/contrib/llvm/lib/IR/DIBuilder.cpp b/contrib/llvm/lib/IR/DIBuilder.cpp index 7e6f9a7804b9..7754ac03b43d 100644 --- a/contrib/llvm/lib/IR/DIBuilder.cpp +++ b/contrib/llvm/lib/IR/DIBuilder.cpp @@ -39,6 +39,21 @@ void DIBuilder::trackIfUnresolved(MDNode *N) { UnresolvedNodes.emplace_back(N); } +void DIBuilder::finalizeSubprogram(DISubprogram *SP) { + MDTuple *Temp = SP->getVariables().get(); + if (!Temp || !Temp->isTemporary()) + return; + + SmallVector Variables; + + auto PV = PreservedVariables.find(SP); + if (PV != PreservedVariables.end()) + Variables.append(PV->second.begin(), PV->second.end()); + + DINodeArray AV = getOrCreateArray(Variables); + TempMDTuple(Temp)->replaceAllUsesWith(AV.get()); +} + void DIBuilder::finalize() { if (!CUNode) { assert(!AllowUnresolvedNodes && @@ -62,25 +77,11 @@ void DIBuilder::finalize() { CUNode->replaceRetainedTypes(MDTuple::get(VMContext, RetainValues)); DISubprogramArray SPs = MDTuple::get(VMContext, AllSubprograms); - auto resolveVariables = [&](DISubprogram *SP) { - MDTuple *Temp = SP->getVariables().get(); - if (!Temp) - return; - - SmallVector Variables; - - auto PV = PreservedVariables.find(SP); - if (PV != PreservedVariables.end()) - Variables.append(PV->second.begin(), PV->second.end()); - - DINodeArray AV = getOrCreateArray(Variables); - TempMDTuple(Temp)->replaceAllUsesWith(AV.get()); - }; for (auto *SP : SPs) - resolveVariables(SP); + finalizeSubprogram(SP); for (auto *N : RetainValues) if (auto *SP = dyn_cast(N)) - resolveVariables(SP); + finalizeSubprogram(SP); if (!AllGVs.empty()) CUNode->replaceGlobalVariables(MDTuple::get(VMContext, AllGVs)); diff --git a/contrib/llvm/lib/IR/DebugLoc.cpp b/contrib/llvm/lib/IR/DebugLoc.cpp index b7e3f0c6779e..0485fece7c42 100644 --- a/contrib/llvm/lib/IR/DebugLoc.cpp +++ b/contrib/llvm/lib/IR/DebugLoc.cpp @@ -99,87 +99,6 @@ DebugLoc DebugLoc::appendInlinedAt(DebugLoc DL, DILocation *InlinedAt, return Last; } -/// Reparent \c Scope from \c OrigSP to \c NewSP. -static DIScope *reparentScope(LLVMContext &Ctx, DIScope *Scope, - DISubprogram *OrigSP, DISubprogram *NewSP, - DenseMap &Cache) { - SmallVector ScopeChain; - DIScope *Last = NewSP; - DIScope *CurScope = Scope; - do { - if (auto *SP = dyn_cast(CurScope)) { - // Don't rewrite this scope chain if it doesn't lead to the replaced SP. - if (SP != OrigSP) - return Scope; - Cache.insert({OrigSP, NewSP}); - break; - } - if (auto *Found = Cache[CurScope]) { - Last = cast(Found); - break; - } - ScopeChain.push_back(CurScope); - } while ((CurScope = CurScope->getScope().resolve())); - - // Starting from the top, rebuild the nodes to point to the new inlined-at - // location (then rebuilding the rest of the chain behind it) and update the - // map of already-constructed inlined-at nodes. - for (const DIScope *MD : reverse(ScopeChain)) { - if (auto *LB = dyn_cast(MD)) - Cache[MD] = Last = DILexicalBlock::getDistinct( - Ctx, Last, LB->getFile(), LB->getLine(), LB->getColumn()); - else if (auto *LB = dyn_cast(MD)) - Cache[MD] = Last = DILexicalBlockFile::getDistinct( - Ctx, Last, LB->getFile(), LB->getDiscriminator()); - else - llvm_unreachable("illegal parent scope"); - } - return Last; -} - -void DebugLoc::reparentDebugInfo(Instruction &I, DISubprogram *OrigSP, - DISubprogram *NewSP, - DenseMap &Cache) { - auto DL = I.getDebugLoc(); - if (!OrigSP || !NewSP || OrigSP == NewSP || !DL) - return; - - // Reparent the debug location. - auto &Ctx = I.getContext(); - DILocation *InlinedAt = DL->getInlinedAt(); - if (InlinedAt) { - while (auto *IA = InlinedAt->getInlinedAt()) - InlinedAt = IA; - auto NewScope = - reparentScope(Ctx, InlinedAt->getScope(), OrigSP, NewSP, Cache); - InlinedAt = - DebugLoc::get(InlinedAt->getLine(), InlinedAt->getColumn(), NewScope); - } - I.setDebugLoc( - DebugLoc::get(DL.getLine(), DL.getCol(), - reparentScope(Ctx, DL->getScope(), OrigSP, NewSP, Cache), - DebugLoc::appendInlinedAt(DL, InlinedAt, Ctx, Cache, - ReplaceLastInlinedAt))); - - // Fix up debug variables to point to NewSP. - auto reparentVar = [&](DILocalVariable *Var) { - return DILocalVariable::get( - Ctx, - cast( - reparentScope(Ctx, Var->getScope(), OrigSP, NewSP, Cache)), - Var->getName(), Var->getFile(), Var->getLine(), Var->getType(), - Var->getArg(), Var->getFlags(), Var->getAlignInBits()); - }; - if (auto *DbgValue = dyn_cast(&I)) { - auto *Var = DbgValue->getVariable(); - I.setOperand(2, MetadataAsValue::get(Ctx, reparentVar(Var))); - } else if (auto *DbgDeclare = dyn_cast(&I)) { - auto *Var = DbgDeclare->getVariable(); - I.setOperand(1, MetadataAsValue::get(Ctx, reparentVar(Var))); - } -} - - #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void DebugLoc::dump() const { if (!Loc) diff --git a/contrib/llvm/lib/IR/OptBisect.cpp b/contrib/llvm/lib/IR/OptBisect.cpp index b670c817569a..a03a6fb62237 100644 --- a/contrib/llvm/lib/IR/OptBisect.cpp +++ b/contrib/llvm/lib/IR/OptBisect.cpp @@ -16,6 +16,7 @@ #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/RegionInfo.h" #include "llvm/IR/Module.h" #include "llvm/IR/OptBisect.h" #include "llvm/Pass.h" @@ -53,13 +54,20 @@ static std::string getDescription(const BasicBlock &BB) { } static std::string getDescription(const Loop &L) { - // FIXME: I'd like to be able to provide a better description here, but - // calling L->getHeader() would introduce a new dependency on the - // LLVMCore library. + // FIXME: Move into LoopInfo so we can get a better description + // (and avoid a circular dependency between IR and Analysis). return "loop"; } +static std::string getDescription(const Region &R) { + // FIXME: Move into RegionInfo so we can get a better description + // (and avoid a circular dependency between IR and Analysis). + return "region"; +} + static std::string getDescription(const CallGraphSCC &SCC) { + // FIXME: Move into CallGraphSCCPass to avoid circular dependency between + // IR and Analysis. std::string Desc = "SCC ("; bool First = true; for (CallGraphNode *CGN : SCC) { @@ -83,6 +91,7 @@ template bool OptBisect::shouldRunPass(const Pass *, const Function &); template bool OptBisect::shouldRunPass(const Pass *, const BasicBlock &); template bool OptBisect::shouldRunPass(const Pass *, const Loop &); template bool OptBisect::shouldRunPass(const Pass *, const CallGraphSCC &); +template bool OptBisect::shouldRunPass(const Pass *, const Region &); template bool OptBisect::shouldRunPass(const Pass *P, const UnitT &U) { diff --git a/contrib/llvm/lib/LTO/LTO.cpp b/contrib/llvm/lib/LTO/LTO.cpp index 9efc095f9fcf..92145aaf667a 100644 --- a/contrib/llvm/lib/LTO/LTO.cpp +++ b/contrib/llvm/lib/LTO/LTO.cpp @@ -122,6 +122,7 @@ static void computeCacheKey( AddUnsigned(Conf.CGOptLevel); AddUnsigned(Conf.CGFileType); AddUnsigned(Conf.OptLevel); + AddUnsigned(Conf.UseNewPM); AddString(Conf.OptPipeline); AddString(Conf.AAPipeline); AddString(Conf.OverrideTriple); @@ -621,6 +622,19 @@ unsigned LTO::getMaxTasks() const { } Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) { + // Compute "dead" symbols, we don't want to import/export these! + DenseSet GUIDPreservedSymbols; + for (auto &Res : GlobalResolutions) { + if (Res.second.VisibleOutsideThinLTO && + // IRName will be defined if we have seen the prevailing copy of + // this value. If not, no need to preserve any ThinLTO copies. + !Res.second.IRName.empty()) + GUIDPreservedSymbols.insert(GlobalValue::getGUID( + GlobalValue::dropLLVMManglingEscape(Res.second.IRName))); + } + + computeDeadSymbols(ThinLTO.CombinedIndex, GUIDPreservedSymbols); + // Save the status of having a regularLTO combined module, as // this is needed for generating the ThinLTO Task ID, and // the CombinedModule will be moved at the end of runRegularLTO. @@ -930,6 +944,17 @@ ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix, }; } +static bool IsLiveByGUID(const ModuleSummaryIndex &Index, + GlobalValue::GUID GUID) { + auto VI = Index.getValueInfo(GUID); + if (!VI) + return false; + for (auto &I : VI.getSummaryList()) + if (Index.isGlobalValueLive(I.get())) + return true; + return false; +} + Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache, bool HasRegularLTO) { if (ThinLTO.ModuleMap.empty()) @@ -962,22 +987,8 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache, StringMap> ResolvedODR; if (Conf.OptLevel > 0) { - // Compute "dead" symbols, we don't want to import/export these! - DenseSet GUIDPreservedSymbols; - for (auto &Res : GlobalResolutions) { - if (Res.second.VisibleOutsideThinLTO && - // IRName will be defined if we have seen the prevailing copy of - // this value. If not, no need to preserve any ThinLTO copies. - !Res.second.IRName.empty()) - GUIDPreservedSymbols.insert(GlobalValue::getGUID( - GlobalValue::dropLLVMManglingEscape(Res.second.IRName))); - } - - auto DeadSymbols = - computeDeadSymbols(ThinLTO.CombinedIndex, GUIDPreservedSymbols); - ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries, - ImportLists, ExportLists, &DeadSymbols); + ImportLists, ExportLists); std::set ExportedGUIDs; for (auto &Res : GlobalResolutions) { @@ -992,7 +1003,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache, auto GUID = GlobalValue::getGUID( GlobalValue::dropLLVMManglingEscape(Res.second.IRName)); // Mark exported unless index-based analysis determined it to be dead. - if (!DeadSymbols.count(GUID)) + if (IsLiveByGUID(ThinLTO.CombinedIndex, GUID)) ExportedGUIDs.insert(GUID); } diff --git a/contrib/llvm/lib/LTO/LTOBackend.cpp b/contrib/llvm/lib/LTO/LTOBackend.cpp index f9c41f5c9744..3f72e446cdf2 100644 --- a/contrib/llvm/lib/LTO/LTOBackend.cpp +++ b/contrib/llvm/lib/LTO/LTOBackend.cpp @@ -42,11 +42,6 @@ using namespace llvm; using namespace lto; -static cl::opt - LTOUseNewPM("lto-use-new-pm", - cl::desc("Run LTO passes using the new pass manager"), - cl::init(false), cl::Hidden); - LLVM_ATTRIBUTE_NORETURN static void reportOpenError(StringRef Path, Twine Msg) { errs() << "failed to open " << Path << ": " << Msg << '\n'; errs().flush(); @@ -266,7 +261,7 @@ bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod, if (!Conf.OptPipeline.empty()) runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline, Conf.DisableVerify); - else if (LTOUseNewPM) + else if (Conf.UseNewPM) runNewPMPasses(Mod, TM, Conf.OptLevel, IsThinLTO); else runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary); diff --git a/contrib/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/contrib/llvm/lib/LTO/ThinLTOCodeGenerator.cpp index ca3fc60f9501..6b221a347c17 100644 --- a/contrib/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/contrib/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -628,13 +628,13 @@ void ThinLTOCodeGenerator::promote(Module &TheModule, PreservedSymbols, Triple(TheModule.getTargetTriple())); // Compute "dead" symbols, we don't want to import/export these! - auto DeadSymbols = computeDeadSymbols(Index, GUIDPreservedSymbols); + computeDeadSymbols(Index, GUIDPreservedSymbols); // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists, &DeadSymbols); + ExportLists); // Resolve LinkOnce/Weak symbols. StringMap> ResolvedODR; @@ -673,13 +673,13 @@ void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule, PreservedSymbols, Triple(TheModule.getTargetTriple())); // Compute "dead" symbols, we don't want to import/export these! - auto DeadSymbols = computeDeadSymbols(Index, GUIDPreservedSymbols); + computeDeadSymbols(Index, GUIDPreservedSymbols); // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists, &DeadSymbols); + ExportLists); auto &ImportList = ImportLists[TheModule.getModuleIdentifier()]; crossImportIntoModule(TheModule, Index, ModuleMap, ImportList); @@ -750,13 +750,13 @@ void ThinLTOCodeGenerator::internalize(Module &TheModule, Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); // Compute "dead" symbols, we don't want to import/export these! - auto DeadSymbols = computeDeadSymbols(Index, GUIDPreservedSymbols); + computeDeadSymbols(Index, GUIDPreservedSymbols); // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists, &DeadSymbols); + ExportLists); auto &ExportList = ExportLists[ModuleIdentifier]; // Be friendly and don't nuke totally the module when the client didn't @@ -902,14 +902,14 @@ void ThinLTOCodeGenerator::run() { computeGUIDPreservedSymbols(PreservedSymbols, TMBuilder.TheTriple); // Compute "dead" symbols, we don't want to import/export these! - auto DeadSymbols = computeDeadSymbols(*Index, GUIDPreservedSymbols); + computeDeadSymbols(*Index, GUIDPreservedSymbols); // Collect the import/export lists for all modules from the call-graph in the // combined index. StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists, &DeadSymbols); + ExportLists); // We use a std::map here to be able to have a defined ordering when // producing a hash for the cache entry. diff --git a/contrib/llvm/lib/MC/WasmObjectWriter.cpp b/contrib/llvm/lib/MC/WasmObjectWriter.cpp index 8c3df36cfb48..9b2031f05043 100644 --- a/contrib/llvm/lib/MC/WasmObjectWriter.cpp +++ b/contrib/llvm/lib/MC/WasmObjectWriter.cpp @@ -40,6 +40,7 @@ using namespace llvm; #define DEBUG_TYPE "reloc-info" namespace { + // For patching purposes, we need to remember where each section starts, both // for patching up the section size field, and for patching up references to // locations within the section. @@ -50,6 +51,82 @@ struct SectionBookkeeping { uint64_t ContentsOffset; }; +// The signature of a wasm function, in a struct capable of being used as a +// DenseMap key. +struct WasmFunctionType { + // Support empty and tombstone instances, needed by DenseMap. + enum { Plain, Empty, Tombstone } State; + + // The return types of the function. + SmallVector Returns; + + // The parameter types of the function. + SmallVector Params; + + WasmFunctionType() : State(Plain) {} + + bool operator==(const WasmFunctionType &Other) const { + return State == Other.State && Returns == Other.Returns && + Params == Other.Params; + } +}; + +// Traits for using WasmFunctionType in a DenseMap. +struct WasmFunctionTypeDenseMapInfo { + static WasmFunctionType getEmptyKey() { + WasmFunctionType FuncTy; + FuncTy.State = WasmFunctionType::Empty; + return FuncTy; + } + static WasmFunctionType getTombstoneKey() { + WasmFunctionType FuncTy; + FuncTy.State = WasmFunctionType::Tombstone; + return FuncTy; + } + static unsigned getHashValue(const WasmFunctionType &FuncTy) { + uintptr_t Value = FuncTy.State; + for (wasm::ValType Ret : FuncTy.Returns) + Value += DenseMapInfo::getHashValue(int32_t(Ret)); + for (wasm::ValType Param : FuncTy.Params) + Value += DenseMapInfo::getHashValue(int32_t(Param)); + return Value; + } + static bool isEqual(const WasmFunctionType &LHS, + const WasmFunctionType &RHS) { + return LHS == RHS; + } +}; + +// A wasm import to be written into the import section. +struct WasmImport { + StringRef ModuleName; + StringRef FieldName; + unsigned Kind; + int32_t Type; +}; + +// A wasm function to be written into the function section. +struct WasmFunction { + int32_t Type; + const MCSymbolWasm *Sym; +}; + +// A wasm export to be written into the export section. +struct WasmExport { + StringRef FieldName; + unsigned Kind; + uint32_t Index; +}; + +// A wasm global to be written into the global section. +struct WasmGlobal { + wasm::ValType Type; + bool IsMutable; + bool HasImport; + uint64_t InitialValue; + uint32_t ImportIndex; +}; + class WasmObjectWriter : public MCObjectWriter { /// Helper struct for containing some precomputed information on symbols. struct WasmSymbolData { @@ -91,18 +168,10 @@ public: : MCObjectWriter(OS, /*IsLittleEndian=*/true), TargetObjectWriter(MOTW) {} private: - void reset() override { - MCObjectWriter::reset(); - } - ~WasmObjectWriter() override; void writeHeader(const MCAssembler &Asm); - void writeValueType(wasm::ValType Ty) { - encodeSLEB128(int32_t(Ty), getStream()); - } - void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, @@ -112,7 +181,37 @@ private: const MCAsmLayout &Layout) override; void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; + + void writeValueType(wasm::ValType Ty) { + encodeSLEB128(int32_t(Ty), getStream()); + } + + void writeTypeSection(const SmallVector &FunctionTypes); + void writeImportSection(const SmallVector &Imports); + void writeFunctionSection(const SmallVector &Functions); + void writeTableSection(const SmallVector &TableElems); + void writeMemorySection(const SmallVector &DataBytes); + void writeGlobalSection(const SmallVector &Globals); + void writeExportSection(const SmallVector &Exports); + void writeElemSection(const SmallVector &TableElems); + void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout, + DenseMap &SymbolIndices, + const SmallVector &Functions); + uint64_t + writeDataSection(const SmallVector &DataBytes, + DenseMap &SymbolIndices); + void writeNameSection(const SmallVector &Functions, + const SmallVector &Imports, + uint32_t NumFuncImports); + void writeCodeRelocSection( + DenseMap &SymbolIndices); + void writeDataRelocSection( + DenseMap &SymbolIndices, + uint64_t DataSectionHeaderSize); + void writeLinkingMetaDataSection(bool HasStackPointer, + uint32_t StackPointerGlobal); }; + } // end anonymous namespace WasmObjectWriter::~WasmObjectWriter() {} @@ -278,86 +377,6 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, DataRelocations.push_back(Rec); } -namespace { - -// The signature of a wasm function, in a struct capable of being used as a -// DenseMap key. -struct WasmFunctionType { - // Support empty and tombstone instances, needed by DenseMap. - enum { Plain, Empty, Tombstone } State; - - // The return types of the function. - SmallVector Returns; - - // The parameter types of the function. - SmallVector Params; - - WasmFunctionType() : State(Plain) {} - - bool operator==(const WasmFunctionType &Other) const { - return State == Other.State && Returns == Other.Returns && - Params == Other.Params; - } -}; - -// Traits for using WasmFunctionType in a DenseMap. -struct WasmFunctionTypeDenseMapInfo { - static WasmFunctionType getEmptyKey() { - WasmFunctionType FuncTy; - FuncTy.State = WasmFunctionType::Empty; - return FuncTy; - } - static WasmFunctionType getTombstoneKey() { - WasmFunctionType FuncTy; - FuncTy.State = WasmFunctionType::Tombstone; - return FuncTy; - } - static unsigned getHashValue(const WasmFunctionType &FuncTy) { - uintptr_t Value = FuncTy.State; - for (wasm::ValType Ret : FuncTy.Returns) - Value += DenseMapInfo::getHashValue(int32_t(Ret)); - for (wasm::ValType Param : FuncTy.Params) - Value += DenseMapInfo::getHashValue(int32_t(Param)); - return Value; - } - static bool isEqual(const WasmFunctionType &LHS, - const WasmFunctionType &RHS) { - return LHS == RHS; - } -}; - -// A wasm import to be written into the import section. -struct WasmImport { - StringRef ModuleName; - StringRef FieldName; - unsigned Kind; - int32_t Type; -}; - -// A wasm function to be written into the function section. -struct WasmFunction { - int32_t Type; - const MCSymbolWasm *Sym; -}; - -// A wasm export to be written into the export section. -struct WasmExport { - StringRef FieldName; - unsigned Kind; - uint32_t Index; -}; - -// A wasm global to be written into the global section. -struct WasmGlobal { - wasm::ValType Type; - bool IsMutable; - bool HasImport; - uint64_t InitialValue; - uint32_t ImportIndex; -}; - -} // end anonymous namespace - // Write X as an (unsigned) LEB value at offset Offset in Stream, padded // to allow patching. static void @@ -529,6 +548,367 @@ static void WriteTypeRelocations( } } +void WasmObjectWriter::writeTypeSection( + const SmallVector &FunctionTypes) { + if (FunctionTypes.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_TYPE); + + encodeULEB128(FunctionTypes.size(), getStream()); + + for (const WasmFunctionType &FuncTy : FunctionTypes) { + encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream()); + encodeULEB128(FuncTy.Params.size(), getStream()); + for (wasm::ValType Ty : FuncTy.Params) + writeValueType(Ty); + encodeULEB128(FuncTy.Returns.size(), getStream()); + for (wasm::ValType Ty : FuncTy.Returns) + writeValueType(Ty); + } + + endSection(Section); +} + +void WasmObjectWriter::writeImportSection( + const SmallVector &Imports) { + if (Imports.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_IMPORT); + + encodeULEB128(Imports.size(), getStream()); + for (const WasmImport &Import : Imports) { + StringRef ModuleName = Import.ModuleName; + encodeULEB128(ModuleName.size(), getStream()); + writeBytes(ModuleName); + + StringRef FieldName = Import.FieldName; + encodeULEB128(FieldName.size(), getStream()); + writeBytes(FieldName); + + encodeULEB128(Import.Kind, getStream()); + + switch (Import.Kind) { + case wasm::WASM_EXTERNAL_FUNCTION: + encodeULEB128(Import.Type, getStream()); + break; + case wasm::WASM_EXTERNAL_GLOBAL: + encodeSLEB128(int32_t(Import.Type), getStream()); + encodeULEB128(0, getStream()); // mutability + break; + default: + llvm_unreachable("unsupported import kind"); + } + } + + endSection(Section); +} + +void WasmObjectWriter::writeFunctionSection( + const SmallVector &Functions) { + if (Functions.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_FUNCTION); + + encodeULEB128(Functions.size(), getStream()); + for (const WasmFunction &Func : Functions) + encodeULEB128(Func.Type, getStream()); + + endSection(Section); +} + +void WasmObjectWriter::writeTableSection( + const SmallVector &TableElems) { + // For now, always emit the table section, since indirect calls are not + // valid without it. In the future, we could perhaps be more clever and omit + // it if there are no indirect calls. + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_TABLE); + + // The number of tables, fixed to 1 for now. + encodeULEB128(1, getStream()); + + encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); + + encodeULEB128(0, getStream()); // flags + encodeULEB128(TableElems.size(), getStream()); // initial + + endSection(Section); +} + +void WasmObjectWriter::writeMemorySection( + const SmallVector &DataBytes) { + // For now, always emit the memory section, since loads and stores are not + // valid without it. In the future, we could perhaps be more clever and omit + // it if there are no loads or stores. + SectionBookkeeping Section; + uint32_t NumPages = + (DataBytes.size() + wasm::WasmPageSize - 1) / wasm::WasmPageSize; + + startSection(Section, wasm::WASM_SEC_MEMORY); + encodeULEB128(1, getStream()); // number of memory spaces + + encodeULEB128(0, getStream()); // flags + encodeULEB128(NumPages, getStream()); // initial + + endSection(Section); +} + +void WasmObjectWriter::writeGlobalSection( + const SmallVector &Globals) { + if (Globals.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_GLOBAL); + + encodeULEB128(Globals.size(), getStream()); + for (const WasmGlobal &Global : Globals) { + writeValueType(Global.Type); + write8(Global.IsMutable); + + if (Global.HasImport) { + assert(Global.InitialValue == 0); + write8(wasm::WASM_OPCODE_GET_GLOBAL); + encodeULEB128(Global.ImportIndex, getStream()); + } else { + assert(Global.ImportIndex == 0); + write8(wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(Global.InitialValue, getStream()); // offset + } + write8(wasm::WASM_OPCODE_END); + } + + endSection(Section); +} + +void WasmObjectWriter::writeExportSection( + const SmallVector &Exports) { + if (Exports.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_EXPORT); + + encodeULEB128(Exports.size(), getStream()); + for (const WasmExport &Export : Exports) { + encodeULEB128(Export.FieldName.size(), getStream()); + writeBytes(Export.FieldName); + + encodeSLEB128(Export.Kind, getStream()); + + encodeULEB128(Export.Index, getStream()); + } + + endSection(Section); +} + +void WasmObjectWriter::writeElemSection( + const SmallVector &TableElems) { + if (TableElems.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_ELEM); + + encodeULEB128(1, getStream()); // number of "segments" + encodeULEB128(0, getStream()); // the table index + + // init expr for starting offset + write8(wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(0, getStream()); + write8(wasm::WASM_OPCODE_END); + + encodeULEB128(TableElems.size(), getStream()); + for (uint32_t Elem : TableElems) + encodeULEB128(Elem, getStream()); + + endSection(Section); +} + +void WasmObjectWriter::writeCodeSection( + const MCAssembler &Asm, const MCAsmLayout &Layout, + DenseMap &SymbolIndices, + const SmallVector &Functions) { + if (Functions.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CODE); + + encodeULEB128(Functions.size(), getStream()); + + for (const WasmFunction &Func : Functions) { + MCSectionWasm &FuncSection = + static_cast(Func.Sym->getSection()); + + if (Func.Sym->isVariable()) + report_fatal_error("weak symbols not supported yet"); + + if (Func.Sym->getOffset() != 0) + report_fatal_error("function sections must contain one function each"); + + if (!Func.Sym->getSize()) + report_fatal_error("function symbols must have a size set with .size"); + + int64_t Size = 0; + if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout)) + report_fatal_error(".size expression must be evaluatable"); + + encodeULEB128(Size, getStream()); + + FuncSection.setSectionOffset(getStream().tell() - + Section.ContentsOffset); + + Asm.writeSectionData(&FuncSection, Layout); + } + + // Apply the type index fixups for call_indirect etc. instructions. + for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) { + uint32_t Type = TypeIndexFixupTypes[i]; + unsigned Padding = PaddingFor5ByteULEB128(Type); + + const WasmRelocationEntry &Fixup = TypeIndexFixups[i]; + assert(Fixup.Addend == 0); + assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); + uint64_t Offset = Fixup.Offset + + Fixup.FixupSection->getSectionOffset(); + + uint8_t Buffer[16]; + unsigned SizeLen = encodeULEB128(Type, Buffer, Padding); + assert(SizeLen == 5); + getStream().pwrite((char *)Buffer, SizeLen, + Section.ContentsOffset + Offset); + } + + // Apply fixups. + ApplyRelocations(CodeRelocations, getStream(), SymbolIndices, + Section.ContentsOffset); + + endSection(Section); +} + +uint64_t WasmObjectWriter::writeDataSection( + const SmallVector &DataBytes, + DenseMap &SymbolIndices) { + if (DataBytes.empty()) + return 0; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_DATA); + + encodeULEB128(1, getStream()); // count + encodeULEB128(0, getStream()); // memory index + write8(wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(0, getStream()); // offset + write8(wasm::WASM_OPCODE_END); + encodeULEB128(DataBytes.size(), getStream()); // size + uint32_t HeaderSize = getStream().tell() - Section.ContentsOffset; + writeBytes(DataBytes); // data + + // Apply fixups. + ApplyRelocations(DataRelocations, getStream(), SymbolIndices, + Section.ContentsOffset + HeaderSize); + + endSection(Section); + return HeaderSize; +} + +void WasmObjectWriter::writeNameSection( + const SmallVector &Functions, + const SmallVector &Imports, + unsigned NumFuncImports) { + uint32_t TotalFunctions = NumFuncImports + Functions.size(); + if (TotalFunctions == 0) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, "name"); + SectionBookkeeping SubSection; + startSection(SubSection, wasm::WASM_NAMES_FUNCTION); + + encodeULEB128(TotalFunctions, getStream()); + uint32_t Index = 0; + for (const WasmImport &Import : Imports) { + if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) { + encodeULEB128(Index, getStream()); + encodeULEB128(Import.FieldName.size(), getStream()); + writeBytes(Import.FieldName); + ++Index; + } + } + for (const WasmFunction &Func : Functions) { + encodeULEB128(Index, getStream()); + encodeULEB128(Func.Sym->getName().size(), getStream()); + writeBytes(Func.Sym->getName()); + ++Index; + } + + endSection(SubSection); + endSection(Section); +} + +void WasmObjectWriter::writeCodeRelocSection( + DenseMap &SymbolIndices) { + // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md + // for descriptions of the reloc sections. + + if (CodeRelocations.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE"); + + encodeULEB128(wasm::WASM_SEC_CODE, getStream()); + encodeULEB128(CodeRelocations.size() + TypeIndexFixups.size(), getStream()); + + WriteRelocations(CodeRelocations, getStream(), SymbolIndices, 0); + WriteTypeRelocations(TypeIndexFixups, TypeIndexFixupTypes, getStream()); + + endSection(Section); +} + +void WasmObjectWriter::writeDataRelocSection( + DenseMap &SymbolIndices, + uint64_t DataSectionHeaderSize) { + // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md + // for descriptions of the reloc sections. + + if (DataRelocations.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA"); + + encodeULEB128(wasm::WASM_SEC_DATA, getStream()); + encodeULEB128(DataRelocations.size(), getStream()); + + WriteRelocations(DataRelocations, getStream(), SymbolIndices, + DataSectionHeaderSize); + + endSection(Section); +} + +void WasmObjectWriter::writeLinkingMetaDataSection( + bool HasStackPointer, uint32_t StackPointerGlobal) { + if (!HasStackPointer) + return; + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); + + encodeULEB128(1, getStream()); // count + + encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type + encodeULEB128(StackPointerGlobal, getStream()); // id + + endSection(Section); +} + void WasmObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { MCContext &Ctx = Asm.getContext(); @@ -730,16 +1110,21 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, if (IsAddressTaken.count(&WS)) TableElems.push_back(Index); } else { - if (WS.getOffset() != 0) - report_fatal_error("data sections must contain one variable each"); - if (!WS.getSize()) - report_fatal_error("data symbols must have a size set with .size"); - - int64_t Size = 0; - if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) - report_fatal_error(".size expression must be evaluatable"); + if (WS.isTemporary() && !WS.getSize()) + continue; if (WS.isDefined(false)) { + if (WS.getOffset() != 0) + report_fatal_error("data sections must contain one variable each: " + + WS.getName()); + if (!WS.getSize()) + report_fatal_error("data symbols must have a size set with .size: " + + WS.getName()); + + int64_t Size = 0; + if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) + report_fatal_error(".size expression must be evaluatable"); + MCSectionWasm &DataSection = static_cast(WS.getSection()); @@ -827,322 +1212,23 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, // Write out the Wasm header. writeHeader(Asm); - SectionBookkeeping Section; - - // === Type Section ========================================================= - if (!FunctionTypes.empty()) { - startSection(Section, wasm::WASM_SEC_TYPE); - - encodeULEB128(FunctionTypes.size(), getStream()); - - for (WasmFunctionType &FuncTy : FunctionTypes) { - encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream()); - encodeULEB128(FuncTy.Params.size(), getStream()); - for (wasm::ValType Ty : FuncTy.Params) - writeValueType(Ty); - encodeULEB128(FuncTy.Returns.size(), getStream()); - for (wasm::ValType Ty : FuncTy.Returns) - writeValueType(Ty); - } - - endSection(Section); - } - - // === Import Section ======================================================== - if (!Imports.empty()) { - startSection(Section, wasm::WASM_SEC_IMPORT); - - encodeULEB128(Imports.size(), getStream()); - for (const WasmImport &Import : Imports) { - StringRef ModuleName = Import.ModuleName; - encodeULEB128(ModuleName.size(), getStream()); - writeBytes(ModuleName); - - StringRef FieldName = Import.FieldName; - encodeULEB128(FieldName.size(), getStream()); - writeBytes(FieldName); - - encodeULEB128(Import.Kind, getStream()); - - switch (Import.Kind) { - case wasm::WASM_EXTERNAL_FUNCTION: - encodeULEB128(Import.Type, getStream()); - break; - case wasm::WASM_EXTERNAL_GLOBAL: - encodeSLEB128(int32_t(Import.Type), getStream()); - encodeULEB128(0, getStream()); // mutability - break; - default: - llvm_unreachable("unsupported import kind"); - } - } - - endSection(Section); - } - - // === Function Section ====================================================== - if (!Functions.empty()) { - startSection(Section, wasm::WASM_SEC_FUNCTION); - - encodeULEB128(Functions.size(), getStream()); - for (const WasmFunction &Func : Functions) - encodeULEB128(Func.Type, getStream()); - - endSection(Section); - } - - // === Table Section ========================================================= - // For now, always emit the table section, since indirect calls are not - // valid without it. In the future, we could perhaps be more clever and omit - // it if there are no indirect calls. - startSection(Section, wasm::WASM_SEC_TABLE); - - // The number of tables, fixed to 1 for now. - encodeULEB128(1, getStream()); - - encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); - - encodeULEB128(0, getStream()); // flags - encodeULEB128(TableElems.size(), getStream()); // initial - - endSection(Section); - - // === Memory Section ======================================================== - // For now, always emit the memory section, since loads and stores are not - // valid without it. In the future, we could perhaps be more clever and omit - // it if there are no loads or stores. - uint32_t NumPages = - (DataBytes.size() + wasm::WasmPageSize - 1) / wasm::WasmPageSize; - - startSection(Section, wasm::WASM_SEC_MEMORY); - encodeULEB128(1, getStream()); // number of memory spaces - - encodeULEB128(0, getStream()); // flags - encodeULEB128(NumPages, getStream()); // initial - - endSection(Section); - - // === Global Section ======================================================== - if (!Globals.empty()) { - startSection(Section, wasm::WASM_SEC_GLOBAL); - - encodeULEB128(Globals.size(), getStream()); - for (const WasmGlobal &Global : Globals) { - writeValueType(Global.Type); - write8(Global.IsMutable); - - if (Global.HasImport) { - assert(Global.InitialValue == 0); - write8(wasm::WASM_OPCODE_GET_GLOBAL); - encodeULEB128(Global.ImportIndex, getStream()); - } else { - assert(Global.ImportIndex == 0); - write8(wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(Global.InitialValue, getStream()); // offset - } - write8(wasm::WASM_OPCODE_END); - } - - endSection(Section); - } - - // === Export Section ======================================================== - if (!Exports.empty()) { - startSection(Section, wasm::WASM_SEC_EXPORT); - - encodeULEB128(Exports.size(), getStream()); - for (const WasmExport &Export : Exports) { - encodeULEB128(Export.FieldName.size(), getStream()); - writeBytes(Export.FieldName); - - encodeSLEB128(Export.Kind, getStream()); - - encodeULEB128(Export.Index, getStream()); - } - - endSection(Section); - } - -#if 0 // TODO: Start Section - if (HaveStartFunction) { - // === Start Section ========================================================= - startSection(Section, wasm::WASM_SEC_START); - - encodeSLEB128(StartFunction, getStream()); - - endSection(Section); - } -#endif - - // === Elem Section ========================================================== - if (!TableElems.empty()) { - startSection(Section, wasm::WASM_SEC_ELEM); - - encodeULEB128(1, getStream()); // number of "segments" - encodeULEB128(0, getStream()); // the table index - - // init expr for starting offset - write8(wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(0, getStream()); - write8(wasm::WASM_OPCODE_END); - - encodeULEB128(TableElems.size(), getStream()); - for (uint32_t Elem : TableElems) - encodeULEB128(Elem, getStream()); - - endSection(Section); - } - - // === Code Section ========================================================== - if (!Functions.empty()) { - startSection(Section, wasm::WASM_SEC_CODE); - - encodeULEB128(Functions.size(), getStream()); - - for (const WasmFunction &Func : Functions) { - MCSectionWasm &FuncSection = - static_cast(Func.Sym->getSection()); - - if (Func.Sym->isVariable()) - report_fatal_error("weak symbols not supported yet"); - - if (Func.Sym->getOffset() != 0) - report_fatal_error("function sections must contain one function each"); - - if (!Func.Sym->getSize()) - report_fatal_error("function symbols must have a size set with .size"); - - int64_t Size = 0; - if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout)) - report_fatal_error(".size expression must be evaluatable"); - - encodeULEB128(Size, getStream()); - - FuncSection.setSectionOffset(getStream().tell() - - Section.ContentsOffset); - - Asm.writeSectionData(&FuncSection, Layout); - } - - // Apply the type index fixups for call_indirect etc. instructions. - for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) { - uint32_t Type = TypeIndexFixupTypes[i]; - unsigned Padding = PaddingFor5ByteULEB128(Type); - - const WasmRelocationEntry &Fixup = TypeIndexFixups[i]; - assert(Fixup.Addend == 0); - assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); - uint64_t Offset = Fixup.Offset + - Fixup.FixupSection->getSectionOffset(); - - uint8_t Buffer[16]; - unsigned SizeLen = encodeULEB128(Type, Buffer, Padding); - assert(SizeLen == 5); - getStream().pwrite((char *)Buffer, SizeLen, - Section.ContentsOffset + Offset); - } - - // Apply fixups. - ApplyRelocations(CodeRelocations, getStream(), SymbolIndices, - Section.ContentsOffset); - - endSection(Section); - } - - // === Data Section ========================================================== - uint32_t DataSectionHeaderSize = 0; - if (!DataBytes.empty()) { - startSection(Section, wasm::WASM_SEC_DATA); - - encodeULEB128(1, getStream()); // count - encodeULEB128(0, getStream()); // memory index - write8(wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(0, getStream()); // offset - write8(wasm::WASM_OPCODE_END); - encodeULEB128(DataBytes.size(), getStream()); // size - DataSectionHeaderSize = getStream().tell() - Section.ContentsOffset; - writeBytes(DataBytes); // data - - // Apply fixups. - ApplyRelocations(DataRelocations, getStream(), SymbolIndices, - Section.ContentsOffset + DataSectionHeaderSize); - - endSection(Section); - } - - // === Name Section ========================================================== - uint32_t TotalFunctions = NumFuncImports + Functions.size(); - if (TotalFunctions != 0) { - startSection(Section, wasm::WASM_SEC_CUSTOM, "name"); - SectionBookkeeping SubSection; - startSection(SubSection, wasm::WASM_NAMES_FUNCTION); - - encodeULEB128(TotalFunctions, getStream()); - uint32_t Index = 0; - for (const WasmImport &Import : Imports) { - if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) { - encodeULEB128(Index, getStream()); - encodeULEB128(Import.FieldName.size(), getStream()); - writeBytes(Import.FieldName); - ++Index; - } - } - for (const WasmFunction &Func : Functions) { - encodeULEB128(Index, getStream()); - encodeULEB128(Func.Sym->getName().size(), getStream()); - writeBytes(Func.Sym->getName()); - ++Index; - } - - endSection(SubSection); - endSection(Section); - } - - // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md - // for descriptions of the reloc sections. - - // === Code Reloc Section ==================================================== - if (!CodeRelocations.empty()) { - startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE"); - - encodeULEB128(wasm::WASM_SEC_CODE, getStream()); - - encodeULEB128(CodeRelocations.size() + TypeIndexFixups.size(), getStream()); - - WriteRelocations(CodeRelocations, getStream(), SymbolIndices, 0); - WriteTypeRelocations(TypeIndexFixups, TypeIndexFixupTypes, getStream()); - - endSection(Section); - } - - // === Data Reloc Section ==================================================== - if (!DataRelocations.empty()) { - startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA"); - - encodeULEB128(wasm::WASM_SEC_DATA, getStream()); - - encodeULEB128(DataRelocations.size(), getStream()); - - WriteRelocations(DataRelocations, getStream(), SymbolIndices, - DataSectionHeaderSize); - - endSection(Section); - } - - // === Linking Metadata Section ============================================== - if (HasStackPointer) { - startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); - - encodeULEB128(1, getStream()); // count - - encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type - encodeULEB128(StackPointerGlobal, getStream()); // id - - endSection(Section); - } + writeTypeSection(FunctionTypes); + writeImportSection(Imports); + writeFunctionSection(Functions); + writeTableSection(TableElems); + writeMemorySection(DataBytes); + writeGlobalSection(Globals); + writeExportSection(Exports); + // TODO: Start Section + writeElemSection(TableElems); + writeCodeSection(Asm, Layout, SymbolIndices, Functions); + uint64_t DataSectionHeaderSize = writeDataSection(DataBytes, SymbolIndices); + writeNameSection(Functions, Imports, NumFuncImports); + writeCodeRelocSection(SymbolIndices); + writeDataRelocSection(SymbolIndices, DataSectionHeaderSize); + writeLinkingMetaDataSection(HasStackPointer, StackPointerGlobal); // TODO: Translate the .comment section to the output. - // TODO: Translate debug sections to the output. } diff --git a/contrib/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/contrib/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp index f652ff57f30d..21d29835624e 100644 --- a/contrib/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp +++ b/contrib/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp @@ -17,6 +17,11 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" @@ -36,16 +41,80 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef) LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false) +LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind) LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind) LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags) -LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceLineEntry) -LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceColumnEntry) -LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceFileChecksumEntry) -LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceLineInfo) -LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceLineBlock) -LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::InlineeInfo) -LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::InlineeSite) +LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry) +LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry) +LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry) +LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock) +LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite) + +namespace llvm { +namespace CodeViewYAML { +namespace detail { +struct YAMLSubsectionBase { + explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {} + DebugSubsectionKind Kind; + virtual ~YAMLSubsectionBase() {} + + virtual void map(IO &IO) = 0; + virtual std::unique_ptr + toCodeViewSubsection(DebugStringTableSubsection *UseStrings, + DebugChecksumsSubsection *UseChecksums) const = 0; +}; +} +} +} + +namespace { +struct YAMLChecksumsSubsection : public YAMLSubsectionBase { + YAMLChecksumsSubsection() + : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {} + + void map(IO &IO) override; + std::unique_ptr + toCodeViewSubsection(DebugStringTableSubsection *Strings, + DebugChecksumsSubsection *Checksums) const override; + static Expected> + fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &FC); + + std::vector Checksums; +}; + +struct YAMLLinesSubsection : public YAMLSubsectionBase { + YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {} + + void map(IO &IO) override; + std::unique_ptr + toCodeViewSubsection(DebugStringTableSubsection *Strings, + DebugChecksumsSubsection *Checksums) const override; + static Expected> + fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums, + const DebugLinesSubsectionRef &Lines); + + SourceLineInfo Lines; +}; + +struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase { + YAMLInlineeLinesSubsection() + : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {} + + void map(IO &IO) override; + std::unique_ptr + toCodeViewSubsection(DebugStringTableSubsection *Strings, + DebugChecksumsSubsection *Checksums) const override; + static Expected> + fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums, + const DebugInlineeLinesSubsectionRef &Lines); + + InlineeInfo InlineeLines; +}; +} void ScalarBitSetTraits::bitset(IO &io, LineFlags &Flags) { io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns); @@ -99,21 +168,6 @@ void MappingTraits::mapping( IO.mapRequired("Checksum", Obj.ChecksumBytes); } -void MappingTraits::mapping(IO &IO, SourceLineInfo &Obj) { - IO.mapRequired("CodeSize", Obj.CodeSize); - - IO.mapRequired("Flags", Obj.Flags); - IO.mapRequired("RelocOffset", Obj.RelocOffset); - IO.mapRequired("RelocSegment", Obj.RelocSegment); - IO.mapRequired("Blocks", Obj.Blocks); -} - -void MappingTraits::mapping(IO &IO, SourceFileInfo &Obj) { - IO.mapOptional("Checksums", Obj.FileChecksums); - IO.mapOptional("Lines", Obj.LineFragments); - IO.mapOptional("InlineeLines", Obj.Inlinees); -} - void MappingTraits::mapping(IO &IO, InlineeSite &Obj) { IO.mapRequired("FileName", Obj.FileName); IO.mapRequired("LineNum", Obj.SourceLineNum); @@ -121,7 +175,310 @@ void MappingTraits::mapping(IO &IO, InlineeSite &Obj) { IO.mapOptional("ExtraFiles", Obj.ExtraFiles); } -void MappingTraits::mapping(IO &IO, InlineeInfo &Obj) { - IO.mapRequired("HasExtraFiles", Obj.HasExtraFiles); - IO.mapRequired("Sites", Obj.Sites); +void YAMLChecksumsSubsection::map(IO &IO) { + IO.mapTag("!FileChecksums", true); + IO.mapRequired("Checksums", Checksums); +} + +void YAMLLinesSubsection::map(IO &IO) { + IO.mapTag("!Lines", true); + IO.mapRequired("CodeSize", Lines.CodeSize); + + IO.mapRequired("Flags", Lines.Flags); + IO.mapRequired("RelocOffset", Lines.RelocOffset); + IO.mapRequired("RelocSegment", Lines.RelocSegment); + IO.mapRequired("Blocks", Lines.Blocks); +} + +void YAMLInlineeLinesSubsection::map(IO &IO) { + IO.mapTag("!InlineeLines", true); + IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles); + IO.mapRequired("Sites", InlineeLines.Sites); +} + +void MappingTraits::mapping( + IO &IO, YAMLDebugSubsection &Subsection) { + if (!IO.outputting()) { + if (IO.mapTag("!FileChecksums")) { + auto SS = std::make_shared(); + Subsection.Subsection = SS; + } else if (IO.mapTag("!Lines")) { + Subsection.Subsection = std::make_shared(); + } else if (IO.mapTag("!InlineeLines")) { + Subsection.Subsection = std::make_shared(); + } else { + llvm_unreachable("Unexpected subsection tag!"); + } + } + Subsection.Subsection->map(IO); +} + +static Expected +findChecksums(ArrayRef Subsections) { + for (const auto &SS : Subsections) { + if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) { + return static_cast(*SS.Subsection); + } + } + return make_error(cv_error_code::no_records); +} + +std::unique_ptr YAMLChecksumsSubsection::toCodeViewSubsection( + DebugStringTableSubsection *UseStrings, + DebugChecksumsSubsection *UseChecksums) const { + assert(UseStrings && !UseChecksums); + auto Result = llvm::make_unique(*UseStrings); + for (const auto &CS : Checksums) { + Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes); + } + return std::move(Result); +} + +std::unique_ptr YAMLLinesSubsection::toCodeViewSubsection( + DebugStringTableSubsection *UseStrings, + DebugChecksumsSubsection *UseChecksums) const { + assert(UseStrings && UseChecksums); + auto Result = + llvm::make_unique(*UseChecksums, *UseStrings); + Result->setCodeSize(Lines.CodeSize); + Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset); + Result->setFlags(Lines.Flags); + for (const auto &LC : Lines.Blocks) { + Result->createBlock(LC.FileName); + if (Result->hasColumnInfo()) { + for (const auto &Item : zip(LC.Lines, LC.Columns)) { + auto &L = std::get<0>(Item); + auto &C = std::get<1>(Item); + uint32_t LE = L.LineStart + L.EndDelta; + Result->addLineAndColumnInfo(L.Offset, + LineInfo(L.LineStart, LE, L.IsStatement), + C.StartColumn, C.EndColumn); + } + } else { + for (const auto &L : LC.Lines) { + uint32_t LE = L.LineStart + L.EndDelta; + Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement)); + } + } + } + return llvm::cast(std::move(Result)); +} + +std::unique_ptr +YAMLInlineeLinesSubsection::toCodeViewSubsection( + DebugStringTableSubsection *UseStrings, + DebugChecksumsSubsection *UseChecksums) const { + assert(UseChecksums); + auto Result = llvm::make_unique( + *UseChecksums, InlineeLines.HasExtraFiles); + + for (const auto &Site : InlineeLines.Sites) { + Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName, + Site.SourceLineNum); + if (!InlineeLines.HasExtraFiles) + continue; + + for (auto EF : Site.ExtraFiles) { + Result->addExtraFile(EF); + } + } + return llvm::cast(std::move(Result)); +} + +static Expected +convertOneChecksum(const DebugStringTableSubsectionRef &Strings, + const FileChecksumEntry &CS) { + auto ExpectedString = Strings.getString(CS.FileNameOffset); + if (!ExpectedString) + return ExpectedString.takeError(); + + SourceFileChecksumEntry Result; + Result.ChecksumBytes.Bytes = CS.Checksum; + Result.Kind = CS.Kind; + Result.FileName = *ExpectedString; + return Result; +} + +static Expected +getFileName(const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) { + auto Iter = Checksums.getArray().at(FileID); + if (Iter == Checksums.getArray().end()) + return make_error(cv_error_code::no_records); + uint32_t Offset = Iter->FileNameOffset; + return Strings.getString(Offset); +} + +Expected> +YAMLChecksumsSubsection::fromCodeViewSubsection( + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &FC) { + auto Result = std::make_shared(); + + for (const auto &CS : FC) { + auto ConvertedCS = convertOneChecksum(Strings, CS); + if (!ConvertedCS) + return ConvertedCS.takeError(); + Result->Checksums.push_back(*ConvertedCS); + } + return Result; +} + +Expected> +YAMLLinesSubsection::fromCodeViewSubsection( + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums, + const DebugLinesSubsectionRef &Lines) { + auto Result = std::make_shared(); + Result->Lines.CodeSize = Lines.header()->CodeSize; + Result->Lines.RelocOffset = Lines.header()->RelocOffset; + Result->Lines.RelocSegment = Lines.header()->RelocSegment; + Result->Lines.Flags = static_cast(uint16_t(Lines.header()->Flags)); + for (const auto &L : Lines) { + SourceLineBlock Block; + auto EF = getFileName(Strings, Checksums, L.NameIndex); + if (!EF) + return EF.takeError(); + Block.FileName = *EF; + if (Lines.hasColumnInfo()) { + for (const auto &C : L.Columns) { + SourceColumnEntry SCE; + SCE.EndColumn = C.EndColumn; + SCE.StartColumn = C.StartColumn; + Block.Columns.push_back(SCE); + } + } + for (const auto &LN : L.LineNumbers) { + SourceLineEntry SLE; + LineInfo LI(LN.Flags); + SLE.Offset = LN.Offset; + SLE.LineStart = LI.getStartLine(); + SLE.EndDelta = LI.getLineDelta(); + SLE.IsStatement = LI.isStatement(); + Block.Lines.push_back(SLE); + } + Result->Lines.Blocks.push_back(Block); + } + return Result; +} + +Expected> +YAMLInlineeLinesSubsection::fromCodeViewSubsection( + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums, + const DebugInlineeLinesSubsectionRef &Lines) { + auto Result = std::make_shared(); + + Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles(); + for (const auto &IL : Lines) { + InlineeSite Site; + auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID); + if (!ExpF) + return ExpF.takeError(); + Site.FileName = *ExpF; + Site.Inlinee = IL.Header->Inlinee.getIndex(); + Site.SourceLineNum = IL.Header->SourceLineNum; + if (Lines.hasExtraFiles()) { + for (const auto EF : IL.ExtraFiles) { + auto ExpF2 = getFileName(Strings, Checksums, EF); + if (!ExpF2) + return ExpF2.takeError(); + Site.ExtraFiles.push_back(*ExpF2); + } + } + Result->InlineeLines.Sites.push_back(Site); + } + return Result; +} + +Expected>> +llvm::CodeViewYAML::convertSubsectionList( + ArrayRef Subsections, + DebugStringTableSubsection &Strings) { + std::vector> Result; + if (Subsections.empty()) + return std::move(Result); + + auto Checksums = findChecksums(Subsections); + if (!Checksums) + return Checksums.takeError(); + auto ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr); + DebugChecksumsSubsection &CS = + llvm::cast(*ChecksumsBase); + for (const auto &SS : Subsections) { + // We've already converted the checksums subsection, don't do it + // twice. + std::unique_ptr CVS; + if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) + CVS = std::move(ChecksumsBase); + else + CVS = SS.Subsection->toCodeViewSubsection(&Strings, &CS); + Result.push_back(std::move(CVS)); + } + return std::move(Result); +} + +namespace { +struct SubsectionConversionVisitor : public DebugSubsectionVisitor { + explicit SubsectionConversionVisitor( + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums) + : Strings(Strings), Checksums(Checksums) {} + + Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override; + Error visitLines(DebugLinesSubsectionRef &Lines) override; + Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums) override; + Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees) override; + + YAMLDebugSubsection Subsection; + +private: + const DebugStringTableSubsectionRef &Strings; + const DebugChecksumsSubsectionRef &Checksums; +}; + +Error SubsectionConversionVisitor::visitUnknown( + DebugUnknownSubsectionRef &Unknown) { + return make_error(cv_error_code::operation_unsupported); +} + +Error SubsectionConversionVisitor::visitLines(DebugLinesSubsectionRef &Lines) { + auto Result = + YAMLLinesSubsection::fromCodeViewSubsection(Strings, Checksums, Lines); + if (!Result) + return Result.takeError(); + Subsection.Subsection = *Result; + return Error::success(); +} + +Error SubsectionConversionVisitor::visitFileChecksums( + DebugChecksumsSubsectionRef &Checksums) { + auto Result = + YAMLChecksumsSubsection::fromCodeViewSubsection(Strings, Checksums); + if (!Result) + return Result.takeError(); + Subsection.Subsection = *Result; + return Error::success(); +} + +Error SubsectionConversionVisitor::visitInlineeLines( + DebugInlineeLinesSubsectionRef &Inlinees) { + auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection( + Strings, Checksums, Inlinees); + if (!Result) + return Result.takeError(); + Subsection.Subsection = *Result; + return Error::success(); +} +} + +Expected YAMLDebugSubsection::fromCodeViewSubection( + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums, + const DebugSubsectionRecord &SS) { + SubsectionConversionVisitor V(Strings, Checksums); + if (auto EC = visitDebugSubsection(SS, V)) + return std::move(EC); + + return V.Subsection; } diff --git a/contrib/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp b/contrib/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp index 6e8bb5c7372c..bd97af3a9323 100644 --- a/contrib/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp +++ b/contrib/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp @@ -148,7 +148,8 @@ struct SymbolRecordBase { virtual ~SymbolRecordBase() {} virtual void map(yaml::IO &io) = 0; virtual codeview::CVSymbol - toCodeViewSymbol(BumpPtrAllocator &Allocator) const = 0; + toCodeViewSymbol(BumpPtrAllocator &Allocator, + CodeViewContainer Container) const = 0; virtual Error fromCodeViewSymbol(codeview::CVSymbol Type) = 0; }; @@ -159,8 +160,9 @@ template struct SymbolRecordImpl : public SymbolRecordBase { void map(yaml::IO &io) override; codeview::CVSymbol - toCodeViewSymbol(BumpPtrAllocator &Allocator) const override { - return SymbolSerializer::writeOneSymbol(Symbol, Allocator); + toCodeViewSymbol(BumpPtrAllocator &Allocator, + CodeViewContainer Container) const override { + return SymbolSerializer::writeOneSymbol(Symbol, Allocator, Container); } Error fromCodeViewSymbol(codeview::CVSymbol CVS) override { return SymbolDeserializer::deserializeAs(CVS, Symbol); @@ -429,8 +431,8 @@ template <> void SymbolRecordImpl::map(IO &IO) { } CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol( - BumpPtrAllocator &Allocator) const { - return Symbol->toCodeViewSymbol(Allocator); + BumpPtrAllocator &Allocator, CodeViewContainer Container) const { + return Symbol->toCodeViewSymbol(Allocator, Container); } namespace llvm { diff --git a/contrib/llvm/lib/Passes/PassBuilder.cpp b/contrib/llvm/lib/Passes/PassBuilder.cpp index eb81e58b9b0e..17c60348633c 100644 --- a/contrib/llvm/lib/Passes/PassBuilder.cpp +++ b/contrib/llvm/lib/Passes/PassBuilder.cpp @@ -310,6 +310,10 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, // Catch trivial redundancies FPM.addPass(EarlyCSEPass()); + // Hoisting of scalars and load expressions. + if (EnableGVNHoist) + FPM.addPass(GVNHoistPass()); + // Speculative execution if the target has divergent branches; otherwise nop. FPM.addPass(SpeculativeExecutionPass()); @@ -473,8 +477,6 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, EarlyFPM.addPass(SROA()); EarlyFPM.addPass(EarlyCSEPass()); EarlyFPM.addPass(LowerExpectIntrinsicPass()); - if (EnableGVNHoist) - EarlyFPM.addPass(GVNHoistPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(EarlyFPM))); // Interprocedural constant propagation now that basic cleanup has occured diff --git a/contrib/llvm/lib/Support/Triple.cpp b/contrib/llvm/lib/Support/Triple.cpp index 318e21da999d..f7b7ad89e959 100644 --- a/contrib/llvm/lib/Support/Triple.cpp +++ b/contrib/llvm/lib/Support/Triple.cpp @@ -649,12 +649,10 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { case Triple::tce: case Triple::tcele: case Triple::thumbeb: - case Triple::xcore: - return Triple::ELF; - case Triple::wasm32: case Triple::wasm64: - return Triple::Wasm; + case Triple::xcore: + return Triple::ELF; case Triple::ppc: case Triple::ppc64: diff --git a/contrib/llvm/lib/Target/AArch64/AArch64PBQPRegAlloc.h b/contrib/llvm/lib/Target/AArch64/AArch64PBQPRegAlloc.h index 4f656f94ea12..b99c1d1d6b3e 100644 --- a/contrib/llvm/lib/Target/AArch64/AArch64PBQPRegAlloc.h +++ b/contrib/llvm/lib/Target/AArch64/AArch64PBQPRegAlloc.h @@ -1,4 +1,4 @@ -//===-- AArch64PBQPRegAlloc.h - AArch64 specific PBQP constraints -------===// +//==- AArch64PBQPRegAlloc.h - AArch64 specific PBQP constraints --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -15,6 +15,8 @@ namespace llvm { +class TargetRegisterInfo; + /// Add the accumulator chaining constraint to a PBQP graph class A57ChainingConstraint : public PBQPRAConstraint { public: @@ -33,6 +35,7 @@ private: // Add constraints between existing chains void addInterChainConstraint(PBQPRAGraph &G, unsigned Rd, unsigned Ra); }; -} + +} // end namespace llvm #endif // LLVM_LIB_TARGET_AARCH64_AARCH64PBQPREGALOC_H diff --git a/contrib/llvm/lib/Target/AArch64/AArch64SchedFalkorDetails.td b/contrib/llvm/lib/Target/AArch64/AArch64SchedFalkorDetails.td index d098cf7a5a37..7402bcf1346c 100644 --- a/contrib/llvm/lib/Target/AArch64/AArch64SchedFalkorDetails.td +++ b/contrib/llvm/lib/Target/AArch64/AArch64SchedFalkorDetails.td @@ -56,12 +56,14 @@ def FalkorWr_1Z_0cyc : SchedWriteRes<[FalkorUnitZ]> { let Latency = 0; } def FalkorWr_1ZB_0cyc : SchedWriteRes<[FalkorUnitZB]> { let Latency = 0; } def FalkorWr_1LD_3cyc : SchedWriteRes<[FalkorUnitLD]> { let Latency = 3; } def FalkorWr_1LD_4cyc : SchedWriteRes<[FalkorUnitLD]> { let Latency = 4; } +def FalkorWr_1XYZ_0cyc : SchedWriteRes<[FalkorUnitXYZ]> { let Latency = 0; } def FalkorWr_1XYZ_1cyc : SchedWriteRes<[FalkorUnitXYZ]> { let Latency = 1; } def FalkorWr_1XYZ_2cyc : SchedWriteRes<[FalkorUnitXYZ]> { let Latency = 2; } def FalkorWr_1XYZB_0cyc : SchedWriteRes<[FalkorUnitXYZB]>{ let Latency = 0; } def FalkorWr_1XYZB_1cyc : SchedWriteRes<[FalkorUnitXYZB]>{ let Latency = 1; } def FalkorWr_1none_0cyc : SchedWriteRes<[]> { let Latency = 0; } +def FalkorWr_1VXVY_0cyc : SchedWriteRes<[FalkorUnitVXVY]>{ let Latency = 0; } def FalkorWr_1VXVY_1cyc : SchedWriteRes<[FalkorUnitVXVY]>{ let Latency = 1; } def FalkorWr_1VXVY_2cyc : SchedWriteRes<[FalkorUnitVXVY]>{ let Latency = 2; } def FalkorWr_1VXVY_3cyc : SchedWriteRes<[FalkorUnitVXVY]>{ let Latency = 3; } @@ -76,6 +78,7 @@ def FalkorWr_1LD_0cyc : SchedWriteRes<[FalkorUnitLD]> { let Latency = 0; } def FalkorWr_1ST_0cyc : SchedWriteRes<[FalkorUnitST]> { let Latency = 0; } def FalkorWr_1ST_3cyc : SchedWriteRes<[FalkorUnitST]> { let Latency = 3; } +def FalkorWr_1GTOV_0cyc : SchedWriteRes<[FalkorUnitGTOV]>{ let Latency = 0; } def FalkorWr_1GTOV_1cyc : SchedWriteRes<[FalkorUnitGTOV]>{ let Latency = 1; } def FalkorWr_1GTOV_4cyc : SchedWriteRes<[FalkorUnitGTOV]>{ let Latency = 4; } def FalkorWr_1VTOG_1cyc : SchedWriteRes<[FalkorUnitVTOG]>{ let Latency = 1; } @@ -83,6 +86,10 @@ def FalkorWr_1VTOG_1cyc : SchedWriteRes<[FalkorUnitVTOG]>{ let Latency = 1; } //===----------------------------------------------------------------------===// // Define 2 micro-op types +def FalkorWr_2VXVY_0cyc : SchedWriteRes<[FalkorUnitVXVY, FalkorUnitVXVY]> { + let Latency = 0; + let NumMicroOps = 2; +} def FalkorWr_2VXVY_1cyc : SchedWriteRes<[FalkorUnitVXVY, FalkorUnitVXVY]> { let Latency = 1; let NumMicroOps = 2; @@ -476,17 +483,19 @@ def FalkorReadFMA64 : SchedReadAdvance<2, [FalkorWr_FMUL64_1VXVY_6cyc, FalkorWr // SchedPredicates and WriteVariants for Immediate Zero and LSLFast/ASRFast // ----------------------------------------------------------------------------- def FalkorImmZPred : SchedPredicate<[{MI->getOperand(1).getImm() == 0}]>; -def FalkorFMOVZrReg : SchedPredicate<[{MI->getOperand(1).getReg() == AArch64::WZR || +def FalkorOp1ZrReg : SchedPredicate<[{MI->getOperand(1).getReg() == AArch64::WZR || + MI->getOperand(1).getReg() == AArch64::XZR}]>; def FalkorShiftExtFastPred : SchedPredicate<[{TII->isFalkorShiftExtFast(*MI)}]>; def FalkorWr_FMOV : SchedWriteVariant<[ - SchedVar, + SchedVar, SchedVar]>; def FalkorWr_MOVZ : SchedWriteVariant<[ SchedVar, - SchedVar]>; + SchedVar]>; // imm fwd + def FalkorWr_ADDSUBsx : SchedWriteVariant<[ SchedVar, @@ -500,6 +509,10 @@ def FalkorWr_LDRSro : SchedWriteVariant<[ SchedVar, SchedVar]>; +def FalkorWr_ORRi : SchedWriteVariant<[ + SchedVar, // imm fwd + SchedVar]>; + def FalkorWr_PRFMro : SchedWriteVariant<[ SchedVar, SchedVar]>; @@ -810,7 +823,8 @@ def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^BIC(S)?(W|X)r(r|s)$")>; def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^EON(W|X)r(r|s)$")>; def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^EOR(W|X)r(i|r|s)$")>; def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^ORN(W|X)r(r|s)$")>; -def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^ORR(W|X)r(i|r|s)$")>; +def : InstRW<[FalkorWr_ORRi], (instregex "^ORR(W|X)ri$")>; +def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^ORR(W|X)r(r|s)$")>; def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^SBC(S)?(W|X)r$")>; def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^SUB(S)?(W|X)r(r|i)$")>; def : InstRW<[FalkorWr_ADDSUBsx], (instregex "^ADD(S)?(W|X)r(s|x|x64)$")>; @@ -825,7 +839,7 @@ def : InstRW<[FalkorWr_1GTOV_1cyc], (instregex "^INSv(i8|i16)(gpr|lane)$")>; def : InstRW<[FalkorWr_1VTOG_1cyc], (instregex "^(S|U)MOVv.*$")>; def : InstRW<[FalkorWr_1VXVY_1cyc], (instregex "^(BIF|BIT|BSL)v8i8$")>; def : InstRW<[FalkorWr_1VXVY_1cyc], (instrs EXTv8i8)>; -def : InstRW<[FalkorWr_1VXVY_1cyc], (instregex "(MOVI|MVNI)(D|v8b_ns|v2i32|v4i16|v2s_msl)$")>; +def : InstRW<[FalkorWr_1VXVY_0cyc], (instregex "(MOVI|MVNI)(D|v8b_ns|v2i32|v4i16|v2s_msl)$")>; // imm fwd def : InstRW<[FalkorWr_1VXVY_1cyc], (instrs TBLv8i8One)>; def : InstRW<[FalkorWr_1VXVY_1cyc], (instrs NOTv8i8)>; def : InstRW<[FalkorWr_1VXVY_1cyc], (instregex "^REV(16|32|64)v.*$")>; @@ -849,7 +863,7 @@ def : InstRW<[FalkorWr_1GTOV_1VXVY_2cyc], def : InstRW<[FalkorWr_2GTOV_1cyc], (instregex "^DUP(v4i32|v2i64)(gpr|lane)$")>; def : InstRW<[FalkorWr_2VXVY_1cyc], (instregex "^(BIF|BIT|BSL)v16i8$")>; def : InstRW<[FalkorWr_2VXVY_1cyc], (instrs EXTv16i8)>; -def : InstRW<[FalkorWr_2VXVY_1cyc], (instregex "(MOVI|MVNI)(v2d_ns|v16b_ns|v4i32|v8i16|v4s_msl)$")>; +def : InstRW<[FalkorWr_2VXVY_0cyc], (instregex "(MOVI|MVNI)(v2d_ns|v16b_ns|v4i32|v8i16|v4s_msl)$")>; // imm fwd def : InstRW<[FalkorWr_2VXVY_1cyc], (instrs NOTv16i8)>; def : InstRW<[FalkorWr_2VXVY_1cyc], (instrs TBLv16i8One)>; @@ -1036,13 +1050,13 @@ def : InstRW<[FalkorWr_FMUL64_1VXVY_6cyc, ReadDefault, ReadDefault, FalkorReadFM // FP Miscellaneous Instructions // ----------------------------------------------------------------------------- def : InstRW<[FalkorWr_FMOV], (instregex "^FMOV(WS|XD|XDHigh)r$")>; -def : InstRW<[FalkorWr_1GTOV_1cyc], (instregex "^FMOV(S|D)i$")>; +def : InstRW<[FalkorWr_1GTOV_0cyc], (instregex "^FMOV(S|D)i$")>; // imm fwd def : InstRW<[FalkorWr_1VTOG_1cyc], (instregex "^FCVTZ(S|U)S(W|X)(D|S)ri$")>; def : InstRW<[FalkorWr_1VTOG_1cyc], (instregex "^FCVTZ(S|U)(d|s)$")>; def : InstRW<[FalkorWr_1VTOG_1cyc], (instregex "^FMOV(SW|DX|DXHigh)r$")>; -def : InstRW<[FalkorWr_1VXVY_1cyc], (instregex "^FMOV(Sr|Dr|v.*_ns)$")>; +def : InstRW<[FalkorWr_1VXVY_0cyc], (instregex "^FMOV(Sr|Dr|v.*_ns)$")>; // imm fwd // FIXME: We are currently generating movi v0.2d, #0 for these, which is worse than fmov wzr/xzr -def : InstRW<[FalkorWr_2VXVY_1cyc], (instrs FMOVD0, FMOVS0)>; +def : InstRW<[FalkorWr_2VXVY_0cyc], (instrs FMOVD0, FMOVS0)>; // imm fwd def : InstRW<[FalkorWr_1GTOV_4cyc], (instregex "^(S|U)CVTF(S|U)(W|X)(D|S)ri$")>; def : InstRW<[FalkorWr_1VXVY_4cyc], (instregex "^(S|U)CVTF(v1i32|v2i32|v1i64|v2f32|d|s)(_shift)?")>; @@ -1107,11 +1121,12 @@ def : InstRW<[FalkorWr_VMUL32_2VXVY_4cyc, FalkorReadVMA], // Move and Shift Instructions // ----------------------------------------------------------------------------- -def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^(LSLV|LSRV|ASRV|RORV|MOVK)(W|X).*")>; -def : InstRW<[FalkorWr_1XYZB_1cyc], (instregex "^ADRP?$")>; -def : InstRW<[FalkorWr_1XYZB_1cyc], (instregex "^MOVN(W|X)i$")>; +def : InstRW<[FalkorWr_1XYZ_1cyc], (instregex "^(LSLV|LSRV|ASRV|RORV)(W|X)r$")>; +def : InstRW<[FalkorWr_1XYZ_0cyc], (instregex "^MOVK(W|X)i$")>; // imm fwd +def : InstRW<[FalkorWr_1XYZB_0cyc], (instregex "^ADRP?$")>; // imm fwd +def : InstRW<[FalkorWr_1XYZB_0cyc], (instregex "^MOVN(W|X)i$")>; // imm fwd def : InstRW<[FalkorWr_MOVZ], (instregex "^MOVZ(W|X)i$")>; -def : InstRW<[FalkorWr_1XYZ_1cyc], (instrs MOVi32imm, MOVi64imm)>; +def : InstRW<[FalkorWr_1XYZ_0cyc], (instrs MOVi32imm, MOVi64imm)>; // imm fwd (approximation) def : InstRW<[WriteSequence<[FalkorWr_1XYZ_1cyc, FalkorWr_1XYZ_1cyc]>], (instrs MOVaddr, MOVaddrBA, MOVaddrCP, MOVaddrEXT, MOVaddrJT, MOVaddrTLS)>; def : InstRW<[WriteSequence<[FalkorWr_1LD_3cyc, FalkorWr_1XYZ_1cyc]>], diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPU.h b/contrib/llvm/lib/Target/AMDGPU/AMDGPU.h index 78ff3bbe3d1a..55d18c3f3646 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPU.h +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPU.h @@ -55,6 +55,8 @@ FunctionPass *createAMDGPUMachineCFGStructurizerPass(); void initializeAMDGPUMachineCFGStructurizerPass(PassRegistry&); extern char &AMDGPUMachineCFGStructurizerID; +void initializeAMDGPUAlwaysInlinePass(PassRegistry&); + ModulePass *createAMDGPUAnnotateKernelFeaturesPass(); void initializeAMDGPUAnnotateKernelFeaturesPass(PassRegistry &); extern char &AMDGPUAnnotateKernelFeaturesID; diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPU.td b/contrib/llvm/lib/Target/AMDGPU/AMDGPU.td index e7ebb37a9d62..b50e8d1d659e 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPU.td +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPU.td @@ -365,6 +365,13 @@ def FeatureFlatForGlobal : SubtargetFeature<"flat-for-global", "Force to generate flat instruction for global" >; +def FeatureAutoWaitcntBeforeBarrier : SubtargetFeature < + "auto-waitcnt-before-barrier", + "AutoWaitcntBeforeBarrier", + "true", + "Hardware automatically inserts waitcnt before barrier" +>; + // Dummy feature used to disable assembler instructions. def FeatureDisable : SubtargetFeature<"", "FeatureDisable","true", diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp b/contrib/llvm/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp index 1d03714874e2..8084d368c80f 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp @@ -22,18 +22,22 @@ using namespace llvm; namespace { class AMDGPUAlwaysInline : public ModulePass { - static char ID; - bool GlobalOpt; public: - AMDGPUAlwaysInline(bool GlobalOpt) : ModulePass(ID), GlobalOpt(GlobalOpt) { } + static char ID; + + AMDGPUAlwaysInline(bool GlobalOpt = false) : + ModulePass(ID), GlobalOpt(GlobalOpt) { } bool runOnModule(Module &M) override; StringRef getPassName() const override { return "AMDGPU Always Inline Pass"; } }; } // End anonymous namespace +INITIALIZE_PASS(AMDGPUAlwaysInline, "amdgpu-always-inline", + "AMDGPU Inline All Functions", false, false) + char AMDGPUAlwaysInline::ID = 0; bool AMDGPUAlwaysInline::runOnModule(Module &M) { diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/contrib/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index 57905be18813..267f4807a788 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -28,11 +28,16 @@ using namespace llvm; AMDGPULegalizerInfo::AMDGPULegalizerInfo() { using namespace TargetOpcode; + const LLT S1= LLT::scalar(1); const LLT S32 = LLT::scalar(32); const LLT S64 = LLT::scalar(64); const LLT P1 = LLT::pointer(1, 64); const LLT P2 = LLT::pointer(2, 64); + // FIXME: i1 operands to intrinsics should always be legal, but other i1 + // values may not be legal. We need to figure out how to distinguish + // between these two scenarios. + setAction({G_CONSTANT, S1}, Legal); setAction({G_CONSTANT, S32}, Legal); setAction({G_CONSTANT, S64}, Legal); diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp b/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp index 6e301b4ad527..8d157e2f98f2 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp @@ -91,6 +91,7 @@ AMDGPUSubtarget::AMDGPUSubtarget(const Triple &TT, StringRef GPU, StringRef FS, FPExceptions(false), DX10Clamp(false), FlatForGlobal(false), + AutoWaitcntBeforeBarrier(false), UnalignedScratchAccess(false), UnalignedBufferAccess(false), diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h b/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h index 0582ce95693a..ed9cbb994fad 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -110,6 +110,7 @@ protected: bool FPExceptions; bool DX10Clamp; bool FlatForGlobal; + bool AutoWaitcntBeforeBarrier; bool UnalignedScratchAccess; bool UnalignedBufferAccess; bool HasApertureRegs; @@ -195,7 +196,8 @@ public: } bool isOpenCLEnv() const { - return TargetTriple.getEnvironment() == Triple::OpenCL; + return TargetTriple.getEnvironment() == Triple::OpenCL || + TargetTriple.getEnvironmentName() == "amdgizcl"; } Generation getGeneration() const { @@ -363,6 +365,10 @@ public: return FlatForGlobal; } + bool hasAutoWaitcntBeforeBarrier() const { + return AutoWaitcntBeforeBarrier; + } + bool hasUnalignedBufferAccess() const { return UnalignedBufferAccess; } @@ -727,12 +733,6 @@ public: /// Return the maximum number of waves per SIMD for kernels using \p VGPRs VGPRs unsigned getOccupancyWithNumVGPRs(unsigned VGPRs) const; - /// \returns True if waitcnt instruction is needed before barrier instruction, - /// false otherwise. - bool needWaitcntBeforeBarrier() const { - return true; - } - /// \returns true if the flat_scratch register should be initialized with the /// pointer to the wave's scratch memory rather than a size and offset. bool flatScratchIsPointer() const { diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/contrib/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 596f02ae4a64..404598ff4738 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -116,7 +116,7 @@ static cl::opt EnableAMDGPUAliasAnalysis("enable-amdgpu-aa", cl::Hidden, static cl::opt EnableSIInsertWaitcntsPass( "enable-si-insert-waitcnts", cl::desc("Use new waitcnt insertion pass"), - cl::init(false)); + cl::init(true)); // Option to run late CFG structurizer static cl::opt LateCFGStructurize( @@ -139,6 +139,7 @@ extern "C" void LLVMInitializeAMDGPUTarget() { initializeSIShrinkInstructionsPass(*PR); initializeSIFixControlFlowLiveIntervalsPass(*PR); initializeSILoadStoreOptimizerPass(*PR); + initializeAMDGPUAlwaysInlinePass(*PR); initializeAMDGPUAnnotateKernelFeaturesPass(*PR); initializeAMDGPUAnnotateUniformValuesPass(*PR); initializeAMDGPULowerIntrinsicsPass(*PR); diff --git a/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp b/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp index f13629a3185f..dfac068d1f69 100644 --- a/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp @@ -35,9 +35,12 @@ struct FoldCandidate { }; unsigned char UseOpNo; MachineOperand::MachineOperandType Kind; + bool Commuted; - FoldCandidate(MachineInstr *MI, unsigned OpNo, MachineOperand *FoldOp) : - UseMI(MI), OpToFold(nullptr), UseOpNo(OpNo), Kind(FoldOp->getType()) { + FoldCandidate(MachineInstr *MI, unsigned OpNo, MachineOperand *FoldOp, + bool Commuted_ = false) : + UseMI(MI), OpToFold(nullptr), UseOpNo(OpNo), Kind(FoldOp->getType()), + Commuted(Commuted_) { if (FoldOp->isImm()) { ImmToFold = FoldOp->getImm(); } else if (FoldOp->isFI()) { @@ -59,6 +62,10 @@ struct FoldCandidate { bool isReg() const { return Kind == MachineOperand::MO_Register; } + + bool isCommuted() const { + return Commuted; + } }; class SIFoldOperands : public MachineFunctionPass { @@ -237,8 +244,13 @@ static bool tryAddToFoldList(SmallVectorImpl &FoldList, !TII->commuteInstruction(*MI, false, CommuteIdx0, CommuteIdx1)) return false; - if (!TII->isOperandLegal(*MI, OpNo, OpToFold)) + if (!TII->isOperandLegal(*MI, OpNo, OpToFold)) { + TII->commuteInstruction(*MI, false, CommuteIdx0, CommuteIdx1); return false; + } + + FoldList.push_back(FoldCandidate(MI, OpNo, OpToFold, true)); + return true; } FoldList.push_back(FoldCandidate(MI, OpNo, OpToFold)); @@ -699,6 +711,9 @@ void SIFoldOperands::foldInstOperand(MachineInstr &MI, DEBUG(dbgs() << "Folded source from " << MI << " into OpNo " << static_cast(Fold.UseOpNo) << " of " << *Fold.UseMI << '\n'); tryFoldInst(TII, Fold.UseMI); + } else if (Fold.isCommuted()) { + // Restoring instruction's original operand order if fold has failed. + TII->commuteInstruction(*Fold.UseMI, false); } } } diff --git a/contrib/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/contrib/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 76c2644867aa..b48b23911105 100644 --- a/contrib/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -3571,7 +3571,7 @@ SDValue SITargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const { } if (AS == AMDGPUASI.CONSTANT_ADDRESS || AS == AMDGPUASI.GLOBAL_ADDRESS) { if (Subtarget->getScalarizeGlobalBehavior() && isMemOpUniform(Load) && - isMemOpHasNoClobberedMemOperand(Load)) + !Load->isVolatile() && isMemOpHasNoClobberedMemOperand(Load)) return SDValue(); // Non-uniform loads will be selected to MUBUF instructions, so they // have the same legalization requirements as global and private diff --git a/contrib/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp b/contrib/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp index e22166d03e9a..c10badba88f3 100644 --- a/contrib/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp @@ -1009,7 +1009,8 @@ MachineInstr *SIInsertWaitcnts::generateSWaitCntInstBefore( // occurs before the instruction. Doing it here prevents any additional // S_WAITCNTs from being emitted if the instruction was marked as // requiring a WAITCNT beforehand. - if (MI.getOpcode() == AMDGPU::S_BARRIER && ST->needWaitcntBeforeBarrier()) { + if (MI.getOpcode() == AMDGPU::S_BARRIER && + !ST->hasAutoWaitcntBeforeBarrier()) { EmitSwaitcnt |= ScoreBrackets->updateByWait(VM_CNT, ScoreBrackets->getScoreUB(VM_CNT)); EmitSwaitcnt |= ScoreBrackets->updateByWait( diff --git a/contrib/llvm/lib/Target/AMDGPU/SIInsertWaits.cpp b/contrib/llvm/lib/Target/AMDGPU/SIInsertWaits.cpp index 9f32ecfa52ff..bc86515d8b1f 100644 --- a/contrib/llvm/lib/Target/AMDGPU/SIInsertWaits.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/SIInsertWaits.cpp @@ -630,7 +630,7 @@ bool SIInsertWaits::runOnMachineFunction(MachineFunction &MF) { // but we also want to wait for any other outstanding transfers before // signalling other hardware blocks if ((I->getOpcode() == AMDGPU::S_BARRIER && - ST->needWaitcntBeforeBarrier()) || + !ST->hasAutoWaitcntBeforeBarrier()) || I->getOpcode() == AMDGPU::S_SENDMSG || I->getOpcode() == AMDGPU::S_SENDMSGHALT) Required = LastIssued; diff --git a/contrib/llvm/lib/Target/AMDGPU/SMInstructions.td b/contrib/llvm/lib/Target/AMDGPU/SMInstructions.td index 5b840a14dbc3..73dd8b7daa4e 100644 --- a/contrib/llvm/lib/Target/AMDGPU/SMInstructions.td +++ b/contrib/llvm/lib/Target/AMDGPU/SMInstructions.td @@ -229,6 +229,7 @@ def smrd_load : PatFrag <(ops node:$ptr), (load node:$ptr), [{ ((Ld->getAddressSpace() == AMDGPUASI.CONSTANT_ADDRESS && static_cast(getTargetLowering())->isMemOpUniform(N)) || (Subtarget->getScalarizeGlobalBehavior() && Ld->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS && + !Ld->isVolatile() && static_cast(getTargetLowering())->isMemOpUniform(N) && static_cast(getTargetLowering())->isMemOpHasNoClobberedMemOperand(N))); }]>; diff --git a/contrib/llvm/lib/Target/AMDGPU/VOP3Instructions.td b/contrib/llvm/lib/Target/AMDGPU/VOP3Instructions.td index 001fc960b228..77fc9551cff9 100644 --- a/contrib/llvm/lib/Target/AMDGPU/VOP3Instructions.td +++ b/contrib/llvm/lib/Target/AMDGPU/VOP3Instructions.td @@ -245,9 +245,10 @@ def V_MAD_I64_I32 : VOP3Inst <"v_mad_i64_i32", VOP3b_I64_I1_I32_I32_I64>; let SubtargetPredicate = Has16BitInsts in { +def V_DIV_FIXUP_F16 : VOP3Inst <"v_div_fixup_f16", VOP3_Profile, AMDGPUdiv_fixup>; + let isCommutable = 1 in { -def V_DIV_FIXUP_F16 : VOP3Inst <"v_div_fixup_f16", VOP3_Profile, AMDGPUdiv_fixup>; def V_FMA_F16 : VOP3Inst <"v_fma_f16", VOP3_Profile, fma>; def V_INTERP_P1LL_F16 : VOP3Inst <"v_interp_p1ll_f16", VOP3_Profile>; def V_INTERP_P1LV_F16 : VOP3Inst <"v_interp_p1lv_f16", VOP3_Profile>; diff --git a/contrib/llvm/lib/Target/ARM/ARM.td b/contrib/llvm/lib/Target/ARM/ARM.td index 46fd1f70ee99..ca68f5d42c32 100644 --- a/contrib/llvm/lib/Target/ARM/ARM.td +++ b/contrib/llvm/lib/Target/ARM/ARM.td @@ -205,6 +205,13 @@ def FeatureAvoidPartialCPSR : SubtargetFeature<"avoid-partial-cpsr", "AvoidCPSRPartialUpdate", "true", "Avoid CPSR partial update for OOO execution">; +/// Disable +1 predication cost for instructions updating CPSR. +/// Enabled for Cortex-A57. +def FeatureCheapPredicableCPSR : SubtargetFeature<"cheap-predicable-cpsr", + "CheapPredicableCPSRDef", + "true", + "Disable +1 predication cost for instructions updating CPSR">; + def FeatureAvoidMOVsShOp : SubtargetFeature<"avoid-movs-shop", "AvoidMOVsShifterOperand", "true", "Avoid movs instructions with shifter operand">; @@ -788,12 +795,14 @@ def : ProcNoItin<"cortex-a53", [ARMv8a, ProcA53, FeatureCRC, FeatureFPAO]>; -def : ProcNoItin<"cortex-a57", [ARMv8a, ProcA57, - FeatureHWDivThumb, - FeatureHWDivARM, - FeatureCrypto, - FeatureCRC, - FeatureFPAO]>; +def : ProcessorModel<"cortex-a57", CortexA57Model, [ARMv8a, ProcA57, + FeatureHWDivThumb, + FeatureHWDivARM, + FeatureCrypto, + FeatureCRC, + FeatureFPAO, + FeatureAvoidPartialCPSR, + FeatureCheapPredicableCPSR]>; def : ProcNoItin<"cortex-a72", [ARMv8a, ProcA72, FeatureHWDivThumb, diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index 5c9d589e2625..f8b65573f9cd 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -558,13 +558,68 @@ bool ARMBaseInstrInfo::DefinesPredicate( return Found; } -static bool isCPSRDefined(const MachineInstr *MI) { - for (const auto &MO : MI->operands()) +bool ARMBaseInstrInfo::isCPSRDefined(const MachineInstr &MI) { + for (const auto &MO : MI.operands()) if (MO.isReg() && MO.getReg() == ARM::CPSR && MO.isDef() && !MO.isDead()) return true; return false; } +bool ARMBaseInstrInfo::isAddrMode3OpImm(const MachineInstr &MI, + unsigned Op) const { + const MachineOperand &Offset = MI.getOperand(Op + 1); + return Offset.getReg() != 0; +} + +// Load with negative register offset requires additional 1cyc and +I unit +// for Cortex A57 +bool ARMBaseInstrInfo::isAddrMode3OpMinusReg(const MachineInstr &MI, + unsigned Op) const { + const MachineOperand &Offset = MI.getOperand(Op + 1); + const MachineOperand &Opc = MI.getOperand(Op + 2); + assert(Opc.isImm()); + assert(Offset.isReg()); + int64_t OpcImm = Opc.getImm(); + + bool isSub = ARM_AM::getAM3Op(OpcImm) == ARM_AM::sub; + return (isSub && Offset.getReg() != 0); +} + +bool ARMBaseInstrInfo::isLdstScaledReg(const MachineInstr &MI, + unsigned Op) const { + const MachineOperand &Opc = MI.getOperand(Op + 2); + unsigned OffImm = Opc.getImm(); + return ARM_AM::getAM2ShiftOpc(OffImm) != ARM_AM::no_shift; +} + +// Load, scaled register offset, not plus LSL2 +bool ARMBaseInstrInfo::isLdstScaledRegNotPlusLsl2(const MachineInstr &MI, + unsigned Op) const { + const MachineOperand &Opc = MI.getOperand(Op + 2); + unsigned OffImm = Opc.getImm(); + + bool isAdd = ARM_AM::getAM2Op(OffImm) == ARM_AM::add; + unsigned Amt = ARM_AM::getAM2Offset(OffImm); + ARM_AM::ShiftOpc ShiftOpc = ARM_AM::getAM2ShiftOpc(OffImm); + if (ShiftOpc == ARM_AM::no_shift) return false; // not scaled + bool SimpleScaled = (isAdd && ShiftOpc == ARM_AM::lsl && Amt == 2); + return !SimpleScaled; +} + +// Minus reg for ldstso addr mode +bool ARMBaseInstrInfo::isLdstSoMinusReg(const MachineInstr &MI, + unsigned Op) const { + unsigned OffImm = MI.getOperand(Op + 2).getImm(); + return ARM_AM::getAM2Op(OffImm) == ARM_AM::sub; +} + +// Load, scaled register offset +bool ARMBaseInstrInfo::isAm2ScaledReg(const MachineInstr &MI, + unsigned Op) const { + unsigned OffImm = MI.getOperand(Op + 2).getImm(); + return ARM_AM::getAM2ShiftOpc(OffImm) != ARM_AM::no_shift; +} + static bool isEligibleForITBlock(const MachineInstr *MI) { switch (MI->getOpcode()) { default: return true; @@ -590,7 +645,7 @@ static bool isEligibleForITBlock(const MachineInstr *MI) { case ARM::tSUBi3: // SUB (immediate) T1 case ARM::tSUBi8: // SUB (immediate) T2 case ARM::tSUBrr: // SUB (register) T1 - return !isCPSRDefined(MI); + return !ARMBaseInstrInfo::isCPSRDefined(*MI); } } @@ -3349,6 +3404,22 @@ ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, return DefCycle; } +bool ARMBaseInstrInfo::isLDMBaseRegInList(const MachineInstr &MI) const { + unsigned BaseReg = MI.getOperand(0).getReg(); + for (unsigned i = 1, sz = MI.getNumOperands(); i < sz; ++i) { + const auto &Op = MI.getOperand(i); + if (Op.isReg() && Op.getReg() == BaseReg) + return true; + } + return false; +} +unsigned +ARMBaseInstrInfo::getLDMVariableDefsSize(const MachineInstr &MI) const { + // ins GPR:$Rn, pred:$p (2xOp), reglist:$regs, variable_ops + // (outs GPR:$wb), (ins GPR:$Rn, pred:$p (2xOp), reglist:$regs, variable_ops) + return MI.getNumOperands() + 1 - MI.getDesc().getNumOperands(); +} + int ARMBaseInstrInfo::getLDMDefCycle(const InstrItineraryData *ItinData, const MCInstrDesc &DefMCID, @@ -4119,7 +4190,8 @@ unsigned ARMBaseInstrInfo::getPredicationCost(const MachineInstr &MI) const { const MCInstrDesc &MCID = MI.getDesc(); - if (MCID.isCall() || MCID.hasImplicitDefOfPhysReg(ARM::CPSR)) { + if (MCID.isCall() || (MCID.hasImplicitDefOfPhysReg(ARM::CPSR) && + !Subtarget.cheapPredicableCPSRDef())) { // When predicated, CPSR is an additional source operand for CPSR updating // instructions, this apparently increases their latencies. return 1; @@ -4148,7 +4220,8 @@ unsigned ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, } const MCInstrDesc &MCID = MI.getDesc(); - if (PredCost && (MCID.isCall() || MCID.hasImplicitDefOfPhysReg(ARM::CPSR))) { + if (PredCost && (MCID.isCall() || (MCID.hasImplicitDefOfPhysReg(ARM::CPSR) && + !Subtarget.cheapPredicableCPSRDef()))) { // When predicated, CPSR is an additional source operand for CPSR updating // instructions, this apparently increases their latencies. *PredCost = 1; diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h index dd7fe871345a..c52e572786d4 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -159,6 +159,24 @@ public: bool isPredicable(const MachineInstr &MI) const override; + // CPSR defined in instruction + static bool isCPSRDefined(const MachineInstr &MI); + bool isAddrMode3OpImm(const MachineInstr &MI, unsigned Op) const; + bool isAddrMode3OpMinusReg(const MachineInstr &MI, unsigned Op) const; + + // Load, scaled register offset + bool isLdstScaledReg(const MachineInstr &MI, unsigned Op) const; + // Load, scaled register offset, not plus LSL2 + bool isLdstScaledRegNotPlusLsl2(const MachineInstr &MI, unsigned Op) const; + // Minus reg for ldstso addr mode + bool isLdstSoMinusReg(const MachineInstr &MI, unsigned Op) const; + // Scaled register offset in address mode 2 + bool isAm2ScaledReg(const MachineInstr &MI, unsigned Op) const; + // Load multiple, base reg in list + bool isLDMBaseRegInList(const MachineInstr &MI) const; + // get LDM variable defs size + unsigned getLDMVariableDefsSize(const MachineInstr &MI) const; + /// GetInstSize - Returns the size of the specified MachineInstr. /// unsigned getInstSizeInBytes(const MachineInstr &MI) const override; diff --git a/contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp index 31a2f499a9a7..a33d025d114e 100644 --- a/contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp @@ -34,7 +34,7 @@ ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI) static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI, Type *T) { - if (T->isArrayTy()) + if (T->isArrayTy() || T->isStructTy()) return true; EVT VT = TLI.getValueType(DL, T, true); @@ -167,8 +167,11 @@ void ARMCallLowering::splitToValueTypes( if (SplitVTs.size() == 1) { // Even if there is no splitting to do, we still want to replace the // original type (e.g. pointer type -> integer). - SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx), - OrigArg.Flags, OrigArg.IsFixed); + auto Flags = OrigArg.Flags; + unsigned OriginalAlignment = DL.getABITypeAlignment(OrigArg.Ty); + Flags.setOrigAlign(OriginalAlignment); + SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx), Flags, + OrigArg.IsFixed); return; } @@ -177,6 +180,10 @@ void ARMCallLowering::splitToValueTypes( EVT SplitVT = SplitVTs[i]; Type *SplitTy = SplitVT.getTypeForEVT(Ctx); auto Flags = OrigArg.Flags; + + unsigned OriginalAlignment = DL.getABITypeAlignment(SplitTy); + Flags.setOrigAlign(OriginalAlignment); + bool NeedsConsecutiveRegisters = TLI.functionArgumentNeedsConsecutiveRegisters( SplitTy, F->getCallingConv(), F->isVarArg()); @@ -185,6 +192,7 @@ void ARMCallLowering::splitToValueTypes( if (i == e - 1) Flags.setInConsecutiveRegsLast(); } + SplitArgs.push_back( ArgInfo{MRI.createGenericVirtualRegister(getLLTForType(*SplitTy, DL)), SplitTy, Flags, OrigArg.IsFixed}); diff --git a/contrib/llvm/lib/Target/ARM/ARMSchedule.td b/contrib/llvm/lib/Target/ARM/ARMSchedule.td index ec5b97cba8cd..1c7902520f2d 100644 --- a/contrib/llvm/lib/Target/ARM/ARMSchedule.td +++ b/contrib/llvm/lib/Target/ARM/ARMSchedule.td @@ -147,6 +147,9 @@ def : PredicateProlog<[{ const ARMBaseInstrInfo *TII = static_cast(SchedModel->getInstrInfo()); (void)TII; + const ARMSubtarget *STI = + static_cast(SchedModel->getSubtargetInfo()); + (void)STI; }]>; def IsPredicatedPred : SchedPredicate<[{TII->isPredicated(*MI)}]>; @@ -420,3 +423,4 @@ include "ARMScheduleA8.td" include "ARMScheduleA9.td" include "ARMScheduleSwift.td" include "ARMScheduleR52.td" +include "ARMScheduleA57.td" diff --git a/contrib/llvm/lib/Target/ARM/ARMScheduleA57.td b/contrib/llvm/lib/Target/ARM/ARMScheduleA57.td new file mode 100644 index 000000000000..525079d12d51 --- /dev/null +++ b/contrib/llvm/lib/Target/ARM/ARMScheduleA57.td @@ -0,0 +1,1471 @@ +//=- ARMScheduleA57.td - ARM Cortex-A57 Scheduling Defs -----*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the machine model for ARM Cortex-A57 to support +// instruction scheduling and other instruction cost heuristics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// *** Common description and scheduling model parameters taken from AArch64 *** +// The Cortex-A57 is a traditional superscalar microprocessor with a +// conservative 3-wide in-order stage for decode and dispatch. Combined with the +// much wider out-of-order issue stage, this produced a need to carefully +// schedule micro-ops so that all three decoded each cycle are successfully +// issued as the reservation station(s) simply don't stay occupied for long. +// Therefore, IssueWidth is set to the narrower of the two at three, while still +// modeling the machine as out-of-order. + +def IsCPSRDefinedPred : SchedPredicate<[{TII->isCPSRDefined(*MI)}]>; +def IsCPSRDefinedAndPredicatedPred : + SchedPredicate<[{TII->isCPSRDefined(*MI) && TII->isPredicated(*MI)}]>; + +// Cortex A57 rev. r1p0 or later (false = r0px) +def IsR1P0AndLaterPred : SchedPredicate<[{false}]>; + +// If Addrmode3 contains register offset (not immediate) +def IsLdrAm3RegOffPred : + SchedPredicate<[{!TII->isAddrMode3OpImm(*MI, 1)}]>; +// The same predicate with operand offset 2 and 3: +def IsLdrAm3RegOffPredX2 : + SchedPredicate<[{!TII->isAddrMode3OpImm(*MI, 2)}]>; +def IsLdrAm3RegOffPredX3 : + SchedPredicate<[{!TII->isAddrMode3OpImm(*MI, 3)}]>; + +// If Addrmode3 contains "minus register" +def IsLdrAm3NegRegOffPred : + SchedPredicate<[{TII->isAddrMode3OpMinusReg(*MI, 1)}]>; +// The same predicate with operand offset 2 and 3: +def IsLdrAm3NegRegOffPredX2 : + SchedPredicate<[{TII->isAddrMode3OpMinusReg(*MI, 2)}]>; +def IsLdrAm3NegRegOffPredX3 : + SchedPredicate<[{TII->isAddrMode3OpMinusReg(*MI, 3)}]>; + +// Load, scaled register offset, not plus LSL2 +def IsLdstsoScaledNotOptimalPredX0 : + SchedPredicate<[{TII->isLdstScaledRegNotPlusLsl2(*MI, 0)}]>; +def IsLdstsoScaledNotOptimalPred : + SchedPredicate<[{TII->isLdstScaledRegNotPlusLsl2(*MI, 1)}]>; +def IsLdstsoScaledNotOptimalPredX2 : + SchedPredicate<[{TII->isLdstScaledRegNotPlusLsl2(*MI, 2)}]>; + +// Load, scaled register offset +def IsLdstsoScaledPred : + SchedPredicate<[{TII->isLdstScaledReg(*MI, 1)}]>; +def IsLdstsoScaledPredX2 : + SchedPredicate<[{TII->isLdstScaledReg(*MI, 2)}]>; + +def IsLdstsoMinusRegPredX0 : + SchedPredicate<[{TII->isLdstSoMinusReg(*MI, 0)}]>; +def IsLdstsoMinusRegPred : + SchedPredicate<[{TII->isLdstSoMinusReg(*MI, 1)}]>; +def IsLdstsoMinusRegPredX2 : + SchedPredicate<[{TII->isLdstSoMinusReg(*MI, 2)}]>; + +// Load, scaled register offset +def IsLdrAm2ScaledPred : + SchedPredicate<[{TII->isAm2ScaledReg(*MI, 1)}]>; + +// LDM, base reg in list +def IsLdmBaseRegInList : + SchedPredicate<[{TII->isLDMBaseRegInList(*MI)}]>; + +class A57WriteLMOpsListType writes> { + list Writes = writes; + SchedMachineModel SchedModel = ?; +} + +// *** Common description and scheduling model parameters taken from AArch64 *** +// (AArch64SchedA57.td) +def CortexA57Model : SchedMachineModel { + let IssueWidth = 3; // 3-way decode and dispatch + let MicroOpBufferSize = 128; // 128 micro-op re-order buffer + let LoadLatency = 4; // Optimistic load latency + let MispredictPenalty = 16; // Fetch + Decode/Rename/Dispatch + Branch + + // Enable partial & runtime unrolling. + let LoopMicroOpBufferSize = 16; + let CompleteModel = 1; +} + +//===----------------------------------------------------------------------===// +// Define each kind of processor resource and number available on Cortex-A57. +// Cortex A-57 has 8 pipelines that each has its own 8-entry queue where +// micro-ops wait for their operands and then issue out-of-order. + +def A57UnitB : ProcResource<1>; // Type B micro-ops +def A57UnitI : ProcResource<2>; // Type I micro-ops +def A57UnitM : ProcResource<1>; // Type M micro-ops +def A57UnitL : ProcResource<1>; // Type L micro-ops +def A57UnitS : ProcResource<1>; // Type S micro-ops + +def A57UnitX : ProcResource<1>; // Type X micro-ops (F1) +def A57UnitW : ProcResource<1>; // Type W micro-ops (F0) + +let SchedModel = CortexA57Model in { + def A57UnitV : ProcResGroup<[A57UnitX, A57UnitW]>; // Type V micro-ops +} + +let SchedModel = CortexA57Model in { + +//===----------------------------------------------------------------------===// +// Define customized scheduler read/write types specific to the Cortex-A57. + +include "ARMScheduleA57WriteRes.td" + +// To have "CompleteModel = 1", support of pseudos and special instructions +def : InstRW<[WriteNoop], (instregex "(t)?BKPT$", "(t2)?CDP(2)?$", + "(t2)?CLREX$", "CONSTPOOL_ENTRY$", "COPY_STRUCT_BYVAL_I32$", + "(t2)?CPS[123]p$", "(t2)?DBG$", "(t2)?DMB$", "(t2)?DSB$", "ERET$", + "(t2|t)?HINT$", "(t)?HLT$", "(t2)?HVC$", "(t2)?ISB$", "ITasm$", + "(t2)?RFE(DA|DB|IA|IB)", "(t)?SETEND", "(t2)?SETPAN", "(t2)?SMC", "SPACE", + "(t2)?SRS(DA|DB|IA|IB)", "SWP(B)?", "t?TRAP", "UDF$", "t2DCPS", "t2SG", + "t2TT", "tCPS", "CMP_SWAP", "t?SVC", "t2IT", "CompilerBarrier")>; + +def : InstRW<[WriteNoop], (instregex "VMRS", "VMSR", "FMSTAT")>; + +// Specific memory instrs +def : InstRW<[WriteNoop, WriteNoop], (instregex "(t2)?LDA", "(t2)?LDC", "(t2)?STC", + "(t2)?STL", "(t2)?LDREX", "(t2)?STREX", "MEMCPY")>; + +// coprocessor moves +def : InstRW<[WriteNoop, WriteNoop], (instregex + "(t2)?MCR(2|R|R2)?$", "(t2)?MRC(2)?$", + "(t2)?MRRC(2)?$", "(t2)?MRS(banked|sys|_AR|_M|sys_AR)?$", + "(t2)?MSR(banked|i|_AR|_M)?$")>; + +// Deprecated instructions +def : InstRW<[WriteNoop], (instregex "FLDM", "FSTM")>; + +// Pseudos +def : InstRW<[WriteNoop], (instregex "(t2)?ABS$", + "(t)?ADJCALLSTACKDOWN$", "(t)?ADJCALLSTACKUP$", "(t2|t)?Int_eh_sjlj", + "tLDRpci_pic", "t2SUBS_PC_LR", + "JUMPTABLE", "tInt_WIN_eh_sjlj_longjmp", + "VLD(1|2)LN(d|q)(WB_fixed_|WB_register_)?Asm", + "VLD(3|4)(DUP|LN)?(d|q)(WB_fixed_|WB_register_)?Asm", + "VST(1|2)LN(d|q)(WB_fixed_|WB_register_)?Asm", + "VST(3|4)(DUP|LN)?(d|q)(WB_fixed_|WB_register_)?Asm", + "WIN__CHKSTK", "WIN__DBZCHK")>; + +// Miscellaneous +// ----------------------------------------------------------------------------- + +def : InstRW<[A57Write_1cyc_1I], (instrs COPY)>; + +// --- 3.2 Branch Instructions --- +// B, BX, BL, BLX (imm, reg != LR, reg == LR), CBZ, CBNZ + +def : InstRW<[A57Write_1cyc_1B], (instregex "(t2|t)?B$", "t?BX", "(t2|t)?Bcc$", + "t?TAILJMP(d|r)", "TCRETURN(d|r)i", "tBfar", "tCBN?Z")>; +def : InstRW<[A57Write_1cyc_1B_1I], + (instregex "t?BL$", "BL_pred$", "t?BLXi", "t?TPsoft")>; +def : InstRW<[A57Write_2cyc_1B_1I], (instregex "BLX", "tBLX(NS)?r")>; +// Pseudos +def : InstRW<[A57Write_2cyc_1B_1I], (instregex "BCCi64", "BCCZi64")>; +def : InstRW<[A57Write_3cyc_1B_1I], (instregex "BR_JTadd", "t?BR_JTr", + "t2BR_JT", "t2BXJ", "(t2)?TB(B|H)(_JT)?$", "tBRIND")>; +def : InstRW<[A57Write_6cyc_1B_1L], (instregex "BR_JTm")>; + +// --- 3.3 Arithmetic and Logical Instructions --- +// ADD{S}, ADC{S}, ADR, AND{S}, BIC{S}, CMN, CMP, EOR{S}, ORN{S}, ORR{S}, +// RSB{S}, RSC{S}, SUB{S}, SBC{S}, TEQ, TST + +def : InstRW<[A57Write_1cyc_1I], (instregex "tADDframe")>; + +// shift by register, conditional or unconditional +// TODO: according to the doc, conditional uses I0/I1, unconditional uses M +// Why more complex instruction uses more simple pipeline? +// May be an error in doc. +def A57WriteALUsi : SchedWriteVariant<[ + // lsl #2, lsl #1, or lsr #1. + SchedVar, + SchedVar +]>; +def A57WriteALUsr : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def A57WriteALUSsr : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def A57ReadALUsr : SchedReadVariant<[ + SchedVar, + SchedVar +]>; +def : SchedAlias; +def : SchedAlias; +def : SchedAlias; +def : SchedAlias; + +def A57WriteCMPsr : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : SchedAlias; +def : SchedAlias; +def : SchedAlias; + +// --- 3.4 Move and Shift Instructions --- +// Move, basic +// MOV{S}, MOVW, MVN{S} +def : InstRW<[A57Write_1cyc_1I], (instregex "MOV(r|i|i16|r_TC)", + "(t2)?MVN(CC)?(r|i)", "BMOVPCB_CALL", "BMOVPCRX_CALL", + "MOVCC(r|i|i16|i32imm)", "tMOV", "tMVN")>; + +// Move, shift by immed, setflags/no setflags +// (ASR, LSL, LSR, ROR, RRX)=MOVsi, MVN +// setflags = isCPSRDefined +def A57WriteMOVsi : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteMOVsi], (instregex "MOV(CC)?si", "MVNsi", + "ASRi", "(t2|t)ASRri", "LSRi", "(t2|t)LSRri", "LSLi", "(t2|t)LSLri", "RORi", + "(t2|t)RORri", "(t2)?RRX", "t2MOV", "tROR")>; + +// shift by register, conditional or unconditional, setflags/no setflags +def A57WriteMOVsr : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteMOVsr], (instregex "MOV(CC)?sr", "MVNsr", "t2MVNs", + "ASRr", "(t2|t)ASRrr", "LSRr", "(t2|t)LSRrr", "LSLr", "(t2|t)?LSLrr", "RORr", + "(t2|t)RORrr")>; + +// Move, top +// MOVT - A57Write_2cyc_1M for r0px, A57Write_1cyc_1I for r1p0 and later +def A57WriteMOVT : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteMOVT], (instregex "MOVTi16")>; + +def A57WriteI2pc : + WriteSequence<[A57Write_1cyc_1I, A57Write_1cyc_1I, A57Write_1cyc_1I]>; +def A57WriteI2ld : + WriteSequence<[A57Write_1cyc_1I, A57Write_1cyc_1I, A57Write_4cyc_1L]>; +def : InstRW< [A57WriteI2pc], (instregex "MOV_ga_pcrel")>; +def : InstRW< [A57WriteI2ld], (instregex "MOV_ga_pcrel_ldr")>; + +// +2cyc for branch forms +def : InstRW<[A57Write_3cyc_1I], (instregex "MOVPC(LR|RX)")>; + +// --- 3.5 Divide and Multiply Instructions --- +// Divide: SDIV, UDIV +// latency from documentration: 4 ­‐ 20, maximum taken +def : SchedAlias; +// Multiply: tMul not bound to common WriteRes types +def : InstRW<[A57Write_3cyc_1M], (instregex "tMUL")>; +def : SchedAlias; +def : SchedAlias; +def : ReadAdvance; + +// Multiply accumulate: MLA, MLS, SMLABB, SMLABT, SMLATB, SMLATT, SMLAWB, +// SMLAWT, SMLAD{X}, SMLSD{X}, SMMLA{R}, SMMLS{R} +// Multiply-accumulate pipelines support late-forwarding of accumulate operands +// from similar μops, allowing a typical sequence of multiply-accumulate μops +// to issue one every 1 cycle (sched advance = 2). +def A57WriteMLA : SchedWriteRes<[A57UnitM]> { let Latency = 3; } +def A57WriteMLAL : SchedWriteRes<[A57UnitM]> { let Latency = 4; } +def A57ReadMLA : SchedReadAdvance<2, [A57WriteMLA, A57WriteMLAL]>; + +def : SchedAlias; +def : SchedAlias; +def : SchedAlias; + +def : SchedAlias; +def : SchedAlias; + +// Multiply long: SMULL, UMULL +def : SchedAlias; +def : SchedAlias; + +// --- 3.6 Saturating and Parallel Arithmetic Instructions --- +// Parallel arith +// SADD16, SADD8, SSUB16, SSUB8, UADD16, UADD8, USUB16, USUB8 +// Conditional GE-setting instructions require three extra μops +// and two additional cycles to conditionally update the GE field. +def A57WriteParArith : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW< [A57WriteParArith], (instregex + "(t2)?SADD(16|8)", "(t2)?SSUB(16|8)", + "(t2)?UADD(16|8)", "(t2)?USUB(16|8)")>; + +// Parallel arith with exchange: SASX, SSAX, UASX, USAX +def A57WriteParArithExch : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteParArithExch], + (instregex "(t2)?SASX", "(t2)?SSAX", "(t2)?UASX", "(t2)?USAX")>; + +// Parallel halving arith +// SHADD16, SHADD8, SHSUB16, SHSUB8, UHADD16, UHADD8, UHSUB16, UHSUB8 +def : InstRW<[A57Write_2cyc_1M], (instregex + "(t2)?SHADD(16|8)", "(t2)?SHSUB(16|8)", + "(t2)?UHADD(16|8)", "(t2)?UHSUB(16|8)")>; + +// Parallel halving arith with exchange +// SHASX, SHSAX, UHASX, UHSAX +def : InstRW<[A57Write_3cyc_1I_1M], (instregex "(t2)?SHASX", "(t2)?SHSAX", + "(t2)?UHASX", "(t2)?UHSAX")>; + +// Parallel saturating arith +// QADD16, QADD8, QSUB16, QSUB8, UQADD16, UQADD8, UQSUB16, UQSUB8 +def : InstRW<[A57Write_2cyc_1M], (instregex "QADD(16|8)", "QSUB(16|8)", + "UQADD(16|8)", "UQSUB(16|8)", "t2(U?)QADD", "t2(U?)QSUB")>; + +// Parallel saturating arith with exchange +// QASX, QSAX, UQASX, UQSAX +def : InstRW<[A57Write_3cyc_1I_1M], (instregex "(t2)?QASX", "(t2)?QSAX", + "(t2)?UQASX", "(t2)?UQSAX")>; + +// Saturate: SSAT, SSAT16, USAT, USAT16 +def : InstRW<[A57Write_2cyc_1M], + (instregex "(t2)?SSAT(16)?", "(t2)?USAT(16)?")>; + +// Saturating arith: QADD, QSUB +def : InstRW<[A57Write_2cyc_1M], (instregex "QADD$", "QSUB$")>; + +// Saturating doubling arith: QDADD, QDSUB +def : InstRW<[A57Write_3cyc_1I_1M], (instregex "(t2)?QDADD", "(t2)?QDSUB")>; + +// --- 3.7 Miscellaneous Data-Processing Instructions --- +// Bit field extract: SBFX, UBFX +def : InstRW<[A57Write_1cyc_1I], (instregex "(t2)?SBFX", "(t2)?UBFX")>; + +// Bit field insert/clear: BFI, BFC +def : InstRW<[A57Write_2cyc_1M], (instregex "(t2)?BFI", "(t2)?BFC")>; + +// Select bytes, conditional/unconditional +def A57WriteSEL : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteSEL], (instregex "(t2)?SEL")>; + +// Sign/zero extend, normal: SXTB, SXTH, UXTB, UXTH +def : InstRW<[A57Write_1cyc_1I], + (instregex "(t2|t)?SXT(B|H)$", "(t2|t)?UXT(B|H)$")>; + +// Sign/zero extend and add, normal: SXTAB, SXTAH, UXTAB, UXTAH +def : InstRW<[A57Write_2cyc_1M], + (instregex "(t2)?SXTA(B|H)$", "(t2)?UXTA(B|H)$")>; + +// Sign/zero extend and add, parallel: SXTAB16, UXTAB16 +def : InstRW<[A57Write_4cyc_1M], (instregex "(t2)?SXTAB16", "(t2)?UXTAB16")>; + +// Sum of absolute differences: USAD8, USADA8 +def : InstRW<[A57Write_3cyc_1M], (instregex "(t2)?USAD8", "(t2)?USADA8")>; + +// --- 3.8 Load Instructions --- + +// Load, immed offset +// LDR and LDRB have LDRi12 and LDRBi12 forms for immediate +def : InstRW<[A57Write_4cyc_1L], (instregex "LDRi12", "LDRBi12", + "LDRcp", "(t2|t)?LDRConstPool", "LDRLIT_ga_(pcrel|abs)", + "PICLDR", "tLDR")>; + +def : InstRW<[A57Write_4cyc_1L], + (instregex "t2LDRS?(B|H)?(pcrel|T|i8|i12|pci|pci_pic|s)?$")>; + +// For "Load, register offset, minus" we need +1cyc, +1I +def A57WriteLdrAm3 : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteLdrAm3], (instregex "LDR(H|SH|SB)$")>; +def A57WriteLdrAm3X2 : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteLdrAm3X2, A57WriteLdrAm3X2], (instregex "LDRD$")>; +def : InstRW<[A57Write_4cyc_1L, A57Write_4cyc_1L], (instregex "t2LDRDi8")>; + +def A57WriteLdrAmLDSTSO : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteLdrAmLDSTSO], (instregex "LDRrs", "LDRBrs")>; + +def A57WrBackOne : SchedWriteRes<[]> { + let Latency = 1; + let NumMicroOps = 0; +} +def A57WrBackTwo : SchedWriteRes<[]> { + let Latency = 2; + let NumMicroOps = 0; +} +def A57WrBackThree : SchedWriteRes<[]> { + let Latency = 3; + let NumMicroOps = 0; +} + +// --- LDR pre-indexed --- +// Load, immed pre-indexed (4 cyc for load result, 1 cyc for Base update) +def : InstRW<[A57Write_4cyc_1L_1I, A57WrBackOne], (instregex "LDR_PRE_IMM", + "LDRB_PRE_IMM", "t2LDRB_PRE")>; + +// Load, register pre-indexed (4 cyc for load result, 2 cyc for Base update) +// (5 cyc load result for not-lsl2 scaled) +def A57WriteLdrAmLDSTSOPre : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteLdrAmLDSTSOPre, A57WrBackTwo], + (instregex "LDR_PRE_REG", "LDRB_PRE_REG")>; + +def A57WriteLdrAm3PreWrBack : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57Write_4cyc_1L, A57WriteLdrAm3PreWrBack], + (instregex "LDR(H|SH|SB)_PRE")>; +def : InstRW<[A57Write_4cyc_1L, A57WrBackOne], + (instregex "t2LDR(H|SH|SB)?_PRE")>; + +// LDRD pre-indexed: 5(2) cyc for reg, 4(1) cyc for imm. +def A57WriteLdrDAm3Pre : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def A57WriteLdrDAm3PreWrBack : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteLdrDAm3Pre, A57WriteLdrDAm3Pre, A57WriteLdrDAm3PreWrBack], + (instregex "LDRD_PRE")>; +def : InstRW<[A57Write_4cyc_1L_1I, A57Write_4cyc_1L_1I, A57WrBackOne], + (instregex "t2LDRD_PRE")>; + +// --- LDR post-indexed --- +def : InstRW<[A57Write_4cyc_1L_1I, A57WrBackOne], (instregex "LDR(T?)_POST_IMM", + "LDRB(T?)_POST_IMM", "LDR(SB|H|SH)Ti", "t2LDRB_POST")>; + +def A57WriteLdrAm3PostWrBack : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57Write_4cyc_1L_1I, A57WriteLdrAm3PostWrBack], + (instregex "LDR(H|SH|SB)_POST")>; +def : InstRW<[A57Write_4cyc_1L, A57WrBackOne], + (instregex "t2LDR(H|SH|SB)?_POST")>; + +def : InstRW<[A57Write_4cyc_1L_1I, A57WrBackTwo], (instregex "LDR_POST_REG", + "LDRB_POST_REG", "LDR(B?)T_POST$")>; + +def A57WriteLdrTRegPost : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def A57WriteLdrTRegPostWrBack : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +// 4(3) "I0/I1,L,M" for scaled register, otherwise 4(2) "I0/I1,L" +def : InstRW<[A57WriteLdrTRegPost, A57WriteLdrTRegPostWrBack], + (instregex "LDRT_POST_REG", "LDRBT_POST_REG")>; + +def : InstRW<[A57Write_4cyc_1L_1I, A57WrBackTwo], (instregex "LDR(SB|H|SH)Tr")>; + +def A57WriteLdrAm3PostWrBackX3 : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +// LDRD post-indexed: 4(2) cyc for reg, 4(1) cyc for imm. +def : InstRW<[A57Write_4cyc_1L_1I, A57Write_4cyc_1L_1I, + A57WriteLdrAm3PostWrBackX3], (instregex "LDRD_POST")>; +def : InstRW<[A57Write_4cyc_1L_1I, A57Write_4cyc_1L_1I, A57WrBackOne], + (instregex "t2LDRD_POST")>; + +// --- Preload instructions --- +// Preload, immed offset +def : InstRW<[A57Write_4cyc_1L], (instregex "(t2)?PLDi12", "(t2)?PLDWi12", + "t2PLDW?(i8|pci|s)", "(t2)?PLI")>; + +// Preload, register offset, +// 5cyc "I0/I1,L" for minus reg or scaled not plus lsl2 +// otherwise 4cyc "L" +def A57WritePLD : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar +]>; +def : InstRW<[A57WritePLD], (instregex "PLDrs", "PLDWrs")>; + +// --- Load multiple instructions --- +foreach NumAddr = 1-8 in { + def A57LMAddrPred#NumAddr : + SchedPredicate<"(TII->getLDMVariableDefsSize(*MI)+1)/2 == "#NumAddr>; +} + +def A57LDMOpsListNoregin : A57WriteLMOpsListType< + [A57Write_3cyc_1L, A57Write_3cyc_1L, + A57Write_4cyc_1L, A57Write_4cyc_1L, + A57Write_5cyc_1L, A57Write_5cyc_1L, + A57Write_6cyc_1L, A57Write_6cyc_1L, + A57Write_7cyc_1L, A57Write_7cyc_1L, + A57Write_8cyc_1L, A57Write_8cyc_1L, + A57Write_9cyc_1L, A57Write_9cyc_1L, + A57Write_10cyc_1L, A57Write_10cyc_1L]>; +def A57WriteLDMnoreginlist : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]> { let Variadic=1; } + +def A57LDMOpsListRegin : A57WriteLMOpsListType< + [A57Write_4cyc_1L_1I, A57Write_4cyc_1L_1I, + A57Write_5cyc_1L_1I, A57Write_5cyc_1L_1I, + A57Write_6cyc_1L_1I, A57Write_6cyc_1L_1I, + A57Write_7cyc_1L_1I, A57Write_7cyc_1L_1I, + A57Write_8cyc_1L_1I, A57Write_8cyc_1L_1I, + A57Write_9cyc_1L_1I, A57Write_9cyc_1L_1I, + A57Write_10cyc_1L_1I, A57Write_10cyc_1L_1I, + A57Write_11cyc_1L_1I, A57Write_11cyc_1L_1I]>; +def A57WriteLDMreginlist : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]> { let Variadic=1; } + +def A57LDMOpsList_Upd : A57WriteLMOpsListType< + [A57WrBackOne, + A57Write_3cyc_1L_1I, A57Write_3cyc_1L_1I, + A57Write_4cyc_1L_1I, A57Write_4cyc_1L_1I, + A57Write_5cyc_1L_1I, A57Write_5cyc_1L_1I, + A57Write_6cyc_1L_1I, A57Write_6cyc_1L_1I, + A57Write_7cyc_1L_1I, A57Write_7cyc_1L_1I, + A57Write_8cyc_1L_1I, A57Write_8cyc_1L_1I, + A57Write_9cyc_1L_1I, A57Write_9cyc_1L_1I, + A57Write_10cyc_1L_1I, A57Write_10cyc_1L_1I]>; +def A57WriteLDM_Upd : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]> { let Variadic=1; } + +def A57WriteLDM : SchedWriteVariant<[ + SchedVar, + SchedVar +]> { let Variadic=1; } + +def : InstRW<[A57WriteLDM], (instregex "(t|t2|sys)?LDM(IA|DA|DB|IB)$")>; + +// TODO: no writeback latency defined in documentation (implemented as 1 cyc) +def : InstRW<[A57WriteLDM_Upd], + (instregex "(t|t2|sys)?LDM(IA_UPD|DA_UPD|DB_UPD|IB_UPD|IA_RET)", "tPOP")>; + +// --- 3.9 Store Instructions --- + +// Store, immed offset +def : InstRW<[A57Write_1cyc_1S], (instregex "STRi12", "STRBi12", "PICSTR", + "t2STR(B?)(T|i12|i8|s)", "t2STRDi8", "t2STRH(i12|i8|s)", "tSTR")>; + +// Store, register offset +// For minus or for not plus lsl2 scaled we need 3cyc "I0/I1, S", +// otherwise 1cyc S. +def A57WriteStrAmLDSTSO : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteStrAmLDSTSO], (instregex "STRrs", "STRBrs")>; + +// STRH,STRD: 3cyc "I0/I1, S" for minus reg, 1cyc S for imm or for plus reg. +def A57WriteStrAm3 : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteStrAm3], (instregex "STRH$")>; +def A57WriteStrAm3X2 : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteStrAm3X2], (instregex "STRD$")>; + +// Store, immed pre-indexed (1cyc "S, I0/I1", 1cyc writeback) +def : InstRW<[A57WrBackOne, A57Write_1cyc_1S_1I], (instregex "STR_PRE_IMM", + "STRB_PRE_IMM", "STR(B)?(r|i)_preidx", "(t2)?STRH_(preidx|PRE)", + "t2STR(B?)_(PRE|preidx)", "t2STRD_PRE")>; + +// Store, register pre-indexed: +// 1(1) "S, I0/I1" for plus reg +// 3(2) "I0/I1, S" for minus reg +// 1(2) "S, M" for scaled plus lsl2 +// 3(2) "I0/I1, S" for other scaled +def A57WriteStrAmLDSTSOPre : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar +]>; +def A57WriteStrAmLDSTSOPreWrBack : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteStrAmLDSTSOPreWrBack, A57WriteStrAmLDSTSOPre], + (instregex "STR_PRE_REG", "STRB_PRE_REG")>; + +// pre-indexed STRH/STRD (STRH_PRE, STRD_PRE) +// 1(1) "S, I0/I1" for imm or reg plus +// 3(2) "I0/I1, S" for reg minus +def A57WriteStrAm3PreX2 : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def A57WriteStrAm3PreWrBackX2 : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteStrAm3PreWrBackX2, A57WriteStrAm3PreX2], + (instregex "STRH_PRE")>; + +def A57WriteStrAm3PreX3 : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def A57WriteStrAm3PreWrBackX3 : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteStrAm3PreWrBackX3, A57WriteStrAm3PreX3], + (instregex "STRD_PRE")>; + +def : InstRW<[A57WrBackOne, A57Write_1cyc_1S_1I], (instregex "STR(T?)_POST_IMM", + "STRB(T?)_POST_IMM", "t2STR(B?)_POST")>; + +// 1(2) "S, M" for STR/STRB register post-indexed (both scaled or not) +def : InstRW<[A57WrBackTwo, A57Write_1cyc_1S_1M], (instregex "STR(T?)_POST_REG", + "STRB(T?)_POST_REG", "STR(B?)T_POST$")>; + +// post-indexed STRH/STRD(STRH_POST, STRD_POST), STRHTi, STRHTr +// 1(1) "S, I0/I1" both for reg or imm +def : InstRW<[A57WrBackOne, A57Write_1cyc_1S_1I], + (instregex "(t2)?STR(H|D)_POST", "STRHT(i|r)", "t2STRHT")>; + +// --- Store multiple instructions --- +// TODO: no writeback latency defined in documentation +def A57WriteSTM : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]>; +def A57WriteSTM_Upd : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]>; + +def : InstRW<[A57WriteSTM], (instregex "(t2|sys|t)?STM(IA|DA|DB|IB)$")>; +def : InstRW<[A57WrBackOne, A57WriteSTM_Upd], + (instregex "(t2|sys|t)?STM(IA_UPD|DA_UPD|DB_UPD|IB_UPD)", "tPUSH")>; + +// --- 3.10 FP Data Processing Instructions --- +def : SchedAlias; +def : SchedAlias; + +def : InstRW<[A57Write_3cyc_1V], (instregex "VABS(S|D|H)")>; + +// fp compare - 3cyc F1 for unconditional, 6cyc "F0/F1, F1" for conditional +def A57WriteVcmp : SchedWriteVariant<[ + SchedVar, + SchedVar +]>; +def : InstRW<[A57WriteVcmp], + (instregex "VCMP(D|S|H|ZD|ZS|ZH)$", "VCMPE(D|S|H|ZD|ZS|ZH)")>; + +// fp convert +def : InstRW<[A57Write_5cyc_1V], (instregex + "VCVT(A|N|P|M)(SH|UH|SS|US|SD|UD)", "VCVT(BDH|THD|TDH)")>; + +def : SchedAlias; + +// FP round to integral +def : InstRW<[A57Write_5cyc_1V], (instregex "VRINT(A|N|P|M|Z|R|X)(H|S|D)$")>; + +// FP divide, FP square root +def : SchedAlias; +def : SchedAlias; +def : SchedAlias; +def : SchedAlias; + +// FP max/min +def : InstRW<[A57Write_5cyc_1V], (instregex "VMAX", "VMIN")>; + +// FP multiply-accumulate pipelines support late forwarding of the result +// from FP multiply μops to the accumulate operands of an +// FP multiply-accumulate μop. The latter can potentially be issued 1 cycle +// after the FP multiply μop has been issued +// FP multiply, FZ +def A57WriteVMUL : SchedWriteRes<[A57UnitV]> { let Latency = 5; } + +def : SchedAlias; +def : SchedAlias; +def : ReadAdvance; + +// FP multiply accumulate, FZ: 9cyc "F0/F1" or 4 cyc for sequenced accumulate +// VFMA, VFMS, VFNMA, VFNMS, VMLA, VMLS, VNMLA, VNMLS +def A57WriteVFMA : SchedWriteRes<[A57UnitV]> { let Latency = 9; } + +// VFMA takes 9 cyc for common case and 4 cyc for VFMA->VFMA chain (5 read adv.) +// VMUL takes 5 cyc for common case and 1 cyc for VMUL->VFMA chain (4 read adv.) +// Currently, there is no way to define different read advances for VFMA operand +// from VFMA or from VMUL, so there will be 5 read advance. +// Zero latency (instead of one) for VMUL->VFMA shouldn't break something. +// The same situation with ASIMD VMUL/VFMA instructions +// def A57ReadVFMA : SchedRead; +// def : ReadAdvance; +// def : ReadAdvance; +def A57ReadVFMA5 : SchedReadAdvance<5, [A57WriteVFMA, A57WriteVMUL]>; + +def : SchedAlias; +def : SchedAlias; +def : SchedAlias; + +def : InstRW<[A57Write_3cyc_1V], (instregex "VNEG")>; +def : InstRW<[A57Write_3cyc_1V], (instregex "VSEL")>; + +// --- 3.11 FP Miscellaneous Instructions --- +// VMOV: 3cyc "F0/F1" for imm/reg +def : InstRW<[A57Write_3cyc_1V], (instregex "FCONST(D|S|H)")>; +def : InstRW<[A57Write_3cyc_1V], (instregex "VMOV(D|S|H)(cc)?$")>; + +// 5cyc L for FP transfer, vfp to core reg, +// 5cyc L for FP transfer, core reg to vfp +def : SchedAlias; +// VMOVRRS/VMOVRRD in common code declared with one WriteFPMOV (instead of 2). +def : InstRW<[A57Write_5cyc_1L, A57Write_5cyc_1L], (instregex "VMOV(RRS|RRD)")>; + +// 8cyc "L,F0/F1" for FP transfer, core reg to upper or lower half of vfp D-reg +def : InstRW<[A57Write_8cyc_1L_1I], (instregex "VMOVDRR")>; + +// --- 3.12 FP Load Instructions --- +def : InstRW<[A57Write_5cyc_1L], (instregex "VLDR(D|S|H)")>; + +def : InstRW<[A57Write_5cyc_1L], (instregex "VLDMQIA$")>; + +// FP load multiple (VLDM) + +def A57VLDMOpsListUncond : A57WriteLMOpsListType< + [A57Write_5cyc_1L, A57Write_5cyc_1L, + A57Write_6cyc_1L, A57Write_6cyc_1L, + A57Write_7cyc_1L, A57Write_7cyc_1L, + A57Write_8cyc_1L, A57Write_8cyc_1L, + A57Write_9cyc_1L, A57Write_9cyc_1L, + A57Write_10cyc_1L, A57Write_10cyc_1L, + A57Write_11cyc_1L, A57Write_11cyc_1L, + A57Write_12cyc_1L, A57Write_12cyc_1L]>; +def A57WriteVLDMuncond : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]> { let Variadic=1; } + +def A57VLDMOpsListCond : A57WriteLMOpsListType< + [A57Write_5cyc_1L, A57Write_6cyc_1L, + A57Write_7cyc_1L, A57Write_8cyc_1L, + A57Write_9cyc_1L, A57Write_10cyc_1L, + A57Write_11cyc_1L, A57Write_12cyc_1L, + A57Write_13cyc_1L, A57Write_14cyc_1L, + A57Write_15cyc_1L, A57Write_16cyc_1L, + A57Write_17cyc_1L, A57Write_18cyc_1L, + A57Write_19cyc_1L, A57Write_20cyc_1L]>; +def A57WriteVLDMcond : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]> { let Variadic=1; } + +def A57WriteVLDM : SchedWriteVariant<[ + SchedVar, + SchedVar +]> { let Variadic=1; } + +def : InstRW<[A57WriteVLDM], (instregex "VLDM(DIA|SIA)$")>; + +def A57VLDMOpsListUncond_Upd : A57WriteLMOpsListType< + [A57Write_5cyc_1L_1I, A57Write_5cyc_1L_1I, + A57Write_6cyc_1L_1I, A57Write_6cyc_1L_1I, + A57Write_7cyc_1L_1I, A57Write_7cyc_1L_1I, + A57Write_8cyc_1L_1I, A57Write_8cyc_1L_1I, + A57Write_9cyc_1L_1I, A57Write_9cyc_1L_1I, + A57Write_10cyc_1L_1I, A57Write_10cyc_1L_1I, + A57Write_11cyc_1L_1I, A57Write_11cyc_1L_1I, + A57Write_12cyc_1L_1I, A57Write_12cyc_1L_1I]>; +def A57WriteVLDMuncond_UPD : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]> { let Variadic=1; } + +def A57VLDMOpsListCond_Upd : A57WriteLMOpsListType< + [A57Write_5cyc_1L_1I, A57Write_6cyc_1L_1I, + A57Write_7cyc_1L_1I, A57Write_8cyc_1L_1I, + A57Write_9cyc_1L_1I, A57Write_10cyc_1L_1I, + A57Write_11cyc_1L_1I, A57Write_12cyc_1L_1I, + A57Write_13cyc_1L_1I, A57Write_14cyc_1L_1I, + A57Write_15cyc_1L_1I, A57Write_16cyc_1L_1I, + A57Write_17cyc_1L_1I, A57Write_18cyc_1L_1I, + A57Write_19cyc_1L_1I, A57Write_20cyc_1L_1I]>; +def A57WriteVLDMcond_UPD : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]> { let Variadic=1; } + +def A57WriteVLDM_UPD : SchedWriteVariant<[ + SchedVar, + SchedVar +]> { let Variadic=1; } + +def : InstRW<[A57WrBackOne, A57WriteVLDM_UPD], + (instregex "VLDM(DIA_UPD|DDB_UPD|SIA_UPD|SDB_UPD)")>; + +// --- 3.13 FP Store Instructions --- +def : InstRW<[A57Write_1cyc_1S], (instregex "VSTR(D|S|H)")>; + +def : InstRW<[A57Write_2cyc_1S], (instregex "VSTMQIA$")>; + +def A57WriteVSTMs : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]>; +def A57WriteVSTMd : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]>; +def A57WriteVSTMs_Upd : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]>; +def A57WriteVSTMd_Upd : SchedWriteVariant<[ + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar, + SchedVar +]>; + +def : InstRW<[A57WriteVSTMs], (instregex "VSTMSIA$")>; +def : InstRW<[A57WriteVSTMd], (instregex "VSTMDIA$")>; +def : InstRW<[A57WrBackOne, A57WriteVSTMs_Upd], + (instregex "VSTM(SIA_UPD|SDB_UPD)")>; +def : InstRW<[A57WrBackOne, A57WriteVSTMd_Upd], + (instregex "VSTM(DIA_UPD|DDB_UPD)")>; + +// --- 3.14 ASIMD Integer Instructions --- + +// ASIMD absolute diff, 3cyc F0/F1 for integer VABD +def : InstRW<[A57Write_3cyc_1V], (instregex "VABD(s|u)")>; + +// ASIMD absolute diff accum: 4(1) F1 for D-form, 5(2) F1 for Q-form +def A57WriteVABAD : SchedWriteRes<[A57UnitX]> { let Latency = 4; } +def A57ReadVABAD : SchedReadAdvance<3, [A57WriteVABAD]>; +def : InstRW<[A57WriteVABAD, A57ReadVABAD], + (instregex "VABA(s|u)(v8i8|v4i16|v2i32)")>; +def A57WriteVABAQ : SchedWriteRes<[A57UnitX]> { let Latency = 5; } +def A57ReadVABAQ : SchedReadAdvance<3, [A57WriteVABAQ]>; +def : InstRW<[A57WriteVABAQ, A57ReadVABAQ], + (instregex "VABA(s|u)(v16i8|v8i16|v4i32)")>; + +// ASIMD absolute diff accum long: 4(1) F1 for VABAL +def A57WriteVABAL : SchedWriteRes<[A57UnitX]> { let Latency = 4; } +def A57ReadVABAL : SchedReadAdvance<3, [A57WriteVABAL]>; +def : InstRW<[A57WriteVABAL, A57ReadVABAL], (instregex "VABAL(s|u)")>; + +// ASIMD absolute diff long: 3cyc F0/F1 for VABDL +def : InstRW<[A57Write_3cyc_1V], (instregex "VABDL(s|u)")>; + +// ASIMD arith, basic +def : InstRW<[A57Write_3cyc_1V], (instregex "VADD", "VADDL", "VADDW", + "VNEG(s8d|s16d|s32d|s8q|s16q|s32q|d|q)", + "VPADDi", "VPADDL", "VSUB", "VSUBL", "VSUBW")>; + +// ASIMD arith, complex +def : InstRW<[A57Write_3cyc_1V], (instregex "VABS", "VADDHN", "VHADD", "VHSUB", + "VQABS", "VQADD", "VQNEG", "VQSUB", + "VRADDHN", "VRHADD", "VRSUBHN", "VSUBHN")>; + +// ASIMD compare +def : InstRW<[A57Write_3cyc_1V], + (instregex "VCEQ", "VCGE", "VCGT", "VCLE", "VTST", "VCLT")>; + +// ASIMD logical +def : InstRW<[A57Write_3cyc_1V], + (instregex "VAND", "VBIC", "VMVN", "VORR", "VORN", "VEOR")>; + +// ASIMD max/min +def : InstRW<[A57Write_3cyc_1V], + (instregex "(VMAX|VMIN)(s|u)", "(VPMAX|VPMIN)(s8|s16|s32|u8|u16|u32)")>; + +// ASIMD multiply, D-form: 5cyc F0 for r0px, 4cyc F0 for r1p0 and later +// Cortex-A57 r1p0 and later reduce the latency of ASIMD multiply +// and multiply-with-accumulate instructions relative to r0pX. +def A57WriteVMULD_VecInt : SchedWriteVariant<[ + SchedVar, + SchedVar]>; +def : InstRW<[A57WriteVMULD_VecInt], (instregex + "VMUL(v8i8|v4i16|v2i32|pd)", "VMULsl(v4i16|v2i32)", + "VQDMULH(sl)?(v4i16|v2i32)", "VQRDMULH(sl)?(v4i16|v2i32)")>; + +// ASIMD multiply, Q-form: 6cyc F0 for r0px, 5cyc F0 for r1p0 and later +def A57WriteVMULQ_VecInt : SchedWriteVariant<[ + SchedVar, + SchedVar]>; +def : InstRW<[A57WriteVMULQ_VecInt], (instregex + "VMUL(v16i8|v8i16|v4i32|pq)", "VMULsl(v8i16|v4i32)", + "VQDMULH(sl)?(v8i16|v4i32)", "VQRDMULH(sl)?(v8i16|v4i32)")>; + +// ASIMD multiply accumulate, D-form +// 5cyc F0 for r0px, 4cyc F0 for r1p0 and later, 1cyc for accumulate sequence +// (4 or 3 ReadAdvance) +def A57WriteVMLAD_VecInt : SchedWriteVariant<[ + SchedVar, + SchedVar]>; +def A57ReadVMLAD_VecInt : SchedReadVariant<[ + SchedVar]>, + SchedVar]> +]>; +def : InstRW<[A57WriteVMLAD_VecInt, A57ReadVMLAD_VecInt], + (instregex "VMLA(sl)?(v8i8|v4i16|v2i32)", "VMLS(sl)?(v8i8|v4i16|v2i32)")>; + +// ASIMD multiply accumulate, Q-form +// 6cyc F0 for r0px, 5cyc F0 for r1p0 and later, 2cyc for accumulate sequence +// (4 or 3 ReadAdvance) +def A57WriteVMLAQ_VecInt : SchedWriteVariant<[ + SchedVar, + SchedVar]>; +def A57ReadVMLAQ_VecInt : SchedReadVariant<[ + SchedVar]>, + SchedVar]> +]>; +def : InstRW<[A57WriteVMLAQ_VecInt, A57ReadVMLAQ_VecInt], + (instregex "VMLA(sl)?(v16i8|v8i16|v4i32)", "VMLS(sl)?(v16i8|v8i16|v4i32)")>; + +// ASIMD multiply accumulate long +// 5cyc F0 for r0px, 4cyc F0 for r1p0 and later, 1cyc for accumulate sequence +// (4 or 3 ReadAdvance) +def A57WriteVMLAL_VecInt : SchedWriteVariant<[ + SchedVar, + SchedVar]>; +def A57ReadVMLAL_VecInt : SchedReadVariant<[ + SchedVar]>, + SchedVar]> +]>; +def : InstRW<[A57WriteVMLAL_VecInt, A57ReadVMLAL_VecInt], + (instregex "VMLAL(s|u)", "VMLSL(s|u)")>; + +// ASIMD multiply accumulate saturating long +// 5cyc F0 for r0px, 4cyc F0 for r1p0 and later, 2cyc for accumulate sequence +// (3 or 2 ReadAdvance) +def A57WriteVQDMLAL_VecInt : SchedWriteVariant<[ + SchedVar, + SchedVar]>; +def A57ReadVQDMLAL_VecInt : SchedReadVariant<[ + SchedVar]>, + SchedVar]> +]>; +def : InstRW<[A57WriteVQDMLAL_VecInt, A57ReadVQDMLAL_VecInt], + (instregex "VQDMLAL", "VQDMLSL")>; + +// ASIMD multiply long +// 5cyc F0 for r0px, 4cyc F0 for r1p0 and later +def A57WriteVMULL_VecInt : SchedWriteVariant<[ + SchedVar, + SchedVar]>; +def : InstRW<[A57WriteVMULL_VecInt], + (instregex "VMULL(s|u|p8|sls|slu)", "VQDMULL")>; + +// ASIMD pairwise add and accumulate +// 4cyc F1, 1cyc for accumulate sequence (3cyc ReadAdvance) +def A57WriteVPADAL : SchedWriteRes<[A57UnitX]> { let Latency = 4; } +def A57ReadVPADAL : SchedReadAdvance<3, [A57WriteVPADAL]>; +def : InstRW<[A57WriteVPADAL, A57ReadVPADAL], (instregex "VPADAL(s|u)")>; + +// ASIMD shift accumulate +// 4cyc F1, 1cyc for accumulate sequence (3cyc ReadAdvance) +def A57WriteVSRA : SchedWriteRes<[A57UnitX]> { let Latency = 4; } +def A57ReadVSRA : SchedReadAdvance<3, [A57WriteVSRA]>; +def : InstRW<[A57WriteVSRA, A57ReadVSRA], (instregex "VSRA", "VRSRA")>; + +// ASIMD shift by immed, basic +def : InstRW<[A57Write_3cyc_1X], + (instregex "VMOVL", "VSHLi", "VSHLL", "VSHR(s|u)", "VSHRN")>; + +// ASIMD shift by immed, complex +def : InstRW<[A57Write_4cyc_1X], (instregex + "VQRSHRN", "VQRSHRUN", "VQSHL(si|ui|su)", "VQSHRN", "VQSHRUN", "VRSHR(s|u)", + "VRSHRN")>; + +// ASIMD shift by immed and insert, basic, D-form +def : InstRW<[A57Write_4cyc_1X], (instregex + "VSLI(v8i8|v4i16|v2i32|v1i64)", "VSRI(v8i8|v4i16|v2i32|v1i64)")>; + +// ASIMD shift by immed and insert, basic, Q-form +def : InstRW<[A57Write_5cyc_1X], (instregex + "VSLI(v16i8|v8i16|v4i32|v2i64)", "VSRI(v16i8|v8i16|v4i32|v2i64)")>; + +// ASIMD shift by register, basic, D-form +def : InstRW<[A57Write_3cyc_1X], (instregex + "VSHL(s|u)(v8i8|v4i16|v2i32|v1i64)")>; + +// ASIMD shift by register, basic, Q-form +def : InstRW<[A57Write_4cyc_1X], (instregex + "VSHL(s|u)(v16i8|v8i16|v4i32|v2i64)")>; + +// ASIMD shift by register, complex, D-form +// VQRSHL, VQSHL, VRSHL +def : InstRW<[A57Write_4cyc_1X], (instregex + "VQRSHL(s|u)(v8i8|v4i16|v2i32|v1i64)", "VQSHL(s|u)(v8i8|v4i16|v2i32|v1i64)", + "VRSHL(s|u)(v8i8|v4i16|v2i32|v1i64)")>; + +// ASIMD shift by register, complex, Q-form +def : InstRW<[A57Write_5cyc_1X], (instregex + "VQRSHL(s|u)(v16i8|v8i16|v4i32|v2i64)", "VQSHL(s|u)(v16i8|v8i16|v4i32|v2i64)", + "VRSHL(s|u)(v16i8|v8i16|v4i32|v2i64)")>; + +// --- 3.15 ASIMD Floating-Point Instructions --- +// ASIMD FP absolute value +def : InstRW<[A57Write_3cyc_1V], (instregex "VABS(fd|fq|hd|hq)")>; + +// ASIMD FP arith +def : InstRW<[A57Write_5cyc_1V], (instregex "VABD(fd|fq|hd|hq)", + "VADD(fd|fq|hd|hq)", "VPADD(f|h)", "VSUB(fd|fq|hd|hq)")>; + +// ASIMD FP compare +def : InstRW<[A57Write_5cyc_1V], (instregex "VAC(GE|GT|LE|LT)", + "VC(EQ|GE|GT|LE)(fd|fq|hd|hq)")>; + +// ASIMD FP convert, integer +def : InstRW<[A57Write_5cyc_1V], (instregex + "VCVT(f2sd|f2ud|s2fd|u2fd|f2sq|f2uq|s2fq|u2fq|f2xsd|f2xud|xs2fd|xu2fd)", + "VCVT(f2xsq|f2xuq|xs2fq|xu2fq)", + "VCVT(AN|MN|NN|PN)(SDf|SQf|UDf|UQf|SDh|SQh|UDh|UQh)")>; + +// ASIMD FP convert, half-precision: 8cyc F0/F1 +def : InstRW<[A57Write_8cyc_1V], (instregex + "VCVT(h2sd|h2ud|s2hd|u2hd|h2sq|h2uq|s2hq|u2hq|h2xsd|h2xud|xs2hd|xu2hd)", + "VCVT(h2xsq|h2xuq|xs2hq|xu2hq)", + "VCVT(f2h|h2f)")>; + +// ASIMD FP max/min +def : InstRW<[A57Write_5cyc_1V], (instregex + "(VMAX|VMIN)(fd|fq|hd|hq)", "(VPMAX|VPMIN)(f|h)", "VMAXNM", "VMINNM")>; + +// ASIMD FP multiply +def A57WriteVMUL_VecFP : SchedWriteRes<[A57UnitV]> { let Latency = 5; } +def : InstRW<[A57WriteVMUL_VecFP], (instregex "VMUL(sl)?(fd|fq|hd|hq)")>; + +// ASIMD FP multiply accumulate: 9cyc F0/F1, 4cyc for accumulate sequence +def A57WriteVMLA_VecFP : SchedWriteRes<[A57UnitV]> { let Latency = 9; } +def A57ReadVMLA_VecFP : + SchedReadAdvance<5, [A57WriteVMLA_VecFP, A57WriteVMUL_VecFP]>; +def : InstRW<[A57WriteVMLA_VecFP, A57ReadVMLA_VecFP], + (instregex "(VMLA|VMLS)(sl)?(fd|fq|hd|hq)", "(VFMA|VFMS)(fd|fq|hd|hq)")>; + +// ASIMD FP negate +def : InstRW<[A57Write_3cyc_1V], (instregex "VNEG(fd|f32q|hd|hq)")>; + +// ASIMD FP round to integral +def : InstRW<[A57Write_5cyc_1V], (instregex + "VRINT(AN|MN|NN|PN|XN|ZN)(Df|Qf|Dh|Qh)")>; + +// --- 3.16 ASIMD Miscellaneous Instructions --- + +// ASIMD bitwise insert +def : InstRW<[A57Write_3cyc_1V], (instregex "VBIF", "VBIT", "VBSL")>; + +// ASIMD count +def : InstRW<[A57Write_3cyc_1V], (instregex "VCLS", "VCLZ", "VCNT")>; + +// ASIMD duplicate, core reg: 8cyc "L, F0/F1" +def : InstRW<[A57Write_8cyc_1L_1V], (instregex "VDUP(8|16|32)(d|q)")>; + +// ASIMD duplicate, scalar: 3cyc "F0/F1" +def : InstRW<[A57Write_3cyc_1V], (instregex "VDUPLN(8|16|32)(d|q)")>; + +// ASIMD extract +def : InstRW<[A57Write_3cyc_1V], (instregex "VEXT(d|q)(8|16|32|64)")>; + +// ASIMD move, immed +def : InstRW<[A57Write_3cyc_1V], (instregex + "VMOV(v8i8|v16i8|v4i16|v8i16|v2i32|v4i32|v1i64|v2i64|v2f32|v4f32)", + "VMOVQ0")>; + +// ASIMD move, narrowing +def : InstRW<[A57Write_3cyc_1V], (instregex "VMOVN")>; + +// ASIMD move, saturating +def : InstRW<[A57Write_4cyc_1X], (instregex "VQMOVN")>; + +// ASIMD reciprocal estimate +def : InstRW<[A57Write_5cyc_1V], (instregex "VRECPE", "VRSQRTE")>; + +// ASIMD reciprocal step, FZ +def : InstRW<[A57Write_9cyc_1V], (instregex "VRECPS", "VRSQRTS")>; + +// ASIMD reverse, swap, table lookup (1-2 reg) +def : InstRW<[A57Write_3cyc_1V], (instregex "VREV", "VSWP", "VTB(L|X)(1|2)")>; + +// ASIMD table lookup (3-4 reg) +def : InstRW<[A57Write_6cyc_1V], (instregex "VTBL(3|4)", "VTBX(3|4)")>; + +// ASIMD transfer, scalar to core reg: 6cyc "L, I0/I1" +def : InstRW<[A57Write_6cyc_1L_1I], (instregex "VGETLN")>; + +// ASIMD transfer, core reg to scalar: 8cyc "L, F0/F1" +def : InstRW<[A57Write_8cyc_1L_1V], (instregex "VSETLN")>; + +// ASIMD transpose +def : InstRW<[A57Write_3cyc_1V, A57Write_3cyc_1V], (instregex "VTRN")>; + +// ASIMD unzip/zip, D-form +def : InstRW<[A57Write_3cyc_1V, A57Write_3cyc_1V], + (instregex "VUZPd", "VZIPd")>; + +// ASIMD unzip/zip, Q-form +def : InstRW<[A57Write_6cyc_1V, A57Write_6cyc_1V], + (instregex "VUZPq", "VZIPq")>; + +// --- 3.17 ASIMD Load Instructions --- + +// Overriden via InstRW for this processor. +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; + +// 1-2 reg: 5cyc L, +I for writeback, 1 cyc wb latency +def : InstRW<[A57Write_5cyc_1L], (instregex "VLD1(d|q)(8|16|32|64)$")>; +def : InstRW<[A57Write_5cyc_1L_1I, A57WrBackOne], + (instregex "VLD1(d|q)(8|16|32|64)wb")>; + +// 3-4 reg: 6cyc L, +I for writeback, 1 cyc wb latency +def : InstRW<[A57Write_6cyc_1L], + (instregex "VLD1(d|q)(8|16|32|64)(T|Q)$", "VLD1d64(T|Q)Pseudo")>; + +def : InstRW<[A57Write_6cyc_1L_1I, A57WrBackOne], + (instregex "VLD1(d|q)(8|16|32|64)(T|Q)wb")>; + +// ASIMD load, 1 element, one lane and all lanes: 8cyc "L, F0/F1" +def : InstRW<[A57Write_8cyc_1L_1V], (instregex + "VLD1(LN|DUP)(d|q)(8|16|32)$", "VLD1(LN|DUP)(d|q)(8|16|32)Pseudo$")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57WrBackOne], (instregex + "VLD1(LN|DUP)(d|q)(8|16|32)(wb|_UPD)", "VLD1LNq(8|16|32)Pseudo_UPD")>; + +// ASIMD load, 2 element, multiple, 2 reg: 8cyc "L, F0/F1" +def : InstRW<[A57Write_8cyc_1L_1V], + (instregex "VLD2(d|q)(8|16|32)$", "VLD2q(8|16|32)Pseudo$")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD2(d|q)(8|16|32)wb", "VLD2q(8|16|32)PseudoWB")>; + +// ASIMD load, 2 element, multiple, 4 reg: 9cyc "L, F0/F1" +def : InstRW<[A57Write_9cyc_1L_1V], (instregex "VLD2b(8|16|32)$")>; +def : InstRW<[A57Write_9cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD2b(8|16|32)wb")>; + +// ASIMD load, 2 element, one lane and all lanes: 8cyc "L, F0/F1" +def : InstRW<[A57Write_8cyc_1L_1V, A57Write_8cyc_1L_1V], + (instregex "VLD2(DUP|LN)(d|q)(8|16|32|8x2|16x2|32x2)$", + "VLD2LN(d|q)(8|16|32)Pseudo$")>; +// 2 results + wb result +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57Write_8cyc_1L_1V, A57WrBackOne], + (instregex "VLD2LN(d|q)(8|16|32)_UPD$")>; +// 1 result + wb result +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD2DUPd(8|16|32|8x2|16x2|32x2)wb", + "VLD2LN(d|q)(8|16|32)Pseudo_UPD")>; + +// ASIMD load, 3 element, multiple, 3 reg: 9cyc "L, F0/F1" +// 3 results +def : InstRW<[A57Write_9cyc_1L_1V, A57Write_9cyc_1L_1V, A57Write_9cyc_1L_1V], + (instregex "VLD3(d|q)(8|16|32)$")>; +// 1 result +def : InstRW<[A57Write_9cyc_1L_1V], + (instregex "VLD3(d|q)(8|16|32)(oddP|P)seudo$")>; +// 3 results + wb +def : InstRW<[A57Write_9cyc_1L_1V_1I, A57Write_9cyc_1L_1V_1I, + A57Write_9cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD3(d|q)(8|16|32)_UPD$")>; +// 1 result + wb +def : InstRW<[A57Write_9cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD3(d|q)(8|16|32)(oddP|P)seudo_UPD")>; + +// ASIMD load, 3 element, one lane, size 32: 8cyc "L, F0/F1" +def : InstRW<[A57Write_8cyc_1L_1V, A57Write_8cyc_1L_1V, A57Write_8cyc_1L_1V], + (instregex "VLD3LN(d|q)32$", + "VLD3LN(d|q)32Pseudo$")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57Write_8cyc_1L_1V_1I, + A57Write_8cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD3LN(d|q)32_UPD")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD3LN(d|q)32Pseudo_UPD")>; + +// ASIMD load, 3 element, one lane, size 8/16: 9cyc "L, F0/F1" +def : InstRW<[A57Write_9cyc_1L_1V, A57Write_9cyc_1L_1V, A57Write_9cyc_1L_1V], + (instregex "VLD3LN(d|q)(8|16)$", + "VLD3LN(d|q)(8|16)Pseudo$")>; +def : InstRW<[A57Write_9cyc_1L_1V_1I, A57Write_9cyc_1L_1V_1I, + A57Write_9cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD3LN(d|q)(8|16)_UPD")>; +def : InstRW<[A57Write_9cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD3LN(d|q)(8|16)Pseudo_UPD")>; + +// ASIMD load, 3 element, all lanes: 8cyc "L, F0/F1" +def : InstRW<[A57Write_8cyc_1L_1V, A57Write_8cyc_1L_1V, A57Write_8cyc_1L_1V], + (instregex "VLD3DUP(d|q)(8|16|32)$", + "VLD3DUP(d|q)(8|16|32)Pseudo$")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57Write_8cyc_1L_1V_1I, + A57Write_8cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD3DUP(d|q)(8|16|32)_UPD")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD3DUP(d|q)(8|16|32)Pseudo_UPD")>; + +// ASIMD load, 4 element, multiple, 4 reg: 9cyc "L, F0/F1" +def : InstRW<[A57Write_9cyc_1L_1V, A57Write_9cyc_1L_1V, A57Write_9cyc_1L_1V, + A57Write_9cyc_1L_1V], + (instregex "VLD4(d|q)(8|16|32)$")>; +def : InstRW<[A57Write_9cyc_1L_1V], + (instregex "VLD4(d|q)(8|16|32)(oddP|P)seudo$")>; +def : InstRW<[A57Write_9cyc_1L_1V_1I, A57Write_9cyc_1L_1V_1I, + A57Write_9cyc_1L_1V_1I, A57Write_9cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD4(d|q)(8|16|32)_UPD")>; +def : InstRW<[A57Write_9cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD4(d|q)(8|16|32)(oddP|P)seudo_UPD")>; + +// ASIMD load, 4 element, one lane, size 32: 8cyc "L, F0/F1" +def : InstRW<[A57Write_8cyc_1L_1V, A57Write_8cyc_1L_1V, A57Write_8cyc_1L_1V, + A57Write_8cyc_1L_1V], + (instregex "VLD4LN(d|q)32$", + "VLD4LN(d|q)32Pseudo$")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57Write_8cyc_1L_1V_1I, + A57Write_8cyc_1L_1V_1I, A57Write_8cyc_1L_1V_1I, + A57WrBackOne], + (instregex "VLD4LN(d|q)32_UPD")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD4LN(d|q)32Pseudo_UPD")>; + +// ASIMD load, 4 element, one lane, size 8/16: 9cyc "L, F0/F1" +def : InstRW<[A57Write_9cyc_1L_1V, A57Write_9cyc_1L_1V, A57Write_9cyc_1L_1V, + A57Write_9cyc_1L_1V], + (instregex "VLD4LN(d|q)(8|16)$", + "VLD4LN(d|q)(8|16)Pseudo$")>; +def : InstRW<[A57Write_9cyc_1L_1V_1I, A57Write_9cyc_1L_1V_1I, + A57Write_9cyc_1L_1V_1I, A57Write_9cyc_1L_1V_1I, + A57WrBackOne], + (instregex "VLD4LN(d|q)(8|16)_UPD")>; +def : InstRW<[A57Write_9cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD4LN(d|q)(8|16)Pseudo_UPD")>; + +// ASIMD load, 4 element, all lanes: 8cyc "L, F0/F1" +def : InstRW<[A57Write_8cyc_1L_1V, A57Write_8cyc_1L_1V, A57Write_8cyc_1L_1V, + A57Write_8cyc_1L_1V], + (instregex "VLD4DUP(d|q)(8|16|32)$", + "VLD4DUP(d|q)(8|16|32)Pseudo$")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57Write_8cyc_1L_1V_1I, + A57Write_8cyc_1L_1V_1I, A57Write_8cyc_1L_1V_1I, + A57WrBackOne], + (instregex "VLD4DUP(d|q)(8|16|32)_UPD")>; +def : InstRW<[A57Write_8cyc_1L_1V_1I, A57WrBackOne], + (instregex "VLD4DUP(d|q)(8|16|32)Pseudo_UPD")>; + +// --- 3.18 ASIMD Store Instructions --- + +// ASIMD store, 1 element, multiple, 1 reg: 1cyc S +def : InstRW<[A57Write_1cyc_1S], (instregex "VST1d(8|16|32|64)$")>; +def : InstRW<[A57WrBackOne, A57Write_1cyc_1S_1I], + (instregex "VST1d(8|16|32|64)wb")>; +// ASIMD store, 1 element, multiple, 2 reg: 2cyc S +def : InstRW<[A57Write_2cyc_1S], (instregex "VST1q(8|16|32|64)$")>; +def : InstRW<[A57WrBackOne, A57Write_2cyc_1S_1I], + (instregex "VST1q(8|16|32|64)wb")>; +// ASIMD store, 1 element, multiple, 3 reg: 3cyc S +def : InstRW<[A57Write_3cyc_1S], + (instregex "VST1d(8|16|32|64)T$", "VST1d64TPseudo$")>; +def : InstRW<[A57WrBackOne, A57Write_3cyc_1S_1I], + (instregex "VST1d(8|16|32|64)Twb", "VST1d64TPseudoWB")>; +// ASIMD store, 1 element, multiple, 4 reg: 4cyc S +def : InstRW<[A57Write_4cyc_1S], + (instregex "VST1d(8|16|32|64)(Q|QPseudo)$")>; +def : InstRW<[A57WrBackOne, A57Write_4cyc_1S_1I], + (instregex "VST1d(8|16|32|64)(Qwb|QPseudoWB)")>; +// ASIMD store, 1 element, one lane: 3cyc "F0/F1, S" +def : InstRW<[A57Write_3cyc_1S_1V], + (instregex "VST1LNd(8|16|32)$", "VST1LNq(8|16|32)Pseudo$")>; +def : InstRW<[A57WrBackOne, A57Write_3cyc_1S_1V_1I], + (instregex "VST1LNd(8|16|32)_UPD", "VST1LNq(8|16|32)Pseudo_UPD")>; +// ASIMD store, 2 element, multiple, 2 reg: 3cyc "F0/F1, S" +def : InstRW<[A57Write_3cyc_1S_1V], + (instregex "VST2(d|b)(8|16|32)$")>; +def : InstRW<[A57WrBackOne, A57Write_3cyc_1S_1V_1I], + (instregex "VST2(b|d)(8|16|32)wb")>; +// ASIMD store, 2 element, multiple, 4 reg: 4cyc "F0/F1, S" +def : InstRW<[A57Write_4cyc_1S_1V], + (instregex "VST2q(8|16|32)$", "VST2q(8|16|32)Pseudo$")>; +def : InstRW<[A57WrBackOne, A57Write_4cyc_1S_1V_1I], + (instregex "VST2q(8|16|32)wb", "VST2q(8|16|32)PseudoWB")>; +// ASIMD store, 2 element, one lane: 3cyc "F0/F1, S" +def : InstRW<[A57Write_3cyc_1S_1V], + (instregex "VST2LN(d|q)(8|16|32)$", "VST2LN(d|q)(8|16|32)Pseudo$")>; +def : InstRW<[A57WrBackOne, A57Write_3cyc_1S_1V_1I], + (instregex "VST2LN(d|q)(8|16|32)_UPD", + "VST2LN(d|q)(8|16|32)Pseudo_UPD")>; +// ASIMD store, 3 element, multiple, 3 reg +def : InstRW<[A57Write_3cyc_1S_1V], + (instregex "VST3(d|q)(8|16|32)$", "VST3(d|q)(8|16|32)(oddP|P)seudo$")>; +def : InstRW<[A57WrBackOne, A57Write_3cyc_1S_1V_1I], + (instregex "VST3(d|q)(8|16|32)_UPD", + "VST3(d|q)(8|16|32)(oddP|P)seudo_UPD$")>; +// ASIMD store, 3 element, one lane +def : InstRW<[A57Write_3cyc_1S_1V], + (instregex "VST3LN(d|q)(8|16|32)$", "VST3LN(d|q)(8|16|32)Pseudo$")>; +def : InstRW<[A57WrBackOne, A57Write_3cyc_1S_1V_1I], + (instregex "VST3LN(d|q)(8|16|32)_UPD", + "VST3LN(d|q)(8|16|32)Pseudo_UPD")>; +// ASIMD store, 4 element, multiple, 4 reg +def : InstRW<[A57Write_4cyc_1S_1V], + (instregex "VST4(d|q)(8|16|32)$", "VST4(d|q)(8|16|32)(oddP|P)seudo$")>; +def : InstRW<[A57WrBackOne, A57Write_4cyc_1S_1V_1I], + (instregex "VST4(d|q)(8|16|32)_UPD", + "VST4(d|q)(8|16|32)(oddP|P)seudo_UPD$")>; +// ASIMD store, 4 element, one lane +def : InstRW<[A57Write_3cyc_1S_1V], + (instregex "VST4LN(d|q)(8|16|32)$", "VST4LN(d|q)(8|16|32)Pseudo$")>; +def : InstRW<[A57WrBackOne, A57Write_3cyc_1S_1V_1I], + (instregex "VST4LN(d|q)(8|16|32)_UPD", + "VST4LN(d|q)(8|16|32)Pseudo_UPD")>; + +// --- 3.19 Cryptography Extensions --- +// Crypto AES ops +// AESD, AESE, AESIMC, AESMC: 3cyc F0 +def : InstRW<[A57Write_3cyc_1W], (instregex "^AES")>; +// Crypto polynomial (64x64) multiply long (VMULL.P64): 3cyc F0 +def : InstRW<[A57Write_3cyc_1W], (instregex "^VMULLp64")>; +// Crypto SHA1 xor ops: 6cyc F0/F1 +def : InstRW<[A57Write_6cyc_2V], (instregex "^SHA1SU0")>; +// Crypto SHA1 fast ops: 3cyc F0 +def : InstRW<[A57Write_3cyc_1W], (instregex "^SHA1(H|SU1)")>; +// Crypto SHA1 slow ops: 6cyc F0 +def : InstRW<[A57Write_6cyc_2W], (instregex "^SHA1[CMP]")>; +// Crypto SHA256 fast ops: 3cyc F0 +def : InstRW<[A57Write_3cyc_1W], (instregex "^SHA256SU0")>; +// Crypto SHA256 slow ops: 6cyc F0 +def : InstRW<[A57Write_6cyc_2W], (instregex "^SHA256(H|H2|SU1)")>; + +// --- 3.20 CRC --- +def : InstRW<[A57Write_3cyc_1W], (instregex "^(t2)?CRC32")>; + +// ----------------------------------------------------------------------------- +// Common definitions +def : WriteRes { let Latency = 0; let NumMicroOps = 0; } +def : SchedAlias; + +def : SchedAlias; +def : SchedAlias; +def : SchedAlias; +def : SchedAlias; + +def : SchedAlias; +def : SchedAlias; +def : ReadAdvance; + +} // SchedModel = CortexA57Model + diff --git a/contrib/llvm/lib/Target/ARM/ARMScheduleA57WriteRes.td b/contrib/llvm/lib/Target/ARM/ARMScheduleA57WriteRes.td new file mode 100644 index 000000000000..670717dc7c13 --- /dev/null +++ b/contrib/llvm/lib/Target/ARM/ARMScheduleA57WriteRes.td @@ -0,0 +1,323 @@ +//=- ARMScheduleA57WriteRes.td - ARM Cortex-A57 Write Res ---*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains all of the Cortex-A57 specific SchedWriteRes types. The approach +// below is to define a generic SchedWriteRes for every combination of +// latency and microOps. The naming conventions is to use a prefix, one field +// for latency, and one or more microOp count/type designators. +// Prefix: A57Write +// Latency: #cyc +// MicroOp Count/Types: #(B|I|M|L|S|X|W|V) +// +// e.g. A57Write_6cyc_1I_6S_4V means the total latency is 6 and there are +// 11 micro-ops to be issued as follows: one to I pipe, six to S pipes and +// four to V pipes. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Define Generic 1 micro-op types + +def A57Write_5cyc_1M : SchedWriteRes<[A57UnitM]> { let Latency = 5; } +def A57Write_5cyc_1V : SchedWriteRes<[A57UnitV]> { let Latency = 5; } +def A57Write_5cyc_1W : SchedWriteRes<[A57UnitW]> { let Latency = 5; } +def A57Write_10cyc_1V : SchedWriteRes<[A57UnitV]> { let Latency = 10; } +def A57Write_17cyc_1W : SchedWriteRes<[A57UnitW]> { let Latency = 17; + let ResourceCycles = [17]; } +def A57Write_18cyc_1X : SchedWriteRes<[A57UnitX]> { let Latency = 18; + let ResourceCycles = [18]; } +def A57Write_19cyc_1M : SchedWriteRes<[A57UnitM]> { let Latency = 19; + let ResourceCycles = [19]; } +def A57Write_20cyc_1M : SchedWriteRes<[A57UnitM]> { let Latency = 20; + let ResourceCycles = [20]; } +def A57Write_1cyc_1B : SchedWriteRes<[A57UnitB]> { let Latency = 1; } +def A57Write_1cyc_1I : SchedWriteRes<[A57UnitI]> { let Latency = 1; } +def A57Write_2cyc_1I : SchedWriteRes<[A57UnitI]> { let Latency = 2; } +def A57Write_3cyc_1I : SchedWriteRes<[A57UnitI]> { let Latency = 3; } +def A57Write_1cyc_1S : SchedWriteRes<[A57UnitS]> { let Latency = 1; } +def A57Write_2cyc_1S : SchedWriteRes<[A57UnitS]> { let Latency = 2; } +def A57Write_3cyc_1S : SchedWriteRes<[A57UnitS]> { let Latency = 3; } +def A57Write_2cyc_1M : SchedWriteRes<[A57UnitM]> { let Latency = 2; } +def A57Write_32cyc_1W : SchedWriteRes<[A57UnitW]> { let Latency = 32; + let ResourceCycles = [32]; } +def A57Write_32cyc_1X : SchedWriteRes<[A57UnitX]> { let Latency = 32; + let ResourceCycles = [32]; } +def A57Write_35cyc_1M : SchedWriteRes<[A57UnitM]> { let Latency = 35; + let ResourceCycles = [35]; } +def A57Write_3cyc_1M : SchedWriteRes<[A57UnitM]> { let Latency = 3; } +def A57Write_3cyc_1V : SchedWriteRes<[A57UnitV]> { let Latency = 3; } +def A57Write_3cyc_1W : SchedWriteRes<[A57UnitW]> { let Latency = 3; } +def A57Write_3cyc_1X : SchedWriteRes<[A57UnitX]> { let Latency = 3; } + +// A57Write_3cyc_1L - A57Write_20cyc_1L +foreach Lat = 3-20 in { + def A57Write_#Lat#cyc_1L : SchedWriteRes<[A57UnitL]> { + let Latency = Lat; + } +} + +// A57Write_4cyc_1S - A57Write_16cyc_1S +foreach Lat = 4-16 in { + def A57Write_#Lat#cyc_1S : SchedWriteRes<[A57UnitS]> { + let Latency = Lat; + } +} + +def A57Write_4cyc_1M : SchedWriteRes<[A57UnitL]> { let Latency = 4; } +def A57Write_4cyc_1X : SchedWriteRes<[A57UnitX]> { let Latency = 4; } +def A57Write_4cyc_1W : SchedWriteRes<[A57UnitW]> { let Latency = 4; } +def A57Write_5cyc_1X : SchedWriteRes<[A57UnitX]> { let Latency = 5; } +def A57Write_6cyc_1X : SchedWriteRes<[A57UnitX]> { let Latency = 6; } +def A57Write_6cyc_1W : SchedWriteRes<[A57UnitW]> { let Latency = 6; } +def A57Write_8cyc_1V : SchedWriteRes<[A57UnitV]> { let Latency = 8; } +def A57Write_9cyc_1V : SchedWriteRes<[A57UnitV]> { let Latency = 9; } +def A57Write_6cyc_1M : SchedWriteRes<[A57UnitM]> { let Latency = 6; } +def A57Write_6cyc_1V : SchedWriteRes<[A57UnitV]> { let Latency = 6; } + + +//===----------------------------------------------------------------------===// +// Define Generic 2 micro-op types + +def A57Write_64cyc_2X : SchedWriteRes<[A57UnitX, A57UnitX]> { + let Latency = 64; + let NumMicroOps = 2; + let ResourceCycles = [32, 32]; +} +def A57Write_6cyc_1I_1L : SchedWriteRes<[A57UnitI, + A57UnitL]> { + let Latency = 6; + let NumMicroOps = 2; +} +def A57Write_6cyc_1V_1X : SchedWriteRes<[A57UnitV, + A57UnitX]> { + let Latency = 6; + let NumMicroOps = 2; +} +def A57Write_7cyc_1V_1X : SchedWriteRes<[A57UnitV, + A57UnitX]> { + let Latency = 7; + let NumMicroOps = 2; +} +def A57Write_8cyc_1L_1V : SchedWriteRes<[A57UnitL, + A57UnitV]> { + let Latency = 8; + let NumMicroOps = 2; +} +def A57Write_9cyc_1L_1V : SchedWriteRes<[A57UnitL, + A57UnitV]> { + let Latency = 9; + let NumMicroOps = 2; +} +def A57Write_9cyc_2V : SchedWriteRes<[A57UnitV, A57UnitV]> { + let Latency = 9; + let NumMicroOps = 2; +} +def A57Write_8cyc_2X : SchedWriteRes<[A57UnitX, A57UnitX]> { + let Latency = 8; + let NumMicroOps = 2; +} +def A57Write_6cyc_2L : SchedWriteRes<[A57UnitL, A57UnitL]> { + let Latency = 6; + let NumMicroOps = 2; +} +def A57Write_6cyc_2V : SchedWriteRes<[A57UnitV, A57UnitV]> { + let Latency = 6; + let NumMicroOps = 2; +} +def A57Write_6cyc_2W : SchedWriteRes<[A57UnitW, A57UnitW]> { + let Latency = 6; + let NumMicroOps = 2; +} +def A57Write_5cyc_1I_1L : SchedWriteRes<[A57UnitI, + A57UnitL]> { + let Latency = 5; + let NumMicroOps = 2; +} +def A57Write_5cyc_1I_1M : SchedWriteRes<[A57UnitI, + A57UnitM]> { + let Latency = 5; + let NumMicroOps = 2; +} +def A57Write_5cyc_2V : SchedWriteRes<[A57UnitV, A57UnitV]> { + let Latency = 5; + let NumMicroOps = 2; +} +def A57Write_5cyc_2X : SchedWriteRes<[A57UnitX, A57UnitX]> { + let Latency = 5; + let NumMicroOps = 2; +} +def A57Write_10cyc_1L_1V : SchedWriteRes<[A57UnitL, + A57UnitV]> { + let Latency = 10; + let NumMicroOps = 2; +} +def A57Write_10cyc_2V : SchedWriteRes<[A57UnitV, A57UnitV]> { + let Latency = 10; + let NumMicroOps = 2; +} +def A57Write_1cyc_1B_1I : SchedWriteRes<[A57UnitB, + A57UnitI]> { + let Latency = 1; + let NumMicroOps = 2; +} +def A57Write_1cyc_1I_1S : SchedWriteRes<[A57UnitI, + A57UnitS]> { + let Latency = 1; + let NumMicroOps = 2; +} +def A57Write_1cyc_1S_1I : SchedWriteRes<[A57UnitS, + A57UnitI]> { + let Latency = 1; + let NumMicroOps = 2; +} +def A57Write_2cyc_1S_1I : SchedWriteRes<[A57UnitS, + A57UnitI]> { + let Latency = 2; + let NumMicroOps = 2; +} +def A57Write_3cyc_1S_1I : SchedWriteRes<[A57UnitS, + A57UnitI]> { + let Latency = 3; + let NumMicroOps = 2; +} +def A57Write_1cyc_1S_1M : SchedWriteRes<[A57UnitS, + A57UnitM]> { + let Latency = 1; + let NumMicroOps = 2; +} +def A57Write_2cyc_1B_1I : SchedWriteRes<[A57UnitB, + A57UnitI]> { + let Latency = 2; + let NumMicroOps = 2; +} +def A57Write_3cyc_1B_1I : SchedWriteRes<[A57UnitB, + A57UnitI]> { + let Latency = 3; + let NumMicroOps = 2; +} +def A57Write_6cyc_1B_1L : SchedWriteRes<[A57UnitB, + A57UnitI]> { + let Latency = 6; + let NumMicroOps = 2; +} +def A57Write_2cyc_1I_1M : SchedWriteRes<[A57UnitI, + A57UnitM]> { + let Latency = 2; + let NumMicroOps = 2; +} +def A57Write_2cyc_2S : SchedWriteRes<[A57UnitS, A57UnitS]> { + let Latency = 2; + let NumMicroOps = 2; +} +def A57Write_2cyc_2V : SchedWriteRes<[A57UnitV, A57UnitV]> { + let Latency = 2; + let NumMicroOps = 2; +} +def A57Write_36cyc_2X : SchedWriteRes<[A57UnitX, A57UnitX]> { + let Latency = 36; + let NumMicroOps = 2; + let ResourceCycles = [18, 18]; +} +def A57Write_3cyc_1I_1M : SchedWriteRes<[A57UnitI, + A57UnitM]> { + let Latency = 3; + let NumMicroOps = 2; +} +def A57Write_4cyc_1I_1M : SchedWriteRes<[A57UnitI, + A57UnitM]> { + let Latency = 4; + let NumMicroOps = 2; +} + +// A57Write_3cyc_1L_1I - A57Write_20cyc_1L_1I +foreach Lat = 3-20 in { + def A57Write_#Lat#cyc_1L_1I : SchedWriteRes<[A57UnitL, A57UnitI]> { + let Latency = Lat; let NumMicroOps = 2; + } +} + +def A57Write_3cyc_1I_1S : SchedWriteRes<[A57UnitI, + A57UnitS]> { + let Latency = 3; + let NumMicroOps = 2; +} +def A57Write_3cyc_1S_1V : SchedWriteRes<[A57UnitS, + A57UnitV]> { + let Latency = 3; + let NumMicroOps = 2; +} +def A57Write_4cyc_1S_1V : SchedWriteRes<[A57UnitS, + A57UnitV]> { + let Latency = 4; + let NumMicroOps = 2; +} +def A57Write_3cyc_2V : SchedWriteRes<[A57UnitV, A57UnitV]> { + let Latency = 3; + let NumMicroOps = 2; +} + +// A57Write_4cyc_1S_1I - A57Write_16cyc_1S_1I +foreach Lat = 4-16 in { + def A57Write_#Lat#cyc_1S_1I : SchedWriteRes<[A57UnitS, A57UnitI]> { + let Latency = Lat; let NumMicroOps = 2; + } +} + +def A57Write_4cyc_2X : SchedWriteRes<[A57UnitX, A57UnitX]> { + let Latency = 4; + let NumMicroOps = 2; +} + + +//===----------------------------------------------------------------------===// +// Define Generic 3 micro-op types + +def A57Write_10cyc_3V : SchedWriteRes<[A57UnitV, A57UnitV, A57UnitV]> { + let Latency = 10; + let NumMicroOps = 3; +} +def A57Write_2cyc_1I_2S : SchedWriteRes<[A57UnitI, + A57UnitS, A57UnitS]> { + let Latency = 2; + let NumMicroOps = 3; +} +def A57Write_3cyc_1I_1S_1V : SchedWriteRes<[A57UnitI, + A57UnitS, + A57UnitV]> { + let Latency = 3; + let NumMicroOps = 3; +} +def A57Write_3cyc_1S_1V_1I : SchedWriteRes<[A57UnitS, + A57UnitV, + A57UnitI]> { + let Latency = 3; + let NumMicroOps = 3; +} +def A57Write_4cyc_1S_1V_1I : SchedWriteRes<[A57UnitS, + A57UnitV, + A57UnitI]> { + let Latency = 4; + let NumMicroOps = 3; +} +def A57Write_4cyc_1I_1L_1M : SchedWriteRes<[A57UnitI, A57UnitL, A57UnitM]> { + let Latency = 4; + let NumMicroOps = 3; +} +def A57Write_8cyc_1L_1V_1I : SchedWriteRes<[A57UnitL, + A57UnitV, + A57UnitI]> { + let Latency = 8; + let NumMicroOps = 3; +} +def A57Write_9cyc_1L_1V_1I : SchedWriteRes<[A57UnitL, + A57UnitV, + A57UnitI]> { + let Latency = 9; + let NumMicroOps = 3; +} diff --git a/contrib/llvm/lib/Target/ARM/ARMSubtarget.h b/contrib/llvm/lib/Target/ARM/ARMSubtarget.h index d2630685d91b..af682dd8321c 100644 --- a/contrib/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/contrib/llvm/lib/Target/ARM/ARMSubtarget.h @@ -234,6 +234,10 @@ protected: /// CPSR setting instruction. bool AvoidCPSRPartialUpdate = false; + /// CheapPredicableCPSRDef - If true, disable +1 predication cost + /// for instructions updating CPSR. Enabled for Cortex-A57. + bool CheapPredicableCPSRDef = false; + /// AvoidMOVsShifterOperand - If true, codegen should avoid using flag setting /// movs with shifter operand (i.e. asr, lsl, lsr). bool AvoidMOVsShifterOperand = false; @@ -543,6 +547,7 @@ public: bool nonpipelinedVFP() const { return NonpipelinedVFP; } bool prefers32BitThumb() const { return Pref32BitThumb; } bool avoidCPSRPartialUpdate() const { return AvoidCPSRPartialUpdate; } + bool cheapPredicableCPSRDef() const { return CheapPredicableCPSRDef; } bool avoidMOVsShifterOperand() const { return AvoidMOVsShifterOperand; } bool hasRetAddrStack() const { return HasRetAddrStack; } bool hasMPExtension() const { return HasMPExtension; } diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp index 0fef91ec4d3e..b76da727237c 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -3419,9 +3419,7 @@ int HexagonInstrInfo::getDotNewPredOp(const MachineInstr &MI, int NewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode()); if (NewOpcode >= 0) return NewOpcode; - - dbgs() << "Cannot convert to .new: " << getName(MI.getOpcode()) << '\n'; - llvm_unreachable(nullptr); + return 0; } int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const { diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp b/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp index 4593fc92ca6f..35948e36ad91 100644 --- a/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp +++ b/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp @@ -135,6 +135,14 @@ private: // returns true on success. static bool ReduceXWtoXWSP(MachineInstr *MI, const ReduceEntry &Entry); + // Attempts to reduce LBU/LHU instruction into LBU16/LHU16, + // returns true on success. + static bool ReduceLXUtoLXU16(MachineInstr *MI, const ReduceEntry &Entry); + + // Attempts to reduce SB/SH instruction into SB16/SH16, + // returns true on success. + static bool ReduceSXtoSX16(MachineInstr *MI, const ReduceEntry &Entry); + // Attempts to reduce arithmetic instructions, returns true on success static bool ReduceArithmeticInstructions(MachineInstr *MI, const ReduceEntry &Entry); @@ -162,10 +170,26 @@ llvm::SmallVector MicroMipsSizeReduce::ReduceTable = { {RT_OneInstr, OpCodes(Mips::ADDu_MM, Mips::ADDU16_MM), ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), ImmField(0, 0, 0, -1)}, + {RT_OneInstr, OpCodes(Mips::LBu, Mips::LBU16_MM), ReduceLXUtoLXU16, + OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)}, + {RT_OneInstr, OpCodes(Mips::LBu_MM, Mips::LBU16_MM), ReduceLXUtoLXU16, + OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)}, + {RT_OneInstr, OpCodes(Mips::LHu, Mips::LHU16_MM), ReduceLXUtoLXU16, + OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, + {RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16, + OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, {RT_OneInstr, OpCodes(Mips::LW, Mips::LWSP_MM), ReduceXWtoXWSP, OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, {RT_OneInstr, OpCodes(Mips::LW_MM, Mips::LWSP_MM), ReduceXWtoXWSP, OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, + {RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16, + OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)}, + {RT_OneInstr, OpCodes(Mips::SB_MM, Mips::SB16_MM), ReduceSXtoSX16, + OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)}, + {RT_OneInstr, OpCodes(Mips::SH, Mips::SH16_MM), ReduceSXtoSX16, + OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, + {RT_OneInstr, OpCodes(Mips::SH_MM, Mips::SH16_MM), ReduceSXtoSX16, + OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, {RT_OneInstr, OpCodes(Mips::SUBu, Mips::SUBU16_MM), ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), ImmField(0, 0, 0, -1)}, @@ -193,6 +217,13 @@ static bool isMMThreeBitGPRegister(const MachineOperand &MO) { return false; } +// Returns true if the machine operand MO is register $0, $17, or $2-$7. +static bool isMMSourceRegister(const MachineOperand &MO) { + if (MO.isReg() && Mips::GPRMM16ZeroRegClass.contains(MO.getReg())) + return true; + return false; +} + // Returns true if the operand Op is an immediate value // and writes the immediate value into variable Imm static bool GetImm(MachineInstr *MI, unsigned Op, int64_t &Imm) { @@ -279,6 +310,32 @@ bool MicroMipsSizeReduce::ReduceArithmeticInstructions( return ReplaceInstruction(MI, Entry); } +bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI, + const ReduceEntry &Entry) { + + if (!ImmInRange(MI, Entry)) + return false; + + if (!isMMThreeBitGPRegister(MI->getOperand(0)) || + !isMMThreeBitGPRegister(MI->getOperand(1))) + return false; + + return ReplaceInstruction(MI, Entry); +} + +bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI, + const ReduceEntry &Entry) { + + if (!ImmInRange(MI, Entry)) + return false; + + if (!isMMSourceRegister(MI->getOperand(0)) || + !isMMThreeBitGPRegister(MI->getOperand(1))) + return false; + + return ReplaceInstruction(MI, Entry); +} + bool MicroMipsSizeReduce::ReduceMBB(MachineBasicBlock &MBB) { bool Modified = false; MachineBasicBlock::instr_iterator MII = MBB.instr_begin(), diff --git a/contrib/llvm/lib/Target/WebAssembly/known_gcc_test_failures.txt b/contrib/llvm/lib/Target/WebAssembly/known_gcc_test_failures.txt index 54619589c341..35a67134775a 100644 --- a/contrib/llvm/lib/Target/WebAssembly/known_gcc_test_failures.txt +++ b/contrib/llvm/lib/Target/WebAssembly/known_gcc_test_failures.txt @@ -88,6 +88,3 @@ pr45695.c wasm-o pr49279.c wasm-o pr49390.c wasm-o pr52286.c wasm-o - -# fatal error: error in backend: data symbols must have a size set with .size -921110-1.c wasm-o diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp index 0a41f35f9320..5303d7a406ad 100644 --- a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4753,7 +4753,7 @@ static void scaleShuffleMask(int Scale, ArrayRef Mask, SmallVectorImpl &ScaledMask) { assert(0 < Scale && "Unexpected scaling factor"); int NumElts = Mask.size(); - ScaledMask.assign(NumElts * Scale, -1); + ScaledMask.assign(static_cast(NumElts * Scale), -1); for (int i = 0; i != NumElts; ++i) { int M = Mask[i]; @@ -5848,17 +5848,39 @@ static bool getFauxShuffleMask(SDValue N, SmallVectorImpl &Mask, return true; } case ISD::SCALAR_TO_VECTOR: { - // Match against a scalar_to_vector of an extract from a similar vector. + // Match against a scalar_to_vector of an extract from a vector, + // for PEXTRW/PEXTRB we must handle the implicit zext of the scalar. SDValue N0 = N.getOperand(0); - if (N0.getOpcode() != ISD::EXTRACT_VECTOR_ELT || - N0.getOperand(0).getValueType() != VT || - !isa(N0.getOperand(1)) || - NumElts <= N0.getConstantOperandVal(1) || - !N->isOnlyUserOf(N0.getNode())) + SDValue SrcExtract; + + if (N0.getOpcode() == ISD::EXTRACT_VECTOR_ELT && + N0.getOperand(0).getValueType() == VT) { + SrcExtract = N0; + } else if (N0.getOpcode() == ISD::AssertZext && + N0.getOperand(0).getOpcode() == X86ISD::PEXTRW && + cast(N0.getOperand(1))->getVT() == MVT::i16) { + SrcExtract = N0.getOperand(0); + assert(SrcExtract.getOperand(0).getValueType() == MVT::v8i16); + } else if (N0.getOpcode() == ISD::AssertZext && + N0.getOperand(0).getOpcode() == X86ISD::PEXTRB && + cast(N0.getOperand(1))->getVT() == MVT::i8) { + SrcExtract = N0.getOperand(0); + assert(SrcExtract.getOperand(0).getValueType() == MVT::v16i8); + } + + if (!SrcExtract || !isa(SrcExtract.getOperand(1)) || + NumElts <= SrcExtract.getConstantOperandVal(1)) return false; - Ops.push_back(N0.getOperand(0)); - Mask.push_back(N0.getConstantOperandVal(1)); - Mask.append(NumElts - 1, SM_SentinelUndef); + + SDValue SrcVec = SrcExtract.getOperand(0); + EVT SrcVT = SrcVec.getValueType(); + unsigned NumSrcElts = SrcVT.getVectorNumElements(); + unsigned NumZeros = (NumBitsPerElt / SrcVT.getScalarSizeInBits()) - 1; + + Ops.push_back(SrcVec); + Mask.push_back(SrcExtract.getConstantOperandVal(1)); + Mask.append(NumZeros, SM_SentinelZero); + Mask.append(NumSrcElts - Mask.size(), SM_SentinelUndef); return true; } case X86ISD::PINSRB: @@ -6542,12 +6564,12 @@ static Constant *getConstantVector(MVT VT, const APInt &SplatValue, APInt Val = SplatValue.extractBits(ScalarSize, ScalarSize * i); Constant *Const; if (VT.isFloatingPoint()) { - assert((ScalarSize == 32 || ScalarSize == 64) && - "Unsupported floating point scalar size"); - if (ScalarSize == 32) - Const = ConstantFP::get(Type::getFloatTy(C), Val.bitsToFloat()); - else - Const = ConstantFP::get(Type::getDoubleTy(C), Val.bitsToDouble()); + if (ScalarSize == 32) { + Const = ConstantFP::get(C, APFloat(APFloat::IEEEsingle(), Val)); + } else { + assert(ScalarSize == 64 && "Unsupported floating point scalar size"); + Const = ConstantFP::get(C, APFloat(APFloat::IEEEdouble(), Val)); + } } else Const = Constant::getIntegerValue(Type::getIntNTy(C, ScalarSize), Val); ConstantVec.push_back(Const); @@ -6633,11 +6655,13 @@ static SDValue lowerBuildVectorAsBroadcast(BuildVectorSDNode *BVOp, // AVX have support for 32 and 64 bit broadcast for floats only. // No 64bit integer in 32bit subtarget. MVT CVT = MVT::getFloatingPointVT(SplatBitSize); - Constant *C = SplatBitSize == 32 - ? ConstantFP::get(Type::getFloatTy(*Ctx), - SplatValue.bitsToFloat()) - : ConstantFP::get(Type::getDoubleTy(*Ctx), - SplatValue.bitsToDouble()); + // Lower the splat via APFloat directly, to avoid any conversion. + Constant *C = + SplatBitSize == 32 + ? ConstantFP::get(*Ctx, + APFloat(APFloat::IEEEsingle(), SplatValue)) + : ConstantFP::get(*Ctx, + APFloat(APFloat::IEEEdouble(), SplatValue)); SDValue CP = DAG.getConstantPool(C, PVT); unsigned Repeat = VT.getSizeInBits() / SplatBitSize; @@ -8003,7 +8027,7 @@ static bool is128BitLaneCrossingShuffleMask(MVT VT, ArrayRef Mask) { static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef Mask, SmallVectorImpl &RepeatedMask) { - int LaneSize = LaneSizeInBits / VT.getScalarSizeInBits(); + auto LaneSize = LaneSizeInBits / VT.getScalarSizeInBits(); RepeatedMask.assign(LaneSize, -1); int Size = Mask.size(); for (int i = 0; i < Size; ++i) { @@ -16997,7 +17021,7 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget, SDValue Op1 = Op.getOperand(1); SDValue CC = Op.getOperand(2); MVT VT = Op.getSimpleValueType(); - ISD::CondCode SetCCOpcode = cast(CC)->get(); + ISD::CondCode Cond = cast(CC)->get(); bool isFP = Op.getOperand(1).getSimpleValueType().isFloatingPoint(); SDLoc dl(Op); @@ -17024,18 +17048,18 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget, // TODO: This can be avoided if Intel (and only Intel as of 2016) AVX is // available. SDValue Cmp; - unsigned SSECC = translateX86FSETCC(SetCCOpcode, Op0, Op1); + unsigned SSECC = translateX86FSETCC(Cond, Op0, Op1); if (SSECC == 8) { // LLVM predicate is SETUEQ or SETONE. unsigned CC0, CC1; unsigned CombineOpc; - if (SetCCOpcode == ISD::SETUEQ) { + if (Cond == ISD::SETUEQ) { CC0 = 3; // UNORD CC1 = 0; // EQ CombineOpc = Opc == X86ISD::CMPP ? static_cast(X86ISD::FOR) : static_cast(ISD::OR); } else { - assert(SetCCOpcode == ISD::SETONE); + assert(Cond == ISD::SETONE); CC0 = 7; // ORD CC1 = 4; // NEQ CombineOpc = Opc == X86ISD::CMPP ? static_cast(X86ISD::FAND) : @@ -17082,7 +17106,7 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget, // 2. The original operand type has been promoted to a 256-bit vector. // // Note that condition 2. only applies for AVX targets. - SDValue NewOp = DAG.getSetCC(dl, VTOp0, Op0, Op1, SetCCOpcode); + SDValue NewOp = DAG.getSetCC(dl, VTOp0, Op0, Op1, Cond); return DAG.getZExtOrTrunc(NewOp, dl, VT); } @@ -17122,7 +17146,7 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget, VT == MVT::v4i32 || VT == MVT::v2i64) && Subtarget.hasXOP()) { // Translate compare code to XOP PCOM compare mode. unsigned CmpMode = 0; - switch (SetCCOpcode) { + switch (Cond) { default: llvm_unreachable("Unexpected SETCC condition"); case ISD::SETULT: case ISD::SETLT: CmpMode = 0x00; break; @@ -17137,60 +17161,49 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget, } // Are we comparing unsigned or signed integers? - unsigned Opc = ISD::isUnsignedIntSetCC(SetCCOpcode) - ? X86ISD::VPCOMU : X86ISD::VPCOM; + unsigned Opc = + ISD::isUnsignedIntSetCC(Cond) ? X86ISD::VPCOMU : X86ISD::VPCOM; return DAG.getNode(Opc, dl, VT, Op0, Op1, DAG.getConstant(CmpMode, dl, MVT::i8)); } - // We are handling one of the integer comparisons here. Since SSE only has + // We are handling one of the integer comparisons here. Since SSE only has // GT and EQ comparisons for integer, swapping operands and multiple // operations may be required for some comparisons. - unsigned Opc; - bool Swap = false, Invert = false, FlipSigns = false, MinMax = false; - bool Subus = false; - - switch (SetCCOpcode) { - default: llvm_unreachable("Unexpected SETCC condition"); - case ISD::SETNE: Invert = true; LLVM_FALLTHROUGH; - case ISD::SETEQ: Opc = X86ISD::PCMPEQ; break; - case ISD::SETLT: Swap = true; LLVM_FALLTHROUGH; - case ISD::SETGT: Opc = X86ISD::PCMPGT; break; - case ISD::SETGE: Swap = true; LLVM_FALLTHROUGH; - case ISD::SETLE: Opc = X86ISD::PCMPGT; - Invert = true; break; - case ISD::SETULT: Swap = true; LLVM_FALLTHROUGH; - case ISD::SETUGT: Opc = X86ISD::PCMPGT; - FlipSigns = true; break; - case ISD::SETUGE: Swap = true; LLVM_FALLTHROUGH; - case ISD::SETULE: Opc = X86ISD::PCMPGT; - FlipSigns = true; Invert = true; break; - } + unsigned Opc = (Cond == ISD::SETEQ || Cond == ISD::SETNE) ? X86ISD::PCMPEQ + : X86ISD::PCMPGT; + bool Swap = Cond == ISD::SETLT || Cond == ISD::SETULT || + Cond == ISD::SETGE || Cond == ISD::SETUGE; + bool Invert = Cond == ISD::SETNE || + (Cond != ISD::SETEQ && ISD::isTrueWhenEqual(Cond)); + bool FlipSigns = ISD::isUnsignedIntSetCC(Cond); // Special case: Use min/max operations for SETULE/SETUGE MVT VET = VT.getVectorElementType(); - bool hasMinMax = - (Subtarget.hasSSE41() && (VET >= MVT::i8 && VET <= MVT::i32)) - || (Subtarget.hasSSE2() && (VET == MVT::i8)); - - if (hasMinMax) { - switch (SetCCOpcode) { + bool HasMinMax = + (Subtarget.hasSSE41() && (VET >= MVT::i8 && VET <= MVT::i32)) || + (Subtarget.hasSSE2() && (VET == MVT::i8)); + bool MinMax = false; + if (HasMinMax) { + switch (Cond) { default: break; case ISD::SETULE: Opc = ISD::UMIN; MinMax = true; break; case ISD::SETUGE: Opc = ISD::UMAX; MinMax = true; break; } - if (MinMax) { Swap = false; Invert = false; FlipSigns = false; } + if (MinMax) + Swap = Invert = FlipSigns = false; } - bool hasSubus = Subtarget.hasSSE2() && (VET == MVT::i8 || VET == MVT::i16); - if (!MinMax && hasSubus) { + bool HasSubus = Subtarget.hasSSE2() && (VET == MVT::i8 || VET == MVT::i16); + bool Subus = false; + if (!MinMax && HasSubus) { // As another special case, use PSUBUS[BW] when it's profitable. E.g. for // Op0 u<= Op1: // t = psubus Op0, Op1 // pcmpeq t, <0..0> - switch (SetCCOpcode) { + switch (Cond) { default: break; case ISD::SETULT: { // If the comparison is against a constant we can turn this into a diff --git a/contrib/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/contrib/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 613b4a7f03e9..626a891f65c6 100644 --- a/contrib/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/contrib/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -228,7 +228,7 @@ static Function *createClone(Function &F, Twine Suffix, coro::Shape &Shape, SmallVector Returns; - CloneFunctionInto(NewF, &F, VMap, /*ModuleLevelChanges=*/false, Returns); + CloneFunctionInto(NewF, &F, VMap, /*ModuleLevelChanges=*/true, Returns); // Remove old returns. for (ReturnInst *Return : Returns) diff --git a/contrib/llvm/lib/Transforms/Coroutines/Coroutines.cpp b/contrib/llvm/lib/Transforms/Coroutines/Coroutines.cpp index ea48043f9381..44e1f9b404ed 100644 --- a/contrib/llvm/lib/Transforms/Coroutines/Coroutines.cpp +++ b/contrib/llvm/lib/Transforms/Coroutines/Coroutines.cpp @@ -218,6 +218,8 @@ void coro::Shape::buildFrom(Function &F) { size_t FinalSuspendIndex = 0; clear(*this); SmallVector CoroFrames; + SmallVector UnusedCoroSaves; + for (Instruction &I : instructions(F)) { if (auto II = dyn_cast(&I)) { switch (II->getIntrinsicID()) { @@ -229,6 +231,12 @@ void coro::Shape::buildFrom(Function &F) { case Intrinsic::coro_frame: CoroFrames.push_back(cast(II)); break; + case Intrinsic::coro_save: + // After optimizations, coro_suspends using this coro_save might have + // been removed, remember orphaned coro_saves to remove them later. + if (II->use_empty()) + UnusedCoroSaves.push_back(cast(II)); + break; case Intrinsic::coro_suspend: CoroSuspends.push_back(cast(II)); if (CoroSuspends.back()->isFinal()) { @@ -311,4 +319,8 @@ void coro::Shape::buildFrom(Function &F) { if (HasFinalSuspend && FinalSuspendIndex != CoroSuspends.size() - 1) std::swap(CoroSuspends[FinalSuspendIndex], CoroSuspends.back()); + + // Remove orphaned coro.saves. + for (CoroSaveInst *CoroSave : UnusedCoroSaves) + CoroSave->eraseFromParent(); } diff --git a/contrib/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/contrib/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 28cc81c76d4f..5cc29a493798 100644 --- a/contrib/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/contrib/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -1188,6 +1188,10 @@ static bool runImpl(CallGraphSCC &SCC, AARGetterT AARGetter) { SCCNodes.insert(F); } + // Skip it if the SCC only contains optnone functions. + if (SCCNodes.empty()) + return Changed; + Changed |= addArgumentReturnedAttrs(SCCNodes); Changed |= addReadAttrs(SCCNodes, AARGetter); Changed |= addArgumentAttrs(SCCNodes); diff --git a/contrib/llvm/lib/Transforms/IPO/FunctionImport.cpp b/contrib/llvm/lib/Transforms/IPO/FunctionImport.cpp index 231487923fad..6d34ab8b0d96 100644 --- a/contrib/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/contrib/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -292,8 +292,7 @@ static void computeImportForFunction( static void ComputeImportForModule( const GVSummaryMapTy &DefinedGVSummaries, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportList, - StringMap *ExportLists = nullptr, - const DenseSet *DeadSymbols = nullptr) { + StringMap *ExportLists = nullptr) { // Worklist contains the list of function imported in this module, for which // we will analyse the callees and may import further down the callgraph. SmallVector Worklist; @@ -301,7 +300,7 @@ static void ComputeImportForModule( // Populate the worklist with the import for the functions in the current // module for (auto &GVSummary : DefinedGVSummaries) { - if (DeadSymbols && DeadSymbols->count(GVSummary.first)) { + if (!Index.isGlobalValueLive(GVSummary.second)) { DEBUG(dbgs() << "Ignores Dead GUID: " << GVSummary.first << "\n"); continue; } @@ -344,15 +343,14 @@ void llvm::ComputeCrossModuleImport( const ModuleSummaryIndex &Index, const StringMap &ModuleToDefinedGVSummaries, StringMap &ImportLists, - StringMap &ExportLists, - const DenseSet *DeadSymbols) { + StringMap &ExportLists) { // For each module that has function defined, compute the import/export lists. for (auto &DefinedGVSummaries : ModuleToDefinedGVSummaries) { auto &ImportList = ImportLists[DefinedGVSummaries.first()]; DEBUG(dbgs() << "Computing import for Module '" << DefinedGVSummaries.first() << "'\n"); ComputeImportForModule(DefinedGVSummaries.second, Index, ImportList, - &ExportLists, DeadSymbols); + &ExportLists); } // When computing imports we added all GUIDs referenced by anything @@ -414,82 +412,71 @@ void llvm::ComputeCrossModuleImportForModule( #endif } -DenseSet llvm::computeDeadSymbols( - const ModuleSummaryIndex &Index, +void llvm::computeDeadSymbols( + ModuleSummaryIndex &Index, const DenseSet &GUIDPreservedSymbols) { + assert(!Index.withGlobalValueDeadStripping()); if (!ComputeDead) - return DenseSet(); + return; if (GUIDPreservedSymbols.empty()) // Don't do anything when nothing is live, this is friendly with tests. - return DenseSet(); - DenseSet LiveSymbols; + return; + unsigned LiveSymbols = 0; SmallVector Worklist; Worklist.reserve(GUIDPreservedSymbols.size() * 2); for (auto GUID : GUIDPreservedSymbols) { ValueInfo VI = Index.getValueInfo(GUID); if (!VI) continue; - DEBUG(dbgs() << "Live root: " << VI.getGUID() << "\n"); - LiveSymbols.insert(VI); - Worklist.push_back(VI); + for (auto &S : VI.getSummaryList()) + S->setLive(true); } + // Add values flagged in the index as live roots to the worklist. - for (const auto &Entry : Index) { - bool IsLiveRoot = llvm::any_of( - Entry.second.SummaryList, - [&](const std::unique_ptr &Summary) { - return Summary->liveRoot(); - }); - if (!IsLiveRoot) - continue; - DEBUG(dbgs() << "Live root (summary): " << Entry.first << "\n"); - Worklist.push_back(ValueInfo(&Entry)); - } + for (const auto &Entry : Index) + for (auto &S : Entry.second.SummaryList) + if (S->isLive()) { + DEBUG(dbgs() << "Live root: " << Entry.first << "\n"); + Worklist.push_back(ValueInfo(&Entry)); + ++LiveSymbols; + break; + } + + // Make value live and add it to the worklist if it was not live before. + // FIXME: we should only make the prevailing copy live here + auto visit = [&](ValueInfo VI) { + for (auto &S : VI.getSummaryList()) + if (S->isLive()) + return; + for (auto &S : VI.getSummaryList()) + S->setLive(true); + ++LiveSymbols; + Worklist.push_back(VI); + }; while (!Worklist.empty()) { auto VI = Worklist.pop_back_val(); - - // FIXME: we should only make the prevailing copy live here for (auto &Summary : VI.getSummaryList()) { - for (auto Ref : Summary->refs()) { - if (LiveSymbols.insert(Ref).second) { - DEBUG(dbgs() << "Marking live (ref): " << Ref.getGUID() << "\n"); - Worklist.push_back(Ref); - } - } - if (auto *FS = dyn_cast(Summary.get())) { - for (auto Call : FS->calls()) { - if (LiveSymbols.insert(Call.first).second) { - DEBUG(dbgs() << "Marking live (call): " << Call.first.getGUID() - << "\n"); - Worklist.push_back(Call.first); - } - } - } + for (auto Ref : Summary->refs()) + visit(Ref); + if (auto *FS = dyn_cast(Summary.get())) + for (auto Call : FS->calls()) + visit(Call.first); if (auto *AS = dyn_cast(Summary.get())) { auto AliaseeGUID = AS->getAliasee().getOriginalName(); ValueInfo AliaseeVI = Index.getValueInfo(AliaseeGUID); - if (AliaseeVI && LiveSymbols.insert(AliaseeVI).second) { - DEBUG(dbgs() << "Marking live (alias): " << AliaseeGUID << "\n"); - Worklist.push_back(AliaseeVI); - } + if (AliaseeVI) + visit(AliaseeVI); } } } - DenseSet DeadSymbols; - DeadSymbols.reserve( - std::min(Index.size(), Index.size() - LiveSymbols.size())); - for (auto &Entry : Index) { - if (!LiveSymbols.count(ValueInfo(&Entry))) { - DEBUG(dbgs() << "Marking dead: " << Entry.first << "\n"); - DeadSymbols.insert(Entry.first); - } - } - DEBUG(dbgs() << LiveSymbols.size() << " symbols Live, and " - << DeadSymbols.size() << " symbols Dead \n"); - NumDeadSymbols += DeadSymbols.size(); - NumLiveSymbols += LiveSymbols.size(); - return DeadSymbols; + Index.setWithGlobalValueDeadStripping(); + + unsigned DeadSymbols = Index.size() - LiveSymbols; + DEBUG(dbgs() << LiveSymbols << " symbols Live, and " << DeadSymbols + << " symbols Dead \n"); + NumDeadSymbols += DeadSymbols; + NumLiveSymbols += LiveSymbols; } /// Compute the set of summaries needed for a ThinLTO backend compilation of diff --git a/contrib/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/contrib/llvm/lib/Transforms/IPO/LowerTypeTests.cpp index ca4ee92f971a..7bec50d9d25f 100644 --- a/contrib/llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/contrib/llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -1442,9 +1442,8 @@ bool LowerTypeTestsModule::lower() { for (auto &P : *ExportSummary) { for (auto &S : P.second.SummaryList) { auto *FS = dyn_cast(S.get()); - if (!FS) + if (!FS || !ExportSummary->isGlobalValueLive(FS)) continue; - // FIXME: Only add live functions. for (GlobalValue::GUID G : FS->type_tests()) for (Metadata *MD : MetadataByGUID[G]) AddTypeIdUse(MD).IsExported = true; diff --git a/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp b/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp index bc0967448cdd..ea805efc66b7 100644 --- a/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp +++ b/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp @@ -68,6 +68,10 @@ static cl::opt cl::desc("Relative frequency of outline region to " "the entry block")); +static cl::opt ExtraOutliningPenalty( + "partial-inlining-extra-penalty", cl::init(0), cl::Hidden, + cl::desc("A debug option to add additional penalty to the computed one.")); + namespace { struct FunctionOutliningInfo { @@ -83,7 +87,7 @@ struct FunctionOutliningInfo { SmallVector Entries; // The return block that is not included in the outlined region. BasicBlock *ReturnBlock; - // The dominating block of the region ot be outlined. + // The dominating block of the region to be outlined. BasicBlock *NonReturnBlock; // The set of blocks in Entries that that are predecessors to ReturnBlock SmallVector ReturnBlockPreds; @@ -407,11 +411,23 @@ BranchProbability PartialInlinerImpl::getOutliningCallBBRelativeFreq( if (hasProfileData(F, OI)) return OutlineRegionRelFreq; - // When profile data is not available, we need to be very - // conservative in estimating the overall savings. We need to make sure - // the outline region relative frequency is not below the threshold - // specified by the option. - OutlineRegionRelFreq = std::max(OutlineRegionRelFreq, BranchProbability(OutlineRegionFreqPercent, 100)); + // When profile data is not available, we need to be conservative in + // estimating the overall savings. Static branch prediction can usually + // guess the branch direction right (taken/non-taken), but the guessed + // branch probability is usually not biased enough. In case when the + // outlined region is predicted to be likely, its probability needs + // to be made higher (more biased) to not under-estimate the cost of + // function outlining. On the other hand, if the outlined region + // is predicted to be less likely, the predicted probablity is usually + // higher than the actual. For instance, the actual probability of the + // less likely target is only 5%, but the guessed probablity can be + // 40%. In the latter case, there is no need for further adjustement. + // FIXME: add an option for this. + if (OutlineRegionRelFreq < BranchProbability(45, 100)) + return OutlineRegionRelFreq; + + OutlineRegionRelFreq = std::max( + OutlineRegionRelFreq, BranchProbability(OutlineRegionFreqPercent, 100)); return OutlineRegionRelFreq; } @@ -496,6 +512,26 @@ int PartialInlinerImpl::computeBBInlineCost(BasicBlock *BB) { if (isa(I)) continue; + switch (I->getOpcode()) { + case Instruction::BitCast: + case Instruction::PtrToInt: + case Instruction::IntToPtr: + case Instruction::Alloca: + continue; + case Instruction::GetElementPtr: + if (cast(I)->hasAllZeroIndices()) + continue; + default: + break; + } + + IntrinsicInst *IntrInst = dyn_cast(I); + if (IntrInst) { + if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start || + IntrInst->getIntrinsicID() == Intrinsic::lifetime_end) + continue; + } + if (CallInst *CI = dyn_cast(I)) { InlineCost += getCallsiteCost(CallSite(CI), DL); continue; @@ -519,7 +555,13 @@ std::tuple PartialInlinerImpl::computeOutliningCosts( Function *F, const FunctionOutliningInfo *OI, Function *OutlinedFunction, BasicBlock *OutliningCallBB) { // First compute the cost of the outlined region 'OI' in the original - // function 'F': + // function 'F'. + // FIXME: The code extractor (outliner) can now do code sinking/hoisting + // to reduce outlining cost. The hoisted/sunk code currently do not + // incur any runtime cost so it is still OK to compare the outlined + // function cost with the outlined region in the original function. + // If this ever changes, we will need to introduce new extractor api + // to pass the information. int OutlinedRegionCost = 0; for (BasicBlock &BB : *F) { if (&BB != OI->ReturnBlock && @@ -542,8 +584,14 @@ std::tuple PartialInlinerImpl::computeOutliningCosts( assert(OutlinedFunctionCost >= OutlinedRegionCost && "Outlined function cost should be no less than the outlined region"); - int OutliningRuntimeOverhead = - OutliningFuncCallCost + (OutlinedFunctionCost - OutlinedRegionCost); + // The code extractor introduces a new root and exit stub blocks with + // additional unconditional branches. Those branches will be eliminated + // later with bb layout. The cost should be adjusted accordingly: + OutlinedFunctionCost -= 2 * InlineConstants::InstrCost; + + int OutliningRuntimeOverhead = OutliningFuncCallCost + + (OutlinedFunctionCost - OutlinedRegionCost) + + ExtraOutliningPenalty; return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead, OutlinedRegionCost); diff --git a/contrib/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/contrib/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index 9fd3a9021a27..16fba32e9805 100644 --- a/contrib/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/contrib/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -157,7 +157,7 @@ static cl::opt static cl::opt EnableGVNSink( "enable-gvn-sink", cl::init(false), cl::Hidden, - cl::desc("Enable the GVN sinking pass (default = on)")); + cl::desc("Enable the GVN sinking pass (default = off)")); PassManagerBuilder::PassManagerBuilder() { OptLevel = 2; diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 2c2b7317a1c0..c0798e164c39 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4508,13 +4508,16 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { Builder->CreateAnd(A, B), Op1); - // ~x < ~y --> y < x - // ~x < cst --> ~cst < x + // ~X < ~Y --> Y < X + // ~X < C --> X > ~C if (match(Op0, m_Not(m_Value(A)))) { if (match(Op1, m_Not(m_Value(B)))) return new ICmpInst(I.getPredicate(), B, A); - if (ConstantInt *RHSC = dyn_cast(Op1)) - return new ICmpInst(I.getPredicate(), ConstantExpr::getNot(RHSC), A); + + const APInt *C; + if (match(Op1, m_APInt(C))) + return new ICmpInst(I.getSwappedPredicate(), A, + ConstantInt::get(Op1->getType(), ~(*C))); } Instruction *AddI = nullptr; diff --git a/contrib/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/contrib/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index ff753c20a94a..df4ee9969c02 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/contrib/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -2087,6 +2087,7 @@ struct MemorySanitizerVisitor : public InstVisitor { switch (I.getNumArgOperands()) { case 3: assert(isa(I.getArgOperand(2)) && "Invalid rounding mode"); + LLVM_FALLTHROUGH; case 2: CopyOp = I.getArgOperand(0); ConvertOp = I.getArgOperand(1); diff --git a/contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 325b64cd8b43..8aa40d1759de 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/contrib/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -57,6 +57,11 @@ static const char *const SanCovTracePCGuardName = "__sanitizer_cov_trace_pc_guard"; static const char *const SanCovTracePCGuardInitName = "__sanitizer_cov_trace_pc_guard_init"; +static const char *const SanCov8bitCountersInitName = + "__sanitizer_cov_8bit_counters_init"; + +static const char *const SanCovGuardsSectionName = "sancov_guards"; +static const char *const SanCovCountersSectionName = "sancov_counters"; static cl::opt ClCoverageLevel( "sanitizer-coverage-level", @@ -64,14 +69,18 @@ static cl::opt ClCoverageLevel( "3: all blocks and critical edges"), cl::Hidden, cl::init(0)); -static cl::opt ClExperimentalTracePC("sanitizer-coverage-trace-pc", - cl::desc("Experimental pc tracing"), - cl::Hidden, cl::init(false)); +static cl::opt ClTracePC("sanitizer-coverage-trace-pc", + cl::desc("Experimental pc tracing"), cl::Hidden, + cl::init(false)); static cl::opt ClTracePCGuard("sanitizer-coverage-trace-pc-guard", cl::desc("pc tracing with a guard"), cl::Hidden, cl::init(false)); +static cl::opt ClInline8bitCounters("sanitizer-coverage-inline-8bit-counters", + cl::desc("increments 8-bit counter for every edge"), + cl::Hidden, cl::init(false)); + static cl::opt ClCMPTracing("sanitizer-coverage-trace-compares", cl::desc("Tracing of CMP and similar instructions"), @@ -123,9 +132,10 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { Options.TraceCmp |= ClCMPTracing; Options.TraceDiv |= ClDIVTracing; Options.TraceGep |= ClGEPTracing; - Options.TracePC |= ClExperimentalTracePC; + Options.TracePC |= ClTracePC; Options.TracePCGuard |= ClTracePCGuard; - if (!Options.TracePCGuard && !Options.TracePC) + Options.Inline8bitCounters |= ClInline8bitCounters; + if (!Options.TracePCGuard && !Options.TracePC && !Options.Inline8bitCounters) Options.TracePCGuard = true; // TracePCGuard is default. Options.NoPrune |= !ClPruneBlocks; return Options; @@ -159,11 +169,22 @@ private: void InjectTraceForSwitch(Function &F, ArrayRef SwitchTraceTargets); bool InjectCoverage(Function &F, ArrayRef AllBlocks); - void CreateFunctionGuardArray(size_t NumGuards, Function &F); + GlobalVariable *CreateFunctionLocalArrayInSection(size_t NumElements, + Function &F, Type *Ty, + const char *Section); + void CreateFunctionLocalArrays(size_t NumGuards, Function &F); void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx); - StringRef getSanCovTracePCGuardSection() const; - StringRef getSanCovTracePCGuardSectionStart() const; - StringRef getSanCovTracePCGuardSectionEnd() const; + void CreateInitCallForSection(Module &M, const char *InitFunctionName, + Type *Ty, const std::string &Section); + + void SetNoSanitizeMetadata(Instruction *I) { + I->setMetadata(I->getModule()->getMDKindID("nosanitize"), + MDNode::get(*C, None)); + } + + std::string getSectionName(const std::string &Section) const; + std::string getSectionStart(const std::string &Section) const; + std::string getSectionEnd(const std::string &Section) const; Function *SanCovTracePCIndir; Function *SanCovTracePC, *SanCovTracePCGuard; Function *SanCovTraceCmpFunction[4]; @@ -171,20 +192,48 @@ private: Function *SanCovTraceGepFunction; Function *SanCovTraceSwitchFunction; InlineAsm *EmptyAsm; - Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy; + Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, + *Int8Ty, *Int8PtrTy; Module *CurModule; Triple TargetTriple; LLVMContext *C; const DataLayout *DL; GlobalVariable *FunctionGuardArray; // for trace-pc-guard. - bool HasSancovGuardsSection; + GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. SanitizerCoverageOptions Options; }; } // namespace +void SanitizerCoverageModule::CreateInitCallForSection( + Module &M, const char *InitFunctionName, Type *Ty, + const std::string &Section) { + IRBuilder<> IRB(M.getContext()); + Function *CtorFunc; + GlobalVariable *SecStart = + new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr, + getSectionStart(Section)); + SecStart->setVisibility(GlobalValue::HiddenVisibility); + GlobalVariable *SecEnd = + new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, + nullptr, getSectionEnd(Section)); + SecEnd->setVisibility(GlobalValue::HiddenVisibility); + + std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( + M, SanCovModuleCtorName, InitFunctionName, {Ty, Ty}, + {IRB.CreatePointerCast(SecStart, Ty), IRB.CreatePointerCast(SecEnd, Ty)}); + + if (TargetTriple.supportsCOMDAT()) { + // Use comdat to dedup CtorFunc. + CtorFunc->setComdat(M.getOrInsertComdat(SanCovModuleCtorName)); + appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority, CtorFunc); + } else { + appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority); + } +} + bool SanitizerCoverageModule::runOnModule(Module &M) { if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; @@ -192,15 +241,18 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { DL = &M.getDataLayout(); CurModule = &M; TargetTriple = Triple(M.getTargetTriple()); - HasSancovGuardsSection = false; + FunctionGuardArray = nullptr; + Function8bitCounterArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); IRBuilder<> IRB(*C); Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty()); Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); + Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); Int64Ty = IRB.getInt64Ty(); Int32Ty = IRB.getInt32Ty(); + Int8Ty = IRB.getInt8Ty(); SanCovTracePCIndir = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy)); @@ -243,34 +295,13 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { for (auto &F : M) runOnFunction(F); - // Create variable for module (compilation unit) name - if (Options.TracePCGuard) { - if (HasSancovGuardsSection) { - Function *CtorFunc; - GlobalVariable *SecStart = new GlobalVariable( - M, Int32PtrTy, false, GlobalVariable::ExternalLinkage, nullptr, - getSanCovTracePCGuardSectionStart()); - SecStart->setVisibility(GlobalValue::HiddenVisibility); - GlobalVariable *SecEnd = new GlobalVariable( - M, Int32PtrTy, false, GlobalVariable::ExternalLinkage, nullptr, - getSanCovTracePCGuardSectionEnd()); - SecEnd->setVisibility(GlobalValue::HiddenVisibility); + if (FunctionGuardArray) + CreateInitCallForSection(M, SanCovTracePCGuardInitName, Int32PtrTy, + SanCovGuardsSectionName); + if (Function8bitCounterArray) + CreateInitCallForSection(M, SanCov8bitCountersInitName, Int8PtrTy, + SanCovCountersSectionName); - std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( - M, SanCovModuleCtorName, SanCovTracePCGuardInitName, - {Int32PtrTy, Int32PtrTy}, - {IRB.CreatePointerCast(SecStart, Int32PtrTy), - IRB.CreatePointerCast(SecEnd, Int32PtrTy)}); - - if (TargetTriple.supportsCOMDAT()) { - // Use comdat to dedup CtorFunc. - CtorFunc->setComdat(M.getOrInsertComdat(SanCovModuleCtorName)); - appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority, CtorFunc); - } else { - appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority); - } - } - } return true; } @@ -393,17 +424,26 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) { InjectTraceForGep(F, GepTraceTargets); return true; } -void SanitizerCoverageModule::CreateFunctionGuardArray(size_t NumGuards, - Function &F) { - if (!Options.TracePCGuard) return; - HasSancovGuardsSection = true; - ArrayType *ArrayOfInt32Ty = ArrayType::get(Int32Ty, NumGuards); - FunctionGuardArray = new GlobalVariable( - *CurModule, ArrayOfInt32Ty, false, GlobalVariable::PrivateLinkage, - Constant::getNullValue(ArrayOfInt32Ty), "__sancov_gen_"); + +GlobalVariable *SanitizerCoverageModule::CreateFunctionLocalArrayInSection( + size_t NumElements, Function &F, Type *Ty, const char *Section) { + ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); + auto Array = new GlobalVariable( + *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, + Constant::getNullValue(ArrayTy), "__sancov_gen_"); if (auto Comdat = F.getComdat()) - FunctionGuardArray->setComdat(Comdat); - FunctionGuardArray->setSection(getSanCovTracePCGuardSection()); + Array->setComdat(Comdat); + Array->setSection(getSectionName(Section)); + return Array; +} +void SanitizerCoverageModule::CreateFunctionLocalArrays(size_t NumGuards, + Function &F) { + if (Options.TracePCGuard) + FunctionGuardArray = CreateFunctionLocalArrayInSection( + NumGuards, F, Int32Ty, SanCovGuardsSectionName); + if (Options.Inline8bitCounters) + Function8bitCounterArray = CreateFunctionLocalArrayInSection( + NumGuards, F, Int8Ty, SanCovCountersSectionName); } bool SanitizerCoverageModule::InjectCoverage(Function &F, @@ -413,11 +453,11 @@ bool SanitizerCoverageModule::InjectCoverage(Function &F, case SanitizerCoverageOptions::SCK_None: return false; case SanitizerCoverageOptions::SCK_Function: - CreateFunctionGuardArray(1, F); + CreateFunctionLocalArrays(1, F); InjectCoverageAtBlock(F, F.getEntryBlock(), 0); return true; default: { - CreateFunctionGuardArray(AllBlocks.size(), F); + CreateFunctionLocalArrays(AllBlocks.size(), F); for (size_t i = 0, N = AllBlocks.size(); i < N; i++) InjectCoverageAtBlock(F, *AllBlocks[i], i); return true; @@ -436,7 +476,7 @@ void SanitizerCoverageModule::InjectCoverageForIndirectCalls( Function &F, ArrayRef IndirCalls) { if (IndirCalls.empty()) return; - assert(Options.TracePC || Options.TracePCGuard); + assert(Options.TracePC || Options.TracePCGuard || Options.Inline8bitCounters); for (auto I : IndirCalls) { IRBuilder<> IRB(I); CallSite CS(I); @@ -564,8 +604,8 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, if (Options.TracePC) { IRB.CreateCall(SanCovTracePC); // gets the PC using GET_CALLER_PC. IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge. - } else { - assert(Options.TracePCGuard); + } + if (Options.TracePCGuard) { auto GuardPtr = IRB.CreateIntToPtr( IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), ConstantInt::get(IntptrTy, Idx * 4)), @@ -573,26 +613,39 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, IRB.CreateCall(SanCovTracePCGuard, GuardPtr); IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge. } + if (Options.Inline8bitCounters) { + auto CounterPtr = IRB.CreateGEP( + Function8bitCounterArray, + {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); + auto Load = IRB.CreateLoad(CounterPtr); + auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1)); + auto Store = IRB.CreateStore(Inc, CounterPtr); + SetNoSanitizeMetadata(Load); + SetNoSanitizeMetadata(Store); + } } -StringRef SanitizerCoverageModule::getSanCovTracePCGuardSection() const { +std::string +SanitizerCoverageModule::getSectionName(const std::string &Section) const { if (TargetTriple.getObjectFormat() == Triple::COFF) return ".SCOV$M"; if (TargetTriple.isOSBinFormatMachO()) - return "__DATA,__sancov_guards"; - return "__sancov_guards"; + return "__DATA,__" + Section; + return "__" + Section; } -StringRef SanitizerCoverageModule::getSanCovTracePCGuardSectionStart() const { +std::string +SanitizerCoverageModule::getSectionStart(const std::string &Section) const { if (TargetTriple.isOSBinFormatMachO()) - return "\1section$start$__DATA$__sancov_guards"; - return "__start___sancov_guards"; + return "\1section$start$__DATA$__" + Section; + return "__start___" + Section; } -StringRef SanitizerCoverageModule::getSanCovTracePCGuardSectionEnd() const { +std::string +SanitizerCoverageModule::getSectionEnd(const std::string &Section) const { if (TargetTriple.isOSBinFormatMachO()) - return "\1section$end$__DATA$__sancov_guards"; - return "__stop___sancov_guards"; + return "\1section$end$__DATA$__" + Section; + return "__stop___" + Section; } diff --git a/contrib/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/contrib/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index 3953198fe605..9a7882211bac 100644 --- a/contrib/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1823,6 +1823,7 @@ static PHINode *getLoopPhiForCounter(Value *IncV, Loop *L, DominatorTree *DT) { // An IV counter must preserve its type. if (IncI->getNumOperands() == 2) break; + LLVM_FALLTHROUGH; default: return nullptr; } diff --git a/contrib/llvm/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp b/contrib/llvm/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp index 930696b036c0..7d8da9b453f9 100644 --- a/contrib/llvm/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp @@ -14,6 +14,7 @@ #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" @@ -83,6 +84,149 @@ static bool handleSwitchExpect(SwitchInst &SI) { return true; } +/// Handler for PHINodes that define the value argument to an +/// @llvm.expect call. +/// +/// If the operand of the phi has a constant value and it 'contradicts' +/// with the expected value of phi def, then the corresponding incoming +/// edge of the phi is unlikely to be taken. Using that information, +/// the branch probability info for the originating branch can be inferred. +static void handlePhiDef(CallInst *Expect) { + Value &Arg = *Expect->getArgOperand(0); + ConstantInt *ExpectedValue = cast(Expect->getArgOperand(1)); + const APInt &ExpectedPhiValue = ExpectedValue->getValue(); + + // Walk up in backward a list of instructions that + // have 'copy' semantics by 'stripping' the copies + // until a PHI node or an instruction of unknown kind + // is reached. Negation via xor is also handled. + // + // C = PHI(...); + // B = C; + // A = B; + // D = __builtin_expect(A, 0); + // + Value *V = &Arg; + SmallVector Operations; + while (!isa(V)) { + if (ZExtInst *ZExt = dyn_cast(V)) { + V = ZExt->getOperand(0); + Operations.push_back(ZExt); + continue; + } + + if (SExtInst *SExt = dyn_cast(V)) { + V = SExt->getOperand(0); + Operations.push_back(SExt); + continue; + } + + BinaryOperator *BinOp = dyn_cast(V); + if (!BinOp || BinOp->getOpcode() != Instruction::Xor) + return; + + ConstantInt *CInt = dyn_cast(BinOp->getOperand(1)); + if (!CInt) + return; + + V = BinOp->getOperand(0); + Operations.push_back(BinOp); + } + + // Executes the recorded operations on input 'Value'. + auto ApplyOperations = [&](const APInt &Value) { + APInt Result = Value; + for (auto Op : llvm::reverse(Operations)) { + switch (Op->getOpcode()) { + case Instruction::Xor: + Result ^= cast(Op->getOperand(1))->getValue(); + break; + case Instruction::ZExt: + Result = Result.zext(Op->getType()->getIntegerBitWidth()); + break; + case Instruction::SExt: + Result = Result.sext(Op->getType()->getIntegerBitWidth()); + break; + default: + llvm_unreachable("Unexpected operation"); + } + } + return Result; + }; + + auto *PhiDef = dyn_cast(V); + + // Get the first dominating conditional branch of the operand + // i's incoming block. + auto GetDomConditional = [&](unsigned i) -> BranchInst * { + BasicBlock *BB = PhiDef->getIncomingBlock(i); + BranchInst *BI = dyn_cast(BB->getTerminator()); + if (BI && BI->isConditional()) + return BI; + BB = BB->getSinglePredecessor(); + if (!BB) + return nullptr; + BI = dyn_cast(BB->getTerminator()); + if (!BI || BI->isUnconditional()) + return nullptr; + return BI; + }; + + // Now walk through all Phi operands to find phi oprerands with values + // conflicting with the expected phi output value. Any such operand + // indicates the incoming edge to that operand is unlikely. + for (unsigned i = 0, e = PhiDef->getNumIncomingValues(); i != e; ++i) { + + Value *PhiOpnd = PhiDef->getIncomingValue(i); + ConstantInt *CI = dyn_cast(PhiOpnd); + if (!CI) + continue; + + // Not an interesting case when IsUnlikely is false -- we can not infer + // anything useful when the operand value matches the expected phi + // output. + if (ExpectedPhiValue == ApplyOperations(CI->getValue())) + continue; + + BranchInst *BI = GetDomConditional(i); + if (!BI) + continue; + + MDBuilder MDB(PhiDef->getContext()); + + // There are two situations in which an operand of the PhiDef comes + // from a given successor of a branch instruction BI. + // 1) When the incoming block of the operand is the successor block; + // 2) When the incoming block is BI's enclosing block and the + // successor is the PhiDef's enclosing block. + // + // Returns true if the operand which comes from OpndIncomingBB + // comes from outgoing edge of BI that leads to Succ block. + auto *OpndIncomingBB = PhiDef->getIncomingBlock(i); + auto IsOpndComingFromSuccessor = [&](BasicBlock *Succ) { + if (OpndIncomingBB == Succ) + // If this successor is the incoming block for this + // Phi operand, then this successor does lead to the Phi. + return true; + if (OpndIncomingBB == BI->getParent() && Succ == PhiDef->getParent()) + // Otherwise, if the edge is directly from the branch + // to the Phi, this successor is the one feeding this + // Phi operand. + return true; + return false; + }; + + if (IsOpndComingFromSuccessor(BI->getSuccessor(1))) + BI->setMetadata( + LLVMContext::MD_prof, + MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight)); + else if (IsOpndComingFromSuccessor(BI->getSuccessor(0))) + BI->setMetadata( + LLVMContext::MD_prof, + MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight)); + } +} + // Handle both BranchInst and SelectInst. template static bool handleBrSelExpect(BrSelInst &BSI) { @@ -99,25 +243,31 @@ template static bool handleBrSelExpect(BrSelInst &BSI) { ICmpInst *CmpI = dyn_cast(BSI.getCondition()); CmpInst::Predicate Predicate; - uint64_t ValueComparedTo = 0; + ConstantInt *CmpConstOperand = nullptr; if (!CmpI) { CI = dyn_cast(BSI.getCondition()); Predicate = CmpInst::ICMP_NE; - ValueComparedTo = 0; } else { Predicate = CmpI->getPredicate(); if (Predicate != CmpInst::ICMP_NE && Predicate != CmpInst::ICMP_EQ) return false; - ConstantInt *CmpConstOperand = dyn_cast(CmpI->getOperand(1)); + + CmpConstOperand = dyn_cast(CmpI->getOperand(1)); if (!CmpConstOperand) return false; - ValueComparedTo = CmpConstOperand->getZExtValue(); CI = dyn_cast(CmpI->getOperand(0)); } if (!CI) return false; + uint64_t ValueComparedTo = 0; + if (CmpConstOperand) { + if (CmpConstOperand->getBitWidth() > 64) + return false; + ValueComparedTo = CmpConstOperand->getZExtValue(); + } + Function *Fn = CI->getCalledFunction(); if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect) return false; @@ -181,6 +331,10 @@ static bool lowerExpectIntrinsic(Function &F) { Function *Fn = CI->getCalledFunction(); if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) { + // Before erasing the llvm.expect, walk backward to find + // phi that define llvm.expect's first arg, and + // infer branch probability: + handlePhiDef(CI); Value *Exp = CI->getArgOperand(0); CI->replaceAllUsesWith(Exp); CI->eraseFromParent(); diff --git a/contrib/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/contrib/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp index 77b2bd84f9b6..350b50ffcdd4 100644 --- a/contrib/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// // -// Rewrite an existing set of gc.statepoints such that they make potential -// relocations performed by the garbage collector explicit in the IR. +// Rewrite call/invoke instructions so as to make potential relocations +// performed by the garbage collector explicit in the IR. // //===----------------------------------------------------------------------===// @@ -2094,9 +2094,9 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, // live in the IR. We'll remove all of these when done. SmallVector Holders; - // Insert a dummy call with all of the arguments to the vm_state we'll need - // for the actual safepoint insertion. This ensures reference arguments in - // the deopt argument list are considered live through the safepoint (and + // Insert a dummy call with all of the deopt operands we'll need for the + // actual safepoint insertion as arguments. This ensures reference operands + // in the deopt argument list are considered live through the safepoint (and // thus makes sure they get relocated.) for (CallSite CS : ToUpdate) { SmallVector DeoptValues; diff --git a/contrib/llvm/lib/Transforms/Scalar/SROA.cpp b/contrib/llvm/lib/Transforms/Scalar/SROA.cpp index 6e113bccff94..fb1b5813fd79 100644 --- a/contrib/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/SROA.cpp @@ -3698,7 +3698,8 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { int Idx = 0, Size = Offsets.Splits.size(); for (;;) { auto *PartTy = Type::getIntNTy(Ty->getContext(), PartSize * 8); - auto *PartPtrTy = PartTy->getPointerTo(SI->getPointerAddressSpace()); + auto *LoadPartPtrTy = PartTy->getPointerTo(LI->getPointerAddressSpace()); + auto *StorePartPtrTy = PartTy->getPointerTo(SI->getPointerAddressSpace()); // Either lookup a split load or create one. LoadInst *PLoad; @@ -3709,7 +3710,7 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { PLoad = IRB.CreateAlignedLoad( getAdjustedPtr(IRB, DL, LoadBasePtr, APInt(DL.getPointerSizeInBits(), PartOffset), - PartPtrTy, LoadBasePtr->getName() + "."), + LoadPartPtrTy, LoadBasePtr->getName() + "."), getAdjustedAlignment(LI, PartOffset, DL), /*IsVolatile*/ false, LI->getName()); } @@ -3719,7 +3720,7 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { StoreInst *PStore = IRB.CreateAlignedStore( PLoad, getAdjustedPtr(IRB, DL, StoreBasePtr, APInt(DL.getPointerSizeInBits(), PartOffset), - PartPtrTy, StoreBasePtr->getName() + "."), + StorePartPtrTy, StoreBasePtr->getName() + "."), getAdjustedAlignment(SI, PartOffset, DL), /*IsVolatile*/ false); // Now build a new slice for the alloca. diff --git a/contrib/llvm/lib/Transforms/Utils/CloneFunction.cpp b/contrib/llvm/lib/Transforms/Utils/CloneFunction.cpp index 1ec3d0d49637..1c1a75c111e9 100644 --- a/contrib/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/contrib/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -37,10 +37,10 @@ using namespace llvm; /// See comments in Cloning.h. -BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, - ValueToValueMapTy &VMap, +BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix, Function *F, - ClonedCodeInfo *CodeInfo) { + ClonedCodeInfo *CodeInfo, + DebugInfoFinder *DIFinder) { DenseMap Cache; BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), "", F); if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix); @@ -50,10 +50,11 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, // Loop over all instructions, and copy them over. for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end(); II != IE; ++II) { + + if (DIFinder && F->getParent() && II->getDebugLoc()) + DIFinder->processLocation(*F->getParent(), II->getDebugLoc().get()); + Instruction *NewInst = II->clone(); - if (F && F->getSubprogram()) - DebugLoc::reparentDebugInfo(*NewInst, BB->getParent()->getSubprogram(), - F->getSubprogram(), Cache); if (II->hasName()) NewInst->setName(II->getName()+NameSuffix); NewBB->getInstList().push_back(NewInst); @@ -122,31 +123,38 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, AttributeList::get(NewFunc->getContext(), OldAttrs.getFnAttributes(), OldAttrs.getRetAttributes(), NewArgAttrs)); + bool MustCloneSP = + OldFunc->getParent() && OldFunc->getParent() == NewFunc->getParent(); + DISubprogram *SP = OldFunc->getSubprogram(); + if (SP) { + assert(!MustCloneSP || ModuleLevelChanges); + // Add mappings for some DebugInfo nodes that we don't want duplicated + // even if they're distinct. + auto &MD = VMap.MD(); + MD[SP->getUnit()].reset(SP->getUnit()); + MD[SP->getType()].reset(SP->getType()); + MD[SP->getFile()].reset(SP->getFile()); + // If we're not cloning into the same module, no need to clone the + // subprogram + if (!MustCloneSP) + MD[SP].reset(SP); + } + SmallVector, 1> MDs; OldFunc->getAllMetadata(MDs); for (auto MD : MDs) { - MDNode *NewMD; - bool MustCloneSP = - (MD.first == LLVMContext::MD_dbg && OldFunc->getParent() && - OldFunc->getParent() == NewFunc->getParent()); - if (MustCloneSP) { - auto *SP = cast(MD.second); - NewMD = DISubprogram::getDistinct( - NewFunc->getContext(), SP->getScope(), SP->getName(), - SP->getLinkageName(), SP->getFile(), SP->getLine(), SP->getType(), - SP->isLocalToUnit(), SP->isDefinition(), SP->getScopeLine(), - SP->getContainingType(), SP->getVirtuality(), SP->getVirtualIndex(), - SP->getThisAdjustment(), SP->getFlags(), SP->isOptimized(), - SP->getUnit(), SP->getTemplateParams(), SP->getDeclaration(), - SP->getVariables(), SP->getThrownTypes()); - } else - NewMD = - MapMetadata(MD.second, VMap, - ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, - TypeMapper, Materializer); - NewFunc->addMetadata(MD.first, *NewMD); + NewFunc->addMetadata( + MD.first, + *MapMetadata(MD.second, VMap, + ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, + TypeMapper, Materializer)); } + // When we remap instructions, we want to avoid duplicating inlined + // DISubprograms, so record all subprograms we find as we duplicate + // instructions and then freeze them in the MD map. + DebugInfoFinder DIFinder; + // Loop over all of the basic blocks in the function, cloning them as // appropriate. Note that we save BE this way in order to handle cloning of // recursive functions into themselves. @@ -156,7 +164,8 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, const BasicBlock &BB = *BI; // Create a new basic block and copy instructions into it! - BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo); + BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo, + SP ? &DIFinder : nullptr); // Add basic block mapping. VMap[&BB] = CBB; @@ -178,6 +187,12 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, Returns.push_back(RI); } + for (DISubprogram *ISP : DIFinder.subprograms()) { + if (ISP != SP) { + VMap.MD()[ISP].reset(ISP); + } + } + // Loop over all of the instructions in the function, fixing up operand // references as we go. This uses VMap to do all the hard work. for (Function::iterator BB = @@ -226,7 +241,7 @@ Function *llvm::CloneFunction(Function *F, ValueToValueMapTy &VMap, } SmallVector Returns; // Ignore returns cloned. - CloneFunctionInto(NewF, F, VMap, /*ModuleLevelChanges=*/false, Returns, "", + CloneFunctionInto(NewF, F, VMap, F->getSubprogram() != nullptr, Returns, "", CodeInfo); return NewF; diff --git a/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 8b9a64c220cc..799eef21dc4e 100644 --- a/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -4779,6 +4779,7 @@ void InnerLoopVectorizer::vectorizeInstruction(Instruction &I) { scalarizeInstruction(&I, true); break; } + LLVM_FALLTHROUGH; case Instruction::Add: case Instruction::FAdd: case Instruction::Sub: @@ -7396,6 +7397,7 @@ unsigned LoopVectorizationCostModel::getInstructionCost(Instruction *I, // likely. return Cost / getReciprocalPredBlockProb(); } + LLVM_FALLTHROUGH; case Instruction::Add: case Instruction::FAdd: case Instruction::Sub: diff --git a/contrib/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/contrib/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index e6f78e6b94a3..d1349535f298 100644 --- a/contrib/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/contrib/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -259,6 +259,7 @@ static bool InTreeUserNeedToExtract(Value *Scalar, Instruction *UserInst, if (hasVectorInstrinsicScalarOpd(ID, 1)) { return (CI->getArgOperand(1) == Scalar); } + LLVM_FALLTHROUGH; } default: return false; @@ -4749,56 +4750,18 @@ static Value *getReductionValue(const DominatorTree *DT, PHINode *P, return nullptr; } -namespace { -/// Tracks instructons and its children. -class WeakTrackingVHWithLevel final : public CallbackVH { - /// Operand index of the instruction currently beeing analized. - unsigned Level = 0; - /// Is this the instruction that should be vectorized, or are we now - /// processing children (i.e. operands of this instruction) for potential - /// vectorization? - bool IsInitial = true; - -public: - explicit WeakTrackingVHWithLevel() = default; - WeakTrackingVHWithLevel(Value *V) : CallbackVH(V){}; - /// Restart children analysis each time it is repaced by the new instruction. - void allUsesReplacedWith(Value *New) override { - setValPtr(New); - Level = 0; - IsInitial = true; - } - /// Check if the instruction was not deleted during vectorization. - bool isValid() const { return !getValPtr(); } - /// Is the istruction itself must be vectorized? - bool isInitial() const { return IsInitial; } - /// Try to vectorize children. - void clearInitial() { IsInitial = false; } - /// Are all children processed already? - bool isFinal() const { - assert(getValPtr() && - (isa(getValPtr()) && - cast(getValPtr())->getNumOperands() >= Level)); - return getValPtr() && - cast(getValPtr())->getNumOperands() == Level; - } - /// Get next child operation. - Value *nextOperand() { - assert(getValPtr() && isa(getValPtr()) && - cast(getValPtr())->getNumOperands() > Level); - return cast(getValPtr())->getOperand(Level++); - } - virtual ~WeakTrackingVHWithLevel() = default; -}; -} // namespace - -/// \brief Attempt to reduce a horizontal reduction. -/// If it is legal to match a horizontal reduction feeding -/// the phi node P with reduction operators Root in a basic block BB, then check -/// if it can be done. -/// \returns true if a horizontal reduction was matched and reduced. -/// \returns false if a horizontal reduction was not matched. -static bool canBeVectorized( +/// Attempt to reduce a horizontal reduction. +/// If it is legal to match a horizontal reduction feeding the phi node \a P +/// with reduction operators \a Root (or one of its operands) in a basic block +/// \a BB, then check if it can be done. If horizontal reduction is not found +/// and root instruction is a binary operation, vectorization of the operands is +/// attempted. +/// \returns true if a horizontal reduction was matched and reduced or operands +/// of one of the binary instruction were vectorized. +/// \returns false if a horizontal reduction was not matched (or not possible) +/// or no vectorization of any binary operation feeding \a Root instruction was +/// performed. +static bool tryToVectorizeHorReductionOrInstOperands( PHINode *P, Instruction *Root, BasicBlock *BB, BoUpSLP &R, TargetTransformInfo *TTI, const function_ref Vectorize) { @@ -4810,56 +4773,62 @@ static bool canBeVectorized( if (Root->getParent() != BB) return false; - SmallVector Stack(1, Root); + // Start analysis starting from Root instruction. If horizontal reduction is + // found, try to vectorize it. If it is not a horizontal reduction or + // vectorization is not possible or not effective, and currently analyzed + // instruction is a binary operation, try to vectorize the operands, using + // pre-order DFS traversal order. If the operands were not vectorized, repeat + // the same procedure considering each operand as a possible root of the + // horizontal reduction. + // Interrupt the process if the Root instruction itself was vectorized or all + // sub-trees not higher that RecursionMaxDepth were analyzed/vectorized. + SmallVector, 8> Stack(1, {Root, 0}); SmallSet VisitedInstrs; bool Res = false; while (!Stack.empty()) { - Value *V = Stack.back(); - if (!V) { - Stack.pop_back(); + Value *V; + unsigned Level; + std::tie(V, Level) = Stack.pop_back_val(); + if (!V) continue; - } auto *Inst = dyn_cast(V); - if (!Inst || isa(Inst)) { - Stack.pop_back(); + if (!Inst || isa(Inst)) continue; - } - if (Stack.back().isInitial()) { - Stack.back().clearInitial(); - if (auto *BI = dyn_cast(Inst)) { - HorizontalReduction HorRdx; - if (HorRdx.matchAssociativeReduction(P, BI)) { - if (HorRdx.tryToReduce(R, TTI)) { - Res = true; - P = nullptr; - continue; - } - } - if (P) { - Inst = dyn_cast(BI->getOperand(0)); - if (Inst == P) - Inst = dyn_cast(BI->getOperand(1)); - if (!Inst) { - P = nullptr; - continue; - } + if (auto *BI = dyn_cast(Inst)) { + HorizontalReduction HorRdx; + if (HorRdx.matchAssociativeReduction(P, BI)) { + if (HorRdx.tryToReduce(R, TTI)) { + Res = true; + // Set P to nullptr to avoid re-analysis of phi node in + // matchAssociativeReduction function unless this is the root node. + P = nullptr; + continue; } } - P = nullptr; - if (Vectorize(dyn_cast(Inst), R)) { - Res = true; - continue; + if (P) { + Inst = dyn_cast(BI->getOperand(0)); + if (Inst == P) + Inst = dyn_cast(BI->getOperand(1)); + if (!Inst) { + // Set P to nullptr to avoid re-analysis of phi node in + // matchAssociativeReduction function unless this is the root node. + P = nullptr; + continue; + } } } - if (Stack.back().isFinal()) { - Stack.pop_back(); + // Set P to nullptr to avoid re-analysis of phi node in + // matchAssociativeReduction function unless this is the root node. + P = nullptr; + if (Vectorize(dyn_cast(Inst), R)) { + Res = true; continue; } - if (auto *NextV = dyn_cast(Stack.back().nextOperand())) - if (NextV->getParent() == BB && VisitedInstrs.insert(NextV).second && - Stack.size() < RecursionMaxDepth) - Stack.push_back(NextV); + // Try to vectorize operands. + if (++Level < RecursionMaxDepth) + for (auto *Op : Inst->operand_values()) + Stack.emplace_back(Op, Level); } return Res; } @@ -4876,10 +4845,10 @@ bool SLPVectorizerPass::vectorizeRootInstruction(PHINode *P, Value *V, if (!isa(I)) P = nullptr; // Try to match and vectorize a horizontal reduction. - return canBeVectorized(P, I, BB, R, TTI, - [this](BinaryOperator *BI, BoUpSLP &R) -> bool { - return tryToVectorize(BI, R); - }); + return tryToVectorizeHorReductionOrInstOperands( + P, I, BB, R, TTI, [this](BinaryOperator *BI, BoUpSLP &R) -> bool { + return tryToVectorize(BI, R); + }); } bool SLPVectorizerPass::vectorizeChainsInBlock(BasicBlock *BB, BoUpSLP &R) { diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td index b393ce5f1545..447f06945660 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -664,6 +664,12 @@ def warn_mmap_mismatched_top_level_private : Warning< InGroup; def note_mmap_rename_top_level_private_as_submodule : Note< "make '%0' a submodule of '%1' to ensure it can be found by name">; +def err_mmap_duplicate_header_attribute : Error< + "header attribute '%0' specified multiple times">; +def err_mmap_invalid_header_attribute_value : Error< + "expected integer literal as value for header attribute '%0'">; +def err_mmap_expected_header_attribute : Error< + "expected a header attribute name ('size' or 'mtime')">; def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4de4f47b8a5a..a5a5c74afe69 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4584,7 +4584,7 @@ def warn_missing_prototype : Warning< def note_declaration_not_a_prototype : Note< "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">; def warn_strict_prototypes : Warning< - "this %select{function declaration is not|" + "this %select{function declaration is not|block declaration is not|" "old-style function definition is not preceded by}0 a prototype">, InGroup>, DefaultIgnore; def warn_missing_variable_declarations : Warning< @@ -7268,7 +7268,7 @@ def err_invalid_conversion_between_vector_and_integer : Error< "invalid conversion between vector type %0 and integer type %1 " "of different size">; -def err_opencl_function_pointer_variable : Error< +def err_opencl_function_pointer : Error< "pointers to functions are not allowed">; def err_opencl_taking_function_address : Error< diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td index 35e2f67e24b6..f9e7b8fa9b56 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -174,10 +174,6 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "method %2 with %ordinal3 parameter of type %4%select{| decayed from %6}5|" "method %2 with %ordinal3 parameter named %4}1">; -def warn_module_uses_date_time : Warning< - "%select{precompiled header|module}0 uses __DATE__ or __TIME__">, - InGroup>; - def warn_duplicate_module_file_extension : Warning< "duplicate module file extension block name '%0'">, InGroup; @@ -186,7 +182,15 @@ def warn_module_system_bit_conflict : Warning< "module file '%0' was validated as a system module and is now being imported " "as a non-system module; any difference in diagnostic options will be ignored">, InGroup; +} // let CategoryName +let CategoryName = "AST Serialization Issue" in { +def warn_module_uses_date_time : Warning< + "%select{precompiled header|module}0 uses __DATE__ or __TIME__">, + InGroup>; +def err_module_no_size_mtime_for_header : Error< + "cannot emit module %0: %select{size|mtime}1 must be explicitly specified " + "for missing header file \"%2\"">; } // let CategoryName } // let Component diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Module.h b/contrib/llvm/tools/clang/include/clang/Basic/Module.h index 326d84eeb6c2..1e52b29367b2 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Module.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Module.h @@ -154,11 +154,19 @@ public: /// \brief Stored information about a header directive that was found in the /// module map file but has not been resolved to a file. struct UnresolvedHeaderDirective { + HeaderKind Kind = HK_Normal; SourceLocation FileNameLoc; std::string FileName; - bool IsUmbrella; + bool IsUmbrella = false; + bool HasBuiltinHeader = false; + Optional Size; + Optional ModTime; }; + /// Headers that are mentioned in the module map file but that we have not + /// yet attempted to resolve to a file on the file system. + SmallVector UnresolvedHeaders; + /// \brief Headers that are mentioned in the module map file but could not be /// found on the file system. SmallVector MissingHeaders; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h index bfa8e516edd3..5317720095e0 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h @@ -61,8 +61,8 @@ struct SanitizerSet { Mask = Value ? (Mask | K) : (Mask & ~K); } - /// \brief Disable all sanitizers. - void clear() { Mask = 0; } + /// Disable the sanitizers specified in \p K. + void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; } /// \brief Returns true if at least one sanitizer is enabled. bool empty() const { return Mask == 0; } @@ -79,6 +79,12 @@ SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups); /// this group enables. SanitizerMask expandSanitizerGroups(SanitizerMask Kinds); +/// Return the sanitizers which do not affect preprocessing. +static inline SanitizerMask getPPTransparentSanitizers() { + return SanitizerKind::CFI | SanitizerKind::Integer | + SanitizerKind::Nullability | SanitizerKind::Undefined; +} + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td index b55289dc35a1..1132d1345f60 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td @@ -293,6 +293,9 @@ def fsanitize_coverage_trace_gep def fsanitize_coverage_8bit_counters : Flag<["-"], "fsanitize-coverage-8bit-counters">, HelpText<"Enable frequency counters in sanitizer coverage">; +def fsanitize_coverage_inline_8bit_counters + : Flag<["-"], "fsanitize-coverage-inline-8bit-counters">, + HelpText<"Enable inline 8-bit counters in sanitizer coverage">; def fsanitize_coverage_trace_pc : Flag<["-"], "fsanitize-coverage-trace-pc">, HelpText<"Enable PC tracing in sanitizer coverage">; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def index 9a13854671d2..d7cd805fa10a 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def @@ -163,6 +163,7 @@ CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing ///< in sanitizer coverage. CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters. CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning. CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h index c05faa4a8201..11506939f9b1 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h @@ -26,6 +26,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/Twine.h" #include #include @@ -116,6 +117,11 @@ public: // Adjust ModuleMap::addHeader. }; + /// Convert a header kind to a role. Requires Kind to not be HK_Excluded. + static ModuleHeaderRole headerKindToRole(Module::HeaderKind Kind); + /// Convert a header role to a kind. + static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role); + /// \brief A header that is known to reside within a given module, /// whether it was included or excluded. class KnownHeader { @@ -165,7 +171,13 @@ private: /// \brief Mapping from each header to the module that owns the contents of /// that header. HeadersMap Headers; - + + /// Map from file sizes to modules with lazy header directives of that size. + mutable llvm::DenseMap> LazyHeadersBySize; + /// Map from mtimes to modules with lazy header directives with those mtimes. + mutable llvm::DenseMap> + LazyHeadersByModTime; + /// \brief Mapping from directories with umbrella headers to the module /// that is generated from the umbrella header. /// @@ -257,22 +269,30 @@ private: /// resolved. Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const; - /// Resolve the given header directive to an actual header file. + /// Add an unresolved header to a module. + void addUnresolvedHeader(Module *Mod, + Module::UnresolvedHeaderDirective Header); + + /// Look up the given header directive to find an actual header file. /// /// \param M The module in which we're resolving the header directive. /// \param Header The header directive to resolve. /// \param RelativePathName Filled in with the relative path name from the /// module to the resolved header. /// \return The resolved file, if any. - const FileEntry *resolveHeader(Module *M, - Module::UnresolvedHeaderDirective Header, - SmallVectorImpl &RelativePathName); + const FileEntry *findHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header, + SmallVectorImpl &RelativePathName); + + /// Resolve the given header directive. + void resolveHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header); /// Attempt to resolve the specified header directive as naming a builtin /// header. - const FileEntry * - resolveAsBuiltinHeader(Module *M, Module::UnresolvedHeaderDirective Header, - SmallVectorImpl &BuiltinPathName); + /// \return \c true if a corresponding builtin header was found. + bool resolveAsBuiltinHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header); /// \brief Looks up the modules that \p File corresponds to. /// @@ -368,6 +388,15 @@ public: /// the preferred module for the header. ArrayRef findAllModulesForHeader(const FileEntry *File) const; + /// Resolve all lazy header directives for the specified file. + /// + /// This ensures that the HeaderFileInfo on HeaderSearch is up to date. This + /// is effectively internal, but is exposed so HeaderSearch can call it. + void resolveHeaderDirectives(const FileEntry *File) const; + + /// Resolve all lazy header directives for the specified module. + void resolveHeaderDirectives(Module *Mod) const; + /// \brief Reports errors if a module must not include a specific file. /// /// \param RequestingModule The module including a file. diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp index f81133f3aad3..389f3655aa52 100644 --- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp @@ -78,6 +78,7 @@ public: } } // Pass through. + LLVM_FALLTHROUGH; case OMF_retain: case OMF_release: if (E->getReceiverKind() == ObjCMessageExpr::Instance) diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp index c628b54ed414..4f3fb5845925 100644 --- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp +++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp @@ -539,6 +539,7 @@ void TransformActionsImpl::addRemoval(CharSourceRange range) { return; case Range_Contains: RI->End = newRange.End; + LLVM_FALLTHROUGH; case Range_ExtendsBegin: newRange.End = RI->End; Removals.erase(RI); diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 29d970e66d71..34c4d2617ec9 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -6240,6 +6240,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += "{objc_class=}"; return; } + // TODO: Double check to make sure this intentially falls through. + LLVM_FALLTHROUGH; } case Type::ObjCInterface: { diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 03e6115a0dba..b43c28deb362 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -360,6 +360,7 @@ void clang::FormatASTNodeDiagnosticArgument( Modifier = StringRef(); Argument = StringRef(); // Fall through + LLVM_FALLTHROUGH; } case DiagnosticsEngine::ak_qualtype: { assert(Modifier.empty() && Argument.empty() && diff --git a/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp b/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp index 9376ee1d4ee4..eff1aa5e323d 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -424,6 +424,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; // Fall through to check the bits common with FunctionNoProtoType. + LLVM_FALLTHROUGH; } case Type::FunctionNoProto: { diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index bc8a34c93653..6eeba88e4033 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -1189,7 +1189,9 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { for (const auto *PI : OMD->parameters()) { // FIXME: selector is missing here! pos = name.find_first_of(':', lastPos); - Out << " " << name.substr(lastPos, pos - lastPos) << ':'; + if (lastPos != 0) + Out << " "; + Out << name.substr(lastPos, pos - lastPos) << ':'; PrintObjCMethodType(OMD->getASTContext(), PI->getObjCDeclQualifier(), PI->getType()); @@ -1198,7 +1200,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { } if (OMD->param_begin() == OMD->param_end()) - Out << " " << name; + Out << name; if (OMD->isVariadic()) Out << ", ..."; diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index d523a0f93cf6..c21cd3f65bd4 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -1576,6 +1576,7 @@ bool CastExpr::CastConsistency() const { getSubExpr()->getType()->isBlockPointerType()); assert(getType()->getPointeeType().getAddressSpace() != getSubExpr()->getType()->getPointeeType().getAddressSpace()); + LLVM_FALLTHROUGH; // These should not have an inheritance path. case CK_Dynamic: case CK_ToUnion: @@ -2102,6 +2103,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, } // Fallthrough for generic call handling. + LLVM_FALLTHROUGH; } case CallExprClass: case CXXMemberCallExprClass: diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index c19812e341c0..17d0ce67dcf9 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -736,6 +736,7 @@ namespace { if (!HasFoldFailureDiagnostic) break; // We've already failed to fold something. Keep that diagnostic. + LLVM_FALLTHROUGH; case EM_ConstantExpression: case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: @@ -10374,6 +10375,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { } // OffsetOf falls through here. + LLVM_FALLTHROUGH; } case Expr::OffsetOfExprClass: { // Note that per C99, offsetof must be an ICE. And AFAIK, using @@ -10476,6 +10478,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return Worst(LHSResult, RHSResult); } } + LLVM_FALLTHROUGH; } case Expr::ImplicitCastExprClass: case Expr::CStyleCastExprClass: diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index 7db0b4d8e4ff..c9bb45a37eb5 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -1459,8 +1459,6 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. MethodQuals.removeRestrict(); - // __unaligned is not currently mangled in any way, so remove it. - MethodQuals.removeUnaligned(); mangleQualifiers(MethodQuals); mangleRefQualifier(Method->getRefQualifier()); } @@ -2140,7 +2138,8 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { } void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { - // Vendor qualifiers come first. + // Vendor qualifiers come first and if they are order-insensitive they must + // be emitted in reversed alphabetical order, see Itanium ABI 5.1.5. // Address space qualifiers start with an ordinary letter. if (Quals.hasAddressSpace()) { @@ -2176,17 +2175,28 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { } // The ARC ownership qualifiers start with underscores. - switch (Quals.getObjCLifetime()) { // Objective-C ARC Extension: // // ::= U "__strong" // ::= U "__weak" // ::= U "__autoreleasing" + // + // Note: we emit __weak first to preserve the order as + // required by the Itanium ABI. + if (Quals.getObjCLifetime() == Qualifiers::OCL_Weak) + mangleVendorQualifier("__weak"); + + // __unaligned (from -fms-extensions) + if (Quals.hasUnaligned()) + mangleVendorQualifier("__unaligned"); + + // Remaining ARC ownership qualifiers. + switch (Quals.getObjCLifetime()) { case Qualifiers::OCL_None: break; case Qualifiers::OCL_Weak: - mangleVendorQualifier("__weak"); + // Do nothing as we already handled this case above. break; case Qualifiers::OCL_Strong: @@ -3775,6 +3785,7 @@ recurse: Out << "v1U" << Kind.size() << Kind; } // Fall through to mangle the cast itself. + LLVM_FALLTHROUGH; case Expr::CStyleCastExprClass: mangleCastExpression(E, "cv"); @@ -4327,7 +4338,7 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { /// substitutions. static bool hasMangledSubstitutionQualifiers(QualType T) { Qualifiers Qs = T.getQualifiers(); - return Qs.getCVRQualifiers() || Qs.hasAddressSpace(); + return Qs.getCVRQualifiers() || Qs.hasAddressSpace() || Qs.hasUnaligned(); } bool CXXNameMangler::mangleSubstitution(QualType T) { diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index 514c7c9f5b33..e2e0dbeec0dd 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -290,6 +290,7 @@ NestedNameSpecifier::print(raw_ostream &OS, case TypeSpecWithTemplate: OS << "template "; // Fall through to print the type. + LLVM_FALLTHROUGH; case TypeSpec: { const Type *T = getAsType(); diff --git a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp index ed7193ecb437..60556697113a 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp @@ -441,6 +441,7 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, case LengthModifier::AsShort: if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) return Ctx.IntTy; + LLVM_FALLTHROUGH; default: return ArgType::Invalid(); } diff --git a/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp b/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp index 614f676fb193..83b545a7be83 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp @@ -109,6 +109,7 @@ void PseudoConstantAnalysis::RunAnalysis() { // Do not visit the children continue; + LLVM_FALLTHROUGH; } case BO_AddAssign: case BO_SubAssign: diff --git a/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp index 3b93f1a57f1f..534225985460 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp @@ -341,6 +341,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsShort: if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) return ArgType::PtrTo(ArgType::AnyCharTy); + LLVM_FALLTHROUGH; default: return ArgType::Invalid(); } @@ -357,6 +358,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsShort: if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) return ArgType::PtrTo(ArgType::AnyCharTy); + LLVM_FALLTHROUGH; default: return ArgType::Invalid(); } diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp index 74c85376c7db..372e0c417fd4 100644 --- a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp @@ -551,6 +551,7 @@ ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) { case 's': if (startsWithWord(name, "shared")) return OIT_ReturnsSelf; if (startsWithWord(name, "standard")) return OIT_Singleton; + break; case 'i': if (startsWithWord(name, "init")) return OIT_Init; default: diff --git a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp index c8a774311efe..db81507aa209 100644 --- a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp @@ -29,9 +29,7 @@ void LangOptions::resetNonModularOptions() { Name = Default; #include "clang/Basic/LangOptions.def" - // FIXME: This should not be reset; modules can be different with different - // sanitizer options (this affects __has_feature(address_sanitizer) etc). - Sanitize.clear(); + // These options do not affect AST generation. SanitizerBlacklistFiles.clear(); XRayAlwaysInstrumentFiles.clear(); XRayNeverInstrumentFiles.clear(); diff --git a/contrib/llvm/tools/clang/lib/Basic/Module.cpp b/contrib/llvm/tools/clang/lib/Basic/Module.cpp index ac3d7c559679..83c524877ab0 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Module.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Module.cpp @@ -394,11 +394,30 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { {"exclude ", HK_Excluded}}; for (auto &K : Kinds) { + assert(&K == &Kinds[K.Kind] && "kinds in wrong order"); for (auto &H : Headers[K.Kind]) { OS.indent(Indent + 2); OS << K.Prefix << "header \""; OS.write_escaped(H.NameAsWritten); - OS << "\"\n"; + OS << "\" { size " << H.Entry->getSize() + << " mtime " << H.Entry->getModificationTime() << " }\n"; + } + } + for (auto *Unresolved : {&UnresolvedHeaders, &MissingHeaders}) { + for (auto &U : *Unresolved) { + OS.indent(Indent + 2); + OS << Kinds[U.Kind].Prefix << "header \""; + OS.write_escaped(U.FileName); + OS << "\""; + if (U.Size || U.ModTime) { + OS << " {"; + if (U.Size) + OS << " size " << *U.Size; + if (U.ModTime) + OS << " mtime " << *U.ModTime; + OS << " }"; + } + OS << "\n"; } } diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp index e19404dc54cb..8cfd8bde9cbb 100644 --- a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp @@ -143,9 +143,11 @@ const char *TargetInfo::getTypeConstantSuffix(IntType T) const { case UnsignedChar: if (getCharWidth() < getIntWidth()) return ""; + LLVM_FALLTHROUGH; case UnsignedShort: if (getShortWidth() < getIntWidth()) return ""; + LLVM_FALLTHROUGH; case UnsignedInt: return "U"; case UnsignedLong: return "UL"; case UnsignedLongLong: return "ULL"; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp index 0f07169ac8b0..fd193bcf1a69 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp @@ -49,6 +49,7 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" @@ -186,6 +187,7 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, Opts.TracePC = CGOpts.SanitizeCoverageTracePC; Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard; Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune; + Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters; PM.add(createSanitizerCoverageModulePass(Opts)); } @@ -897,6 +899,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( // create that pass manager here and use it as needed below. legacy::PassManager CodeGenPasses; bool NeedCodeGen = false; + Optional ThinLinkOS; // Append any output we need to the pass manager. switch (Action) { @@ -904,9 +907,24 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( break; case Backend_EmitBC: - MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, - CodeGenOpts.EmitSummaryIndex, - CodeGenOpts.EmitSummaryIndex)); + if (CodeGenOpts.EmitSummaryIndex) { + if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { + std::error_code EC; + ThinLinkOS.emplace(CodeGenOpts.ThinLinkBitcodeFile, EC, + llvm::sys::fs::F_None); + if (EC) { + Diags.Report(diag::err_fe_unable_to_open_output) + << CodeGenOpts.ThinLinkBitcodeFile << EC.message(); + return; + } + } + MPM.addPass( + ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &*ThinLinkOS : nullptr)); + } else { + MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, + CodeGenOpts.EmitSummaryIndex, + CodeGenOpts.EmitSummaryIndex)); + } break; case Backend_EmitLL: @@ -1029,6 +1047,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, Conf.CGOptLevel = getCGOptLevel(CGOpts); initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); Conf.SampleProfile = std::move(SampleProfile); + Conf.UseNewPM = CGOpts.ExperimentalNewPassManager; switch (Action) { case Backend_EmitNothing: Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp index 2134fb9e03e4..3b4f8854a9ca 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp @@ -2659,6 +2659,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), llvm::ArrayRef(Args))); } + LLVM_FALLTHROUGH; } // OpenCL v2.0 s6.13.17.6 - Kernel query functions need bitcast of block // parameter. @@ -3813,6 +3814,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vcalt_v: case NEON::BI__builtin_neon_vcaltq_v: std::swap(Ops[0], Ops[1]); + LLVM_FALLTHROUGH; case NEON::BI__builtin_neon_vcage_v: case NEON::BI__builtin_neon_vcageq_v: case NEON::BI__builtin_neon_vcagt_v: @@ -5056,6 +5058,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vsri_n_v: case NEON::BI__builtin_neon_vsriq_n_v: rightShift = true; + LLVM_FALLTHROUGH; case NEON::BI__builtin_neon_vsli_n_v: case NEON::BI__builtin_neon_vsliq_n_v: Ops[2] = EmitNeonShiftVector(Ops[2], Ty, rightShift); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp index 8f405eee6e52..079064733585 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp @@ -4259,6 +4259,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Builder.CreateStore(elt, eltAddr); } // FALLTHROUGH + LLVM_FALLTHROUGH; } case ABIArgInfo::InAlloca: diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp index f65fb5b9232a..bc5f6327c9a0 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp @@ -625,6 +625,7 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_id has" " been used earlier in this function"); // Fallthrough to the next case to add TokenNone as the first argument. + LLVM_FALLTHROUGH; } // @llvm.coro.suspend takes a token parameter. Add token 'none' as the first // argument. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp index 0a1dc09211c2..02db79159b58 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2781,6 +2781,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { // them distinct if they are ODR-uniqued. if (FullName.empty()) break; + LLVM_FALLTHROUGH; case llvm::dwarf::DW_TAG_structure_type: case llvm::dwarf::DW_TAG_union_type: @@ -3263,7 +3264,7 @@ void CGDebugInfo::EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD) { void CGDebugInfo::EmitInlineFunctionEnd(CGBuilderTy &Builder) { assert(CurInlinedAt && "unbalanced inline scope stack"); - EmitFunctionEnd(Builder); + EmitFunctionEnd(Builder, nullptr); setInlinedAt(llvm::DebugLoc(CurInlinedAt).getInlinedAt()); } @@ -3332,7 +3333,7 @@ void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, LexicalBlockStack.pop_back(); } -void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { +void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn) { assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); unsigned RCount = FnBeginRegionCount.back(); assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch"); @@ -3344,6 +3345,9 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { LexicalBlockStack.pop_back(); } FnBeginRegionCount.pop_back(); + + if (Fn && Fn->getSubprogram()) + DBuilder.finalizeSubprogram(Fn->getSubprogram()); } llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h index 7de48f278994..39249c7cf4da 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h @@ -367,7 +367,7 @@ public: void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType); /// Constructs the debug code for exiting a function. - void EmitFunctionEnd(CGBuilderTy &Builder); + void EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn); /// Emit metadata to indicate the beginning of a new lexical block /// and push the block onto the stack. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp index 84ce896506d5..2aa045879213 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp @@ -1487,9 +1487,9 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, // Handle vectors differently to get better performance. if (Ty->isVectorType()) { llvm::Type *SrcTy = Value->getType(); - auto *VecTy = cast(SrcTy); + auto *VecTy = dyn_cast(SrcTy); // Handle vec3 special. - if (VecTy->getNumElements() == 3) { + if (VecTy && VecTy->getNumElements() == 3) { // Our source is a vec3, do a shuffle vector to make it a vec4. llvm::Constant *Mask[] = {Builder.getInt32(0), Builder.getInt32(1), Builder.getInt32(2), diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp index d604b4130a23..f9d1fe468748 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp @@ -3887,7 +3887,7 @@ Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, /// Return the result of the given binary operation. auto eval = [&](BinaryOperator::Opcode Opcode, llvm::Value *LHS, llvm::Value *RHS) -> llvm::Value * { - assert(Opcode == BO_Add || Opcode == BO_Mul && "Can't eval binop"); + assert((Opcode == BO_Add || Opcode == BO_Mul) && "Can't eval binop"); // If the operands are constants, return a constant result. if (auto *LHSCI = dyn_cast(LHS)) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp index 85da3ae47db0..b6d7f0255017 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp @@ -348,7 +348,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // Emit debug descriptor for function end. if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitFunctionEnd(Builder); + DI->EmitFunctionEnd(Builder, CurFn); // Reset the debug location to that of the simple 'return' expression, if any // rather than that of the end of the function's scope '}'. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp index c61a5f6ffa71..dde8f2e36920 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp @@ -3841,6 +3841,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { // Skip variable templates if (cast(D)->getDescribedVarTemplate()) return; + LLVM_FALLTHROUGH; case Decl::VarTemplateSpecialization: EmitGlobal(cast(D)); if (auto *DD = dyn_cast(D)) diff --git a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp index 9ab2e176845c..ad2b4ada9a83 100644 --- a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp @@ -48,13 +48,14 @@ enum CoverageFeature { CoverageBB = 1 << 1, CoverageEdge = 1 << 2, CoverageIndirCall = 1 << 3, - CoverageTraceBB = 1 << 4, + CoverageTraceBB = 1 << 4, // Deprecated. CoverageTraceCmp = 1 << 5, CoverageTraceDiv = 1 << 6, CoverageTraceGep = 1 << 7, - Coverage8bitCounters = 1 << 8, + Coverage8bitCounters = 1 << 8, // Deprecated. CoverageTracePC = 1 << 9, CoverageTracePCGuard = 1 << 10, + CoverageInline8bitCounters = 1 << 12, CoverageNoPrune = 1 << 11, }; @@ -530,7 +531,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, } // trace-pc w/o func/bb/edge implies edge. - if ((CoverageFeatures & (CoverageTracePC | CoverageTracePCGuard)) && + if ((CoverageFeatures & + (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters)) && !(CoverageFeatures & InsertionPointTypes)) CoverageFeatures |= CoverageEdge; @@ -637,6 +639,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"), std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"), std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard"), + std::make_pair(CoverageInline8bitCounters, "-fsanitize-coverage-inline-8bit-counters"), std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune")}; for (auto F : CoverageFlags) { if (CoverageFeatures & F.first) @@ -798,6 +801,7 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) { .Case("trace-pc", CoverageTracePC) .Case("trace-pc-guard", CoverageTracePCGuard) .Case("no-prune", CoverageNoPrune) + .Case("inline-8bit-counters", CoverageInline8bitCounters) .Default(0); if (F == 0) D.Diag(clang::diag::err_drv_unsupported_option_argument) diff --git a/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index 2148316532de..dc501b564eea 100644 --- a/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -798,24 +798,28 @@ static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, case NSAPI::NSNumberWithUnsignedInt: case NSAPI::NSNumberWithUnsignedInteger: CallIsUnsigned = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithInt: case NSAPI::NSNumberWithInteger: break; case NSAPI::NSNumberWithUnsignedLong: CallIsUnsigned = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithLong: CallIsLong = true; break; case NSAPI::NSNumberWithUnsignedLongLong: CallIsUnsigned = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithLongLong: CallIsLongLong = true; break; case NSAPI::NSNumberWithDouble: CallIsDouble = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithFloat: CallIsFloating = true; break; diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp index a7b5fa7dfd29..e92672a785da 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp @@ -1727,6 +1727,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, diag::warn_module_config_mismatch) << ModuleFileName; // Fall through to error out. + LLVM_FALLTHROUGH; case ASTReader::VersionMismatch: case ASTReader::HadErrors: ModuleLoader::HadFatalFailure = true; diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp index 47c763d29357..adb15f1730bf 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp @@ -768,6 +768,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeCoverageTracePCGuard = Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard); Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune); + Opts.SanitizeCoverageInline8bitCounters = + Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeMemoryUseAfterDtor = @@ -2700,6 +2702,13 @@ std::string CompilerInvocation::getModuleHash() const { code = ext->hashExtension(code); } + // Extend the signature with the enabled sanitizers, if at least one is + // enabled. Sanitizers which cannot affect AST generation aren't hashed. + SanitizerSet SanHash = LangOpts->Sanitize; + SanHash.clear(getPPTransparentSanitizers()); + if (!SanHash.empty()) + code = hash_combine(code, SanHash.Mask); + return llvm::APInt(64, code).toString(36, /*Signed=*/false); } diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp index cd67e469ddad..e2fbe965349f 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp @@ -289,14 +289,28 @@ static void addHeaderInclude(StringRef HeaderName, /// /// \param Includes Will be augmented with the set of \#includes or \#imports /// needed to load all of the named headers. -static std::error_code -collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, - ModuleMap &ModMap, clang::Module *Module, - SmallVectorImpl &Includes) { +static std::error_code collectModuleHeaderIncludes( + const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag, + ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl &Includes) { // Don't collect any headers for unavailable modules. if (!Module->isAvailable()) return std::error_code(); + // Resolve all lazy header directives to header files. + ModMap.resolveHeaderDirectives(Module); + + // If any headers are missing, we can't build this module. In most cases, + // diagnostics for this should have already been produced; we only get here + // if explicit stat information was provided. + // FIXME: If the name resolves to a file with different stat information, + // produce a better diagnostic. + if (!Module->MissingHeaders.empty()) { + auto &MissingHeader = Module->MissingHeaders.front(); + Diag.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) + << MissingHeader.IsUmbrella << MissingHeader.FileName; + return std::error_code(); + } + // Add includes for each of these headers. for (auto HK : {Module::HK_Normal, Module::HK_Private}) { for (Module::Header &H : Module->Headers[HK]) { @@ -367,7 +381,7 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, SubEnd = Module->submodule_end(); Sub != SubEnd; ++Sub) if (std::error_code Err = collectModuleHeaderIncludes( - LangOpts, FileMgr, ModMap, *Sub, Includes)) + LangOpts, FileMgr, Diag, ModMap, *Sub, Includes)) return Err; return std::error_code(); @@ -494,7 +508,7 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) { addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents, CI.getLangOpts(), M->IsExternC); Err = collectModuleHeaderIncludes( - CI.getLangOpts(), FileMgr, + CI.getLangOpts(), FileMgr, CI.getDiagnostics(), CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M, HeaderContents); diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp index baaf93b167bc..89ac385ca45d 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp @@ -546,8 +546,11 @@ void PrintPreprocessedAction::ExecuteAction() { // module itself before switching to the input buffer. auto &Input = getCurrentInput(); if (Input.getKind().getFormat() == InputKind::ModuleMap) { - if (Input.isFile()) - (*OS) << "# 1 \"" << Input.getFile() << "\"\n"; + if (Input.isFile()) { + (*OS) << "# 1 \""; + OS->write_escaped(Input.getFile()); + (*OS) << "\"\n"; + } // FIXME: Include additional information here so that we don't need the // original source files to exist on disk. getCurrentModule()->print(*OS); diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp index d50fb6d788a4..1d7c8a0c871b 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp @@ -221,6 +221,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, case llvm::Triple::Win32: if (triple.getEnvironment() != llvm::Triple::Cygnus) break; + LLVM_FALLTHROUGH; default: // FIXME: temporary hack: hard-coded paths. AddPath("/usr/local/include", System, false); @@ -343,6 +344,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, AddPath(BaseSDKPath + "/target/include", System, false); if (triple.isPS4CPU()) AddPath(BaseSDKPath + "/target/include_common", System, false); + LLVM_FALLTHROUGH; } default: AddPath("/usr/include", ExternCSystem, false); diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp index 8c5eb161b5ab..b2dfd2941130 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp @@ -200,8 +200,11 @@ void RewriteIncludesAction::ExecuteAction() { // module itself before switching to the input buffer. auto &Input = getCurrentInput(); if (Input.getKind().getFormat() == InputKind::ModuleMap) { - if (Input.isFile()) - (*OS) << "# 1 \"" << Input.getFile() << "\"\n"; + if (Input.isFile()) { + (*OS) << "# 1 \""; + OS->write_escaped(Input.getFile()); + (*OS) << "\"\n"; + } // FIXME: Include additional information here so that we don't need the // original source files to exist on disk. getCurrentModule()->print(*OS); diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp index d45cbc01df8c..3564cebba8a8 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -177,7 +177,9 @@ void InclusionRewriter::FileSkipped(const FileEntry &/*SkippedFile*/, /// directives. It does not say whether the file has been included, but it /// provides more information about the directive (hash location instead /// of location inside the included file). It is assumed that the matching -/// FileChanged() or FileSkipped() is called after this. +/// FileChanged() or FileSkipped() is called after this (or neither is +/// called if this #include results in an error or does not textually include +/// anything). void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, const Token &/*IncludeTok*/, StringRef /*FileName*/, @@ -187,9 +189,6 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, StringRef /*SearchPath*/, StringRef /*RelativePath*/, const Module *Imported) { - assert(LastInclusionLocation.isInvalid() && - "Another inclusion directive was found before the previous one " - "was processed"); if (Imported) { auto P = ModuleIncludes.insert( std::make_pair(HashLoc.getRawEncoding(), Imported)); diff --git a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp index c4461d452e7b..8a8161488f44 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp @@ -125,6 +125,7 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) { case Cursor::BlockBegin: if (Stream.SkipBlock()) return SDError::MalformedMetadataBlock; + LLVM_FALLTHROUGH; case Cursor::BlockEnd: if (!VersionChecked) return SDError::MissingVersion; diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp index 9084bc352f76..1ebcc0a1c657 100644 --- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp @@ -1114,6 +1114,8 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, auto TryEnterImported = [&](void) -> bool { if (!ModulesEnabled) 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: // diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp index f5a35e97d6e1..447ff212f06e 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp @@ -2498,6 +2498,7 @@ void Lexer::ReadToEndOfLine(SmallVectorImpl *Result) { break; } // FALL THROUGH. + LLVM_FALLTHROUGH; case '\r': case '\n': // Okay, we found the end of the line. First, back up past the \0, \r, \n. @@ -3247,6 +3248,7 @@ LexNextToken: return LexCharConstant(Result, ConsumeChar(CurPtr, SizeTmp, Result), tok::wide_char_constant); // FALL THROUGH, treating L like the start of an identifier. + LLVM_FALLTHROUGH; // C99 6.4.2: Identifiers. case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp index 1e2cbde825f5..a598a467816a 100644 --- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp @@ -456,10 +456,17 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, // Finally, we write the bytes into ResultBuf. ResultBuf += bytesToWrite; switch (bytesToWrite) { // note: everything falls through. - case 4: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 3: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 2: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 1: *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]); + case 4: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 3: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 2: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 1: + *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]); } // Update the buffer. ResultBuf += bytesToWrite; diff --git a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp index 8c57931e47b7..018d59e5e871 100644 --- a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp @@ -36,6 +36,37 @@ #endif using namespace clang; +Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { + switch ((int)Role) { + default: llvm_unreachable("unknown header role"); + case NormalHeader: + return Module::HK_Normal; + case PrivateHeader: + return Module::HK_Private; + case TextualHeader: + return Module::HK_Textual; + case PrivateHeader | TextualHeader: + return Module::HK_PrivateTextual; + } +} + +ModuleMap::ModuleHeaderRole +ModuleMap::headerKindToRole(Module::HeaderKind Kind) { + switch ((int)Kind) { + case Module::HK_Normal: + return NormalHeader; + case Module::HK_Private: + return PrivateHeader; + case Module::HK_Textual: + return TextualHeader; + case Module::HK_PrivateTextual: + return ModuleHeaderRole(PrivateHeader | TextualHeader); + case Module::HK_Excluded: + llvm_unreachable("unexpected header kind"); + } + llvm_unreachable("unknown header kind"); +} + Module::ExportDecl ModuleMap::resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, @@ -104,12 +135,22 @@ static void appendSubframeworkPaths(Module *Mod, } const FileEntry * -ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header, - SmallVectorImpl &RelativePathName) { +ModuleMap::findHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header, + SmallVectorImpl &RelativePathName) { + auto GetFile = [&](StringRef Filename) -> const FileEntry * { + auto *File = SourceMgr.getFileManager().getFile(Filename); + if (!File || + (Header.Size && File->getSize() != *Header.Size) || + (Header.ModTime && File->getModificationTime() != *Header.ModTime)) + return nullptr; + return File; + }; + if (llvm::sys::path::is_absolute(Header.FileName)) { RelativePathName.clear(); RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); - return SourceMgr.getFileManager().getFile(Header.FileName); + return GetFile(Header.FileName); } // Search for the header file within the module's home directory. @@ -124,7 +165,7 @@ ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header, // Check whether this file is in the public headers. llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - if (auto *File = SourceMgr.getFileManager().getFile(FullPathName)) + if (auto *File = GetFile(FullPathName)) return File; // Check whether this file is in the private headers. @@ -141,31 +182,74 @@ ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header, llvm::sys::path::append(RelativePathName, "PrivateHeaders", Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - return SourceMgr.getFileManager().getFile(FullPathName); + return GetFile(FullPathName); } // Lookup for normal headers. llvm::sys::path::append(RelativePathName, Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - return SourceMgr.getFileManager().getFile(FullPathName); + return GetFile(FullPathName); } -const FileEntry * -ModuleMap::resolveAsBuiltinHeader(Module *M, - Module::UnresolvedHeaderDirective Header, - SmallVectorImpl &BuiltinPathName) { - if (llvm::sys::path::is_absolute(Header.FileName) || M->isPartOfFramework() || - !M->IsSystem || Header.IsUmbrella || !BuiltinIncludeDir || - BuiltinIncludeDir == M->Directory || !isBuiltinHeader(Header.FileName)) - return nullptr; +void ModuleMap::resolveHeader(Module *Mod, + const Module::UnresolvedHeaderDirective &Header) { + SmallString<128> RelativePathName; + if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) { + if (Header.IsUmbrella) { + const DirectoryEntry *UmbrellaDir = File->getDir(); + if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) + Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) + << UmbrellaMod->getFullModuleName(); + else + // Record this umbrella header. + setUmbrellaHeader(Mod, File, RelativePathName.str()); + } else { + Module::Header H = {RelativePathName.str(), File}; + if (Header.Kind == Module::HK_Excluded) + excludeHeader(Mod, H); + else + addHeader(Mod, H, headerKindToRole(Header.Kind)); + } + } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { + // There's a builtin header but no corresponding on-disk header. Assume + // this was supposed to modularize the builtin header alone. + } else if (Header.Kind == Module::HK_Excluded) { + // Ignore missing excluded header files. They're optional anyway. + } else { + // If we find a module that has a missing header, we mark this module as + // unavailable and store the header directive for displaying diagnostics. + Mod->MissingHeaders.push_back(Header); + // A missing header with stat information doesn't make the module + // unavailable; this keeps our behavior consistent as headers are lazily + // resolved. (Such a module still can't be built though, except from + // preprocessed source.) + if (!Header.Size && !Header.ModTime) + Mod->markUnavailable(); + } +} + +bool ModuleMap::resolveAsBuiltinHeader( + Module *Mod, const Module::UnresolvedHeaderDirective &Header) { + if (Header.Kind == Module::HK_Excluded || + llvm::sys::path::is_absolute(Header.FileName) || + Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || + !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || + !isBuiltinHeader(Header.FileName)) + return false; // This is a system module with a top-level header. This header // may have a counterpart (or replacement) in the set of headers // supplied by Clang. Find that builtin header. - llvm::sys::path::append(BuiltinPathName, BuiltinIncludeDir->getName(), - Header.FileName); - return SourceMgr.getFileManager().getFile( - StringRef(BuiltinPathName.data(), BuiltinPathName.size())); + SmallString<128> Path; + llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); + auto *File = SourceMgr.getFileManager().getFile(Path); + if (!File) + return false; + + auto Role = headerKindToRole(Header.Kind); + Module::Header H = {Path.str(), File}; + addHeader(Mod, H, Role); + return true; } ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, @@ -246,6 +330,7 @@ bool ModuleMap::isBuiltinHeader(StringRef FileName) { ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(const FileEntry *File) { + resolveHeaderDirectives(File); HeadersMap::iterator Known = Headers.find(File); if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && Known == Headers.end() && File->getDir() == BuiltinIncludeDir && @@ -328,8 +413,10 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) return; - if (RequestingModule) + if (RequestingModule) { resolveUses(RequestingModule, /*Complain=*/false); + resolveHeaderDirectives(RequestingModule); + } bool Excluded = false; Module *Private = nullptr; @@ -511,6 +598,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { ArrayRef ModuleMap::findAllModulesForHeader(const FileEntry *File) const { + resolveHeaderDirectives(File); auto It = Headers.find(File); if (It == Headers.end()) return None; @@ -524,6 +612,7 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { bool ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, const Module *RequestingModule) const { + resolveHeaderDirectives(Header); HeadersMap::const_iterator Known = Headers.find(Header); if (Known != Headers.end()) { for (SmallVectorImpl::const_iterator @@ -896,18 +985,63 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, UmbrellaDirs[UmbrellaDir] = Mod; } -static Module::HeaderKind headerRoleToKind(ModuleMap::ModuleHeaderRole Role) { - switch ((int)Role) { - default: llvm_unreachable("unknown header role"); - case ModuleMap::NormalHeader: - return Module::HK_Normal; - case ModuleMap::PrivateHeader: - return Module::HK_Private; - case ModuleMap::TextualHeader: - return Module::HK_Textual; - case ModuleMap::PrivateHeader | ModuleMap::TextualHeader: - return Module::HK_PrivateTextual; +void ModuleMap::addUnresolvedHeader(Module *Mod, + Module::UnresolvedHeaderDirective Header) { + // If there is a builtin counterpart to this file, add it now so it can + // wrap the system header. + if (resolveAsBuiltinHeader(Mod, Header)) { + // If we have both a builtin and system version of the file, the + // builtin version may want to inject macros into the system header, so + // force the system header to be treated as a textual header in this + // case. + Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( + headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); + Header.HasBuiltinHeader = true; } + + // If possible, don't stat the header until we need to. This requires the + // user to have provided us with some stat information about the file. + // FIXME: Add support for lazily stat'ing umbrella headers and excluded + // headers. + if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && + Header.Kind != Module::HK_Excluded) { + // We expect more variation in mtime than size, so if we're given both, + // use the mtime as the key. + if (Header.ModTime) + LazyHeadersByModTime[*Header.ModTime].push_back(Mod); + else + LazyHeadersBySize[*Header.Size].push_back(Mod); + Mod->UnresolvedHeaders.push_back(Header); + return; + } + + // We don't have stat information or can't defer looking this file up. + // Perform the lookup now. + resolveHeader(Mod, Header); +} + +void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { + auto BySize = LazyHeadersBySize.find(File->getSize()); + if (BySize != LazyHeadersBySize.end()) { + for (auto *M : BySize->second) + resolveHeaderDirectives(M); + LazyHeadersBySize.erase(BySize); + } + + auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); + if (ByModTime != LazyHeadersByModTime.end()) { + for (auto *M : ByModTime->second) + resolveHeaderDirectives(M); + LazyHeadersByModTime.erase(ByModTime); + } +} + +void ModuleMap::resolveHeaderDirectives(Module *Mod) const { + for (auto &Header : Mod->UnresolvedHeaders) + // This operation is logically const; we're just changing how we represent + // the header information for this file. + const_cast(this)->resolveHeader(Mod, Header); + Mod->UnresolvedHeaders.clear(); } void ModuleMap::addHeader(Module *Mod, Module::Header Header, @@ -1063,6 +1197,7 @@ namespace clang { RequiresKeyword, Star, StringLiteral, + IntegerLiteral, TextualKeyword, LBrace, RBrace, @@ -1072,7 +1207,12 @@ namespace clang { unsigned Location; unsigned StringLength; - const char *StringData; + union { + // If Kind != IntegerLiteral. + const char *StringData; + // If Kind == IntegerLiteral. + uint64_t IntegerValue; + }; void clear() { Kind = EndOfFile; @@ -1086,9 +1226,14 @@ namespace clang { SourceLocation getLocation() const { return SourceLocation::getFromRawEncoding(Location); } + + uint64_t getInteger() const { + return Kind == IntegerLiteral ? IntegerValue : 0; + } StringRef getString() const { - return StringRef(StringData, StringLength); + return Kind == IntegerLiteral ? StringRef() + : StringRef(StringData, StringLength); } }; @@ -1278,6 +1423,25 @@ retry: Tok.StringLength = Length; break; } + + case tok::numeric_constant: { + // We don't support any suffixes or other complications. + SmallString<32> SpellingBuffer; + SpellingBuffer.resize(LToken.getLength() + 1); + const char *Start = SpellingBuffer.data(); + unsigned Length = + Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); + uint64_t Value; + if (StringRef(Start, Length).getAsInteger(0, Value)) { + Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); + HadError = true; + goto retry; + } + + Tok.Kind = MMToken::IntegerLiteral; + Tok.IntegerValue = Value; + break; + } case tok::comment: goto retry; @@ -1904,6 +2068,9 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, Header.FileName = Tok.getString(); Header.FileNameLoc = consumeToken(); Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; + Header.Kind = + (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded + : Map.headerRoleToKind(Role)); // Check whether we already have an umbrella. if (Header.IsUmbrella && ActiveModule->Umbrella) { @@ -1913,64 +2080,62 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, return; } - // Look for this file by name if we don't have any stat information. - SmallString<128> RelativePathName, BuiltinPathName; - const FileEntry *File = - Map.resolveHeader(ActiveModule, Header, RelativePathName); - const FileEntry *BuiltinFile = - Map.resolveAsBuiltinHeader(ActiveModule, Header, BuiltinPathName); + // If we were given stat information, parse it so we can skip looking for + // the file. + if (Tok.is(MMToken::LBrace)) { + SourceLocation LBraceLoc = consumeToken(); - // If Clang supplies this header but the underlying system does not, - // just silently swap in our builtin version. Otherwise, we'll end - // up adding both (later). - if (BuiltinFile && !File) { - RelativePathName = BuiltinPathName; - File = BuiltinFile; - BuiltinFile = nullptr; - } + while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { + enum Attribute { Size, ModTime, Unknown }; + StringRef Str = Tok.getString(); + SourceLocation Loc = consumeToken(); + switch (llvm::StringSwitch(Str) + .Case("size", Size) + .Case("mtime", ModTime) + .Default(Unknown)) { + case Size: + if (Header.Size) + Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; + if (!Tok.is(MMToken::IntegerLiteral)) { + Diags.Report(Tok.getLocation(), + diag::err_mmap_invalid_header_attribute_value) << Str; + skipUntil(MMToken::RBrace); + break; + } + Header.Size = Tok.getInteger(); + consumeToken(); + break; - // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. - // Come up with a lazy way to do this. - if (File) { - if (Header.IsUmbrella) { - const DirectoryEntry *UmbrellaDir = File->getDir(); - if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) { - Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash) - << UmbrellaModule->getFullModuleName(); - HadError = true; - } else { - // Record this umbrella header. - Map.setUmbrellaHeader(ActiveModule, File, RelativePathName.str()); + case ModTime: + if (Header.ModTime) + Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; + if (!Tok.is(MMToken::IntegerLiteral)) { + Diags.Report(Tok.getLocation(), + diag::err_mmap_invalid_header_attribute_value) << Str; + skipUntil(MMToken::RBrace); + break; + } + Header.ModTime = Tok.getInteger(); + consumeToken(); + break; + + case Unknown: + Diags.Report(Loc, diag::err_mmap_expected_header_attribute); + skipUntil(MMToken::RBrace); + break; } - } else if (LeadingToken == MMToken::ExcludeKeyword) { - Module::Header H = {RelativePathName.str(), File}; - Map.excludeHeader(ActiveModule, H); - } else { - // If there is a builtin counterpart to this file, add it now so it can - // wrap the system header. - if (BuiltinFile) { - Module::Header H = { BuiltinPathName.str(), BuiltinFile }; - Map.addHeader(ActiveModule, H, Role); - - // If we have both a builtin and system version of the file, the - // builtin version may want to inject macros into the system header, so - // force the system header to be treated as a textual header in this - // case. - Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); - } - - // Record this header. - Module::Header H = { RelativePathName.str(), File }; - Map.addHeader(ActiveModule, H, Role); } - } else if (LeadingToken != MMToken::ExcludeKeyword) { - // Ignore excluded header files. They're optional anyway. - // If we find a module that has a missing header, we mark this module as - // unavailable and store the header directive for displaying diagnostics. - ActiveModule->markUnavailable(); - ActiveModule->MissingHeaders.push_back(Header); + if (Tok.is(MMToken::RBrace)) + consumeToken(); + else { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); + Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); + HadError = true; + } } + + Map.addUnresolvedHeader(ActiveModule, std::move(Header)); } static int compareModuleHeaders(const Module::Header *A, @@ -2521,6 +2686,7 @@ bool ModuleMapParser::parseModuleMapFile() { case MMToken::RequiresKeyword: case MMToken::Star: case MMToken::StringLiteral: + case MMToken::IntegerLiteral: case MMToken::TextualKeyword: case MMToken::UmbrellaKeyword: case MMToken::UseKeyword: diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp index 8b5877934f61..2d3ad690987e 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp @@ -689,6 +689,8 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, while (!Loc.isInvalid() && !SM.isInMainFile(Loc)) { auto ID = SM.getFileID(SM.getExpansionLoc(Loc)); auto *FE = SM.getFileEntryForID(ID); + if (!FE) + break; bool InTextualHeader = false; for (auto Header : HeaderInfo.getModuleMap().findAllModulesForHeader(FE)) { diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index b785f5f7d2e6..22696a957a10 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -2552,6 +2552,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, } } // Fall through. + LLVM_FALLTHROUGH; } case tok::comma: case tok::equal: @@ -3678,6 +3679,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = true; break; }; + LLVM_FALLTHROUGH; case tok::kw___private: case tok::kw___global: case tok::kw___local: @@ -5045,6 +5047,7 @@ void Parser::ParseTypeQualifierListOpt( if (TryKeywordIdentFallback(false)) continue; } + LLVM_FALLTHROUGH; case tok::kw___sptr: case tok::kw___w64: case tok::kw___ptr64: @@ -5094,6 +5097,7 @@ void Parser::ParseTypeQualifierListOpt( continue; // do *not* consume the next token! } // otherwise, FALL THROUGH! + LLVM_FALLTHROUGH; default: DoneWithTypeQuals: // If this is not a type-qualifier token, we're done reading type diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index 527d45b1e203..4c117f531ef1 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -4215,6 +4215,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. + LLVM_FALLTHROUGH; case IEB_Skip: Braces.skipToEnd(); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index c739a50f0b38..aacb00e8be64 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -1314,6 +1314,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } // Fall through to treat the template-id as an id-expression. + LLVM_FALLTHROUGH; } case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id @@ -1484,9 +1485,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { nullptr, LHS.get()); break; } - // Fall through; this isn't a message send. - + LLVM_FALLTHROUGH; + default: // Not a postfix-expression suffix. return LHS; case tok::l_square: { // postfix-expression: p-e '[' expression ']' diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp index f48d01e0f630..90f3561cb963 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp @@ -501,7 +501,8 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. - + LLVM_FALLTHROUGH; + case IEB_Skip: Braces.skipToEnd(); return false; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp index b925dd7053dc..2e5e36242ed5 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp @@ -192,6 +192,7 @@ static DeclarationName parseOpenMPReductionId(Parser &P) { case tok::identifier: // identifier if (!WithOperator) break; + LLVM_FALLTHROUGH; default: P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, @@ -869,6 +870,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( // pseudo-clause OMPFlushClause. PP.EnterToken(Tok); } + LLVM_FALLTHROUGH; case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -883,6 +885,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( } HasAssociatedStatement = false; // Fall through for further analysis. + LLVM_FALLTHROUGH; case OMPD_parallel: case OMPD_simd: case OMPD_for: @@ -1184,6 +1187,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } + LLVM_FALLTHROUGH; case OMPC_if: Clause = ParseOpenMPSingleExprWithArgClause(CKind); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index d147ab0a5674..b1fbb20c721b 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -203,6 +203,7 @@ Retry: } // Fall through + LLVM_FALLTHROUGH; } default: { diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp index 0d783131dd6e..d6684c39aa73 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp @@ -1450,6 +1450,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::False; } // If that succeeded, fallthrough into the generic simple-type-id case. + LLVM_FALLTHROUGH; // The ambiguity resides in a simple-type-specifier/typename-specifier // followed by a '('. The '(' could either be the start of: @@ -1492,6 +1493,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::True; } + LLVM_FALLTHROUGH; case tok::kw_char: case tok::kw_wchar_t: diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 4fe038d271ad..af29b5e9c673 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -763,6 +763,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, } // This must be 'export template'. Parse it so we can diagnose our lack // of support. + LLVM_FALLTHROUGH; case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: @@ -1875,6 +1876,7 @@ bool Parser::isTokenEqualOrEqualTypo() { Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal) << Kind << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); + LLVM_FALLTHROUGH; case tok::equal: return true; } diff --git a/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp b/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp index 27bb976a6e1a..9e307f31be11 100644 --- a/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp +++ b/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp @@ -409,6 +409,7 @@ void html::SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP) { ++TokOffs; --TokLen; // FALL THROUGH to chop the 8 + LLVM_FALLTHROUGH; case tok::wide_string_literal: case tok::utf16_string_literal: case tok::utf32_string_literal: diff --git a/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h b/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h index 954a0f100ebb..33a368d92ff4 100644 --- a/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h +++ b/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h @@ -51,6 +51,9 @@ public: /// name lookup. bool buildDependentStatements(); + /// \brief Build just parameter moves. To use for rebuilding in TreeTransform. + bool buildParameterMoves(); + bool isInvalid() const { return !this->IsValid; } private: diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index 8fb2f4139236..224d9e9a0ee2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -1866,6 +1866,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, case Sema::PCC_Condition: AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); // Fall through: conditions and statements can have expressions. + LLVM_FALLTHROUGH; case Sema::PCC_ParenthesizedExpression: if (SemaRef.getLangOpts().ObjCAutoRefCount && @@ -1895,6 +1896,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result(Builder.TakeString())); } // Fall through + LLVM_FALLTHROUGH; case Sema::PCC_Expression: { if (SemaRef.getLangOpts().CPlusPlus) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp index 8a548c0ab861..06ae66076e8a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp @@ -832,6 +832,12 @@ bool CoroutineStmtBuilder::buildDependentStatements() { return this->IsValid; } +bool CoroutineStmtBuilder::buildParameterMoves() { + assert(this->IsValid && "coroutine already invalid"); + assert(this->ParamMoves.empty() && "param moves already built"); + return this->IsValid = makeParamMoves(); +} + bool CoroutineStmtBuilder::makePromiseStmt() { // Form a declaration statement for the promise declaration, so that AST // visitors can more easily find it. @@ -1244,14 +1250,13 @@ static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) { .get(); } + /// \brief Build a variable declaration for move parameter. static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, - StringRef Name) { - DeclContext *DC = S.CurContext; - IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name); + IdentifierInfo *II) { TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc); VarDecl *Decl = - VarDecl::Create(S.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); + VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type, TInfo, SC_None); Decl->setImplicit(); return Decl; } @@ -1264,9 +1269,6 @@ bool CoroutineStmtBuilder::makeParamMoves() { // No need to copy scalars, llvm will take care of them. if (Ty->getAsCXXRecordDecl()) { - if (!paramDecl->getIdentifier()) - continue; - ExprResult ParamRef = S.BuildDeclRefExpr(paramDecl, paramDecl->getType(), ExprValueKind::VK_LValue, Loc); // FIXME: scope? @@ -1275,8 +1277,7 @@ bool CoroutineStmtBuilder::makeParamMoves() { Expr *RCast = castForMoving(S, ParamRef.get()); - auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()->getName()); - + auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()); S.AddInitializerToDecl(D, RCast, /*DirectInit=*/true); // Convert decl to a statement. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index ea1f7526a832..ef6dfaa2f28c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -404,6 +404,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, } } // If typo correction failed or was not performed, fall through + LLVM_FALLTHROUGH; case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: Result.suppressDiagnostics(); @@ -6160,7 +6161,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( QualType NR = R; while (NR->isPointerType()) { if (NR->isFunctionPointerType()) { - Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer_variable); + Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer); D.setInvalidType(); break; } @@ -12309,7 +12310,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, TypeSourceInfo *TI = FD->getTypeSourceInfo(); TypeLoc TL = TI->getTypeLoc(); FunctionTypeLoc FTL = TL.getAsAdjusted(); - Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1; + Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 2; } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index d9528be2d383..acacdc263c08 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -14639,6 +14639,7 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { case EST_ComputedNoexcept: if (!Finder.TraverseStmt(Proto->getNoexceptExpr())) return true; + LLVM_FALLTHROUGH; case EST_Dynamic: for (const auto &E : Proto->exceptions()) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index b1a07ffb7206..4e7fb19b282b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -11462,6 +11462,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, break; case BO_And: checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc); + LLVM_FALLTHROUGH; case BO_Xor: case BO_Or: ResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc); @@ -11504,6 +11505,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, case BO_AndAssign: case BO_OrAssign: // fallthrough DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc); + LLVM_FALLTHROUGH; case BO_XorAssign: CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc); CompLHSTy = CompResultTy; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp index 4b1d7fd3cf23..a6239283b47b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp @@ -337,6 +337,7 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC, return nullptr; } // Fall through to get the current context. + LLVM_FALLTHROUGH; case DataMember: // -- the in-class initializers of class members diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index c97da740e4d2..1d32e5796812 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -2594,6 +2594,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { for (const auto &Arg : Proto->param_types()) Queue.push_back(Arg.getTypePtr()); // fallthrough + LLVM_FALLTHROUGH; } case Type::FunctionNoProto: { const FunctionType *FnType = cast(T); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 33a8f9c4afa3..dcb2c11c73c7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -1288,17 +1288,22 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, } namespace { + // Use SetVector since the diagnostic cares about the ordering of the Decl's. + using DeclSetVector = + llvm::SetVector, + llvm::SmallPtrSet>; + // This visitor will traverse a conditional statement and store all // the evaluated decls into a vector. Simple is set to true if none // of the excluded constructs are used. class DeclExtractor : public EvaluatedExprVisitor { - llvm::SmallPtrSetImpl &Decls; + DeclSetVector &Decls; SmallVectorImpl &Ranges; bool Simple; public: typedef EvaluatedExprVisitor Inherited; - DeclExtractor(Sema &S, llvm::SmallPtrSetImpl &Decls, + DeclExtractor(Sema &S, DeclSetVector &Decls, SmallVectorImpl &Ranges) : Inherited(S.Context), Decls(Decls), @@ -1370,14 +1375,13 @@ namespace { // DeclMatcher checks to see if the decls are used in a non-evaluated // context. class DeclMatcher : public EvaluatedExprVisitor { - llvm::SmallPtrSetImpl &Decls; + DeclSetVector &Decls; bool FoundDecl; public: typedef EvaluatedExprVisitor Inherited; - DeclMatcher(Sema &S, llvm::SmallPtrSetImpl &Decls, - Stmt *Statement) : + DeclMatcher(Sema &S, DeclSetVector &Decls, Stmt *Statement) : Inherited(S.Context), Decls(Decls), FoundDecl(false) { if (!Statement) return; @@ -1459,7 +1463,7 @@ namespace { return; PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body); - llvm::SmallPtrSet Decls; + DeclSetVector Decls; SmallVector Ranges; DeclExtractor DE(S, Decls, Ranges); DE.Visit(Second); @@ -1471,11 +1475,9 @@ namespace { if (Decls.size() == 0) return; // Don't warn on volatile, static, or global variables. - for (llvm::SmallPtrSetImpl::iterator I = Decls.begin(), - E = Decls.end(); - I != E; ++I) - if ((*I)->getType().isVolatileQualified() || - (*I)->hasGlobalStorage()) return; + for (auto *VD : Decls) + if (VD->getType().isVolatileQualified() || VD->hasGlobalStorage()) + return; if (DeclMatcher(S, Decls, Second).FoundDeclInUse() || DeclMatcher(S, Decls, Third).FoundDeclInUse() || @@ -1483,25 +1485,16 @@ namespace { return; // Load decl names into diagnostic. - if (Decls.size() > 4) + if (Decls.size() > 4) { PDiag << 0; - else { - PDiag << Decls.size(); - for (llvm::SmallPtrSetImpl::iterator I = Decls.begin(), - E = Decls.end(); - I != E; ++I) - PDiag << (*I)->getDeclName(); + } else { + PDiag << (unsigned)Decls.size(); + for (auto *VD : Decls) + PDiag << VD->getDeclName(); } - // Load SourceRanges into diagnostic if there is room. - // Otherwise, load the SourceRange of the conditional expression. - if (Ranges.size() <= PartialDiagnostic::MaxArguments) - for (SmallVectorImpl::iterator I = Ranges.begin(), - E = Ranges.end(); - I != E; ++I) - PDiag << *I; - else - PDiag << Second->getSourceRange(); + for (auto Range : Ranges) + PDiag << Range; S.Diag(Ranges.begin()->getBegin(), PDiag); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp index 5f91cac14a38..c182b35bfad4 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp @@ -277,6 +277,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); + LLVM_FALLTHROUGH; default: return StmtError(Diag(OutputExpr->getLocStart(), diag::err_asm_invalid_lvalue_in_output) diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index ebdf6dd57fc5..75b69ae04f56 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2383,7 +2383,8 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( bool HasDefaultArg = false; TemplateDecl *TD = dyn_cast(Template); if (!TD) { - assert(isa(Template)); + assert(isa(Template) || + isa(Template)); return Sema::TDK_Incomplete; } @@ -5093,6 +5094,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, cast(T)->getSizeExpr(), OnlyDeduced, Depth, Used); // Fall through to check the element type + LLVM_FALLTHROUGH; case Type::ConstantArray: case Type::IncompleteArray: diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index e7315934b515..c189112e3455 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -643,6 +643,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; // fallthrough + LLVM_FALLTHROUGH; FUNCTION_TYPE_ATTRS_CASELIST: distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType); @@ -1881,6 +1882,11 @@ QualType Sema::BuildPointerType(QualType T, return QualType(); } + if (T->isFunctionType() && getLangOpts().OpenCL) { + Diag(Loc, diag::err_opencl_function_pointer); + return QualType(); + } + if (checkQualifiedFunction(*this, T, Loc, QFK_Pointer)) return QualType(); @@ -4347,19 +4353,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (FTI.isAmbiguous) warnAboutAmbiguousFunction(S, D, DeclType, T); - // GNU warning -Wstrict-prototypes - // Warn if a function declaration is without a prototype. - // This warning is issued for all kinds of unprototyped function - // declarations (i.e. function type typedef, function pointer etc.) - // C99 6.7.5.3p14: - // The empty list in a function declarator that is not part of a - // definition of that function specifies that no information - // about the number or types of the parameters is supplied. - if (D.getFunctionDefinitionKind() == FDK_Declaration && - FTI.NumParams == 0 && !LangOpts.CPlusPlus) - S.Diag(DeclType.Loc, diag::warn_strict_prototypes) - << 0 << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void"); - FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex)); if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) { @@ -4602,6 +4595,36 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, const_cast(DeclType.getAttrs())); } + // GNU warning -Wstrict-prototypes + // Warn if a function declaration is without a prototype. + // This warning is issued for all kinds of unprototyped function + // declarations (i.e. function type typedef, function pointer etc.) + // C99 6.7.5.3p14: + // The empty list in a function declarator that is not part of a definition + // of that function specifies that no information about the number or types + // of the parameters is supplied. + if (!LangOpts.CPlusPlus && D.getFunctionDefinitionKind() == FDK_Declaration) { + bool IsBlock = false; + for (const DeclaratorChunk &DeclType : D.type_objects()) { + switch (DeclType.Kind) { + case DeclaratorChunk::BlockPointer: + IsBlock = true; + break; + case DeclaratorChunk::Function: { + const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + if (FTI.NumParams == 0) + S.Diag(DeclType.Loc, diag::warn_strict_prototypes) + << IsBlock + << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void"); + IsBlock = false; + break; + } + default: + break; + } + } + } + assert(!T.isNull() && "T must not be null after this point"); if (LangOpts.CPlusPlus && T->isFunctionType()) { @@ -6925,6 +6948,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; // fallthrough into the function attrs + LLVM_FALLTHROUGH; FUNCTION_TYPE_ATTRS_CASELIST: attr.setUsedAsTypeAttr(); diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index a65584e3c912..7aa8f64d5081 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -6959,6 +6959,8 @@ TreeTransform::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) { Builder.ReturnStmt = Res.get(); } } + if (!Builder.buildParameterMoves()) + return StmtError(); return getDerived().RebuildCoroutineBodyStmt(Builder); } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index b7bbb9dc7be1..e16a9b3ee3b5 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -292,6 +292,33 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, return true; } + // Sanitizer feature mismatches are treated as compatible differences. If + // compatible differences aren't allowed, we still only want to check for + // mismatches of non-modular sanitizers (the only ones which can affect AST + // generation). + if (!AllowCompatibleDifferences) { + SanitizerMask ModularSanitizers = getPPTransparentSanitizers(); + SanitizerSet ExistingSanitizers = ExistingLangOpts.Sanitize; + SanitizerSet ImportedSanitizers = LangOpts.Sanitize; + ExistingSanitizers.clear(ModularSanitizers); + ImportedSanitizers.clear(ModularSanitizers); + if (ExistingSanitizers.Mask != ImportedSanitizers.Mask) { + const std::string Flag = "-fsanitize="; + if (Diags) { +#define SANITIZER(NAME, ID) \ + { \ + bool InExistingModule = ExistingSanitizers.has(SanitizerKind::ID); \ + bool InImportedModule = ImportedSanitizers.has(SanitizerKind::ID); \ + if (InExistingModule != InImportedModule) \ + Diags->Report(diag::err_pch_targetopt_feature_mismatch) \ + << InExistingModule << (Flag + NAME); \ + } +#include "clang/Basic/Sanitizers.def" + } + return true; + } + } + return false; } @@ -3670,6 +3697,8 @@ static void updateModuleTimestamp(ModuleFile &MF) { if (EC) return; OS << "Timestamp file\n"; + OS.close(); + OS.clear_error(); // Avoid triggering a fatal error. } /// \brief Given a cursor at the start of an AST file, scan ahead and drop the diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp index 95cb54f944e4..044a26433a93 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp @@ -1856,24 +1856,31 @@ namespace { // Trait used for the on-disk hash table of header search information. class HeaderFileInfoTrait { ASTWriter &Writer; - const HeaderSearch &HS; // Keep track of the framework names we've used during serialization. SmallVector FrameworkStringData; llvm::StringMap FrameworkNameOffset; public: - HeaderFileInfoTrait(ASTWriter &Writer, const HeaderSearch &HS) - : Writer(Writer), HS(HS) { } - + HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {} + struct key_type { - const FileEntry *FE; StringRef Filename; + off_t Size; + time_t ModTime; }; typedef const key_type &key_type_ref; + + using UnresolvedModule = + llvm::PointerIntPair; - typedef HeaderFileInfo data_type; + struct data_type { + const HeaderFileInfo &HFI; + ArrayRef KnownHeaders; + UnresolvedModule Unresolved; + }; typedef const data_type &data_type_ref; + typedef unsigned hash_value_type; typedef unsigned offset_type; @@ -1881,8 +1888,7 @@ namespace { // The hash is based only on size/time of the file, so that the reader can // match even when symlinking or excess path elements ("foo/../", "../") // change the form of the name. However, complete path is still the key. - return llvm::hash_combine(key.FE->getSize(), - Writer.getTimestampForOutput(key.FE)); + return llvm::hash_combine(key.Size, key.ModTime); } std::pair @@ -1892,68 +1898,74 @@ namespace { unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; - for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) + for (auto ModInfo : Data.KnownHeaders) if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) DataLen += 4; + if (Data.Unresolved.getPointer()) + DataLen += 4; LE.write(DataLen); return std::make_pair(KeyLen, DataLen); } - + void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) { using namespace llvm::support; endian::Writer LE(Out); - LE.write(key.FE->getSize()); + LE.write(key.Size); KeyLen -= 8; - LE.write(Writer.getTimestampForOutput(key.FE)); + LE.write(key.ModTime); KeyLen -= 8; Out.write(key.Filename.data(), KeyLen); } - + void EmitData(raw_ostream &Out, key_type_ref key, data_type_ref Data, unsigned DataLen) { using namespace llvm::support; endian::Writer LE(Out); uint64_t Start = Out.tell(); (void)Start; - unsigned char Flags = (Data.isImport << 4) - | (Data.isPragmaOnce << 3) - | (Data.DirInfo << 1) - | Data.IndexHeaderMapHeader; + unsigned char Flags = (Data.HFI.isImport << 4) + | (Data.HFI.isPragmaOnce << 3) + | (Data.HFI.DirInfo << 1) + | Data.HFI.IndexHeaderMapHeader; LE.write(Flags); - LE.write(Data.NumIncludes); + LE.write(Data.HFI.NumIncludes); - if (!Data.ControllingMacro) - LE.write(Data.ControllingMacroID); + if (!Data.HFI.ControllingMacro) + LE.write(Data.HFI.ControllingMacroID); else - LE.write(Writer.getIdentifierRef(Data.ControllingMacro)); - + LE.write(Writer.getIdentifierRef(Data.HFI.ControllingMacro)); + unsigned Offset = 0; - if (!Data.Framework.empty()) { + if (!Data.HFI.Framework.empty()) { // If this header refers into a framework, save the framework name. llvm::StringMap::iterator Pos - = FrameworkNameOffset.find(Data.Framework); + = FrameworkNameOffset.find(Data.HFI.Framework); if (Pos == FrameworkNameOffset.end()) { Offset = FrameworkStringData.size() + 1; - FrameworkStringData.append(Data.Framework.begin(), - Data.Framework.end()); + FrameworkStringData.append(Data.HFI.Framework.begin(), + Data.HFI.Framework.end()); FrameworkStringData.push_back(0); - FrameworkNameOffset[Data.Framework] = Offset; + FrameworkNameOffset[Data.HFI.Framework] = Offset; } else Offset = Pos->second; } LE.write(Offset); - // FIXME: If the header is excluded, we should write out some - // record of that fact. - for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) { - if (uint32_t ModID = - Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) { - uint32_t Value = (ModID << 2) | (unsigned)ModInfo.getRole(); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { + if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { + uint32_t Value = (ModID << 2) | (unsigned)Role; assert((Value >> 2) == ModID && "overflow in header module info"); LE.write(Value); } - } + }; + + // FIXME: If the header is excluded, we should write out some + // record of that fact. + for (auto ModInfo : Data.KnownHeaders) + EmitModule(ModInfo.getModule(), ModInfo.getRole()); + if (Data.Unresolved.getPointer()) + EmitModule(Data.Unresolved.getPointer(), Data.Unresolved.getInt()); assert(Out.tell() - Start == DataLen && "Wrong data length"); } @@ -1968,16 +1980,72 @@ namespace { /// /// \param HS The header search structure to save. void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { + HeaderFileInfoTrait GeneratorTrait(*this); + llvm::OnDiskChainedHashTableGenerator Generator; + SmallVector SavedStrings; + unsigned NumHeaderSearchEntries = 0; + + // Find all unresolved headers for the current module. We generally will + // have resolved them before we get here, but not necessarily: we might be + // compiling a preprocessed module, where there is no requirement for the + // original files to exist any more. + const HeaderFileInfo Empty; // So we can take a reference. + if (WritingModule) { + llvm::SmallVector Worklist(1, WritingModule); + while (!Worklist.empty()) { + Module *M = Worklist.pop_back_val(); + if (!M->isAvailable()) + continue; + + // Map to disk files where possible, to pick up any missing stat + // information. This also means we don't need to check the unresolved + // headers list when emitting resolved headers in the first loop below. + // FIXME: It'd be preferable to avoid doing this if we were given + // sufficient stat information in the module map. + HS.getModuleMap().resolveHeaderDirectives(M); + + // If the file didn't exist, we can still create a module if we were given + // enough information in the module map. + for (auto U : M->MissingHeaders) { + // Check that we were given enough information to build a module + // without this file existing on disk. + if (!U.Size || (!U.ModTime && IncludeTimestamps)) { + PP->Diag(U.FileNameLoc, diag::err_module_no_size_mtime_for_header) + << WritingModule->getFullModuleName() << U.Size.hasValue() + << U.FileName; + continue; + } + + // Form the effective relative pathname for the file. + SmallString<128> Filename(M->Directory->getName()); + llvm::sys::path::append(Filename, U.FileName); + PreparePathForOutput(Filename); + + StringRef FilenameDup = strdup(Filename.c_str()); + SavedStrings.push_back(FilenameDup.data()); + + HeaderFileInfoTrait::key_type Key = { + FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0 + }; + HeaderFileInfoTrait::data_type Data = { + Empty, {}, {M, ModuleMap::headerKindToRole(U.Kind)} + }; + // FIXME: Deal with cases where there are multiple unresolved header + // directives in different submodules for the same header. + Generator.insert(Key, Data, GeneratorTrait); + ++NumHeaderSearchEntries; + } + + Worklist.append(M->submodule_begin(), M->submodule_end()); + } + } + SmallVector FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); if (FilesByUID.size() > HS.header_file_size()) FilesByUID.resize(HS.header_file_size()); - - HeaderFileInfoTrait GeneratorTrait(*this, HS); - llvm::OnDiskChainedHashTableGenerator Generator; - SmallVector SavedStrings; - unsigned NumHeaderSearchEntries = 0; + for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { const FileEntry *File = FilesByUID[UID]; if (!File) @@ -2004,11 +2072,16 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { SavedStrings.push_back(Filename.data()); } - HeaderFileInfoTrait::key_type key = { File, Filename }; - Generator.insert(key, *HFI, GeneratorTrait); + HeaderFileInfoTrait::key_type Key = { + Filename, File->getSize(), getTimestampForOutput(File) + }; + HeaderFileInfoTrait::data_type Data = { + *HFI, HS.getModuleMap().findAllModulesForHeader(File), {} + }; + Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; } - + // Create the on-disk hash table in a buffer. SmallString<4096> TableData; uint32_t BucketOffset; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index 8ca2a24cffe7..f7b5f61cfb8a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -189,6 +189,7 @@ public: case DeadIncrement: BugType = "Dead increment"; + LLVM_FALLTHROUGH; case Standard: if (!BugType) BugType = "Dead assignment"; os << "Value stored to '" << *V << "' is never read"; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 8ee34190891a..f84c0ee800a3 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1176,6 +1176,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, } } // FALLTHROUGH + LLVM_FALLTHROUGH; } case Stmt::CallExprClass: case Stmt::CXXMemberCallExprClass: diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index ffaa0eda918a..04452e3e7cc2 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -325,6 +325,7 @@ Optional SValBuilder::getConstantVal(const Expr *E) { } } // FALLTHROUGH + LLVM_FALLTHROUGH; } // If we don't have a special case, fall back to the AST's constant evaluator. diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 82ce8b45fe78..9c28457b2139 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -163,6 +163,7 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) { return nonloc::SymbolVal(SymR->getSymbol()); // FALL-THROUGH + LLVM_FALLTHROUGH; } case loc::GotoLabelKind: diff --git a/contrib/llvm/tools/llc/llc.cpp b/contrib/llvm/tools/llc/llc.cpp index 589005943045..e10d112dcf90 100644 --- a/contrib/llvm/tools/llc/llc.cpp +++ b/contrib/llvm/tools/llc/llc.cpp @@ -304,6 +304,9 @@ int main(int argc, char **argv) { initializeScalarizeMaskedMemIntrinPass(*Registry); initializeExpandReductionsPass(*Registry); + // Initialize debugging passes. + initializeScavengerTestPass(*Registry); + // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); diff --git a/contrib/llvm/tools/lld/COFF/DLL.cpp b/contrib/llvm/tools/lld/COFF/DLL.cpp index 3ac14e4ea2b0..d76410b67471 100644 --- a/contrib/llvm/tools/lld/COFF/DLL.cpp +++ b/contrib/llvm/tools/lld/COFF/DLL.cpp @@ -100,17 +100,13 @@ public: void writeTo(uint8_t *Buf) const override { auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff); + E->ImportLookupTableRVA = LookupTab->getRVA(); E->NameRVA = DLLName->getRVA(); - - // The import descriptor table contains two pointers to - // the tables describing dllimported symbols. But the - // Windows loader actually uses only one. So we create - // only one table and set both fields to its address. - E->ImportLookupTableRVA = AddressTab->getRVA(); E->ImportAddressTableRVA = AddressTab->getRVA(); } Chunk *DLLName; + Chunk *LookupTab; Chunk *AddressTab; }; @@ -392,6 +388,7 @@ std::vector IdataContents::getChunks() { // Add each type in the correct order. std::vector V; V.insert(V.end(), Dirs.begin(), Dirs.end()); + V.insert(V.end(), Lookups.begin(), Lookups.end()); V.insert(V.end(), Addresses.begin(), Addresses.end()); V.insert(V.end(), Hints.begin(), Hints.end()); V.insert(V.end(), DLLNames.begin(), DLLNames.end()); @@ -407,18 +404,21 @@ void IdataContents::create() { // we need to create HintName chunks to store the names. // If they don't (if they are import-by-ordinals), we store only // ordinal values to the table. - size_t Base = Addresses.size(); + size_t Base = Lookups.size(); for (DefinedImportData *S : Syms) { uint16_t Ord = S->getOrdinal(); if (S->getExternalName().empty()) { + Lookups.push_back(make(Ord)); Addresses.push_back(make(Ord)); continue; } auto *C = make(S->getExternalName(), Ord); + Lookups.push_back(make(C)); Addresses.push_back(make(C)); Hints.push_back(C); } // Terminate with null values. + Lookups.push_back(make(ptrSize())); Addresses.push_back(make(ptrSize())); for (int I = 0, E = Syms.size(); I < E; ++I) @@ -427,6 +427,7 @@ void IdataContents::create() { // Create the import table header. DLLNames.push_back(make(Syms[0]->getDLLName())); auto *Dir = make(DLLNames.back()); + Dir->LookupTab = Lookups[Base]; Dir->AddressTab = Addresses[Base]; Dirs.push_back(Dir); } diff --git a/contrib/llvm/tools/lld/COFF/DLL.h b/contrib/llvm/tools/lld/COFF/DLL.h index 939771b3290c..ad312789edf1 100644 --- a/contrib/llvm/tools/lld/COFF/DLL.h +++ b/contrib/llvm/tools/lld/COFF/DLL.h @@ -36,6 +36,7 @@ private: std::vector Imports; std::vector Dirs; + std::vector Lookups; std::vector Addresses; std::vector Hints; std::vector DLLNames; diff --git a/contrib/llvm/tools/lld/COFF/Driver.cpp b/contrib/llvm/tools/lld/COFF/Driver.cpp index d871f942737d..96c328b30518 100644 --- a/contrib/llvm/tools/lld/COFF/Driver.cpp +++ b/contrib/llvm/tools/lld/COFF/Driver.cpp @@ -434,7 +434,8 @@ std::vector createCOFFShortExportFromConfig() { std::vector Exports; for (Export &E1 : Config->Exports) { COFFShortExport E2; - E2.Name = E1.Name; + // Use SymbolName, which will have any stdcall or fastcall qualifiers. + E2.Name = E1.SymbolName; E2.ExtName = E1.ExtName; E2.Ordinal = E1.Ordinal; E2.Noname = E1.Noname; diff --git a/contrib/llvm/tools/lld/COFF/PDB.cpp b/contrib/llvm/tools/lld/COFF/PDB.cpp index a3b3ab7bbab0..eb8c3820412d 100644 --- a/contrib/llvm/tools/lld/COFF/PDB.cpp +++ b/contrib/llvm/tools/lld/COFF/PDB.cpp @@ -157,7 +157,8 @@ static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) { fatal(EC, "StreamReader.readArray failed"); TypeDatabase TDB(0); - CVSymbolDumper SymbolDumper(W, TDB, nullptr, false); + CVSymbolDumper SymbolDumper(W, TDB, CodeViewContainer::ObjectFile, nullptr, + false); if (auto EC = SymbolDumper.dump(Symbols)) fatal(EC, "CVSymbolDumper::dump failed"); } diff --git a/contrib/llvm/tools/lld/ELF/LinkerScript.cpp b/contrib/llvm/tools/lld/ELF/LinkerScript.cpp index 75df2cd4bd5c..1ced3e8e8d71 100644 --- a/contrib/llvm/tools/lld/ELF/LinkerScript.cpp +++ b/contrib/llvm/tools/lld/ELF/LinkerScript.cpp @@ -463,12 +463,7 @@ void LinkerScript::fabricateDefaultCommands() { // Prefer user supplied address over additional alignment constraint auto I = Config->SectionStartMap.find(Sec->Name); if (I != Config->SectionStartMap.end()) - Commands.push_back( - make(".", [=] { return I->second; }, "")); - else if (Sec->PageAlign) - OSCmd->AddrExpr = [=] { - return alignTo(Script->getDot(), Config->MaxPageSize); - }; + OSCmd->AddrExpr = [=] { return I->second; }; Commands.push_back(OSCmd); if (Sec->Sections.size()) { diff --git a/contrib/llvm/tools/lld/ELF/OutputSections.cpp b/contrib/llvm/tools/lld/ELF/OutputSections.cpp index 4f8906a32081..8357d6b03bb1 100644 --- a/contrib/llvm/tools/lld/ELF/OutputSections.cpp +++ b/contrib/llvm/tools/lld/ELF/OutputSections.cpp @@ -128,6 +128,7 @@ template void OutputSection::finalize() { // the section to which the relocation applies. InputSectionBase *S = First->getRelocatedSection(); Info = S->getOutputSection()->SectionIndex; + Flags |= SHF_INFO_LINK; } static uint64_t updateOffset(uint64_t Off, InputSection *S) { diff --git a/contrib/llvm/tools/lld/ELF/OutputSections.h b/contrib/llvm/tools/lld/ELF/OutputSections.h index 326348cd5a20..0f2fe68ca708 100644 --- a/contrib/llvm/tools/lld/ELF/OutputSections.h +++ b/contrib/llvm/tools/lld/ELF/OutputSections.h @@ -59,10 +59,6 @@ public: Alignment = Val; } - // If true, this section will be page aligned on disk. - // Typically the first section of each PT_LOAD segment has this flag. - bool PageAlign = false; - // Pointer to the first section in PT_LOAD segment, which this section // also resides in. This field is used to correctly compute file offset // of a section. When two sections share the same load segment, difference diff --git a/contrib/llvm/tools/lld/ELF/Writer.cpp b/contrib/llvm/tools/lld/ELF/Writer.cpp index 0464bff348da..78f679f1f0d9 100644 --- a/contrib/llvm/tools/lld/ELF/Writer.cpp +++ b/contrib/llvm/tools/lld/ELF/Writer.cpp @@ -257,19 +257,20 @@ template void Writer::run() { if (ErrorCount) return; - if (!Script->Opt.HasSections) { - if (!Config->Relocatable) - fixSectionAlignments(); + if (!Script->Opt.HasSections) Script->fabricateDefaultCommands(); - } else { + else Script->synchronize(); - } for (BaseCommand *Base : Script->Opt.Commands) if (auto *Cmd = dyn_cast(Base)) OutputSectionCommands.push_back(Cmd); clearOutputSections(); + + if (!Script->Opt.HasSections &&!Config->Relocatable) + fixSectionAlignments(); + // If -compressed-debug-sections is specified, we need to compress // .debug_* sections. Do it right now because it changes the size of // output sections. @@ -1504,24 +1505,33 @@ void Writer::addPtArmExid(std::vector &Phdrs) { // first section after PT_GNU_RELRO have to be page aligned so that the dynamic // linker can set the permissions. template void Writer::fixSectionAlignments() { + auto PageAlign = [](OutputSection *Sec) { + OutputSectionCommand *Cmd = Script->getCmd(Sec); + if (Cmd && !Cmd->AddrExpr) + Cmd->AddrExpr = [=] { + return alignTo(Script->getDot(), Config->MaxPageSize); + }; + }; + for (const PhdrEntry &P : Phdrs) if (P.p_type == PT_LOAD && P.First) - P.First->PageAlign = true; + PageAlign(P.First); for (const PhdrEntry &P : Phdrs) { if (P.p_type != PT_GNU_RELRO) continue; if (P.First) - P.First->PageAlign = true; + PageAlign(P.First); // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we // have to align it to a page. - auto End = OutputSections.end(); - auto I = std::find(OutputSections.begin(), End, P.Last); + auto End = OutputSectionCommands.end(); + auto I = + std::find(OutputSectionCommands.begin(), End, Script->getCmd(P.Last)); if (I == End || (I + 1) == End) continue; - OutputSection *Sec = *(I + 1); + OutputSection *Sec = (*(I + 1))->Sec; if (needsPtLoad(Sec)) - Sec->PageAlign = true; + PageAlign(Sec); } } diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Config.h.cmake b/contrib/llvm/tools/lldb/include/lldb/Host/Config.h.cmake index 5a16425fe0a9..0deedd151a5e 100644 --- a/contrib/llvm/tools/lldb/include/lldb/Host/Config.h.cmake +++ b/contrib/llvm/tools/lldb/include/lldb/Host/Config.h.cmake @@ -20,4 +20,8 @@ #cmakedefine01 HAVE_SIGACTION +#cmakedefine01 HAVE_PROCESS_VM_READV + +#cmakedefine01 HAVE_NR_PROCESS_VM_READV + #endif // #ifndef LLDB_HOST_CONFIG_H diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp index 8b837b79bed8..608ff0a3a7b5 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp @@ -3938,6 +3938,11 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, const clang::Type::TypeClass type_class = qual_type->getTypeClass(); switch (type_class) { + case clang::Type::Attributed: + return GetTypeInfo( + qual_type->getAs() + ->getModifiedType().getAsOpaquePtr(), + pointee_or_element_clang_type); case clang::Type::Builtin: { const clang::BuiltinType *builtin_type = llvm::dyn_cast( qual_type->getCanonicalTypeInternal()); diff --git a/contrib/llvm/tools/llvm-lto2/llvm-lto2.cpp b/contrib/llvm/tools/llvm-lto2/llvm-lto2.cpp index 3d2643db85bd..89f85157e1df 100644 --- a/contrib/llvm/tools/llvm-lto2/llvm-lto2.cpp +++ b/contrib/llvm/tools/llvm-lto2/llvm-lto2.cpp @@ -99,6 +99,11 @@ static cl::opt OptRemarksWithHotness( cl::desc("Whether to include hotness informations in the remarks.\n" "Has effect only if -pass-remarks-output is specified.")); +static cl::opt + UseNewPM("use-new-pm", + cl::desc("Run LTO passes using the new pass manager"), + cl::init(false), cl::Hidden); + static void check(Error E, std::string Msg) { if (!E) return; @@ -196,6 +201,7 @@ static int run(int argc, char **argv) { Conf.AAPipeline = AAPipeline; Conf.OptLevel = OptLevel - '0'; + Conf.UseNewPM = UseNewPM; switch (CGOptLevel) { case '0': Conf.CGOptLevel = CodeGenOpt::None; @@ -351,7 +357,7 @@ int main(int argc, char **argv) { // FIXME: This should use llvm::cl subcommands, but it isn't currently // possible to pass an argument not associated with a subcommand to a - // subcommand (e.g. -lto-use-new-pm). + // subcommand (e.g. -use-new-pm). if (argc < 2) return usage(); diff --git a/contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp index d95eca1aeddb..31c342cd0f5a 100644 --- a/contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -483,8 +483,8 @@ Error LLVMOutputStyle::dumpStreamBytes() { if (SI >= File.getNumStreams()) return make_error(raw_error_code::no_stream); - auto S = MappedBlockStream::createIndexedStream(File.getMsfLayout(), - File.getMsfBuffer(), SI); + auto S = MappedBlockStream::createIndexedStream( + File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator()); if (!S) continue; DictScope DD(P, "Stream"); @@ -791,7 +791,7 @@ Error LLVMOutputStyle::dumpDbiStream() { if (HasModuleDI && (ShouldDumpSymbols || opts::raw::DumpLineInfo)) { auto ModStreamData = MappedBlockStream::createIndexedStream( File.getMsfLayout(), File.getMsfBuffer(), - Modi.getModuleStreamIndex()); + Modi.getModuleStreamIndex(), File.getAllocator()); ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); if (auto EC = ModS.reload()) @@ -804,7 +804,8 @@ Error LLVMOutputStyle::dumpDbiStream() { auto &Types = *ExpectedTypes; ListScope SS(P, "Symbols"); - codeview::CVSymbolDumper SD(P, Types, nullptr, false); + codeview::CVSymbolDumper SD(P, Types, CodeViewContainer::Pdb, nullptr, + false); bool HadError = false; for (auto S : ModS.symbols(&HadError)) { DictScope LL(P, ""); @@ -830,8 +831,7 @@ Error LLVMOutputStyle::dumpDbiStream() { return ExpectedTypes.takeError(); auto &IpiItems = *ExpectedTypes; C13RawVisitor V(P, File, IpiItems); - if (auto EC = - codeview::visitDebugSubsections(ModS.linesAndChecksums(), V)) + if (auto EC = codeview::visitDebugSubsections(ModS.subsections(), V)) return EC; } } @@ -952,7 +952,7 @@ Error LLVMOutputStyle::dumpPublicsStream() { return ExpectedTypes.takeError(); auto &Tpi = *ExpectedTypes; - codeview::CVSymbolDumper SD(P, Tpi, nullptr, false); + codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr, false); bool HadError = false; for (auto S : Publics->getSymbols(&HadError)) { DictScope DD(P, ""); diff --git a/contrib/llvm/tools/llvm-pdbdump/PdbYaml.cpp b/contrib/llvm/tools/llvm-pdbdump/PdbYaml.cpp index e288063e2afa..b4a41fbfdb8f 100644 --- a/contrib/llvm/tools/llvm-pdbdump/PdbYaml.cpp +++ b/contrib/llvm/tools/llvm-pdbdump/PdbYaml.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h" #include "llvm/DebugInfo/CodeView/TypeSerializer.h" @@ -21,6 +22,7 @@ #include "llvm/DebugInfo/PDB/Native/TpiHashing.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" #include "llvm/ObjectYAML/CodeViewYAMLTypes.h" using namespace llvm; @@ -220,6 +222,6 @@ void MappingTraits::mapping(IO &IO, PdbDbiModuleInfo &Obj) { IO.mapRequired("Module", Obj.Mod); IO.mapOptional("ObjFile", Obj.Obj, Obj.Mod); IO.mapOptional("SourceFiles", Obj.SourceFiles); - IO.mapOptional("LineInfo", Obj.FileLineInfo); + IO.mapOptional("Subsections", Obj.Subsections); IO.mapOptional("Modi", Obj.Modi); } diff --git a/contrib/llvm/tools/llvm-pdbdump/PdbYaml.h b/contrib/llvm/tools/llvm-pdbdump/PdbYaml.h index deb500ec2074..62ed608916fc 100644 --- a/contrib/llvm/tools/llvm-pdbdump/PdbYaml.h +++ b/contrib/llvm/tools/llvm-pdbdump/PdbYaml.h @@ -28,6 +28,9 @@ #include namespace llvm { +namespace codeview { +class DebugStringTableSubsection; +} namespace pdb { namespace yaml { @@ -68,7 +71,7 @@ struct PdbDbiModuleInfo { StringRef Obj; StringRef Mod; std::vector SourceFiles; - Optional FileLineInfo; + std::vector Subsections; Optional Modi; }; diff --git a/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp index 18839a7679d3..ee72b90b12d1 100644 --- a/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ b/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -101,117 +101,6 @@ Error YAMLOutputStyle::dump() { return Error::success(); } -namespace { -class C13YamlVisitor : public C13DebugFragmentVisitor { -public: - C13YamlVisitor(CodeViewYAML::SourceFileInfo &Info, PDBFile &F) - : C13DebugFragmentVisitor(F), Info(Info) {} - - Error handleFileChecksums() override { - for (const auto &C : *Checksums) { - CodeViewYAML::SourceFileChecksumEntry Entry; - if (auto Result = getNameFromStringTable(C.FileNameOffset)) - Entry.FileName = *Result; - else - return Result.takeError(); - - Entry.Kind = C.Kind; - Entry.ChecksumBytes.Bytes = C.Checksum; - Info.FileChecksums.push_back(Entry); - } - return Error::success(); - } - - Error handleLines() override { - for (const auto &LF : Lines) { - Info.LineFragments.emplace_back(); - auto &Fragment = Info.LineFragments.back(); - - Fragment.CodeSize = LF.header()->CodeSize; - Fragment.Flags = - static_cast(uint16_t(LF.header()->Flags)); - Fragment.RelocOffset = LF.header()->RelocOffset; - Fragment.RelocSegment = LF.header()->RelocSegment; - - for (const auto &L : LF) { - Fragment.Blocks.emplace_back(); - auto &Block = Fragment.Blocks.back(); - - if (auto Result = getNameFromChecksumsBuffer(L.NameIndex)) - Block.FileName = *Result; - else - return Result.takeError(); - - for (const auto &N : L.LineNumbers) { - CodeViewYAML::SourceLineEntry Line; - Line.Offset = N.Offset; - codeview::LineInfo LI(N.Flags); - Line.LineStart = LI.getStartLine(); - Line.EndDelta = LI.getLineDelta(); - Line.IsStatement = LI.isStatement(); - Block.Lines.push_back(Line); - } - - if (LF.hasColumnInfo()) { - for (const auto &C : L.Columns) { - CodeViewYAML::SourceColumnEntry Column; - Column.StartColumn = C.StartColumn; - Column.EndColumn = C.EndColumn; - Block.Columns.push_back(Column); - } - } - } - } - return Error::success(); - } - - Error handleInlineeLines() override { - for (const auto &ILF : InlineeLines) { - Info.Inlinees.emplace_back(); - auto &Inlinee = Info.Inlinees.back(); - - Inlinee.HasExtraFiles = ILF.hasExtraFiles(); - for (const auto &IL : ILF) { - Inlinee.Sites.emplace_back(); - auto &Site = Inlinee.Sites.back(); - if (auto Result = getNameFromChecksumsBuffer(IL.Header->FileID)) - Site.FileName = *Result; - else - return Result.takeError(); - - Site.Inlinee = IL.Header->Inlinee.getIndex(); - Site.SourceLineNum = IL.Header->SourceLineNum; - if (ILF.hasExtraFiles()) { - for (const auto &EF : IL.ExtraFiles) { - if (auto Result = getNameFromChecksumsBuffer(EF)) - Site.ExtraFiles.push_back(*Result); - else - return Result.takeError(); - } - } - } - } - return Error::success(); - } - -private: - CodeViewYAML::SourceFileInfo &Info; -}; -} - -Expected> -YAMLOutputStyle::getFileLineInfo(const pdb::ModuleDebugStreamRef &ModS) { - if (!ModS.hasLineInfo()) - return None; - - CodeViewYAML::SourceFileInfo Info; - C13YamlVisitor Visitor(Info, File); - if (auto EC = - codeview::visitDebugSubsections(ModS.linesAndChecksums(), Visitor)) - return std::move(EC); - - return Info; -} Error YAMLOutputStyle::dumpFileHeaders() { if (opts::pdb2yaml::NoFileHeaders) @@ -236,14 +125,17 @@ Error YAMLOutputStyle::dumpFileHeaders() { } Error YAMLOutputStyle::dumpStringTable() { - if (!opts::pdb2yaml::StringTable) + bool RequiresStringTable = opts::pdb2yaml::DbiModuleSourceFileInfo || + opts::pdb2yaml::DbiModuleSourceLineInfo; + bool RequestedStringTable = opts::pdb2yaml::StringTable; + if (!RequiresStringTable && !RequestedStringTable) return Error::success(); - Obj.StringTable.emplace(); auto ExpectedST = File.getStringTable(); if (!ExpectedST) return ExpectedST.takeError(); + Obj.StringTable.emplace(); const auto &ST = ExpectedST.get(); for (auto ID : ST.name_ids()) { auto S = ST.getStringForID(ID); @@ -337,17 +229,30 @@ Error YAMLOutputStyle::dumpDbiStream() { continue; auto ModStreamData = msf::MappedBlockStream::createIndexedStream( - File.getMsfLayout(), File.getMsfBuffer(), ModiStream); + File.getMsfLayout(), File.getMsfBuffer(), ModiStream, + File.getAllocator()); pdb::ModuleDebugStreamRef ModS(MI, std::move(ModStreamData)); if (auto EC = ModS.reload()) return EC; - if (opts::pdb2yaml::DbiModuleSourceLineInfo) { - auto ExpectedInfo = getFileLineInfo(ModS); - if (!ExpectedInfo) - return ExpectedInfo.takeError(); - DMI.FileLineInfo = *ExpectedInfo; + auto ExpectedST = File.getStringTable(); + if (!ExpectedST) + return ExpectedST.takeError(); + if (opts::pdb2yaml::DbiModuleSourceLineInfo && + ModS.hasDebugSubsections()) { + auto ExpectedChecksums = ModS.findChecksumsSubsection(); + if (!ExpectedChecksums) + return ExpectedChecksums.takeError(); + + for (const auto &SS : ModS.subsections()) { + auto Converted = + CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection( + ExpectedST->getStringTable(), *ExpectedChecksums, SS); + if (!Converted) + return Converted.takeError(); + DMI.Subsections.push_back(*Converted); + } } if (opts::pdb2yaml::DbiModuleSyms) { diff --git a/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h b/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h index 6e4067c48f88..3690e3529d4a 100644 --- a/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h +++ b/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h @@ -27,9 +27,6 @@ public: Error dump() override; private: - Expected> - getFileLineInfo(const pdb::ModuleDebugStreamRef &ModS); - Error dumpStringTable(); Error dumpFileHeaders(); Error dumpStreamMetadata(); diff --git a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index 0b2b766a3c52..4626de9c4440 100644 --- a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -476,7 +476,6 @@ static void yamlToPdb(StringRef Path) { std::unique_ptr &Buffer = ErrorOrBuffer.get(); llvm::yaml::Input In(Buffer->getBuffer()); - In.setContext(&Allocator); pdb::yaml::PdbObject YamlObj(Allocator); In >> YamlObj; @@ -535,67 +534,16 @@ static void yamlToPdb(StringRef Path) { ExitOnErr(DbiBuilder.addModuleSourceFile(MI.Mod, S)); if (MI.Modi.hasValue()) { const auto &ModiStream = *MI.Modi; - for (auto Symbol : ModiStream.Symbols) - ModiBuilder.addSymbol(Symbol.toCodeViewSymbol(Allocator)); + for (auto Symbol : ModiStream.Symbols) { + ModiBuilder.addSymbol( + Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb)); + } } - if (MI.FileLineInfo.hasValue()) { - const auto &FLI = *MI.FileLineInfo; - // File Checksums must be emitted before line information, because line - // info records use offsets into the checksum buffer to reference a file's - // source file name. - auto Checksums = llvm::make_unique(Strings); - auto &ChecksumRef = *Checksums; - if (!FLI.FileChecksums.empty()) { - for (auto &FC : FLI.FileChecksums) - Checksums->addChecksum(FC.FileName, FC.Kind, FC.ChecksumBytes.Bytes); - } - ModiBuilder.setC13FileChecksums(std::move(Checksums)); - - for (const auto &Fragment : FLI.LineFragments) { - auto Lines = - llvm::make_unique(ChecksumRef, Strings); - Lines->setCodeSize(Fragment.CodeSize); - Lines->setRelocationAddress(Fragment.RelocSegment, - Fragment.RelocOffset); - Lines->setFlags(Fragment.Flags); - for (const auto &LC : Fragment.Blocks) { - Lines->createBlock(LC.FileName); - if (Lines->hasColumnInfo()) { - for (const auto &Item : zip(LC.Lines, LC.Columns)) { - auto &L = std::get<0>(Item); - auto &C = std::get<1>(Item); - uint32_t LE = L.LineStart + L.EndDelta; - Lines->addLineAndColumnInfo( - L.Offset, LineInfo(L.LineStart, LE, L.IsStatement), - C.StartColumn, C.EndColumn); - } - } else { - for (const auto &L : LC.Lines) { - uint32_t LE = L.LineStart + L.EndDelta; - Lines->addLineInfo(L.Offset, - LineInfo(L.LineStart, LE, L.IsStatement)); - } - } - } - ModiBuilder.addC13Fragment(std::move(Lines)); - } - - for (const auto &Inlinee : FLI.Inlinees) { - auto Inlinees = llvm::make_unique( - ChecksumRef, Inlinee.HasExtraFiles); - for (const auto &Site : Inlinee.Sites) { - Inlinees->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName, - Site.SourceLineNum); - if (!Inlinee.HasExtraFiles) - continue; - - for (auto EF : Site.ExtraFiles) { - Inlinees->addExtraFile(EF); - } - } - ModiBuilder.addC13Fragment(std::move(Inlinees)); - } + auto CodeViewSubsections = + ExitOnErr(CodeViewYAML::convertSubsectionList(MI.Subsections, Strings)); + for (auto &SS : CodeViewSubsections) { + ModiBuilder.addDebugSubsection(std::move(SS)); } } diff --git a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp index 663f7b4c8a82..bc07bd296ad2 100644 --- a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -978,7 +978,8 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, Subsection.bytes_end()); auto CODD = llvm::make_unique(*this, Section, Obj, SectionContents); - CVSymbolDumper CVSD(W, Types, std::move(CODD), opts::CodeViewSubsectionBytes); + CVSymbolDumper CVSD(W, Types, CodeViewContainer::ObjectFile, std::move(CODD), + opts::CodeViewSubsectionBytes); CVSymbolArray Symbols; BinaryStreamReader Reader(BinaryData, llvm::support::little); if (auto EC = Reader.readArray(Symbols, Reader.getLength())) { diff --git a/contrib/llvm/utils/TableGen/X86FoldTablesEmitter.cpp b/contrib/llvm/utils/TableGen/X86FoldTablesEmitter.cpp index b89cee2ce4bb..34f5fbc6ea31 100644 --- a/contrib/llvm/utils/TableGen/X86FoldTablesEmitter.cpp +++ b/contrib/llvm/utils/TableGen/X86FoldTablesEmitter.cpp @@ -101,6 +101,11 @@ const char *const NoFoldSet[] = { "BTS16rr", "BTS32rr", "BTS64rr", "BTS16mr", "BTS32mr", "BTS64mr", + // insertps cannot be folded without adjusting the immediate. There's custom + // code to handle it in X86InstrInfo.cpp, ignore it here. + "INSERTPSrr", "INSERTPSrm", + "VINSERTPSrr", "VINSERTPSrm", "VINSERTPSZrr", "VINSERTPSZrm", + // Memory folding is enabled only when optimizing for size by DAG // patterns only. (issue detailed in D28744 review) "VCVTSS2SDrm", "VCVTSS2SDrr", diff --git a/lib/clang/include/clang/Basic/Version.inc b/lib/clang/include/clang/Basic/Version.inc index 038c60560bdf..2f646d61ab36 100644 --- a/lib/clang/include/clang/Basic/Version.inc +++ b/lib/clang/include/clang/Basic/Version.inc @@ -8,4 +8,4 @@ #define CLANG_VENDOR "FreeBSD " -#define SVN_REVISION "304460" +#define SVN_REVISION "304659" diff --git a/lib/clang/include/lld/Config/Version.inc b/lib/clang/include/lld/Config/Version.inc index 84e763d1b73e..5fe7c683c5ca 100644 --- a/lib/clang/include/lld/Config/Version.inc +++ b/lib/clang/include/lld/Config/Version.inc @@ -4,5 +4,5 @@ #define LLD_VERSION_STRING "5.0.0" #define LLD_VERSION_MAJOR 5 #define LLD_VERSION_MINOR 0 -#define LLD_REVISION_STRING "304460" +#define LLD_REVISION_STRING "304659" #define LLD_REPOSITORY_STRING "FreeBSD" diff --git a/lib/clang/include/lldb/Host/Config.h b/lib/clang/include/lldb/Host/Config.h index 618aabb20954..670eca5b585d 100644 --- a/lib/clang/include/lldb/Host/Config.h +++ b/lib/clang/include/lldb/Host/Config.h @@ -21,4 +21,8 @@ #define HAVE_SIGACTION 1 +#define HAVE_PROCESS_VM_READV 0 + +#define HAVE_NR_PROCESS_VM_READV 0 + #endif // #ifndef LLDB_HOST_CONFIG_H diff --git a/lib/clang/include/llvm/Support/DataTypes.h b/lib/clang/include/llvm/Support/DataTypes.h index 5d02231fabff..49b0b7c69910 100644 --- a/lib/clang/include/llvm/Support/DataTypes.h +++ b/lib/clang/include/llvm/Support/DataTypes.h @@ -133,4 +133,4 @@ typedef signed int ssize_t; #define HUGE_VALF (float)HUGE_VAL #endif -#endif /* SUPPORT_DATATYPES_H */ +#endif /* SUPPORT_DATATYPES_H */ diff --git a/lib/clang/include/llvm/Support/VCSRevision.h b/lib/clang/include/llvm/Support/VCSRevision.h index 95f7041cc421..1b37cf160cb3 100644 --- a/lib/clang/include/llvm/Support/VCSRevision.h +++ b/lib/clang/include/llvm/Support/VCSRevision.h @@ -1,2 +1,2 @@ /* $FreeBSD$ */ -#define LLVM_REVISION "svn-r304460" +#define LLVM_REVISION "svn-r304659" diff --git a/lib/libclang_rt/asan/Makefile b/lib/libclang_rt/asan/Makefile index e8a98f584577..359b4fa60c30 100644 --- a/lib/libclang_rt/asan/Makefile +++ b/lib/libclang_rt/asan/Makefile @@ -37,9 +37,7 @@ SRCS+= sanitizer_common/sancov_flags.cc SRCS+= sanitizer_common/sanitizer_allocator.cc SRCS+= sanitizer_common/sanitizer_common.cc SRCS+= sanitizer_common/sanitizer_common_libcdep.cc -SRCS+= sanitizer_common/sanitizer_coverage_libcdep.cc SRCS+= sanitizer_common/sanitizer_coverage_libcdep_new.cc -SRCS+= sanitizer_common/sanitizer_coverage_mapping_libcdep.cc SRCS+= sanitizer_common/sanitizer_deadlock_detector1.cc SRCS+= sanitizer_common/sanitizer_deadlock_detector2.cc SRCS+= sanitizer_common/sanitizer_flag_parser.cc diff --git a/lib/libclang_rt/asan_dynamic/Makefile b/lib/libclang_rt/asan_dynamic/Makefile index 118fa1b2e968..93e4f1017d6f 100644 --- a/lib/libclang_rt/asan_dynamic/Makefile +++ b/lib/libclang_rt/asan_dynamic/Makefile @@ -38,9 +38,7 @@ SRCS+= sanitizer_common/sancov_flags.cc SRCS+= sanitizer_common/sanitizer_allocator.cc SRCS+= sanitizer_common/sanitizer_common.cc SRCS+= sanitizer_common/sanitizer_common_libcdep.cc -SRCS+= sanitizer_common/sanitizer_coverage_libcdep.cc SRCS+= sanitizer_common/sanitizer_coverage_libcdep_new.cc -SRCS+= sanitizer_common/sanitizer_coverage_mapping_libcdep.cc SRCS+= sanitizer_common/sanitizer_deadlock_detector1.cc SRCS+= sanitizer_common/sanitizer_deadlock_detector2.cc SRCS+= sanitizer_common/sanitizer_flag_parser.cc diff --git a/lib/libclang_rt/stats/Makefile b/lib/libclang_rt/stats/Makefile index 84872811ea15..378f3a943379 100644 --- a/lib/libclang_rt/stats/Makefile +++ b/lib/libclang_rt/stats/Makefile @@ -8,9 +8,7 @@ SRCS+= sanitizer_common/sancov_flags.cc SRCS+= sanitizer_common/sanitizer_allocator.cc SRCS+= sanitizer_common/sanitizer_common.cc SRCS+= sanitizer_common/sanitizer_common_libcdep.cc -SRCS+= sanitizer_common/sanitizer_coverage_libcdep.cc SRCS+= sanitizer_common/sanitizer_coverage_libcdep_new.cc -SRCS+= sanitizer_common/sanitizer_coverage_mapping_libcdep.cc SRCS+= sanitizer_common/sanitizer_deadlock_detector1.cc SRCS+= sanitizer_common/sanitizer_deadlock_detector2.cc SRCS+= sanitizer_common/sanitizer_flag_parser.cc diff --git a/lib/libclang_rt/ubsan_standalone/Makefile b/lib/libclang_rt/ubsan_standalone/Makefile index ed008e54ae2e..01b8f20c634d 100644 --- a/lib/libclang_rt/ubsan_standalone/Makefile +++ b/lib/libclang_rt/ubsan_standalone/Makefile @@ -8,9 +8,7 @@ SRCS+= sanitizer_common/sancov_flags.cc SRCS+= sanitizer_common/sanitizer_allocator.cc SRCS+= sanitizer_common/sanitizer_common.cc SRCS+= sanitizer_common/sanitizer_common_libcdep.cc -SRCS+= sanitizer_common/sanitizer_coverage_libcdep.cc SRCS+= sanitizer_common/sanitizer_coverage_libcdep_new.cc -SRCS+= sanitizer_common/sanitizer_coverage_mapping_libcdep.cc SRCS+= sanitizer_common/sanitizer_deadlock_detector1.cc SRCS+= sanitizer_common/sanitizer_deadlock_detector2.cc SRCS+= sanitizer_common/sanitizer_flag_parser.cc