This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository terminology.

View the commit online.

commit ab06090727a8e627fd08d41725bb2adf2f20f065
Author: Cedric BAIL <[email protected]>
AuthorDate: Mon Aug 3 13:50:34 2026 -0600

    termpty: vectorise the autowrapped marking of saved rows
    
    Every row that scrolls into the backlog is walked to flag its cells as
    continuing onto the next line. GCC already compiles that to five instructions
    per cell -- load the bitfield word, or, store back, advance twelve bytes,
    test -- so there was nothing left to gain from rewriting it scalar.
    
    A twelve-byte stride lines up with a sixteen-byte vector every four cells, so
    the mask repeats every forty-eight bytes and can be applied as three fixed
    vectors, a little over two instructions per cell. That is the record byte-OR
    kernel added here; every other stride falls through to its scalar form rather
    than pretending to be vectorised.
    
    Which byte carries att.autowrapped depends on how the compiler lays out
    Termatt's bitfields, so it is worked out once from a cell that has the bit
    set. Hardcoding the offset would have been quietly invalidated by any change
    to Termatt. If the probe ever came up empty the cells are marked the slow way:
    assert() is compiled out under NDEBUG, and the failure mode of marking nothing
    is wrapped lines that stop rejoining, which is not the kind of thing to leave
    resting on a layout assumption.
    
    The marking cannot be folded into the copy that follows it:
    termpty_text_scroll() only clears the row it just saved when asked to, so the
    source has to keep its marks, and glibc's memcpy is already cheap enough that
    fusing the two passes would not pay for itself.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 src/bin/termpty.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 54 insertions(+), 5 deletions(-)

diff --git a/src/bin/termpty.c b/src/bin/termpty.c
index a7f8d521..98852a1f 100644
--- a/src/bin/termpty.c
+++ b/src/bin/termpty.c
@@ -990,11 +990,62 @@ termpty_line_length(const Termcell *cells, ssize_t nb_cells)
 }
 
 
+/* Flag a run of cells as continuing onto the next line. The byte carrying
+ * att.autowrapped depends on the compiler's bitfield layout, so it is worked
+ * out once from a cell that has the bit set. */
+static void
+_mark_autowrapped(Termcell *cells, ssize_t n)
+{
+   /* NOT_PROBED rather than a zero 'bit', so the probe runs exactly once even
+    * if it ever comes up empty. */
+#define NOT_PROBED ((size_t)-1)
+   static size_t off = NOT_PROBED;
+   static unsigned char bit;
+
+   if (EINA_UNLIKELY(off == NOT_PROBED))
+     {
+        Termcell probe;
+        size_t i;
+
+        memset(&probe, 0, sizeof(probe));
+        probe.att.autowrapped = 1;
+        for (i = 0; i < sizeof(probe); i++)
+          {
+             if (((const unsigned char *)&probe)[i])
+               {
+                  off = i;
+                  bit = ((const unsigned char *)&probe)[i];
+                  break;
+               }
+          }
+        assert(off != NOT_PROBED);
+     }
+
+   if (EINA_UNLIKELY(off == NOT_PROBED))
+     {
+        /* One bitfield bit always lands in some byte, so this is unreachable --
+         * but assert() is gone under NDEBUG, and marking nothing at all would
+         * silently stop wrapped lines from rejoining. Mark them the slow way
+         * instead of trusting the layout. */
+        ssize_t i;
+
+        for (i = 0; i < n; i++)
+          cells[i].att.autowrapped = 1;
+        return;
+     }
+
+   _Static_assert(sizeof(Termcell) == 12,
+                  "Termcell size changed: simd_records_or_byte() vectorises a "
+                  "12-byte stride and silently falls back to scalar otherwise");
+   simd_records_or_byte(cells, (size_t)n, sizeof(Termcell), off, bit);
+#undef NOT_PROBED
+}
+
 void
 termpty_text_save_top(Termpty *ty, Termcell *cells, ssize_t w_max)
 {
    Termsave *ts;
-   ssize_t w, i;
+   ssize_t w;
 
    if (ty->backsize == 0)
      return;
@@ -1003,10 +1054,8 @@ termpty_text_save_top(Termpty *ty, Termcell *cells, ssize_t w_max)
    termpty_backlog_lock();
 
    w = termpty_line_length(cells, w_max);
-   for (i = 0; i < w - 1; i++)
-     {
-        cells[i].att.autowrapped = 1;
-     }
+   if (w > 1)
+     _mark_autowrapped(cells, w - 1);
    if (ty->backsize > 0)
      {
         ts = BACKLOG_ROW_GET(ty, 1);

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to