Я пытаюсь пропатчить gcc, чтобы после fdivd регистр назначения
хранится в стеке, то есть:
fdivd% f0,% f2,% f4; => становится
fdivd% f0,% f2,% f4; стандартный% f4, [% fp + ...]
Я генерирую RTL для divdf3 с использованием последовательности (emit_insn, DONE) в
шаблон define_expand (см. ниже).
В фазе вывода ассемблера я использую define_insn и пишу
out "fdivd \ t %% 1, %% 2, %% 0; std %% 0, %% 3" в качестве строки выражения.
Сгенерированный код вроде бы в порядке. Тем не менее:
Мой вопрос:
Как я могу пометить шаблон так, чтобы не был запланирован в
слот задержки ? Как можно указать, что на выходе будет 2 инструкции
а намекнуть на это планировщику?
Является ли атрибут (set_attr "length" "2") в define_insn divdf3_store
(ниже) уже достаточно?
- Привет Конрад
-------------- changed sparc.md -------------------------
;;;;;;;;;;;;;;;;;; handle divdf3 ;;;;;;;;;;;;;;;;
(define_expand "divdf3"
[(parallel [(set (match_operand:DF 0 "register_operand" "=e")
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))
(clobber (match_scratch:SI 3 ""))])]
"TARGET_FPU"
"{
output_divdf3_emit (operands[0], operands[1], operands[2], operands[3]);
DONE;
}")
(define_insn "divdf3_store"
[(set (match_operand:DF 0 "register_operand" "=e")
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))
(clobber (match_operand:DF 3 "memory_operand" "" ))]
"TARGET_FPU && TARGET_STORE_AFTER_DIVSQRT"
{
return output_divdf3 (operands[0], operands[1], operands[2], operands[3]);
}
[(set_attr "type" "fpdivd")
(set_attr "fptype" "double")
(set_attr "length" "2")])
(define_insn "divdf3_nostore"
[(set (match_operand:DF 0 "register_operand" "=e")
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU && (!TARGET_STORE_AFTER_DIVSQRT)"
"fdivd\t%1, %2, %0"
[(set_attr "type" "fpdivd")
(set_attr "fptype" "double")])
-------------- changed sparc.c -------------------------
/**************************** handle fdivd ****************************/
char *
output_divdf3 (rtx op0, rtx op1, rtx dest, rtx scratch)
{
static char string[128];
if (debug_patch_divsqrt) {
fprintf(stderr, "debug_patch_divsqrt:\n");
debug_rtx(op0);
debug_rtx(op1);
debug_rtx(dest);
fprintf(stderr, "scratch: 0x%x\n",(int)scratch);
}
sprintf(string,"fdivd\t%%1, %%2, %%0; std %%0, %%3 !!!");
return string;
}
void
output_divdf3_emit (rtx dest, rtx op0, rtx op1, rtx scratch)
{
rtx slot0, div, divsave;
if (debug_patch_divsqrt) {
fprintf(stderr, "output_divdf3_emit:\n");
debug_rtx(op0);
debug_rtx(op1);
debug_rtx(dest);
fprintf(stderr, "scratch: 0x%x\n",(int)scratch);
}
div = gen_rtx_SET (VOIDmode,
dest,
gen_rtx_DIV (DFmode,
op0,
op1));
if (TARGET_STORE_AFTER_DIVSQRT) {
slot0 = assign_stack_local (DFmode, 8, 8);
divsave = gen_rtx_SET (VOIDmode, slot0, dest);
emit_insn(divsave);
emit_insn (gen_rtx_PARALLEL(VOIDmode,
gen_rtvec (2,
div,
gen_rtx_CLOBBER (SImode,
slot0))));
} else {
emit_insn(div);
}
}