这实际上是不可能得到GCC产生的,因为在OpenMP的扩展程序的一段代码的for
指令扩张的结果GOMP_loop_static_start
通话快捷键schedule(static)
情况:
3123 static void
3124 expand_omp_for (struct omp_region *region)
3125 {
3126 struct omp_for_data fd;
3127
3128 push_gimplify_context();
3129
3130 extract_omp_for_data (last_stmt (region->entry), &fd);
3131 region->sched_kind = fd.sched_kind;
3132
3133 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3134 && !fd.have_ordered
3135 && region->cont
3136 && region->exit)
3137 {
3138 if (fd.chunk_size == NULL)
3139 expand_omp_for_static_nochunk (region, &fd);
3140 else
3141 expand_omp_for_static_chunk (region, &fd);
3142 }
3143 else
3144 {
3145 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3146 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3147 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3148 expand_omp_for_generic (region, &fd, start_ix, next_ix);
3149 }
3150
3151 pop_gimplify_context (NULL);
3152 }
上面的代码来自GCC 4.2.0,这是第一个正式引入OpenMP支持的版本。自那时以来,事情并没有多大变化(只有OpenMP标准的每个新版本都变得复杂得多)。 extract_omp_for_data()
分析for
指令和相关的for
循环。它放置了在fd.sched_kind
中找到的那种循环调度。如果没有提供schedule
子句,则它使用GCC schedule(static)
的默认值。 expand_omp_for_static_nochunk()
和expand_omp_for_static_chunk()
都不会拨打电话GOMP_loop_static_start
。相反,他们发出一个使用omp_get_num_threads()
和omp_get_thread_num()
计算迭代空间为每个线程代码:
#pragma omp for
for (int i = 0; i < steps; i++)
...
变为:
<bb 2>:
i = 0;
steps.0 = steps;
D.1368 = __builtin_omp_get_num_threads();
D.1369 = __builtin_omp_get_thread_num();
q.1 = steps.0/D.1368;
tt.2 = steps.0 % D.1368;
if (D.1369 < tt.2)
goto <bb 3>;
else
goto <bb 4>;
<bb 3>:
tt.2 = 0;
q.1 = q.1 + 1;
<bb 4>:
D.1372 = q.1 * D.1369;
D.1373 = D.1372 + tt.2;
D.1374 = D.1373 + q.1;
if (D.1373 >= D.1374)
goto <bb 7>;
else
goto <bb 5>;
<bb 5>:
i = D.1373;
<bb 6>:
...
i = i + 1;
if (i < D.1374)
goto <bb 6>;
else
goto <bb 7>;
<bb 7>:
__builtin_GOMP_barrier();
只有expand_omp_for_generic()
可以发出调用GOMP_loop_static_start
代码。为此,执行流程必须输入else
区块,如果循环时间表不是静态的,或者应用了ordered
子句。在前一种情况下,将会调用另一个GOMP_loop_xxx_start()
。在后一种情况下,GOMP_loop_ordered_static_start()
将被调用。
唯一的剩余选项是该区域没有延续(OMP_CONTINUE
)或退出(OMP_RETURN
)块。我认为没有办法实现这一点,因为两个块总是由降低OpenMP for
指令的代码添加。后期版本的编译器删除了退出块的检查,但对我而言仍然不明显,继续块如何被删除。
您可以查看英特尔贡献的Clang的OSS运行时。它应该实现GOMP接口,但不受GPL病毒的阻碍,所以你可以用衍生作品做你想做的事情。 – Jeff