C 如何在源代码级别自动展开源代码中的循环?
我想在源代码级别自动解开用C编写的目标程序中的循环(仅供参考,我使用linux和gcc编译器)。 关于详细的描述,让我们看看下面的简单源代码C 如何在源代码级别自动展开源代码中的循环?,c,loops,model-checking,C,Loops,Model Checking,我想在源代码级别自动解开用C编写的目标程序中的循环(仅供参考,我使用linux和gcc编译器)。 关于详细的描述,让我们看看下面的简单源代码 1: int main(){ 2: int i = 0; 3: while(i<3){ 4: printf("hi\n"); 5: i++; 6: } 7: } 1:int main(){ 2:inti=0; 3:while(i循环展开只是GCC完成的一个(在许多优化中)优化(至少是-O2或-O3),它本身没有意义(它只
1: int main(){
2: int i = 0;
3: while(i<3){
4: printf("hi\n");
5: i++;
6: }
7: }
1:int main(){
2:inti=0;
3:while(i循环展开只是GCC完成的一个(在许多优化中)优化(至少是-O2
或-O3
),它本身没有意义(它只有通过其他优化才有帮助,比如不断传播)
当然,您不能只想要一个源代码(想象一下,对于展开循环的
循环,许多宏可能被扩展为)
我建议您扩展GCC编译器,例如,它是扩展GCC的高级领域特定语言
(或者,如果你有很多时间,用C痛苦地编写你的GCC插件)
然后,您将在一些循环展开(和其他优化)过程之后添加一个过程,该过程将处理Gimple的内部表示(您可以将Gimple理解为一种类似“最小”C语言,只进行基本操作,如lax=y+z;
和调用以及简单测试,如if(x>y)goto l;
)
但我仍然不明白你想对结果做什么。如果你想进一步分析它,请在编译器内部处理(可能是用MELT编码的另一个过程)GCC内部表示。如果你想提供“展开的”编写一些外部工具的代码,编写一个转换过程,将Gimple转换为适当的格式。您应该查看汇编程序,了解编译器在循环展开中的实际性能。但您也可以帮助编译器更好地编程:
for (unsigned i = 0; i < 3; ++i) {
printf("hi\n");
}
for(无符号i=0;i<3;++i){
printf(“hi\n”);
}
也就是说,使用无符号整数类型作为循环变量(size\t
通常是个好主意),并将循环变量设置为本地变量。然后使用类似于-S-O3-march=native的编译器选项检查汇编程序
然后,也只有到那时,如果您对结果不满意,请查看。它有一组宏来进行展开,而不仅仅是循环。查找类似于P99_for
的内容几乎总是,在确定某些代码是否适合展开代码方面,gcc会比您做得更好。根据我的经验,这是极为罕见的您可以比gcc做得更好—唯一合理的情况是当您有非常复杂的代码执行“奇怪”的事情时,您的示例中肯定不是这样
您是否确实尝试过在优化中使用-S选项来查看编译器的功能
当然,编译器可能有不优化这个特定循环的感觉,因为printf()比所有循环加在一起要重得多——但这是一个稍微不同的问题。编译器已经在这样做了……对于您的示例,它可能只会得到三个printf(“hi\n”)实例
没有任何剩余的测试或增量的i
你到底为什么要问?你想对输出做什么?为什么你需要它成为一些“源代码”?你正在将它输入另一个工具吗?哪一个?谢谢你的回答。顺便问一句,有没有一种方法可以在所有循环都不需要的情况下获得源代码?这是我的问题:)转换源代码的覆盖率将通过出于某种目的使用Gcov来衡量。我不理解你的问题。你似乎错误地认为编译器正在转换源代码;事实并非如此。它正在将源代码解析为一些内部表示,并将内部表示转换为其他表示。选项 -fdump tree all
(和其他类似选项)生成数百个转储文件,显示编译各个阶段内部GCC表示的文本形式。
1: void ex(int i){
2: int i = 0;
3: while(i<3){
4: printf("hi\n");
5: i++;
6: }
7: }
1: void ex(int i){
2: if (i<3){
3: printf("hi\n");
4: i++;
5: }
6: if (i<3){
7: printf("hi\n");
8: i++;
9: }
10: if (i<3){
11: printf("hi\n");
12: i++;
13: }
14:}
for (unsigned i = 0; i < 3; ++i) {
printf("hi\n");
}