|
| 1 | +commit 2a8f7dc6ddfc414a66491522501c1574a1343ee1 |
| 2 | +Author: Andrew Chow < [email protected]> |
| 3 | +Date: Sat Nov 21 01:11:04 2020 -0500 |
| 4 | + |
| 5 | + build: Fix determinism issue when building with Clang 8 |
| 6 | + |
| 7 | + When building Qt with LLVM/Clang 8 under -O3 (the default), we run into |
| 8 | + a determinism issue in `qt_interset_spans`. The issue has been fixed for |
| 9 | + LLVM/Clang 9, see |
| 10 | + https://github.com/llvm/llvm-project/commit/db101864bdc938deb1d63fe4f7da761bd38e5cae |
| 11 | + and https://reviews.llvm.org/D64601, however this fix was not backported |
| 12 | + to 8.x. Once LLVM/Clang 9 is used, this patch can be dropped. |
| 13 | + |
| 14 | + The particular issue appears to be an optimization done by -O3 which |
| 15 | + adds a temporary variable for `spans->y` in `qt_intersect_spans`. When |
| 16 | + it does this, sometimes it chooses to use a 32-bit movs instruction |
| 17 | + (movswl), and other times it chooses a 64-bit movs instruction (movswq). |
| 18 | + By patching `qt_intersect_spans` to always make a temporary variable for |
| 19 | + `spans->y`, we are able to sidestep this problem. |
| 20 | + |
| 21 | +diff --git a/qtbase/src/gui/painting/qpaintengine_raster.cpp b/qtbase/src/gui/painting/qpaintengine_raster.cpp |
| 22 | +index 92ab6e8375..f018009e0b 100644 |
| 23 | +--- a/qtbase/src/gui/painting/qpaintengine_raster.cpp |
| 24 | ++++ b/qtbase/src/gui/painting/qpaintengine_raster.cpp |
| 25 | +@@ -3971,22 +3971,23 @@ static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip, |
| 26 | + const QSpan *clipEnd = clip->m_spans + clip->count; |
| 27 | + |
| 28 | + while (available && spans < end ) { |
| 29 | ++ const short spans_y = spans->y; |
| 30 | + if (clipSpans >= clipEnd) { |
| 31 | + spans = end; |
| 32 | + break; |
| 33 | + } |
| 34 | +- if (clipSpans->y > spans->y) { |
| 35 | ++ if (clipSpans->y > spans_y) { |
| 36 | + ++spans; |
| 37 | + continue; |
| 38 | + } |
| 39 | +- if (spans->y != clipSpans->y) { |
| 40 | +- if (spans->y < clip->count && clip->m_clipLines[spans->y].spans) |
| 41 | +- clipSpans = clip->m_clipLines[spans->y].spans; |
| 42 | ++ if (spans_y != clipSpans->y) { |
| 43 | ++ if (spans_y < clip->count && clip->m_clipLines[spans_y].spans) |
| 44 | ++ clipSpans = clip->m_clipLines[spans_y].spans; |
| 45 | + else |
| 46 | + ++clipSpans; |
| 47 | + continue; |
| 48 | + } |
| 49 | +- Q_ASSERT(spans->y == clipSpans->y); |
| 50 | ++ Q_ASSERT(spans_y == clipSpans->y); |
| 51 | + |
| 52 | + int sx1 = spans->x; |
| 53 | + int sx2 = sx1 + spans->len; |
| 54 | +@@ -4005,7 +4006,7 @@ static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip, |
| 55 | + if (len) { |
| 56 | + out->x = qMax(sx1, cx1); |
| 57 | + out->len = qMin(sx2, cx2) - out->x; |
| 58 | +- out->y = spans->y; |
| 59 | ++ out->y = spans_y; |
| 60 | + out->coverage = qt_div_255(spans->coverage * clipSpans->coverage); |
| 61 | + ++out; |
| 62 | + --available; |
| 63 | + |
0 commit comments