0

我想在源代码级别自动展开用 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:   int i = 0;
3:   if (i<3){
4:     printf("hi\n");
5:     i++;
6:   }
7:   if (i<3){
8:     printf("hi\n");
9:     i++;
10:  }
11:  if (i<3){
12:    printf("hi\n");
13:    i++;
14:  }
15:}

我知道CBMC会自动展开循环以进行软件模型检查,但我不确定 CBMC 是否会将源代码转换为展开循环的源代码。我需要获得一个所有循环都展开的程序源代码。

我试图为此找到工具或解决方案,但我找不到。任何建议或意见将不胜感激。谢谢!


很抱歉让您感到困惑。我将详细解释我的最终目标“在源代码级别展开循环”。我展开循环的最终目标是测量执行从循环展开生成的语句的测试用例的数量。参考下面的一个例子

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:}

从上面转换的源代码中,我将测量执行来自“循环展开”的每个语句的测试用例的数量。例如,执行第3,4行或第7,8行或第11,12行的测试用例从原始源代码中的第4行和第5行转换而来的测试用例的数量与测试用例执行行的数量不同#4,5 在原始源代码中。

仅供参考,如果有一种方法可以在不展开循环的情况下实现我的最终目标,那么方法也很好!谢谢!

4

3 回答 3

1

在确定某些代码是否适合展开代码方面,gcc 几乎总是比您做得更好。以我的经验,你可以做得比 gcc 更好的情况是非常罕见的 - 唯一合理的情况是当你有非常复杂的代码来做“奇怪”的事情时,你的例子中肯定不是这种情况。

您是否真的尝试过使用 -S 选项进行优化来查看编译器做了什么?

当然,编译器可能不会优化这个特定的循环,因为 printf() 比所有循环加起来要重得多 - 但这是一个稍微不同的问题。

于 2012-12-31T08:21:41.323 回答
0

循环展开只是 GCC(至少在-O2or处-O3)完成的一项(在许多)优化中,它本身没有意义。(它仅通过其他优化有用,例如不断传播)。

而且您当然不能只想要一个源代码(想象许多宏可以扩展为for循环展开的循环)。

我建议您扩展 GCC 编译器,例如使用MELT,它是一种高级域特定语言来扩展 GCC

(或者,如果您有很多时间,可以痛苦地用 C 编写 GCC 插件)

然后你会在一些循环展开(和其他优化)传递之后添加一个传递,这将处理 Gimple 内部表示(你可以将 Gimple 理解为一种“最小”的 C 语言,只有基本操作 à lax = y + z;和调用和简单的测试,如if (x > y) goto l;) .

但我仍然不明白你想对结果做什么。如果您想进一步分析它,请处理(可能使用 MELT 中编码的另一遍)编译器内部的 GCC 内部表示。如果您想将该“展开”代码提供给某个外部工具,请编写一个转换通道,将 Gimple 转换为某种适当的格式。

于 2012-12-31T08:15:51.640 回答
0

您应该查看汇编器以了解编译器在循环展开中的实际性能。但是你也可以帮助你的编译器更好地编程:

for (unsigned i = 0; i < 3; ++i) {
  printf("hi\n");
}

即使用无符号整数类型作为循环变量(size_t通常是一个好主意)并且将循环变量设为本地。-S -O3 -march=native然后使用编译器选项之类的东西检查汇编器。

然后,只有这样,如果您对结果不满意,请查看P99。它有一组宏来进行展开,而不仅仅是 for 循环。寻找类似的东西P99_FOR

于 2012-12-31T08:17:32.233 回答