-
Notifications
You must be signed in to change notification settings - Fork 262
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge #20447: depends: Patch qt_intersect_spans to avoid non-determin…
…istic behavior in LLVM 8 8f7d1b3 Fix QPainter non-determinism on macOS (Andrew Chow) Pull request description: Aplies a patch to Qt that fixes the non-determinism by modifying Qt. The source of the non-determinism is how LLVM 8 optimizes qt_intersect_spans when compiling. The particular optimization that seems to be causing the problems is that a temp variable is being added for spans->y. For some reason, when it does this, it chooses different instructions to use when making that variable. We bypass this problem by patching qt_intersect_spans to always make and use this local variable. Potential alternative to #20436 and #20440 ACKs for top commit: hebasto: re-ACK 8f7d1b3 ~for merging into the 0.21 branch, but [not into the master](bitcoin/bitcoin#20454) branch.~ fanquake: ACK 8f7d1b3 Tree-SHA512: b0d00a77643554021736524fb64611462ef2ec849a220543c12d99edb0f52f2e8128d2cc61fa82176b7e13b294574774a92d6b649badf8b7630c6d6a7e70ce10
- Loading branch information
Showing
2 changed files
with
65 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
commit 2a8f7dc6ddfc414a66491522501c1574a1343ee1 | ||
Author: Andrew Chow <achow101-github@achow101.com> | ||
Date: Sat Nov 21 01:11:04 2020 -0500 | ||
|
||
build: Fix determinism issue when building with Clang 8 | ||
|
||
When building Qt with LLVM/Clang 8 under -O3 (the default), we run into | ||
a determinism issue in `qt_interset_spans`. The issue has been fixed for | ||
LLVM/Clang 9, see | ||
https://github.com/llvm/llvm-project/commit/db101864bdc938deb1d63fe4f7da761bd38e5cae | ||
and https://reviews.llvm.org/D64601, however this fix was not backported | ||
to 8.x. Once LLVM/Clang 9 is used, this patch can be dropped. | ||
|
||
The particular issue appears to be an optimization done by -O3 which | ||
adds a temporary variable for `spans->y` in `qt_intersect_spans`. When | ||
it does this, sometimes it chooses to use a 32-bit movs instruction | ||
(movswl), and other times it chooses a 64-bit movs instruction (movswq). | ||
By patching `qt_intersect_spans` to always make a temporary variable for | ||
`spans->y`, we are able to sidestep this problem. | ||
|
||
diff --git a/qtbase/src/gui/painting/qpaintengine_raster.cpp b/qtbase/src/gui/painting/qpaintengine_raster.cpp | ||
index 92ab6e8375..f018009e0b 100644 | ||
--- a/qtbase/src/gui/painting/qpaintengine_raster.cpp | ||
+++ b/qtbase/src/gui/painting/qpaintengine_raster.cpp | ||
@@ -3971,22 +3971,23 @@ static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip, | ||
const QSpan *clipEnd = clip->m_spans + clip->count; | ||
|
||
while (available && spans < end ) { | ||
+ const short spans_y = spans->y; | ||
if (clipSpans >= clipEnd) { | ||
spans = end; | ||
break; | ||
} | ||
- if (clipSpans->y > spans->y) { | ||
+ if (clipSpans->y > spans_y) { | ||
++spans; | ||
continue; | ||
} | ||
- if (spans->y != clipSpans->y) { | ||
- if (spans->y < clip->count && clip->m_clipLines[spans->y].spans) | ||
- clipSpans = clip->m_clipLines[spans->y].spans; | ||
+ if (spans_y != clipSpans->y) { | ||
+ if (spans_y < clip->count && clip->m_clipLines[spans_y].spans) | ||
+ clipSpans = clip->m_clipLines[spans_y].spans; | ||
else | ||
++clipSpans; | ||
continue; | ||
} | ||
- Q_ASSERT(spans->y == clipSpans->y); | ||
+ Q_ASSERT(spans_y == clipSpans->y); | ||
|
||
int sx1 = spans->x; | ||
int sx2 = sx1 + spans->len; | ||
@@ -4005,7 +4006,7 @@ static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip, | ||
if (len) { | ||
out->x = qMax(sx1, cx1); | ||
out->len = qMin(sx2, cx2) - out->x; | ||
- out->y = spans->y; | ||
+ out->y = spans_y; | ||
out->coverage = qt_div_255(spans->coverage * clipSpans->coverage); | ||
++out; | ||
--available; | ||
|