https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69049

            Bug ID: 69049
           Summary: [avr] strange/unnecessary commands in compiled code
           Product: gcc
           Version: 4.9.2
            Status: UNCONFIRMED
          Severity: major
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: night_ghost at ykoctpa dot ru
  Target Milestone: ---

small code

void deepSleep(uint16_t milliseconds) {
    uint32_t microseconds = milliseconds * 1000L;
    uint16_t sleep_periods = (microseconds - watchdogTime_us) /
watchdogTime_us;

    while (sleep_periods >= 512) {
      narcoleptic_sleep_down(WDTO_8S);
      sleep_periods -= 512;
    }
    if (sleep_periods & 256) narcoleptic_sleep_down(WDTO_4S); /* xxx */
}

compiled as (see comments)

void deepSleep(uint16_t milliseconds) {

    uint32_t microseconds = milliseconds * 1000L;
    2fb2:       9c 01           movw    r18, r24
    2fb4:       a8 ee           ldi     r26, 0xE8       ; 232
    2fb6:       b3 e0           ldi     r27, 0x03       ; 3
    2fb8:       0e 94 b8 33     call    0x6770  ; 0x6770 <__umulhisi3>

    uint16_t sleep_periods = (microseconds - watchdogTime_us) /
watchdogTime_us;
    2fbc:       6c 19           sub     r22, r12
    2fbe:       7d 09           sbc     r23, r13
    2fc0:       8e 09           sbc     r24, r14
    2fc2:       9f 09           sbc     r25, r15
    2fc4:       a7 01           movw    r20, r14
    2fc6:       96 01           movw    r18, r12
    2fc8:       0e 94 71 33     call    0x66e2  ; 0x66e2 <__udivmodsi4>
    2fcc:       69 01           movw    r12, r18 // r12r13 === sleep_periods,
is'nt it?

    while (sleep_periods >= 512) {
//{ why GCC adds 0 before comparison?
    2fce:       e1 2c           mov     r14, r1
    2fd0:       f1 2c           mov     r15, r1
    2fd2:       c7 01           movw    r24, r14
    2fd4:       8c 0d           add     r24, r12
    2fd6:       9d 1d           adc     r25, r13
// carry NEVER can be set - r1===0
    2fd8:       81 15           cp      r24, r1
//}
    2fda:       92 40           sbci    r25, 0x02       ; 2
    2fdc:       70 f0           brcs    .+28            ; 0x2ffa
<_Z9deepSleepj+0x6c>
      narcoleptic_sleep_down(WDTO_8S);
    2fde:       89 e0           ldi     r24, 0x09       ; 9
//{ why GCC saves unneeded LONG?
    2fe0:       29 83           std     Y+1, r18        ; 0x01
    2fe2:       3a 83           std     Y+2, r19        ; 0x02
    2fe4:       4b 83           std     Y+3, r20        ; 0x03
    2fe6:       5c 83           std     Y+4, r21        ; 0x04
//}
    2fe8:       0e 94 c4 17     call    0x2f88  ; 0x2f88
<_Z22narcoleptic_sleep_downh>
    2fec:       62 e0           ldi     r22, 0x02       ; 2
    2fee:       f6 1a           sub     r15, r22
//{ why GCC restores unneeded LONG?
    2ff0:       5c 81           ldd     r21, Y+4        ; 0x04
    2ff2:       4b 81           ldd     r20, Y+3        ; 0x03
    2ff4:       3a 81           ldd     r19, Y+2        ; 0x02
    2ff6:       29 81           ldd     r18, Y+1        ; 0x01
//}
    2ff8:       ec cf           rjmp    .-40            ; 0x2fd2
<_Z9deepSleepj+0x44>

//{ what the hell here? where such calculations in C code?
    2ffa:       f9 01           movw    r30, r18
    2ffc:       ef 2f           mov     r30, r31
    2ffe:       ff 27           eor     r31, r31
    3000:       e6 95           lsr     r30
    3002:       60 e0           ldi     r22, 0x00       ; 0
    3004:       7e ef           ldi     r23, 0xFE       ; 254
    3006:       e6 9f           mul     r30, r22
    3008:       c0 01           movw    r24, r0
    300a:       e7 9f           mul     r30, r23
    300c:       90 0d           add     r25, r0
    300e:       f6 9f           mul     r31, r22
    3010:       90 0d           add     r25, r0
    3012:       11 24           eor     r1, r1
    3014:       82 0f           add     r24, r18
    3016:       93 1f           adc     r25, r19
//}
      sleep_periods -= 512;
    }

    if (sleep_periods & 256) narcoleptic_sleep_down(WDTO_4S);
    3018:       90 ff           sbrs    r25, 0
    301a:       0d c0           rjmp    .+26            ; 0x3036
<_Z9deepSleepj+0xa8>
    301c:       88 e0           ldi     r24, 0x08       ; 8
}
//{ optimization on size but GCC generates 2nd epilogue to escape tail
recursion while simple CALL takes less memory
    301e:       0f 90           pop     r0
    3020:       0f 90           pop     r0
    3022:       0f 90           pop     r0
    3024:       0f 90           pop     r0
    3026:       df 91           pop     r29
    3028:       cf 91           pop     r28
    302a:       ff 90           pop     r15
    302c:       ef 90           pop     r14
    302e:       df 90           pop     r13
    3030:       cf 90           pop     r12
    while (sleep_periods >= 512) {
      narcoleptic_sleep_down(WDTO_8S);
      sleep_periods -= 512;
    }

    if (sleep_periods & 256) narcoleptic_sleep_down(WDTO_4S); /* xxx */
    3032:       0c 94 c4 17     jmp     0x2f88  ; 0x2f88
