2016-02-05 13 views
7

की एक स्ट्रक्चर कॉपी को अनुकूलित नहीं करता है सबसे पहले मैं एक माइक्रोक्रोनरोलर के लिए विकास कर रहा हूं ताकि रैम और रोम उपयोग प्राथमिकताएं हो।जीसीसी अनियंत्रित स्थिर कॉन्स

मुझे एहसास है कि यह एक बग रिपोर्ट के रूप में पढ़ सकता है या पर्याप्त विशिष्ट नहीं है। अगर मुझे यहां कोई जवाब नहीं मिलता है तो मैं इसे इस तरह फाइल करूंगा।

मुझे static const स्ट्रक्चर का उपयोग डिफ़ॉल्ट रूप से स्टैक संरचनाओं को प्रारंभ करने के लिए करना पसंद है। ज्यादातर मामलों में डिफ़ॉल्ट संरचना सभी शून्य है। मैं बजाय static const structs एक memset (memset or struct assignment, static const assignment)

मेरे वर्तमान toolchain arm-none-eabi-gcc-4_7_3 है, अनुकूलन -Os के साथ एक कॉर्टेक्स एम 4 लक्ष्य के लिए संकलन के साथ ऐसा करना पसंद करते हैं।

मैंने निम्नलिखित पर ध्यान दिया है; यदि मैं (static const struct foo; बनाम static const struct foo = {0}; बनाम) से स्पष्ट रूप से अपने static const संरचना को शून्य से प्रारंभ करता हूं तो जीसीसी अलग-अलग कोड उत्पन्न करता है। विशेष रूप से, यह स्मृति के लिए uninitialised static const structs आवंटित करता है और प्रतिलिपि संचालन करता है।

