From bfa0bf690c2e90cc0844f2f012efa41b916bde7e Mon Sep 17 00:00:00 2001 From: kobalicek Date: Tue, 23 Jan 2024 23:46:27 +0100 Subject: [PATCH] Workaround for issue #427 MSVC incorrectly auto-vectorizes a loop that is used in liveness analysis. Due to this bug the result is wrong, which then affects how registers are allocated. This workarounds a C++ compiler bug. --- src/asmjit/core/rapass.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/asmjit/core/rapass.cpp b/src/asmjit/core/rapass.cpp index 6aab715..6baa64b 100644 --- a/src/asmjit/core/rapass.cpp +++ b/src/asmjit/core/rapass.cpp @@ -762,6 +762,13 @@ namespace LiveOps { static ASMJIT_FORCE_INLINE bool op(BitWord* dst, const BitWord* a, const BitWord* b, const BitWord* c, uint32_t n) noexcept { BitWord changed = 0; +#if defined(_MSC_VER) && _MSC_VER <= 1938 + // MSVC workaround (see #427). + // + // MSVC incorrectly auto-vectorizes this loop when used with operator. For some reason it trashes a content + // of a register, which causes the result to be incorrect. It's a compiler bug we have to prevent unfortunately. + #pragma loop(no_vector) +#endif for (uint32_t i = 0; i < n; i++) { BitWord before = dst[i]; BitWord after = Operator::op(before, a[i], b[i], c[i]); @@ -773,7 +780,7 @@ namespace LiveOps { return changed != 0; } - static ASMJIT_FORCE_INLINE bool recalcInOut(RABlock* block, uint32_t numBitWords, bool initial = false) noexcept { + static ASMJIT_NOINLINE bool recalcInOut(RABlock* block, uint32_t numBitWords, bool initial = false) noexcept { bool changed = initial; const RABlocks& successors = block->successors(); @@ -873,7 +880,7 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { if (tiedReg->hasConsecutiveParent()) { RAWorkReg* consecutiveParentReg = workRegById(tiedReg->consecutiveParent()); - consecutiveParentReg->addImmediateConsecutive(allocator(), workId); + ASMJIT_PROPAGATE(consecutiveParentReg->addImmediateConsecutive(allocator(), workId)); } }