【发布时间】:2018-07-14 21:59:55
【问题描述】:
(更新删除 decltype 并替换为 static_cast,结果相同)
在代码示例中,在宏 MAX 中添加强制转换,代码执行得更快。我不知道为什么它似乎应该是相同的。这发生在两个不同的 ARM 编译器 GCC(和更大代码库中的 armclang)中。对此的任何想法都会非常有帮助。
在下面的代码中,当定义 WITH_CAST 时,编译结果得到了显着改善(在我更大的代码库中结果相同)。表演的演员似乎是多余的。我在 Keil 5.25pre2 中运行它(仅作为模拟器)。我使用 Keil 模拟器来检查性能速度,通过查看 t1 计时器显示的微秒数。
代码片段:
#if defined (WITH_CAST)
#define MAX(a,b) (((a) > (b)) ? (static_cast<mytype>(a)) : (static_cast<mytype>(b)))
#else
#define MAX(a,b) (((a) > (b)) ? ((a)) : ((b)))
#endif
GNU Arm Tools Embedded v. 7 2017-q4-major。
编译器选项: -c -mcpu=cortex-m4 -mthumb -gdwarf-2 -MD -Wall -O -mapcs-frame -mthumb-interwork -std=c++14 -Ofast -I./RTE/_Target_1 -IC:/Keil_v525pre/ ARM/PACK/ARM/CMSIS/5.2.0/CMSIS/包含-IC:/Keil_v525pre/ARM/PACK/ARM/CMSIS/5.2.0/Device/ARM/ARMCM4/包含-I"C:/Program Files (x86 )/GNU Tools ARM Embedded/7 2017-q4-major/arm-none-eabi/include"-I"C:/Program Files (x86)/GNU Tools ARM Embedded/7 2017-q4-major/lib/gcc/ arm-none-eabi/7.2.1/include"-I"C:/Program Files (x86)/GNU Tools ARM Embedded/7 2017-q4-major/arm-none-eabi/include/c++/7.2.1" -I"C:/Program Files (x86)/GNU Tools ARM Embedded/7 2017-q4-major/arm-none-eabi/include/c++/7.2.1/arm-none-eabi" -D__UVISION_VERSION="525" -D__GCC -D__GCC_VERSION="721" -D_RTE_ -DARMCM4 -Wa,-alhms="*.lst" -o *.o
汇编器选项: -mcpu=cortex-m4 -mthumb --gdwarf-2 -mthumb-interwork --MD .d -I./RTE/_Target_1 -IC:/Keil_v525pre/ARM/PACK/ARM/CMSIS/5.2.0/ CMSIS/Include -IC:/Keil_v525pre/ARM/PACK/ARM/CMSIS/5.2.0/Device/ARM/ARMCM4/Include -I"C:/Program Files (x86)/GNU Tools ARM Embedded/7 2017-q4- major/arm-none-eabi/include" -I"C:/Program Files (x86)/GNU Tools ARM Embedded/7 2017-q4-major/lib/gcc/arm-none-eabi/7.2.1/include" -I"C:/Program Files (x86)/GNU Tools ARM Embedded/7 2017-q4-major/arm-none-eabi/include/c++/7.2.1" -I"C:/Program Files (x86)/ GNU 工具 ARM Embedded/7 2017-q4-major/arm-none-eabi/include/c++/7.2.1/arm-none-eabi" -alhms=".lst" -o *.o
链接器选项: -T ./RTE/Device/ARMCM4/gcc_arm.ld -mcpu=cortex-m4 -mthumb -mthumb-interwork -Wl,-Map="./Optimization.map" -o 优化.elf *.o -lm
#include <cstdlib>
#include <cstring>
#include <cstdint>
#define WITH_CAST
struct mytype {
uint32_t value;
__attribute__((const, always_inline)) constexpr friend bool operator>(const mytype & t, const mytype & a) {
return t.value > a.value;
}
};
static mytype output_buf [32];
static mytype * output_memory_ptr = output_buf;
static mytype * volatile * output_memory_tmpp = &output_memory_ptr;
static mytype input_buf [32];
static mytype * input_memory_ptr = input_buf;
static mytype * volatile * input_memory_tmpp = &input_memory_ptr;
#if defined (WITH_CAST)
#define MAX(a,b) (((a) > (b)) ? (static_cast<mytype>(a)) : (static_cast<mytype>(b)))
#else
#define MAX(a,b) (((a) > (b)) ? ((a)) : ((b)))
#endif
int main (void) {
const mytype * input = *input_memory_tmpp;
mytype * output = *output_memory_tmpp;
mytype p = input[0];
mytype c = input[1];
mytype pc = MAX(p, c);
output[0] = pc;
for (int i = 1; i < 31; i ++) {
mytype n = input[i + 1];
mytype cn = MAX(c, n);
output[i] = MAX(pc, cn);
p = c;
c = n;
pc = cn;
}
output[31] = pc;
}
【问题讨论】:
-
强制转换不是多余的——它是对非引用类型的强制转换,这意味着现在
?:的结果不是左值。没有那个演员?:的结果是左值。现在,为什么它让你的代码更快是另一回事了...... -
这导致了某个地方。将 static_cast
更改为 static_cast 会产生相同的次优结果,当然,由于您指出的左值,尝试分配给 MAX 的结果仅适用于 mytype&。仍然无法弄清楚为什么编译器无法识别和优化变量的使用方式。 -
@AnT 添加您的评论作为答案,我会接受。它解释了发生了什么——当然不是为什么,但这似乎是编译器编写者的问题。