使用编译指示进行 C 优化,它会递归吗?还是简单地使用查看文件中编译指示的顺序?

C optimization with pragmas, does it recurse? Or does it simply use look at the order of the pragmas in the file?

提问人:rollsch 提问时间:7/3/2023 最后编辑:rollsch 更新时间:8/7/2023 访问量:80

问:

假设我们为我的项目禁用了项目范围的优化(例如 -O0),我做了以下操作。编辑:我正在使用tricore-gcc(应该与普通GCC相同)。我找不到特定于 tricore-gcc 的关于编译指示的文档。

static void Method1(U8 *data) __attribute__((-fno-inline));
static void Method2(U8 *data) __attribute__((-fno-inline));
//Example 1 (expect method1/method2 to both be optimised at -0s level
#pragma GCC optimize ("-Os")
static void Method1(U8 *data);
{
    ...do stuff
    Method2(data);
}
#pragma GCC optimize ("-O0")

#pragma GCC optimize ("-Os")
static void Method2(U8 *data)
{
    ...do stuff
}
#pragma GCC optimize ("-O0")
//Example 2 Expect method 1 to not be optimised 
//expect method2 to be optimised at -0s level
#pragma GCC optimize ("-O0")
static void Method1(U8 *data)
{
    ...do stuff
    Method2(data);
}
#pragma GCC optimize ("-O0")

#pragma GCC optimize ("-Os")
static void Method2(U8 *data);
{
    ...do stuff
}
#pragma GCC optimize ("-O0")

//Example 3 - Expect method method 1 to not be optimised? 
expect method 2 to be optimised

//No pragma, assume defaults to -O0 as that is the project default
static void Method1(U8 *data)
{
    Method2(data);
}

#pragma GCC optimize ("-Os")
static void Method2(U8 *data);
{
    ...do stuff
}
#pragma GCC optimize ("-O0")

//Example 4 - expect method 1 to be optimised, however will method 2 be optimised?
//as it was called from method1?
#pragma GCC optimize ("-Os")
static void Method1(U8 *data)
{
    ...do stuff
    Method2(data);
}
#pragma GCC optimize ("-O0")

//No pragma, assume defaults to -O0 as that is the project default
//OR does it simply default to the last pragma it saw, eg the -O0 above?
static void Method2(U8 *data);
{
    ...do stuff
}
//Example 6 - expect method 1 to be optimised, however will method 2 be optimised?
//as it was called from method1?
#pragma GCC optimize ("-Os")
static void Method1(U8 *data)
{
    ...do stuff
    Method2(data);
}

//Ommitted #pragma GCC optimize ("-O0"), I assuming that method2
//will be optimised?
static void Method2(U8 *data);
{
    ...do stuff
}

示例 3 和 4 是两个示例,我不确定会发生什么或会发生什么,因为没有编译指示,编译指示是否递归到被调用的函数中?或者编译器只是简单地查找它是否位于编译指示中,以确定是否应该对其进行优化?

示例 5 我相信我明白会发生什么

最后一个问题。我是否需要在文件顶部的函数定义上放置编译指示?还是简单地忽略了它们,而功能本身才是最重要的?

例如,这里的这些行,将编译指示放在这里会混淆事情,什么都不做,或者他们应该去这里而不是根本不在函数上?还是为了简洁起见而两者兼而有之?

static void Method1(U8 *data) __attribute__((-fno-inline));
static void Method2(U8 *data) __attribute__((-fno-inline));

编辑:更新 - 本地化优化的工作方式与尼尔森描述的完全一样。这似乎是一件奇怪的事情,但对于我的用例来说,这正是我想要的。

C 优化 编译指示

评论

1赞 Aconcagua 7/3/2023
顺便说一句:C 措辞(如标准中)没有“方法”的概念,只有“函数的概念......
1赞 Aconcagua 7/3/2023
函数调用是你设置的优化级别的基础(尽管我怀疑会有什么需要优化的......),但不是调用的函数(除非是内联的,但你明确阻止了)。如果优化传播的,如果还有第三个函数的优化级别与再次调用的优化级别不同,则该优化级别最终应用于后者???method1method2
0赞 chux - Reinstate Monica 7/3/2023
@rollsch。代码注释具有 .这些似乎指的是函数和 。但也许不是?如果是这样,请编辑并匹配大小写和间距以提高清晰度。method 1, method 2, method method 1, method1, method2Method1()Method2()
1赞 n. m. could be an AI 7/3/2023
这个问题是关于 GCC,而不是 C。

答:

2赞 nielsen 7/3/2023 #1

编译指示效果是实现定义的,因此不能假定它在不同的编译器中是相同的。该问题集中在 GCC 上,GCC 文档如下:

#pragma GCC 优化(字符串,...)

此编译指示允许您为稍后在源文件中定义的函数设置全局优化选项。[...]在此点之后定义的每个函数都被视为已使用每个字符串参数的一个 optimize(string) 属性声明。[...]

因此,此编译指示从它在文件中出现到文件末尾都有效。

为了在不影响后续函数定义的情况下优化单个函数,可以使用属性表示法:

__attribute__((optimize(3)))
void func()
{
   ...
}

或者,可以通过保存和还原设置来限定编译指示的范围:

#pragma GCC push_options
#pragma GCC optimize ("-O3")
void func()
{
   ...
}
#pragma GCC pop_options

函数定义的优化选项仅影响函数本身,不会传播到被调用的函数。它们将使用在定义它们时生效的选项进行优化。

评论

0赞 rollsch 7/4/2023
太棒了,所以优化不会传播到被调用的函数。这正是我想知道的。谢谢。