<_Z22narcoleptic_sleep_downh>
//}
}
    3036:       0f 90           pop     r0
    3038:       0f 90           pop     r0
    303a:       0f 90           pop     r0
    303c:       0f 90           pop     r0
    303e:       df 91           pop     r29
    3040:       cf 91           pop     r28
    3042:       ff 90           pop     r15
    3044:       ef 90           pop     r14
    3046:       df 90           pop     r13
    3048:       cf 90           pop     r12
    304a:       08 95           ret


But when line commented with "xxx" removed then hell code gone

void deepSleep(uint16_t milliseconds) {
    uint32_t microseconds = milliseconds * 1000L;
    2faa:       9c 01           movw    r18, r24
    2fac:       a8 ee           ldi     r26, 0xE8       ; 232
    2fae:       b3 e0           ldi     r27, 0x03       ; 3
    2fb0:       0e 94 8a 33     call    0x6714  ; 0x6714 <__umulhisi3>
    uint16_t sleep_periods = (microseconds - watchdogTime_us) /
watchdogTime_us;
    2fb4:       6c 19           sub     r22, r12
    2fb6:       7d 09           sbc     r23, r13
    2fb8:       8e 09           sbc     r24, r14
    2fba:       9f 09           sbc     r25, r15
    2fbc:       a7 01           movw    r20, r14
    2fbe:       96 01           movw    r18, r12
    2fc0:       0e 94 43 33     call    0x6686  ; 0x6686 <__udivmodsi4>
    2fc4:       e9 01           movw    r28, r18

    while (sleep_periods >= 512) {
//{ adding 0 still here
    2fc6:       e1 2c           mov     r14, r1
    2fc8:       f1 2c           mov     r15, r1
    2fca:       c7 01           movw    r24, r14
    2fcc:       8c 0f           add     r24, r28
    2fce:       9d 1f           adc     r25, r29
    2fd0:       81 15           cp      r24, r1
//}
    2fd2:       92 40           sbci    r25, 0x02       ; 2
    2fd4:       30 f0           brcs    .+12            ; 0x2fe2
<_Z9deepSleepj+0x54>
      narcoleptic_sleep_down(WDTO_8S);
    2fd6:       89 e0           ldi     r24, 0x09       ; 9
    2fd8:       0e 94 c4 17     call    0x2f88  ; 0x2f88
<_Z22narcoleptic_sleep_downh>
    2fdc:       22 e0           ldi     r18, 0x02       ; 2
    2fde:       f2 1a           sub     r15, r18
    2fe0:       f4 cf           rjmp    .-24            ; 0x2fca
<_Z9deepSleepj+0x3c>
      sleep_periods -= 512;
    }

//    if (sleep_periods & 256) narcoleptic_sleep_down(WDTO_4S); /* xxx */
}
    2fe2:       df 91           pop     r29
    2fe4:       cf 91           pop     r28
    2fe6:       ff 90           pop     r15
    2fe8:       ef 90           pop     r14
    2fea:       df 90           pop     r13
    2fec:       cf 90           pop     r12
    2fee:       08 95           ret




