Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
GCC不会优化未初始化静态常量的结构副本_C_Gcc_Optimization_Struct - Fatal编程技术网

GCC不会优化未初始化静态常量的结构副本

GCC不会优化未初始化静态常量的结构副本,c,gcc,optimization,struct,C,Gcc,Optimization,Struct,首先,我正在开发一个微控制器,所以RAM和ROM的使用是优先考虑的 我意识到这可能是一个错误报告或不够具体。如果我在这里没有得到任何答案,我会将其归档 我喜欢使用static conststructs将堆栈结构初始化为默认值。在大多数情况下,默认结构为全零。我更喜欢使用static conststructs而不是memset(,) 我当前的工具链是arm-none-eabi-gcc-4_7_3,为Cortex M4目标编译,并进行优化-Os 我注意到以下几点:;如果我显式地将我的static c

首先,我正在开发一个微控制器,所以RAM和ROM的使用是优先考虑的

我意识到这可能是一个错误报告或不够具体。如果我在这里没有得到任何答案,我会将其归档

我喜欢使用
static const
structs将堆栈结构初始化为默认值。在大多数情况下,默认结构为全零。我更喜欢使用
static const
structs而不是
memset
(,)

我当前的工具链是
arm-none-eabi-gcc-4_7_3
,为Cortex M4目标编译,并进行优化
-Os

我注意到以下几点:;如果我显式地将我的
static const
struct初始化为零,GCC会生成不同的代码,如果我没有(
static const struct foo;
vs
static const struct foo={0};
)。特别是,它将未初始化的静态常量分配给内存并执行复制操作

下面是一个代码示例:

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;
}
编译后,将生成以下汇编程序列表(为了简洁起见,重新排列和修剪):

我们可以看到,对于
foo2=init\u foo2
bar2=init\u bar2
而言,编译器优化了副本,将零直接存储到
foo2
,或者调用
memset
bar2

我们可以看到,对于
foo1=init\u foo1
bar1=init\u bar1
编译器正在执行显式复制,加载到
foo1
的寄存器并从寄存器中保存,并为
foo2
调用
memcpy

我有几个问题:

  • 这是预期的GCC操作吗?我希望未初始化的
    静态常量
    结构与初始化的
    静态常量
    结构在GCC中遵循相同的路径,从而产生相同的输出
  • 其他版本的ARM GCC是否会出现这种情况?我手头没有其他版本,所有联机
    C
    到汇编编译器实际上都是
    C++
    编译器
  • GCC的其他目标体系结构是否会发生这种情况?同样,我手头没有其他版本

  • 我已经在amd64上进行了测试,令我惊讶的是,它看起来像是一个一致的行为(但我不知道它是否是一个bug)。gcc将foo1_init和bar1_init放在公共数据段中,或由操作系统(.bss)初始化的零值段中。foo2_init和bar2_init放在只读段(.rodata)中,就像它们是非零初始化值一样。使用-O0可以看到这一点。因为您没有使用操作系统,所以操作系统初始化部分由gcc和/或链接器手动初始化,然后复制。gcc通过生成直接memset并消除dead*2_init变量来优化rodata值。不过,clang同样优化了这两种情况

    以下是gcc输出(-O0):


    您可以编辑代码以保持一致性吗?它当前指的是
    foo1\u init
    等,这些未在代码中定义(它定义的是
    init\u foo1
    )。我想这只是一个输入错误,因为
    init\u foo1
    既是一个变量又是一个函数,在同一个范围内。调用
    memcpy()
    在空间上非常便宜,你有没有将其与内联副本的成本进行比较?也许有一种启发式方法,当字节数足够大时发出调用。1。我怀疑这是因为未初始化的变量只是暂时定义的,而编译器生成的代码并不关心变量是否已完全定义。(也就是说,它不检查变量是否在以后的翻译单元中使用初始值设定项完全定义。)我同意@IanAbbott,如果是这种情况,编译器的行为是正确的,因为您将
    foo2_init
    bar2_init
    明确定义为
    常量,并且始终==0。因此,正确的复制优化是将目标数组归零(使用
    memset
    )。另一方面,
    foo1_init
    bar1_init
    常量,但其内容未知,因此编译器会尝试保留将其复制到目标的内容。另外,编译器只知道已经完成的翻译,不关心在使用点之后定义或初始化了什么。@IanAbbott我的理解是未初始化的变量在BSS中,由
    .section.BSS.foo1_init,“aw”、%nobits
    .section.BSS.bar1_init,“aw”、%nobits
    行表示。
     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
    
        .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