如何避免insn beeing计划进入延迟槽 [英] How to avoid insn beeing scheduled into a delay slot
问题描述
我尝试修补gcc,以便在fdivd之后,目标寄存器是存储到堆栈的
,即:
fdivd%f0,%f2, F4%; =>变为
fdivd%f0,%f2,%f4; std%f4,[%fp + ...]
我使用
define_expand模式中的(emit_insn,DONE)序列为divdf3生成rtl(请参阅下面)。
在汇编输出阶段,我使用define_insn并将
写入fdivd\t %% 1,%% 2,%% 0 ; std %% 0,%% 3作为表达式字符串。
生成的代码似乎没问题。但是:
我的问题:
我该如何标记模式,以便 <不要将它们放在
延迟插槽中 ?我怎样才能指定输出为2条指令
并提示调度器呢?
define_insn divdf3_store
(below)中的(set_attrlength2)属性已经足够了吗?
- Konrad Konrad p>
-------------- changed sparc.md ---------- ---------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;处理divdf3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_expanddivdf3
[(parallel [(set(match_operand:DF 0register_operand= e)
(div:DF(match_operand:DF 1register_operande )
(match_operand:DF 2register_operande)))
(clobber(match_scratch:SI 3))])]
TARGET_FPU
{
output_divdf3_emit(操作数[0],操作数[1],操作数[2],操作数[3]);
DONE;
})
define_insndivdf3_store
((match_operand:DF 0register_operand= e)
(div:DF(match_operand:DF 1register_operande)
(match_operand :DF 2register_operande)))
(clobber(match_operand:DF 3memory_operand))]
TARGET_FPU&&& TARGET_STORE_AFTER_DIVSQRT
{
返回output_divdf3(操作数[0],操作数[1],操作数[2],操作数[3]);
}
[(set_attrtypefpdivd)
set_attrfptypedouble)
(s ($)
$($ {$'$'$'$' DF(match_operand:DF 1register_operande)
(match_operand:DF 2register_operande)))]
TARGET_FPU&& (!TARGET_STORE_AFTER_DIVSQRT)
fdivd\t%1,%2,%0
[(set_attrtypefpdivd)
(set_attrfptypedouble) ])
-------------- changed sparc.c -------------- -----------
/ ****************************处理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:\\\
);
debug_rtx (op0);
debug_rtx(op1);
debug_rtx(dest);
fprintf(stderr,scratch:0x%x\\\
,(int)scratch);
}
sprintf(字符串,fdivd\t %% 1,%% 2,%% 0; std %% 0,%% 3 !!!);
返回字符串;
$ b $ 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:\\\
);
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)); (TARGET_STORE_AFTER_DIVSQRT){
slot0 = assign_stack_local(DFmode,8,8);
if(TARGET_STORE_AFTER_DIVSQRT)
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);
}
}
I第二Laurynas。对于这样一个精确的问题,gcc@gcc.gnu.org将会非常有帮助。
I try to patch gcc so that after a fdivd the destination register is stored to the stack,i.e:
fdivd %f0, %f2, %f4; => becomes fdivd %f0, %f2, %f4; std %f4, [%fp+...]
I generate the rtl for divdf3 using a (emit_insn,DONE) sequence in a define_expand pattern (see below).
In the assembler output phase I use a define_insn and write out "fdivd\t%%1, %%2, %%0; std %%0, %%3" as the expression string.
The code generated seems to be ok. However:
My question:
How can I mark the pattern so, that it will not be sheduled into a delay slot? How can I specify that the output will be 2 instructions and hint the scheduler about it? Is the (set_attr "length" "2") attribute in define_insn divdf3_store (below) already sufficient?
-- Greetings Konrad
-------------- 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);
}
}
I second Laurynas. For such a precise question, gcc@gcc.gnu.org will be very helpful.
这篇关于如何避免insn beeing计划进入延迟槽的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!