if to move uint32_t variable to a different function, hell code gone too and
"add 0" code also


void doSleep(uint16_t sleep_periods){
    while (sleep_periods >= 512) {
      narcoleptic_sleep_down(WDTO_8S);
      sleep_periods -= 512;
    }
    if (sleep_periods & 256) narcoleptic_sleep_down(WDTO_4S);
}

void deepSleep(uint16_t milliseconds) {
    uint32_t microseconds = milliseconds * 1000L;
    doSleep((microseconds - watchdogTime_us) / watchdogTime_us);
}


void doSleep(uint16_t sleep_periods){
    2f8e:       0f 93           push    r16
    2f90:       1f 93           push    r17
    2f92:       cf 93           push    r28
    2f94:       df 93           push    r29
    2f96:       8c 01           movw    r16, r24
    while (sleep_periods >= 512) {
    2f98:       ec 01           movw    r28, r24
    2f9a:       c1 15           cp      r28, r1
    2f9c:       82 e0           ldi     r24, 0x02       ; 2
    2f9e:       d8 07           cpc     r29, r24
    2fa0:       28 f0           brcs    .+10            ; 0x2fac
<_Z7doSleepj+0x1e>
      narcoleptic_sleep_down(WDTO_8S);
    2fa2:       89 e0           ldi     r24, 0x09       ; 9
    2fa4:       0e 94 c4 17     call    0x2f88  ; 0x2f88
<_Z22narcoleptic_sleep_downh>
      sleep_periods -= 512;
    2fa8:       d2 50           subi    r29, 0x02       ; 2
    2faa:       f7 cf           rjmp    .-18            ; 0x2f9a
<_Z7doSleepj+0xc>
    }

    if (sleep_periods & 256) narcoleptic_sleep_down(WDTO_4S);
    2fac:       10 ff           sbrs    r17, 0
    2fae:       07 c0           rjmp    .+14            ; 0x2fbe
<_Z7doSleepj+0x30>
    2fb0:       88 e0           ldi     r24, 0x08       ; 8
}
    2fb2:       df 91           pop     r29
    2fb4:       cf 91           pop     r28
    2fb6:       1f 91           pop     r17
    2fb8:       0f 91           pop     r16
    while (sleep_periods >= 512) {
      narcoleptic_sleep_down(WDTO_8S);
      sleep_periods -= 512;
    }

    if (sleep_periods & 256) narcoleptic_sleep_down(WDTO_4S);
    2fba:       0c 94 c4 17     jmp     0x2f88  ; 0x2f88
<_Z22narcoleptic_sleep_downh>
}
    2fbe:       df 91           pop     r29
    2fc0:       cf 91           pop     r28
    2fc2:       1f 91           pop     r17
    2fc4:       0f 91           pop     r16
    2fc6:       08 95           ret

for chip with liliputian memory this bug is very annoying

Reply via email to