Я работаю над плагином для скалярной замены. У меня есть некоторые трудности с заявлением посетителя. Я хотел бы проанализировать инструкции, которые находятся в циклах, для каждой инструкции мне нужно знать, включена ли она в цикл, включен ли сам этот цикл или нет в другой цикл. Вот, например, простой пример моего vstmt_aux:
method! vstmt_aux s =
match s.skind with
| Loop(_, body, l, _, _) -> begin
let lp = (fst l).Lexing.pos_lnum in
Format.printf "Find outer loop at line %d @.\n" lp;
let bst = body.bstmts in List.iter(fun vbody ->
match vbody.skind with
| Loop(_, subbody, lsub, _, _) -> begin
let ls = (fst lsub).Lexing.pos_lnum in
Format.printf "Find inner loop at line %d @.\n" ls;
let sub_st = subbody.bstmts in List.iter(fun ss_body ->
match ss_body.skind with
| Instr(ii) -> Format.printf "Find instruction %a inside inner loop. @.\n" Printer.pp_instr ii
| Loop(_, l_sub, lss, _, _) -> begin
let nss = (fst lss).Lexing.pos_lnum in
Format.printf "Find inner inner loop at line %d @.\n" nss;
let ss_st = l_sub.bstmts in List.iter(fun ss ->
match ss.skind with
| Instr(iii) -> Format.printf "Find instruction %a inner inner loop. @.\n" Printer.pp_instr iii
| _ -> ()
) ss_st
end
| _ -> ()
) sub_st;
end
| Instr(iloop) -> Format.printf "Find instruction %a inside outer loop. @.\n" Printer.pp_instr iloop
| _ -> ()
) bst;
Cil.SkipChildren
end
| Instr(i) -> Format.printf "Find instruction %a. @.\n" Printer.pp_instr i; Cil.SkipChildren
| _ -> Cil.DoChildren
И пример кода, который я хочу проанализировать:
void test(int ni, int nj, int nk, float alpha, float *tmp, float *A) {
int i, j, k;
for (i = 0; i < ni; i++)
for (j = 0; j < nk; j++)
A[i * nk + j] = (float) ((i*j+1) % ni) / ni;
for (i = 0; i < ni; i++)
for (j = 0; j < nj; j++) {
tmp[i * nj + j] = 0.0;
for (k = 0; k < nk; ++k)
tmp[i * nj + j] += alpha * A[i * nk + k] * A[i * nk + k];
}
}
Когда я запускаю этот скрипт для этого кода c, обнаруживается только инструкция A[i * nk + j] = (float) ((i*j+1) % ni) / ni;
.
Найти инструкцию * (A + (i * nk + j)) = (плавать) ((i * j + 1)% ni) / (плавать) ni; внутри внутренней петли.
Когда я использую DoChildren
вместо SkipChildren
в случае с шаблоном цикла, все инструкции внутри циклов обнаруживаются более одного раза. Например:
- инструкция
A[i * nk + j] = (float) ((i*j+1) % ni) / ni;
обнаруживается три раза:
Найти инструкцию * (A + (i * nk + j)) = (плавать) ((i * j + 1)% ni) / (плавать) ni; внутри внутренней петли.
Найти инструкцию * (A + (i * nk + j)) = (плавать) ((i * j + 1)% ni) / (плавать) ni; внутри внешней петли.
Найти инструкцию * (A + (i * nk + j)) = (плавать) ((i * j + 1)% ni) / (плавать) ni;.
, где верно только первое сообщение.
- инструкция
tmp[i * nj + j] = 0.0;
обнаруживается один раз, но выводимое сообщение неверно (пока эта инструкция находится во внутреннем цикле)
Найти инструкцию * (tmp + (i * nj + j)) = (float) 0.0 ;.
- то же самое происходит для инструкции
tmp[i * nj + j] += alpha * A[i * nk + k] * B[k * nj + j];
.
Когда я добавляю фигурные скобки вокруг инструкций каждого цикла плюс DoChildren, все инструкции обнаруживаются шаблоном | Instr(i) -> Format.printf "Find instruction %a. @.\n" Printer.pp_instr i; Cil.SkipChildren
.
У вас есть идеи, как я могу решить эту проблему?
Спасибо