C 常数分割未优化?

C 常数分割未优化?,c,optimization,divide,C,Optimization,Divide,我有以下代码行: #define A 360 #define B 360 temp = (s16_myvar * A) / B; 我的编译器(在本例中为Windriver DIAB PPC,使用标准的扩展优化设置-XO)似乎没有将其优化为类似temp=s16_myvar的值。当我查看汇编列表时,它似乎忠实地将360放入寄存器,然后在执行乘法后,将结果除以360 有没有一个技巧可以让我在最后的代码中去掉乘法和除法 对于那些问“为什么?”的人,假设在某些配置中,B不是==A,你需要缩放一个变量。

我有以下代码行:

#define A 360
#define B 360

temp = (s16_myvar * A) / B;
我的编译器(在本例中为Windriver DIAB PPC,使用标准的扩展优化设置-XO)似乎没有将其优化为类似temp=s16_myvar的值。当我查看汇编列表时,它似乎忠实地将360放入寄存器,然后在执行乘法后,将结果除以360

有没有一个技巧可以让我在最后的代码中去掉乘法和除法


对于那些问“为什么?”的人,假设在某些配置中,B不是==A,你需要缩放一个变量。

只是一个假设:当
B
除以
A
并且
A x
不会溢出时,像
(A/B)/B这样的整数表达式可以简化为
(A/B)x
。这可能是因为优化器设计人员没有深入研究,或者认为这样的表达式不太可能/愚蠢


更新


Olaf注释后,溢出条件是不相关的,因为这是一种未定义的行为,因此运行时可以自由返回任何值。

让有符号16位变量
s16_myvar
为32700。假设A和B是非常好的32位有符号整数,比如360000

然后将变量提升为int,然后进行乘法运算,得到1177200000,即-1112901888

除以B得到-3091


这就是你想要的吗?您可能知道这些数字不会自动换行,但编译器无法假定它。

我将尝试使用此函数形式作为可能的解决方案。我的想法是,如果编译器注意到scale_a和scale_b是相同的,那么它可能会优化掉大部分指令。我会把结果发回去的

__inline__ S16 RESCALE_FUNC(short s16_input, const short *scale_a, const short *scale_b)
{
    return (scale_a==scale_b)?(s16_input):((s16_input*(*scale_a))/(*scale_b));
}   

temp = RESCALE_FUNC(s16_myvar, A, B);

这对我来说是个好行为。评估顺序很重要。 假设您正在执行定点算术(或任何常规整数算术),并且希望计算“输出=输入的80%”。 然后执行以下操作:输出=(输入*80)/100; 假设输入=201。 如果编译器决定先执行80/100: 输出=201*(80/100)=201*0=0。 这是因为80和100是整数(同样适用于int变量)

但由于您显式地添加了一些括号,因此您得到: 输出=(输入*80)/100=(201*80)/100=16080/100=160


在这里,160大约是201的80%(请记住,我们使用的是整数而不是浮点数)。

什么是
##define b360
?可能它没有得到优化,因为编译器担心溢出,在这种情况下,即使
A==B
,结果可能与
s16_myvar
@ouah不同:根据标准,有符号整数溢出总是UB,没有“选项”。但是,如果
A==B
,它们无论如何都会取消。但是,由于括号的存在,编译器可能会被迫这样做。在优化方面,嵌入式编译器非常“保守”(委婉地说),比gcc等编译器保守得多。这就是它们如此昂贵的原因;-)@Olaf在OP表达式的特定情况下,它永远不会溢出,因为
s16_myvar
(在OP系统中)的整数提升,编译器无论如何都可以对其进行优化。@ouah:假设为32位整数,是的。但即使是16位整数,也没关系。这是UB的(少数)优点之一。
s16\u myvar
在乘法之前在他的系统中提升为
int
32位,不可能溢出。@ouah:为什么会提升呢?整数提升规则(
s16\u myvar
在OP系统中为16位,
int
为32位)。如果
a x
溢出,不管怎么说,你是在UB的世界里,所以这对优化并不重要。然而,我同意你的观点,编译器并不擅长优化这种非常常见的情况。大多数情况下,更改为“除法优先”是没有选择的,因为您无法保证第一个约束(仍然有效)。@Yves Daoust:提升不是由整型常量的存在引起的。小于
int
的类型总是无条件地提升为
int
,而不考虑上下文。最初我是在同一行。但是在@Olaf的一句话之后,我明白溢出的表达式是一种未定义的行为,代码生成器可以采取任何行动,包括给出正确的答案!但是编译器知道这些值。它们很小。预处理后,表达式为
(s16_myvar*360)/360
。在32位平台上(如果
s16\u myvar
真的是s16),这绝对等同于
s16\u myvar
@undur\u gongor:当你是一名编译器编写者,编写优化时,你倾向于远离灰色区域,因为你会有10^3-10^6个用户,其中一些用户可能会做一些棘手的事情,比如包装,就像机器指令一样。“bug报告”会让你发疯的。为什么要自找麻烦?早期的结果似乎很有希望。。。现场似乎没有任何额外的装配说明;如果比例相同,编译器似乎优化了函数。我需要尝试更多不同比例的示例,以确保实际工作正常。您好,欢迎使用StackOveflow。请格式化您的代码以使其更具可读性。有关格式设置的帮助,请参阅。