Assembly 优化后目标的破坏排序

Assembly 优化后目标的破坏排序,assembly,g++,arm,sequence-points,Assembly,G++,Arm,Sequence Points,我试图在我的软件中计时一些函数调用,以比较不同的实现 为了获得所需的计时,我正在使用RAII结构在函数的开始和结束处读取ARM A9处理器的PCCNTR寄存器 问题是编译器没有考虑对象的构造-销毁序列。这是编译器中的错误还是允许的优化 编译器是一个arm-none-eabi-g++(Sourcery CodeBench Lite 2012.03-56)4.6.3 #define GET_TICK(var) \ asm volatile (\ "mrc p15, 0, %0, c9

我试图在我的软件中计时一些函数调用,以比较不同的实现

为了获得所需的计时,我正在使用RAII结构在函数的开始和结束处读取ARM A9处理器的PCCNTR寄存器

问题是编译器没有考虑对象的构造-销毁序列。这是编译器中的错误还是允许的优化

编译器是一个
arm-none-eabi-g++(Sourcery CodeBench Lite 2012.03-56)4.6.3

#define GET_TICK(var) \
  asm volatile (\
      "mrc p15, 0, %0, c9, c13, 0;"\
      : "=r" (var)\
      );

struct tick{
  uint32_t &start;
  uint32_t &end;

  tick(uint32_t& s, uint32_t &e) 
    :start(s)
     , end(e)
  {
    GET_TICK(start);
  }

  ~tick(){
    GET_TICK(end);
  }
};

bool mailbox::send(uint32_t &start, uint32_t &end, uint32_t msg){
  tick t(start, end);
  /* now start should have the current timestamp */
  {
    Spinlocker lock(SPINLOCK_LOCK_REG_0); // RAII mutex locker
    uint32_t cnt = mb_msg_max_count + 1;
    do{
      cnt = count();
      if(cnt >= mb_msg_max_count){
        lock.release();
        lock.get();
      }
    }while(cnt >= mb_msg_max_count);
    *(first_message + cnt) = msg;
    inc_counter(); // free function
    MEM_BARRIER; // #define asm volatile("dsb st;")
    /* spinlock should be destroyed but it is only after t */
  }

  return true;
  /* now end should have the current timestamp */
}
生成的汇编代码:

83000a64 <mailbox::get(unsigned long&, unsigned long&)>:
83000a64: b530        push  {r4, r5, lr}
83000a66: 4604        mov r4, r0
83000a68: 680b        ldr r3, [r1, #0]
83000a6a: b083        sub sp, #12
83000a6c: 4615        mov r5, r2
83000a6e: ee19 2f1d   mrc 15, 0, r2, cr9, cr13, {0}
83000a72: f44f 41d0   mov.w r1, #26624  ; 0x6800
83000a76: 601a        str r2, [r3, #0]
83000a78: a801        add r0, sp, #4
83000a7a: f6c4 210f   movt  r1, #18959  ; 0x4a0f
83000a7e: f000 f871   bl  83000b64 <Spinlocker::Spinlocker(unsigned long volatile*)>
83000a82: 6823        ldr r3, [r4, #0]
83000a84: 681a        ldr r2, [r3, #0]
83000a86: b18a        cbz r2, 83000aac <mailbox::get(unsigned long&, unsigned long&)+0x48>
83000a88: 6819        ldr r1, [r3, #0]
83000a8a: 1e48        subs  r0, r1, #1
83000a8c: 6018        str r0, [r3, #0]
83000a8e: f3bf 8f4e   dsb st
83000a92: 6864        ldr r4, [r4, #4]
83000a94: 1e51        subs  r1, r2, #1
83000a96: f854 4021   ldr.w r4, [r4, r1, lsl #2]
83000a9a: ee19 0f1d   mrc 15, 0, r0, cr9, cr13, {0} <- timer is read before Spinlock is destroyed. Is this allowed?
83000a9e: 6028        str r0, [r5, #0]
83000aa0: a801        add r0, sp, #4
83000aa2: f000 f885   bl  83000bb0 <Spinlocker::~Spinlocker()> <- Shouldn't this be done before issuing the MCR assembly?
83000aa6: 4620        mov r0, r4
83000aa8: b003        add sp, #12
83000aaa: bd30        pop {r4, r5, pc}
83000aac: a801        add r0, sp, #4
83000aae: f000 f86b   bl  83000b88 <Spinlocker::release()>
83000ab2: a801        add r0, sp, #4
83000ab4: f000 f86e   bl  83000b94 <Spinlocker::get()>
83000ab8: 6823        ldr r3, [r4, #0]
83000aba: 681a        ldr r2, [r3, #0]
83000abc: 2a00        cmp r2, #0
83000abe: d1e3        bne.n 83000a88 <mailbox::get(unsigned long&, unsigned long&)+0x24>
83000ac0: e7f4        b.n 83000aac <mailbox::get(unsigned long&, unsigned long&)+0x48>
83000ac2: bf00        nop  
83000a64:
83000a64:b530推送{r4,r5,lr}
83000a66:4604 mov r4,r0
83000a68:680b ldr r3[r1,#0]
83000a6a:b083子sp,#12
83000a6c:4615 mov r5,r2
83000a6e:ee19 2f1d mrc 15,0,r2,cr9,cr13,{0}
83000a72:f44f 41d0移动带r1,#26624;0x6800
83000a76:601a str r2[r3,#0]
83000a78:a801添加r0,sp,#4
83000a7a:F6C4210F移动r1,#18959;0x4a0f
83000a7e:f000 f871 bl 83000b64
83000a82:6823 ldr r3[r4,#0]
83000a84:681a ldr r2[r3,#0]
83000a86:b18a cbz r2,83000aac
83000a88:6819 ldr r1[r3,#0]
83000a8a:1e48接头r0、r1、1
83000a8c:6018 str r0[r3,#0]
83000a8e:f3bf 8f4e dsb st
83000a92:6864 ldr r4[r4,#4]
83000a94:1e51接头r1、r2、1
83000a96:f854 4021 ldr.w r4[r4,r1,lsl#2]

83000a9a:ee19 0f1d mrc 15,0,r0,cr9,cr13,{0}在我看来像个bug。它们应该按与创建相反的顺序销毁,请参见此处:您可以通过用户空间中的mrc访问该寄存器吗?如果您将volatile添加到“uint32_t&start;uint32_t&end;”中,它会发生变化吗?这可能是编译器的优化…@auselen这不是在操作系统下运行的,这是裸机代码。所以保护被停用,我可以使用MRC。@auselen使用volatile不会产生任何明显不同的访问模式。