如何防止Atmel Studio gcc 6.3.1将4字节memcmp()优化为4字节直接比较?

如何防止Atmel Studio gcc 6.3.1将4字节memcmp()优化为4字节直接比较?,c,gcc,arm,atmelstudio,memcmp,C,Gcc,Arm,Atmelstudio,Memcmp,使用提供的gcc 6.3.1运行Atmel Studio,为Atmel/微芯片SAMV70(ARM Cortex-M7)芯片构建固件。我的代码使用memcmp()将4字节输入数组与4字节本地数组进行比较。当使用-O0编译以禁用优化时,它可以正常工作。当使用-Os进行编译以优化大小或使用-O3进行最大优化时,编译器将使用直接的4字节比较来替换memcmp()调用(通过检查反汇编进行验证)。不幸的是,优化有时也会将本地4字节数组移动到未对齐的起始地址,因此,尽管memcmp()可以正常工作,但由于未

使用提供的gcc 6.3.1运行Atmel Studio,为Atmel/微芯片SAMV70(ARM Cortex-M7)芯片构建固件。我的代码使用
memcmp()
将4字节输入数组与4字节本地数组进行比较。当使用
-O0
编译以禁用优化时,它可以正常工作。当使用
-Os
进行编译以优化大小或使用
-O3
进行最大优化时,编译器将使用直接的4字节比较来替换
memcmp()
调用(通过检查反汇编进行验证)。不幸的是,优化有时也会将本地4字节数组移动到未对齐的起始地址,因此,尽管
memcmp()
可以正常工作,但由于未对齐的访问,直接比较会触发一个
硬故障

在我看来,这是一个100%的编译器优化错误(可能是gcc,可能是Atmel添加的东西),但我仍然坚持使用提供的编译器,所以更新不是一个选项。所以这里是我的实际问题:有没有一种方法可以让优化保持启用,但禁用这个特定的优化?否则,我将被迫将本地4字节数组与4字节对齐,或者寻找其他解决方法

编译器版本:
gcc版本6.3.1 20170620(发布)[ARM/embedded-6-branch版本249437](Atmel版本:508)

下面是一个可能触发故障的示例函数:

bool example(uint8_t *input_data)
{
    uint8_t local_data[4] = { 0x00, 0x01, 0x02, 0x03 };

    return (memcmp(input_data, local_data, 4) == 0);
}

我的代码总是传递4字节对齐的
输入数据,所以这不是问题,但编译器优化再次认为这是理所当然的,这是不好的形式。

回答我自己的问题,因为Eugene没有发布正式答案:

从gcc ARM选项中:

默认情况下,所有ARMv6之前版本、所有ARMv6-M都禁用未对齐访问 对于ARMv8-M基线体系结构,并为所有其他体系结构启用 架构

这意味着默认情况下,ARMv7-M允许未对齐的访问。事实证明,这是有意义的,因为从ARMv7-M架构参考手册

以下数据访问支持未对齐的寻址,并且仅支持 当CCR.UNALIGN_TRP位设置为1时生成对齐故障, 请参阅配置和控制寄存器:

•非半字对齐LDR{S}H{T}和STRH{T}

•非半字对齐TBH

•非单词对齐的LDR{T}和STR{T}

这意味着ARMv7-M支持一组有限的未对齐访问。但是,它不支持所有未对齐的访问:

以下数据访问始终会生成对齐故障:

•非半字对齐LDREXH和STREXH

•非单词对齐的LDREX和STREX

•非单词对齐的LDRD、LDMIA、LDMDB、POP、LDC、VLDR、VLDM和VPOP

•非字对齐的STRD、STMIA、STMDB、PUSH、STC、VSTR、VSTM和 VPUSH

而且:

对强顺序和设备内存类型的访问必须始终是 自然对齐

以下是促使我提出初始问题的故障条件:

  • 启用优化的gcc正在用直接比较取代4字节的
    memcmp()
    ,这在默认情况下是允许的,因为默认情况下允许未对齐的访问。所以这不是一个编译器错误
  • 包含该
    memcmp()
    数据的闪存区域位于声明为
    强顺序的MPU段中,该段不支持未对齐访问。因此,当用直接比较替换
    memcmp()
    时,数据落在未对齐的地址上,比较触发了一个
    硬故障

  • Eugene在最初的评论中得到了正确的解决方案是将
    -mno unaligned access
    添加到编译器选项中。在我的例子中,这仍然允许编译器用直接4字节比较替换
    memcmp()
    ,但它也强制数据4字节对齐,允许比较成功而不触发故障条件。

    回答我自己的问题,因为Eugene没有发布正式答案:

    从gcc ARM选项中:

    默认情况下,所有ARMv6之前版本、所有ARMv6-M都禁用未对齐访问 对于ARMv8-M基线体系结构,并为所有其他体系结构启用 架构

    这意味着默认情况下,ARMv7-M允许未对齐的访问。事实证明,这是有意义的,因为从ARMv7-M架构参考手册

    以下数据访问支持未对齐的寻址,并且仅支持 当CCR.UNALIGN_TRP位设置为1时生成对齐故障, 请参阅配置和控制寄存器:

    •非半字对齐LDR{S}H{T}和STRH{T}

    •非半字对齐TBH

    •非单词对齐的LDR{T}和STR{T}

    这意味着ARMv7-M支持一组有限的未对齐访问。但是,它不支持所有未对齐的访问:

    以下数据访问始终会生成对齐故障:

    •非半字对齐LDREXH和STREXH

    •非单词对齐的LDREX和STREX

    •非单词对齐的LDRD、LDMIA、LDMDB、POP、LDC、VLDR、VLDM和VPOP

    •非字对齐的STRD、STMIA、STMDB、PUSH、STC、VSTR、VSTM和 VPUSH

    而且:

    对强顺序和设备内存类型的访问必须始终是 自然对齐

    以下是促使我提出初始问题的故障条件:

  • 启用优化的gcc正在用直接比较取代4字节的
    memcmp()
    ,这在默认情况下是允许的,因为默认情况下允许未对齐的访问。所以这不是一个编译器错误
  • 包含该
    memcmp()
    数据的闪存区域位于声明为
    Stron的MPU段中