<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">Am 07.11.2019 um 01:42 schrieb Ben
      Grasset via fpc-pascal:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAL4d7FggB0cBckfwddV6aLnZLCARoc_3Wz2dC2kA79VSWtALPQ@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div dir="ltr">On Wed, Nov 6, 2019 at 7:33 PM Ben Grasset <<a
            href="mailto:operator97@gmail.com" moz-do-not-send="true">operator97@gmail.com</a>>
          wrote:<br>
        </div>
        <div class="gmail_quote">
          <blockquote class="gmail_quote" style="margin:0px 0px 0px
            0.8ex;border-left:1px solid
            rgb(204,204,204);padding-left:1ex">
            <div dir="ltr">
              <div class="gmail_quote">
                <div>Encouraging typecasting (which cares only about the
                  sizes of the types involved, nothing else) at the
                  programmer level is far more error-prone in a variety
                  of ways.<br>
                </div>
              </div>
            </div>
          </blockquote>
          <div><br>
          </div>
          <div>Also: it's slower in many cases, because it tends to
            involve "if" statements that *remain* as if statements in
            the final generated assembly code, whereas a static check
            would allow for simply generating *only* the code for the
            path that's actually taken.</div>
        </div>
      </div>
    </blockquote>
    This is not true. If the compiler can prove at compile time that the
    if-condition is constant then the branch that is not taken is
    removed at the node level. It doesn't even remotely reach the code
    generation phase. (I just checked that yesterday when I implemented
    IsManagedType() and wondered about missing "unreachable code"
    warnings).<br>
    <br>
    Take a look at the test for IsManagedType():<br>
    <br>
    === code begin ===<br>
    <br>
    program tismngd1;<br>
    <br>
    {$mode objfpc}<br>
    {$modeswitch advancedrecords}<br>
    <br>
    uses<br>
      TypInfo;<br>
    <br>
    var<br>
      gError: LongInt = 0;<br>
    <br>
    function NextErrorCode: LongInt; inline;<br>
    begin<br>
      Inc(gError);<br>
      Result := gError;<br>
    end;<br>
    <br>
    generic procedure TestType<T>(aIsMngd: Boolean); inline;<br>
    begin<br>
      if IsManagedType(T) <> aIsMngd then begin<br>
        Writeln('IsManagedType(', PTypeInfo(TypeInfo(T))^.Name, ')
    failure; expected: ', aIsMngd, ', got: ', IsManagedType(T));<br>
        Halt(NextErrorCode);<br>
      end;<br>
      NextErrorCode;<br>
    end;<br>
    <br>
    type<br>
      TTestLongInt = record<br>
        a: LongInt;<br>
      end;<br>
    <br>
      TTestAnsiString = record<br>
        a: AnsiString;<br>
      end;<br>
    <br>
      TTestManaged = record<br>
        a: LongInt;<br>
        class operator Initialize(var aTestManaged: TTestManaged);<br>
      end;<br>
    <br>
      TTestObj = object<br>
        a: LongInt;<br>
      end;<br>
    <br>
      TTestObjAnsiString = object<br>
        a: AnsiString;<br>
      end;<br>
    <br>
    class operator TTestManaged.Initialize(var aTestManaged:
    TTestManaged);<br>
    begin<br>
      aTestManaged.a := 42;<br>
    end;<br>
    <br>
    type<br>
      TProcVar = procedure;<br>
      TMethodVar = procedure of object;<br>
    <br>
      TDynArrayLongInt = array of LongInt;<br>
      TStaticArrayLongInt = array[0..4] of LongInt;<br>
      TStaticArrayAnsiString = array[0..4] of AnsiString;<br>
    <br>
      TEnum = (eOne, eTwo, eThree);<br>
      TSet = set of (sOne, sTwo, sThree);<br>
    <br>
    begin<br>
      specialize TestType<LongInt>(False);<br>
      specialize TestType<Boolean>(False);<br>
      specialize TestType<ShortString>(False);<br>
      specialize TestType<AnsiString>(True);<br>
      specialize TestType<UnicodeString>(True);<br>
      specialize TestType<WideString>(True);<br>
      specialize TestType<Single>(False);<br>
      specialize TestType<TProcVar>(False);<br>
      specialize TestType<TMethodVar>(False);<br>
      specialize TestType<Pointer>(False);<br>
      specialize TestType<IInterface>(True);<br>
      specialize TestType<TObject>(False);<br>
      specialize TestType<TTestLongInt>(False);<br>
      specialize TestType<TTestAnsiString>(True);<br>
      specialize TestType<TTestManaged>(True);<br>
      specialize TestType<TTestObj>(False);<br>
      specialize TestType<TTestObjAnsiString>(True);<br>
      specialize TestType<TDynArrayLongInt>(True);<br>
      specialize TestType<TStaticArrayLongInt>(False);<br>
      specialize TestType<TStaticArrayAnsiString>(True);<br>
      specialize TestType<TEnum>(False);<br>
      specialize TestType<TSet>(False);<br>
      Writeln('Ok');<br>
    end.<br>
    <br>
    === code end ===<br>
    <br>
    Thanks to the node level optimization I mentioned the assembly code
    of the main function will look like this (in this case
    x86_64-win64):<br>
    <br>
    === code begin ===<br>
    <br>
    .section .text.n_main,"ax"<br>
        .balign 16,0x90<br>
    .globl    main<br>
    main:<br>
    .globl    PASCALMAIN<br>
    PASCALMAIN:<br>
    .Lc122:<br>
    .Lc123:<br>
    # Temps allocated between rbp-8 and rbp+0<br>
    .seh_proc main<br>
    # [62] begin<br>
        pushq    %rbp<br>
    .seh_pushreg %rbp<br>
    .Lc124:<br>
    .Lc125:<br>
        movq    %rsp,%rbp<br>
    .Lc126:<br>
        leaq    -48(%rsp),%rsp<br>
    .seh_stackalloc 48<br>
        movq    %rbx,-8(%rbp)<br>
    .seh_savereg %rbx, 40<br>
    .seh_endprologue<br>
        call    fpc_initializeunits<br>
    # [63] specialize TestType<LongInt>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [64] specialize TestType<Boolean>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [65] specialize TestType<ShortString>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [66] specialize TestType<AnsiString>(True);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [67] specialize TestType<UnicodeString>(True);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [68] specialize TestType<WideString>(True);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [69] specialize TestType<Single>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [70] specialize TestType<TProcVar>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [71] specialize TestType<TMethodVar>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [72] specialize TestType<Pointer>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [73] specialize TestType<IInterface>(True);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [74] specialize TestType<TObject>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [75] specialize TestType<TTestLongInt>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [76] specialize TestType<TTestAnsiString>(True);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [77] specialize TestType<TTestManaged>(True);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [78] specialize TestType<TTestObj>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [79] specialize TestType<TTestObjAnsiString>(True);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [80] specialize TestType<TDynArrayLongInt>(True);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [81] specialize TestType<TStaticArrayLongInt>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [82] specialize TestType<TStaticArrayAnsiString>(True);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [83] specialize TestType<TEnum>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [84] specialize TestType<TSet>(False);<br>
        addl    $1,TC_$P$TISMNGD1_$$_GERROR(%rip)<br>
        movl    TC_$P$TISMNGD1_$$_GERROR(%rip),%eax<br>
    # [85] Writeln('Ok');<br>
        call    fpc_get_output<br>
        movq    %rax,%rbx<br>
        leaq    _$TISMNGD1$_Ld3(%rip),%r8<br>
        movq    %rbx,%rdx<br>
        movl    $0,%ecx<br>
        call    fpc_write_text_shortstr<br>
        call    fpc_iocheck<br>
        movq    %rbx,%rcx<br>
        call    fpc_writeln_end<br>
        call    fpc_iocheck<br>
    # [86] end.<br>
        call    fpc_do_exit<br>
        movq    -8(%rbp),%rbx<br>
        leaq    (%rbp),%rsp<br>
        popq    %rbp<br>
        ret<br>
    .seh_endproc<br>
    .Lc121:<br>
    <br>
    === code end ===<br>
    <br>
    As you can see the compiler basically optimized everything except
    the increment of the gError variable away, because it determined it
    can do so. And this was *without* any explicit optimizations
    enabled.<br>
    <br>
    Regards,<br>
    Sven<br>
  </body>
</html>