6 ms·
I don't see the problem. You explicitly asked it to generate the smallest code it can and it did.
by Narishma 3y ago
I don't see the problem. You explicitly asked it to generate the smallest code it can and it did.
- jcalvinowens 3y agoIt's a problem because it's practically useless: almost nobody writing C ever actually wants to optimize for size at the cost of everything else. This isn't an uncommon opinion, people have been complaining about -Os for a decade: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=281dc5c5ec0fb299514567cbc358562649c1af95 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin... https://lwn.net/Articles/534735/ https://lwn.net/Articles/534735/
- jcalvinowens 3y agoClang is much more reasonable, see: {0}[calvinow ~] clang -Os -S test.c -c -o - .text .file "test.c" .globl foo # -- Begin function foo .type foo,@function foo: # @foo .cfi_startproc # %bb.0: # kill: def $edi killed $edi def $rdi leal 3(%rdi), %eax testl %edi, %edi cmovnsl %edi, %eax sarl $2, %eax retq .Lfunc_end0: .size foo, .Lfunc_end0-foo .cfi_endproc # -- End function .ident "Debian clang version 16.0.6 (19)" .section ".note.GNU-stack","",@progbits .addrsig {0}[calvinow ~] clang -Oz -S test.c -c -o - .text .file "test.c" .globl foo # -- Begin function foo .type foo,@function foo: # @foo .cfi_startproc # %bb.0: movl %edi, %eax pushq $4 .cfi_adjust_cfa_offset 8 popq %rcx .cfi_adjust_cfa_offset -8 cltd idivl %ecx retq .Lfunc_end0: .size foo, .Lfunc_end0-foo .cfi_endproc # -- End function .ident "Debian clang version 16.0.6 (19)" .section ".note.GNU-stack","",@progbits .addrsig {0}[calvinow ~] clang -O2 -S test.c -c -o - .text .file "test.c" .globl foo # -- Begin function foo .p2align 4, 0x90 .type foo,@function foo: # @foo .cfi_startproc # %bb.0: # kill: def $edi killed $edi def $rdi leal 3(%rdi), %eax testl %edi, %edi cmovnsl %edi, %eax sarl $2, %eax retq .Lfunc_end0: .size foo, .Lfunc_end0-foo .cfi_endproc # -- End function .ident "Debian clang version 16.0.6 (19)" .section ".note.GNU-stack","",@progbits .addrsig GCC has -Oz now, but they haven't fixed -Os to be softer like clang's is.
- kragen 3y agousually if i'm writing c instead of js, python, or golang the reason is that i want my code to run on a microcontroller. the majority of the microcontrollers i have here have 4 kibibytes of flash, which is a pretty harsh limit, but vastly more cpu power than is needed for the things i'm doing with them, so i almost always actually want to optimize for size at the cost of nearly everything else. the only thing that's more precious than flash is ram (why don't i write assembly? well, sometimes i do, but sometimes c is good enough, and it has major advantages. size-optimizing compilers greatly expand the scope of c's applicability.)
- jcalvinowens 3y agoIn theory, -Oz now serves the "smaller no matter what the cost" case, and allows -Os to make compromises. But with GCC, they still behave like synonyms in my limited experience.
- kragen 3y agoi appreciate the new information! i haven't used clang much for reasons that are probably not very good probably bytecode interpreters are a better solution for this sort of thing anyway, at least when you have more than 512 bytes of program memory or so. in forth with gforth locals the function is : sumarray { a n } 0 n 0 ?do a i cells + @ + loop ; and the body (after the }) consists of 12 instructions, almost all of which would be a single byte each in compact bytecodes like smalltalk-80 or emacs lisp. this might even beat clang's 18-byte rvc version above. there's a sequence of three of them that would conventionally be a single operation (cells + @), but conventionally you'd also use extra instructions to load and store the variable `total` inside and outside the loop instead of leaving it on the stack, so you'd end up with 13 instructions. and the ?do and loop instructions normally have an offset, so you're at 15 bytes, plus the subroutine header gforth of course uses 8 bytes per instruction and doesn't have a structure like smalltalk's method header to compactly encode the number of locals, so gforth itself is not very frugal with code space; instead { a n } compiles to >l >l at the beginning and lp+2 at the end
- 3y ago