[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [PATCH 0/1] vi: further changes to colon addresses
From:       Ron Yorston <rmy () pobox ! com>
Date:       2021-08-29 13:54:52
Message-ID: 612b91ac.0mwMYLMRHKiaD7ju%rmy () pobox ! com
[Download RAW message or body]

In the original vi source from the second BSD there's a comment:

 * If you are tricky you can use this routine and the = command
 * to do simple addition and subtraction of cardinals less
 * than the number of lines in the file.

Thus:

   vi README
   - README 1/204 0%
   :1+2+3=
   6
   :1 2 3=
   6             (who needs operators?)
   :1+2000-1999=
   2             (the limit only applies to the final result)

But I was disappointed that BusyBox vi couldn't handle negative
intermediate values:

   :1-1999+2000=
   2001

The following patch fixes that problem so now we get:

   :1-1999+2000=
   2

It also limits the range of the result to the number of lines in
the file, which it wasn't actually doing before.

Anyway, in making these changes I was surprised at the reduction in
bloat achieved.  It turned out that the code in get_one_address()
was previously using a chain of ifs that all tested the value of the
current character in the buffer:

   if (isblank(*p)) {
   ...
   } else if (*p == '.') {
   ...
   } else if (*p == '\'') {

The compiler spotted this and generated a big jump table:

    jmp *.L608(,%rax,8) #
    .section    .rodata.colon,"a",@progbits
    .align 8
    .align 4
.L608:
    .quad   .L613
    .quad   .L606
    .quad   .L606
    .quad   .L612
    ...

(It's in .rodata.colon because get_one_address() and get_address()
are inlined into colon().)

My modified code was too complicated for the compiler to handle so it
reverted to something more straightforward instead.  The reduction in
bloat was due to the loss of the jump table.  The same effect can be
obtained by disabling the relevant optimisation ("full redundancy
elimination (FRE) on trees") around the code in question:

   #pragma GCC optimize "no-tree-fre"
   //----- The Colon commands -------------------------------------
   #if ENABLE_FEATURE_VI_COLON
   static char *get_one_address(char *p, int *result)
   ...
    colon_s_fail:
    status_line(":s expression missing delimiters");
   # endif
   #endif /* FEATURE_VI_COLON */
   }
   #pragma GCC reset_options

In a 64-bit build this gives:

function                                             old     new   delta
colon                                               4115    4066     -49
.rodata                                           108442  108266    -176
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-225)           Total: -225 bytes

The jump table has 22 8-byte pointers and, apparently, the code to *use*
the jump table is bigger than the non-optimised code.

The -Os flag doesn't save us from this fate.

Ron
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic