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

            Bug ID: 127028
           Summary: Code bloat due to inline expansion of widening mul
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gjl at gcc dot gnu.org
  Target Milestone: ---

Inline expansion of widening multiplication is leading to code bloat, for
example on AVR.  Many AVR devices have very limited memory constraints,
sometimes only a few KiB of program memory.

As it seems, it is due to recent changes like r17-3443.  Here is an example:

typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;

uint16_t wmul16 (uint16_t x)
{
    return ((uint32_t) x * 0xaaab) >> 16;
}

$ avr-gcc x.c -S -Os -dp

wmul16:
        push r28                 ;  129 [c=4 l=1]  pushqi1/0
        push r29                 ;  130 [c=4 l=1]  pushqi1/0
/* stack size = 2 */
        mov r26,r24      ;  139 [c=4 l=1]  movqi_insn/0
        mov r27,r25      ;  140 [c=4 l=1]  movqi_insn/0
        mov r24,r25      ;  103 [c=4 l=1]  movqi_insn/0
        ldi r25,0                ;  104 [c=4 l=1]  movqi_insn/0
        ldi r22,lo8(-85)         ;  144 [c=4 l=1]  movqi_insn/1
        ldi r23,0                ;  145 [c=4 l=1]  movqi_insn/0
        rcall __mulhi3   ;  106 [c=4 l=1]  *mulhi3_call
        mov r28,r24      ;  146 [c=4 l=1]  movqi_insn/0
        mov r29,r25      ;  147 [c=4 l=1]  movqi_insn/0
        mov r24,r26      ;  148 [c=4 l=1]  movqi_insn/0
        ldi r25,0                ;  149 [c=4 l=1]  movqi_insn/0
        ldi r22,lo8(-86)         ;  150 [c=4 l=1]  movqi_insn/1
        ldi r23,0                ;  151 [c=4 l=1]  movqi_insn/0
        rcall __mulhi3   ;  110 [c=4 l=1]  *mulhi3_call
        add r24,r28      ;  111 [c=8 l=2]  *addhi3/0
        adc r25,r29
        mov r30,r24      ;  152 [c=4 l=1]  movqi_insn/0
        mov r31,r25      ;  153 [c=4 l=1]  movqi_insn/0
        mov r24,r26      ;  154 [c=4 l=1]  movqi_insn/0
        ldi r25,0                ;  155 [c=4 l=1]  movqi_insn/0
        ldi r22,lo8(-85)         ;  156 [c=4 l=1]  movqi_insn/1
        ldi r23,0                ;  157 [c=4 l=1]  movqi_insn/0
        rcall __mulhi3   ;  115 [c=4 l=1]  *mulhi3_call
        mov r18,r25      ;  116 [c=4 l=1]  movqi_insn/0
        add r18,r30      ;  117 [c=12 l=3]  *usum_widenqihi3
        clr r19
        rol r19
        mov r18,r19      ;  158 [c=4 l=1]  movqi_insn/0
        ldi r19,0                ;  159 [c=4 l=1]  movqi_insn/0
        mov r24,r27      ;  119 [c=4 l=1]  movqi_insn/0
        ldi r25,0                ;  120 [c=4 l=1]  movqi_insn/0
        ldi r22,lo8(-86)         ;  160 [c=4 l=1]  movqi_insn/1
        ldi r23,0                ;  161 [c=4 l=1]  movqi_insn/0
        rcall __mulhi3   ;  122 [c=4 l=1]  *mulhi3_call
        mov r20,r31      ;  162 [c=4 l=1]  movqi_insn/0
        ldi r21,0                ;  163 [c=4 l=1]  movqi_insn/0
        add r24,r20      ;  124 [c=8 l=2]  *addhi3/0
        adc r25,r21
        add r18,r24      ;  125 [c=8 l=2]  *addhi3/0
        adc r19,r25
        ldi r20,lo8(1)   ;  126 [c=4 l=1]  movqi_insn/1
        cp r30,r28       ;  127 [c=8 l=2]  cmphi3/2
        cpc r31,r29
        brlo .L2                 ;  128 [c=4 l=1]  branch
        ldi r20,0                ;  99  [c=4 l=1]  movqi_insn/0
.L2:
        mov r25,r20      ;  97  [c=4 l=1]  movqi_insn/0
        mov r24,r18      ;  166 [c=4 l=1]  movqi_insn/0
        add r25,r19      ;  167 [c=4 l=1]  *addqi3/0
/* epilogue start */
        pop r29          ;  133 [c=4 l=1]  popqi
        pop r28          ;  134 [c=4 l=1]  popqi
        ret              ;  135 [c=0 l=1]  return_from_epilogue

With v16, all is fine:

$ avr-gcc-16 x.c -S -Os -dp

wmul16:
/* stack size = 0 */
        mov r18,r24      ;  34  [c=4 l=1]  movqi_insn/0
        mov r19,r25      ;  35  [c=4 l=1]  movqi_insn/0
        ldi r20,0                ;  36  [c=4 l=1]  movqi_insn/0
        ldi r21,0                ;  37  [c=4 l=1]  movqi_insn/0
        ldi r22,lo8(-85)         ;  38  [c=4 l=1]  movqi_insn/1
        ldi r23,lo8(-86)         ;  39  [c=4 l=1]  movqi_insn/1
        ldi r24,0                ;  40  [c=4 l=1]  movqi_insn/0
        ldi r25,0                ;  41  [c=4 l=1]  movqi_insn/0
        rcall __mulsi3   ;  29  [c=16 l=1]  *mulsi3_call_pr118012
/* epilogue start */
        ret              ;  32  [c=0 l=1]  return

So the v17 cost extimate is complete moonshine, and the code tries to mimic
stuff like __mulsi3 that libgcc provides as hand-optimized asm.

Using presence / absence of specific insns as a proxy for costs is a blunder. 
Just the fact that an insn exists doesn't mean it's cheap.  It just means that
providing the insns yiels better code than not providing it.

Target: avr
Configured with: ../../source/gcc-master/configure --target=avr --disable-nls
--with-dwarf2 --with-gnu-as --with-gnu-ld --with-long-double=64
--disable-libcc1 --enable-languages=c,c++
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 17.0.0 20260819 (experimental) (GCC)

Reply via email to