home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.arch      Apparently more than just beeps & boops      131,241 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 130,258 of 131,241   
   EricP to Anton Ertl   
   Re: branch splitting   
   11 Nov 25 21:16:22   
   
   From: ThatWouldBeTelling@thevillage.com   
      
   Anton Ertl wrote:   
   > EricP  writes:   
   >> Test1 allocates a dynamic sized buffer and has a static goto Loop   
   >> for which GCC generates a jne .L6 to a mov rsp, rbx that recovers   
   >> the stack allocation inside the {} block.   
   >>   
   >> Test2 is the same but does a goto *dest and GCC does not generate   
   >> code to recover the inner {} block allocation. It just loops over   
   >> the sub rsp, rbx so the stack space just grows.   
   >   
   > Interestingly, gcc optimizes the indirect branch with a constant   
   > target into a direct branch, but then does not continue with the same   
   > code as you get with a plain goto.   
   >   
   >> void Test2 (long len)   
   >> {   
   >>   long ok;   
   >>   void *dest;   
   >>   
   >>   dest = &&Loop;   
   >>   Loop:   
   >>   {   
   >>     char buf[len];   
   >>   
   >>     ok = Sub (len, buf);   
   >>     if (ok)   
   >>       goto *dest;   
   >>   }   
   >> }   
   >>   
   >> Test2(long):   
   >>         push    rbp   
   >>         mov     rbp, rsp   
   >>         push    r12   
   >>         mov     r12, rdi   
   >>         push    rbx   
   >>         lea     rbx, [rdi+15]   
   >>         shr     rbx, 4   
   >>         sal     rbx, 4   
   >> .L8:   
   >>         sub     rsp, rbx   
   >>         mov     rdi, r12   
   >>         mov     rsi, rsp   
   >>         call    Sub(long, char*)   
   >>         test    rax, rax   
   >>         jne     .L8   
   >>         lea     rsp, [rbp-16]   
   >>         pop     rbx   
   >>         pop     r12   
   >>         pop     rbp   
   >>         ret   
   >   
   > Interesting that this bug has not been fixed in the >33 years that   
   > labels-as-values have been in gcc; I don't know how long these   
   > dynamically sized arrays have been in gcc, but IIRC alloca(), a   
   > similar feature, has been available at least as long as   
   > labels-as-values.  The bug has apparently been avoided or worked   
   > around by the users of labels-as-values (e.g., Gforth does not use   
   > alloca or dynamically-sized arrays in the function that contains all   
   > the taken labels and all the "goto *"s.   
      
   alloca is not required to recover storage at the {} block level.   
   MS C does not recover alloca space until the subroutine returns.   
      
   But when they added dynamic allocation to C as a first class feature   
   I figured it should recover storage at the end of a {} block,   
   and I wondered it the superficially non-deterministic nature of   
   goto variable would be a problem.   
      
   > As long as all taken labels have the same stack depth, the bugfix does   
   > not look particularly hard: just put code before each goto * that   
   > adjusts the stack depth to the depth of these labels.   
   >   
   > Things become more interesting if there are labels with different   
   > stack depths, because labels are stored in "void *" variables, and   
   > there is not enough room for a target and a stack depth.  One can ue   
   > the same approach as is used in Test1, however: have the stack depth   
   > for a specific target in some location, and have a copy from that   
   > location to the stack pointer right behind the label.   
   >   
   > ....   
   >>         jmp     .L2   
   >> .L6:   
   >>         mov     rsp, rbx   
   >> .L2:   
   > ....   
   >>         jne     .L6   
   >   
   > All the code that works now would not need these extra copy   
   > intructions, so the bugfix should special-case the case where all the   
   > targets have the same depth.   
   >   
   > - anton   
      
   Below in Test3 I replace the goto variable with a switch statement   
   arranged to be nondeterministic, and it does get it right.   
   I suggest GCC forgot to treat the goto variable as equivalent to a switch   
   statement and threw up its hands and treated the buffer as an alloca.   
      
   This all relates to Niklas's comments as to why the label variables must   
   all be within the current context, so it knows when to recover storage.   
   If the language had destructors the goto variable could have to call them   
   which alloca also does not deal with.   
      
   long Sub (long len, char buf[]);   
      
   void Test3 (long len)   
   {   
      long ok, dest;   
      
      dest = 0;   
      Loop:   
      {   
        char buf[len];   
      
        ok = Sub (len, buf);   
        if (ok)   
          dest = 1;   
      
        switch (dest)   
        {   
          case 0:   
            goto Loop;   
          case 1:   
            goto Out;   
        }   
        Out:   
        ;   
      }   
   }   
      
   # Compilation provided by Compiler Explorer at https://godbolt.org/   
   Test3(long):   
            push    rbp   
            mov     rbp, rsp   
            push    r13   
            mov     r13, rdi   
            push    r12   
            lea     r12, [rdi+15]   
            push    rbx   
            shr     r12, 4   
            sal     r12, 4   
            sub     rsp, 8   
            jmp     .L2   
   .L6:   
            mov     rsp, rbx   
   .L2:   
            mov     rbx, rsp   
            sub     rsp, r12   
            mov     rdi, r13   
            mov     rsi, rsp   
            call    Sub(long, char*)   
            test    rax, rax   
            je      .L6   
            lea     rsp, [rbp-24]   
            pop     rbx   
            pop     r12   
            pop     r13   
            pop     rbp   
            ret   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca