Menu

#2828 modulo optimization regression for constant base-2 divsor

closed-fixed
None
other
5
2020-05-22
2018-10-20
Jens
No

seems like modulo optimization (on powers of two) regression starting somewhere after 3.6.3 #9771
observed behavior:
simple modulo patterns using constant base-2 divisor are using modsint? internal routines

expected behavior:
modulo patterns using a constant base-2 divisor should be using the optimized AND-bitmask pattern

examples:
previous version of sdcc (3.6.3 #9771):

;   src/main.c:382: if ((count % 4) == 0) {
    mov a,_count
    anl a,#0x03
    jnz 00107$

newer version of sdcc (sdcc 3.8.1, #10620):

;   src/main.c:382: if ((count % 4) == 0) {
    mov r5,_count
    mov r6,#0x00
    mov __modsint_PARM_2,#0x04
;   1-genFromRTrack replaced    mov (__modsint_PARM_2 + 1),#0x00
    mov (__modsint_PARM_2 + 1),r6
    mov dpl,r5
    mov dph,r6
    push    ar7
    lcall   __modsint
    mov a,dpl
    mov b,dph
    pop ar7
    orl a,b
    jnz 00107$

Discussion

  • Jens

    Jens - 2018-10-20

    forgot to include here, "count" var is uint8_t. (Not sure if the optimization previously had a 16 bit variant or not)

     
  • Nikolay

    Nikolay - 2018-10-20

    and the same for stm8
    Version 3.8.1 #10625 (MINGW32)
    --opt-code-speed --max-allocs-per-node 100000

    uint8_t mod4(uint8_t op)
    {
        return (op % 4);
    }
    
    _mod4:
    ;   .\Source\main.c: 13: return (op % 4);
        clrw    x
        ld  a, (0x03, sp)
        ld  xl, a
        push    #0x04
        push    #0x00
        pushw   x
        call    __modsint
        addw    sp, #4
        ld  a, xl
    ;   .\Source\main.c: 14: }
        ret
    

    but the next "hint" helps compiler taking right decision:

    uint8_t mod4(uint8_t op)
    {
        return (op % (uint8_t)4);
    }
    
    _mod4:
    ;   .\Source\main.c: 13: return (op % (uint8_t)4);
        ld  a, (0x03, sp)
        and a, #0x03
    ;   .\Source\main.c: 14: }
        ret
    
     

    Last edit: Nikolay 2018-10-20
  • Jens

    Jens - 2018-10-22

    Thanks Nikolay. The casting the constant trick is a good workaround.

     
  • Philipp Klaus Krause

    • Category: MCS51 --> other
     
  • Philipp Klaus Krause

    This is not mcs51-specific. Interestingly.

    unsigned char f(unsigned char j)
    {
        return(j / 4);
    }
    

    still gets optimized, while

    unsigned char f(unsigned char j)
    {
        return(j % 4);
    }
    

    Doesn't.

    Philipp

    P.S.: Not that interesting after all. / gets optimized even for signed operands, and the optimized version is indeed the one for signed operands.

    P.P.S.: The best solution would be to implement generalized constant propagation, so that such optimizations can be done depending on actual possible values, not types.

     

    Last edit: Philipp Klaus Krause 2018-10-24
  • Erik Petrich

    Erik Petrich - 2020-05-22

    Partially fixed by Philipp in [r10643] and fully unregressed by my update in [r11622].

     
  • Erik Petrich

    Erik Petrich - 2020-05-22
    • status: open --> closed-fixed
    • assigned_to: Erik Petrich
     

Log in to post a comment.

MongoDB Logo MongoDB