Skip to content

Commit 4e198a6

Browse files
committed
LATX: add fast REP MOVSB/STOSB lowering
Signed-off-by: Lu Zeng <luzeng87@gmail.com>
1 parent dece35c commit 4e198a6

1 file changed

Lines changed: 160 additions & 0 deletions

File tree

target/i386/latx/translator/tr-mov.c

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,158 @@ static void load_step_to_reg_ir1(IR2_OPND *p_step_opnd, IR1_OPND *opnd_ir1)
645645
ra_free_temp(tmp_step);
646646
}
647647

648+
#ifdef TARGET_X86_64
649+
static bool tr_can_fast_rep_string_b(IR1_INST *pir1, IR1_OPCODE insn)
650+
{
651+
return CODEIS64 &&
652+
ir1_prefix(pir1) == dt_X86_PREFIX_REP &&
653+
pir1->info->id == insn &&
654+
pir1->info->x86.prefix[3] != 0x67;
655+
}
656+
657+
static void tr_emit_rep_string_df_guard(IR2_OPND label_slow)
658+
{
659+
IR2_OPND df_opnd = ra_alloc_itemp();
660+
IR2_OPND eflags_opnd = ra_alloc_eflags();
661+
662+
la_andi(df_opnd, eflags_opnd, 1 << DF_BIT_INDEX);
663+
la_bne(df_opnd, zero_ir2_opnd, label_slow);
664+
665+
ra_free_temp(df_opnd);
666+
}
667+
668+
static void tr_emit_finish_fast_rep_string(IR2_OPND ecx_opnd,
669+
IR2_OPND label_exit)
670+
{
671+
la_or(ecx_opnd, zero_ir2_opnd, zero_ir2_opnd);
672+
store_ireg_to_ir1(ecx_opnd, &rcx_ir1_opnd, false);
673+
la_b(label_exit);
674+
}
675+
676+
static bool tr_emit_fast_rep_movsb(IR1_INST *pir1, IR2_OPND rsi_opnd,
677+
IR2_OPND rdi_opnd, IR2_OPND rcx_opnd,
678+
IR2_OPND label_exit)
679+
{
680+
if (!tr_can_fast_rep_string_b(pir1, dt_X86_INS_MOVSB)) {
681+
return false;
682+
}
683+
684+
IR2_OPND label_slow = ra_alloc_label();
685+
IR2_OPND label_no_overlap = ra_alloc_label();
686+
IR2_OPND label_qword_done = ra_alloc_label();
687+
IR2_OPND label_qword_loop = ra_alloc_label();
688+
IR2_OPND label_tail_done = ra_alloc_label();
689+
IR2_OPND label_tail_loop = ra_alloc_label();
690+
IR2_OPND qwords = ra_alloc_itemp();
691+
IR2_OPND tail = ra_alloc_itemp();
692+
IR2_OPND value = ra_alloc_itemp();
693+
IR2_OPND overlap = ra_alloc_itemp();
694+
695+
tr_emit_rep_string_df_guard(label_slow);
696+
697+
la_bgeu(rsi_opnd, rdi_opnd, label_no_overlap);
698+
la_sub_d(overlap, rdi_opnd, rsi_opnd);
699+
la_bltu(overlap, rcx_opnd, label_slow);
700+
701+
la_label(label_no_overlap);
702+
la_srli_d(qwords, rcx_opnd, 3);
703+
la_andi(tail, rcx_opnd, 7);
704+
705+
la_beq(qwords, zero_ir2_opnd, label_qword_done);
706+
la_label(label_qword_loop);
707+
la_ld_d(value, rsi_opnd, 0);
708+
la_st_d(value, rdi_opnd, 0);
709+
la_addi_d(rsi_opnd, rsi_opnd, 8);
710+
la_addi_d(rdi_opnd, rdi_opnd, 8);
711+
la_addi_d(qwords, qwords, -1);
712+
la_bne(qwords, zero_ir2_opnd, label_qword_loop);
713+
714+
la_label(label_qword_done);
715+
la_beq(tail, zero_ir2_opnd, label_tail_done);
716+
la_label(label_tail_loop);
717+
la_ld_bu(value, rsi_opnd, 0);
718+
la_st_b(value, rdi_opnd, 0);
719+
la_addi_d(rsi_opnd, rsi_opnd, 1);
720+
la_addi_d(rdi_opnd, rdi_opnd, 1);
721+
la_addi_d(tail, tail, -1);
722+
la_bne(tail, zero_ir2_opnd, label_tail_loop);
723+
724+
la_label(label_tail_done);
725+
tr_emit_finish_fast_rep_string(rcx_opnd, label_exit);
726+
727+
la_label(label_slow);
728+
729+
ra_free_temp(qwords);
730+
ra_free_temp(tail);
731+
ra_free_temp(value);
732+
ra_free_temp(overlap);
733+
return true;
734+
}
735+
736+
static void tr_replicate_byte_to_dword(IR2_OPND dst, IR2_OPND src,
737+
IR2_OPND tmp)
738+
{
739+
la_andi(dst, src, 0xff);
740+
la_slli_d(tmp, dst, 8);
741+
la_or(dst, dst, tmp);
742+
la_slli_d(tmp, dst, 16);
743+
la_or(dst, dst, tmp);
744+
la_slli_d(tmp, dst, 32);
745+
la_or(dst, dst, tmp);
746+
}
747+
748+
static bool tr_emit_fast_rep_stosb(IR1_INST *pir1, IR2_OPND rdi_opnd,
749+
IR2_OPND rcx_opnd, IR2_OPND value_opnd,
750+
IR2_OPND label_exit)
751+
{
752+
if (!tr_can_fast_rep_string_b(pir1, dt_X86_INS_STOSB)) {
753+
return false;
754+
}
755+
756+
IR2_OPND label_slow = ra_alloc_label();
757+
IR2_OPND label_qword_done = ra_alloc_label();
758+
IR2_OPND label_qword_loop = ra_alloc_label();
759+
IR2_OPND label_tail_done = ra_alloc_label();
760+
IR2_OPND label_tail_loop = ra_alloc_label();
761+
IR2_OPND qwords = ra_alloc_itemp();
762+
IR2_OPND tail = ra_alloc_itemp();
763+
IR2_OPND fill = ra_alloc_itemp();
764+
IR2_OPND tmp = ra_alloc_itemp();
765+
766+
tr_emit_rep_string_df_guard(label_slow);
767+
768+
tr_replicate_byte_to_dword(fill, value_opnd, tmp);
769+
la_srli_d(qwords, rcx_opnd, 3);
770+
la_andi(tail, rcx_opnd, 7);
771+
772+
la_beq(qwords, zero_ir2_opnd, label_qword_done);
773+
la_label(label_qword_loop);
774+
la_st_d(fill, rdi_opnd, 0);
775+
la_addi_d(rdi_opnd, rdi_opnd, 8);
776+
la_addi_d(qwords, qwords, -1);
777+
la_bne(qwords, zero_ir2_opnd, label_qword_loop);
778+
779+
la_label(label_qword_done);
780+
la_beq(tail, zero_ir2_opnd, label_tail_done);
781+
la_label(label_tail_loop);
782+
la_st_b(fill, rdi_opnd, 0);
783+
la_addi_d(rdi_opnd, rdi_opnd, 1);
784+
la_addi_d(tail, tail, -1);
785+
la_bne(tail, zero_ir2_opnd, label_tail_loop);
786+
787+
la_label(label_tail_done);
788+
tr_emit_finish_fast_rep_string(rcx_opnd, label_exit);
789+
790+
la_label(label_slow);
791+
792+
ra_free_temp(qwords);
793+
ra_free_temp(tail);
794+
ra_free_temp(fill);
795+
ra_free_temp(tmp);
796+
return true;
797+
}
798+
#endif
799+
648800
bool translate_movs(IR1_INST *pir1)
649801
{
650802
IR2_OPND esi_opnd = ra_alloc_gpr(esi_index);
@@ -769,6 +921,10 @@ bool translate_movs(IR1_INST *pir1)
769921
lsassert(0);
770922
}
771923

924+
#ifdef TARGET_X86_64
925+
tr_emit_fast_rep_movsb(pir1, esi_opnd, edi_opnd, ecx_opnd, label_exit);
926+
#endif
927+
772928
/* 2. preparations outside the loop */
773929
IR2_OPND step_opnd = ra_alloc_itemp();
774930
load_step_to_reg_ir1(&step_opnd, mem_di);
@@ -970,6 +1126,10 @@ bool translate_stos(IR1_INST *pir1)
9701126
}
9711127
IR2_OPND eax_value_opnd =
9721128
load_ireg_from_ir1(opnd_eax, SIGN_EXTENSION, false);
1129+
#ifdef TARGET_X86_64
1130+
tr_emit_fast_rep_stosb(pir1, edi_opnd, ecx_opnd, eax_value_opnd,
1131+
label_exit);
1132+
#endif
9731133
IR2_OPND step_opnd = ra_alloc_itemp();
9741134
load_step_to_reg_ir1(&step_opnd, opnd_di);
9751135

0 commit comments

Comments
 (0)