396     .section .bss.foo1_init,"aw",%nobits 
397     .align 2 
398     .set .LANCHOR0,. + 0 
401    foo1_init: 
402 0000 00000000  .space 8 
402  00000000 

    40    .L2: 
    41 0010 00000000  .word .LANCHOR0 
    42 0014 00000000  .word foo1 

    55:     **** foo1 = foo1_init; 
    32     .loc 1 55 0 
    33 0000 034A   ldr r2, .L2 
    34 0002 044B   ldr r3, .L2+4 
    35 0004 92E80300  ldmia r2, {r0, r1} 
    36 0008 83E80300  stmia r3, {r0, r1} 


    67    .L5: 
    68 000c 00000000  .word foo2 

    60:     **** foo2 = foo2_init; 
    60 0000 024B   ldr r3, .L5 
    61 0002 0022   movs r2, #0 
    62 0004 1A60   str r2, [r3, #0] 
    63 0006 5A60   str r2, [r3, #4] 


389     .section .bss.bar1_init,"aw",%nobits 
390     .align 2 
391     .set .LANCHOR1,. + 0 
394    bar1_init: 
395 0000 00000000  .space 80 
395  00000000 
395  00000000 
395  00000000 
395  00000000 

    98    .L8: 
    99 0010 00000000  .word .LANCHOR1 
100 0014 00000000  .word bar1 

    65:     **** bar1 = bar1_init; 
    89     .loc 1 65 0 
    90 0002 0349   ldr r1, .L8 
    91 0004 0348   ldr r0, .L8+4 
    92 0006 5022   movs r2, #80 
    93 0008 FFF7FEFF  bl memcpy 


130    .L11: 
131 0010 00000000  .word bar2 

70:     **** bar2 = bar2_init; 
121     .loc 1 70 0 
122 0002 0021   movs r1, #0 
123 0004 5022   movs r2, #80 
124 0006 0248   ldr r0, .L11 
125 0008 FFF7FEFF  bl memset 

हम देख सकते हैं कि foo2 = init_foo2 और bar2 = init_bar2 संकलक के लिए:

struct foo {int foo; int bar;}; 
struct bar {int bar[20];}; 

static const struct foo foo1_init, foo2_init = {0}; 
static const struct bar bar1_init, bar2_init = {0}; 

extern struct foo foo1, foo2; 
extern struct bar bar1, bar2; 

void init_foo1(void) 
{ 
    foo1 = foo1_init; 
} 

void init_foo2(void) 
{ 
    foo2 = foo2_init; 
} 

void init_bar1(void) 
{ 
    bar1 = bar1_init; 
} 

void init_bar2(void) 
{ 
    bar2 = bar2_init; 
} 

संकलित, यह निम्न कोडांतरक लिस्टिंग (पुन: व्यवस्थित और संक्षिप्तता के लिए छंटनी की) का उत्पादन:

यहाँ एक कोड नमूना है bar2 के लिए शून्य को foo2 पर सीधे संग्रहीत करने या memset पर कॉल करने के लिए कॉपी को अनुकूलित किया गया है।

हम देख सकते हैं कि foo1 = init_foo1 और bar1 = init_bar1 के लिए संकलक स्पष्ट प्रतियां प्रदर्शन कर रहा है, के लिए लोड हो रहा है और foo1 के लिए रजिस्टर से बचत और foo2 के लिए memcpy बुला।

  1. इस उम्मीद जीसीसी आपरेशन है:

    मैं कुछ प्रश्न हैं? मैं उम्मीद नहीं करता कि अनइंस्टाइज्ड static const स्ट्रक्चर जीसीसी के अंदर उसी पथ का पालन करने के लिए प्रारंभिक static const structs के रूप में होगा और इसलिए उसी आउटपुट का उत्पादन करें।

  2. क्या यह एआरएम जीसीसी के अन्य संस्करणों के लिए होता है? मेरे पास अन्य संस्करणों का हाथ नहीं है, और असेंबली कंपाइलर्स के लिए सभी ऑनलाइन C वास्तव में C++ कंपाइलर्स हैं।
  3. क्या यह जीसीसी के अन्य लक्षित आर्किटेक्चर के लिए होता है? दोबारा, मेरे पास अन्य संस्करण नहीं हैं।
+0

आप स्थिरता के लिए अपने कोड को संपादित किया जा सका:

यहाँ जीसीसी निर्गम (-O0) इस प्रकार? यह वर्तमान में 'foo1_init' आदि को संदर्भित करता है, जो आपके कोड में परिभाषित नहीं हैं (यह इसके बजाय 'init_foo1' परिभाषित करता है)। मुझे लगता है कि यह सिर्फ एक टाइपो है, क्योंकि आपके पास 'init_foo1' एक वैरिएबल और एक ही स्कोप में एक फ़ंक्शन दोनों के रूप में है। –

+0

अंतरिक्ष के संदर्भ में 'memcpy() 'के लिए एक कॉल बहुत सस्ता है, क्या आपने इसकी प्रतिलिपि बनाई है कि प्रतियों को इनलाइन करने के लिए क्या खर्च आएगा? शायद एक ह्युरिस्टिक है जो कॉल को उत्सर्जित करता है जब बाइट्स की संख्या काफी बड़ी होती है। – unwind

+0

@ इयान वास्तव में एक टाइपो। मैं मूल रूप से एक और समारोह था जिसका नाम कुछ और था, जिसने असेंबली आउटपुट को समझना मुश्किल बना दिया। –

उत्तर

-1

मैंने amd64 पर परीक्षण किया है और मेरे आश्चर्य के लिए यह एक सतत व्यवहार की तरह दिखता है (लेकिन मुझे नहीं पता कि यह एक बग है)। जीसीसी सामान्य डेटा सेगमेंट में foo1_init और bar1_init रखता है, या ऑपरेटिंग सिस्टम (.bss) द्वारा शून्य-प्रारंभिक मानों का खंड। foo2_init और bar2_init को केवल-पढ़ने वाले सेगमेंट (.rodata) में रखा गया है जैसे कि वे गैर-शून्य प्रारंभिक मान थे। -00 का उपयोग करके इसे देखना संभव है। चूंकि आप ओएस का उपयोग नहीं कर रहे हैं, ओएस प्रारंभिक अनुभाग जीसीसी और/या लिंकर द्वारा शुरू किया गया है और फिर कॉपी किया गया है। जीसीसी सीधी यादृच्छिकता और मृत * 2_init चर को समाप्त करके रॉडाटा मूल्यों को अनुकूलित करता है। क्लैंग दोनों मामलों को समान रूप से अनुकूलित करता है, हालांकि।

.file "defs.c" 
    .local foo1_init 
    .comm foo1_init,8,8 
    .section .rodata 
    .align 8 
    .type foo2_init, @object 
    .size foo2_init, 8 
foo2_init: 
    .zero 8 
    .local bar1_init 
    .comm bar1_init,80,32 
    .align 32 
    .type bar2_init, @object 
    .size bar2_init, 80 
bar2_init: 
    .zero 80 
    .text 
    .globl init_foo1 
    .type init_foo1, @function 
init_foo1: 
.LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    movq foo1_init(%rip), %rax 
    movq %rax, foo1(%rip) 
    nop 
    popq %rbp 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE0: 
    .size init_foo1, .-init_foo1 
    .globl init_foo2 
    .type init_foo2, @function 
init_foo2: 
.LFB1: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    movq $0, foo2(%rip) 
    nop 
    popq %rbp 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE1: 
    .size init_foo2, .-init_foo2 
    .globl init_bar1 
    .type init_bar1, @function 
init_bar1: 
.LFB2: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    movq bar1_init(%rip), %rax 
    movq %rax, bar1(%rip) 
    movq bar1_init+8(%rip), %rax 
    movq %rax, bar1+8(%rip) 
    movq bar1_init+16(%rip), %rax 
    movq %rax, bar1+16(%rip) 
    movq bar1_init+24(%rip), %rax 
    movq %rax, bar1+24(%rip) 
    movq bar1_init+32(%rip), %rax 
    movq %rax, bar1+32(%rip) 
    movq bar1_init+40(%rip), %rax 
    movq %rax, bar1+40(%rip) 
    movq bar1_init+48(%rip), %rax 
    movq %rax, bar1+48(%rip) 
    movq bar1_init+56(%rip), %rax 
    movq %rax, bar1+56(%rip) 
    movq bar1_init+64(%rip), %rax 
    movq %rax, bar1+64(%rip) 
    movq bar1_init+72(%rip), %rax 
    movq %rax, bar1+72(%rip) 
    nop 
    popq %rbp 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE2: 
    .size init_bar1, .-init_bar1 
    .globl init_bar2 
    .type init_bar2, @function 
init_bar2: 
.LFB3: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    movl $bar2, %eax 
    movl $80, %ecx 
    movl $0, %esi 
    movq %rsi, (%rax) 
    movl %ecx, %edx 
    addq %rax, %rdx 
    addq $8, %rdx 
    movq %rsi, -16(%rdx) 
    leaq 8(%rax), %rdx 
    andq $-8, %rdx 
    subq %rdx, %rax 
    addl %eax, %ecx 
    andl $-8, %ecx 
    movl %ecx, %eax 
    shrl $3, %eax 
    movl %eax, %ecx 
    movq %rdx, %rdi 
    movq %rsi, %rax 
    rep stosq 
    nop 
    popq %rbp 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE3: 
    .size init_bar2, .-init_bar2 
    .ident "GCC: (GNU) 6.3.1 20170306" 
    .section .note.GNU-stack,"",@progbits 
संबंधित मुद्दे