@ -3033,10 +3033,6 @@ void tcg_op_remove(TCGContext *s, TCGOp *op)
QTAILQ_REMOVE ( & s - > ops , op , link ) ;
QTAILQ_INSERT_TAIL ( & s - > free_ops , op , link ) ;
s - > nb_ops - - ;
# ifdef CONFIG_PROFILER
qatomic_set ( & s - > prof . del_op_count , s - > prof . del_op_count + 1 ) ;
# endif
}
void tcg_remove_ops_after ( TCGOp * op )
@ -5906,143 +5902,16 @@ static void tcg_out_st_helper_args(TCGContext *s, const TCGLabelQemuLdst *ldst,
tcg_out_helper_load_common_args ( s , ldst , parm , info , next_arg ) ;
}
# ifdef CONFIG_PROFILER
/* avoid copy/paste errors */
# define PROF_ADD(to, from, field) \
do { \
( to ) - > field + = qatomic_read ( & ( ( from ) - > field ) ) ; \
} while ( 0 )
# define PROF_MAX(to, from, field) \
do { \
typeof ( ( from ) - > field ) val__ = qatomic_read ( & ( ( from ) - > field ) ) ; \
if ( val__ > ( to ) - > field ) { \
( to ) - > field = val__ ; \
} \
} while ( 0 )
/* Pass in a zero'ed @prof */
static inline
void tcg_profile_snapshot ( TCGProfile * prof , bool counters , bool table )
{
unsigned int n_ctxs = qatomic_read ( & tcg_cur_ctxs ) ;
unsigned int i ;
for ( i = 0 ; i < n_ctxs ; i + + ) {
TCGContext * s = qatomic_read ( & tcg_ctxs [ i ] ) ;
const TCGProfile * orig = & s - > prof ;
if ( counters ) {
PROF_ADD ( prof , orig , cpu_exec_time ) ;
PROF_ADD ( prof , orig , tb_count1 ) ;
PROF_ADD ( prof , orig , tb_count ) ;
PROF_ADD ( prof , orig , op_count ) ;
PROF_MAX ( prof , orig , op_count_max ) ;
PROF_ADD ( prof , orig , temp_count ) ;
PROF_MAX ( prof , orig , temp_count_max ) ;
PROF_ADD ( prof , orig , del_op_count ) ;
PROF_ADD ( prof , orig , code_in_len ) ;
PROF_ADD ( prof , orig , code_out_len ) ;
PROF_ADD ( prof , orig , search_out_len ) ;
PROF_ADD ( prof , orig , interm_time ) ;
PROF_ADD ( prof , orig , code_time ) ;
PROF_ADD ( prof , orig , la_time ) ;
PROF_ADD ( prof , orig , opt_time ) ;
PROF_ADD ( prof , orig , restore_count ) ;
PROF_ADD ( prof , orig , restore_time ) ;
}
if ( table ) {
int i ;
for ( i = 0 ; i < NB_OPS ; i + + ) {
PROF_ADD ( prof , orig , table_op_count [ i ] ) ;
}
}
}
}
# undef PROF_ADD
# undef PROF_MAX
static void tcg_profile_snapshot_counters ( TCGProfile * prof )
{
tcg_profile_snapshot ( prof , true , false ) ;
}
static void tcg_profile_snapshot_table ( TCGProfile * prof )
{
tcg_profile_snapshot ( prof , false , true ) ;
}
void tcg_dump_op_count ( GString * buf )
{
TCGProfile prof = { } ;
int i ;
tcg_profile_snapshot_table ( & prof ) ;
for ( i = 0 ; i < NB_OPS ; i + + ) {
g_string_append_printf ( buf , " %s % " PRId64 " \n " , tcg_op_defs [ i ] . name ,
prof . table_op_count [ i ] ) ;
}
}
int64_t tcg_cpu_exec_time ( void )
{
unsigned int n_ctxs = qatomic_read ( & tcg_cur_ctxs ) ;
unsigned int i ;
int64_t ret = 0 ;
for ( i = 0 ; i < n_ctxs ; i + + ) {
const TCGContext * s = qatomic_read ( & tcg_ctxs [ i ] ) ;
const TCGProfile * prof = & s - > prof ;
ret + = qatomic_read ( & prof - > cpu_exec_time ) ;
}
return ret ;
}
# else
void tcg_dump_op_count ( GString * buf )
{
g_string_append_printf ( buf , " [TCG profiler not compiled] \n " ) ;
}
int64_t tcg_cpu_exec_time ( void )
{
error_report ( " %s: TCG profiler not compiled " , __func__ ) ;
exit ( EXIT_FAILURE ) ;
}
# endif
int tcg_gen_code ( TCGContext * s , TranslationBlock * tb , uint64_t pc_start )
{
# ifdef CONFIG_PROFILER
TCGProfile * prof = & s - > prof ;
# endif
int i , start_words , num_insns ;
TCGOp * op ;
# ifdef CONFIG_PROFILER
{
int n = 0 ;
QTAILQ_FOREACH ( op , & s - > ops , link ) {
n + + ;
}
qatomic_set ( & prof - > op_count , prof - > op_count + n ) ;
if ( n > prof - > op_count_max ) {
qatomic_set ( & prof - > op_count_max , n ) ;
}
n = s - > nb_temps ;
qatomic_set ( & prof - > temp_count , prof - > temp_count + n ) ;
if ( n > prof - > temp_count_max ) {
qatomic_set ( & prof - > temp_count_max , n ) ;
}
}
# endif
if ( unlikely ( qemu_loglevel_mask ( CPU_LOG_TB_OP )
& & qemu_log_in_addr_range ( pc_start ) ) ) {
FILE * logfile = qemu_log_trylock ( ) ;
@ -6071,17 +5940,8 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
}
# endif
# ifdef CONFIG_PROFILER
qatomic_set ( & prof - > opt_time , prof - > opt_time - profile_getclock ( ) ) ;
# endif
tcg_optimize ( s ) ;
# ifdef CONFIG_PROFILER
qatomic_set ( & prof - > opt_time , prof - > opt_time + profile_getclock ( ) ) ;
qatomic_set ( & prof - > la_time , prof - > la_time - profile_getclock ( ) ) ;
# endif
reachable_code_pass ( s ) ;
liveness_pass_0 ( s ) ;
liveness_pass_1 ( s ) ;
@ -6105,10 +5965,6 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
}
}
# ifdef CONFIG_PROFILER
qatomic_set ( & prof - > la_time , prof - > la_time + profile_getclock ( ) ) ;
# endif
if ( unlikely ( qemu_loglevel_mask ( CPU_LOG_TB_OP_OPT )
& & qemu_log_in_addr_range ( pc_start ) ) ) {
FILE * logfile = qemu_log_trylock ( ) ;
@ -6151,10 +6007,6 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
QTAILQ_FOREACH ( op , & s - > ops , link ) {
TCGOpcode opc = op - > opc ;
# ifdef CONFIG_PROFILER
qatomic_set ( & prof - > table_op_count [ opc ] , prof - > table_op_count [ opc ] + 1 ) ;
# endif
switch ( opc ) {
case INDEX_op_mov_i32 :
case INDEX_op_mov_i64 :
@ -6249,76 +6101,10 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
return tcg_current_code_size ( s ) ;
}
# ifdef CONFIG_PROFILER
void tcg_dump_info ( GString * buf )
{
TCGProfile prof = { } ;
const TCGProfile * s ;
int64_t tb_count ;
int64_t tb_div_count ;
int64_t tot ;
tcg_profile_snapshot_counters ( & prof ) ;
s = & prof ;
tb_count = s - > tb_count ;
tb_div_count = tb_count ? tb_count : 1 ;
tot = s - > interm_time + s - > code_time ;
g_string_append_printf ( buf , " JIT cycles % " PRId64
" (%0.3f s at 2.4 GHz) \n " ,
tot , tot / 2.4e9 ) ;
g_string_append_printf ( buf , " translated TBs % " PRId64
" (aborted=% " PRId64 " %0.1f%%) \n " ,
tb_count , s - > tb_count1 - tb_count ,
( double ) ( s - > tb_count1 - s - > tb_count )
/ ( s - > tb_count1 ? s - > tb_count1 : 1 ) * 100.0 ) ;
g_string_append_printf ( buf , " avg ops/TB %0.1f max=%d \n " ,
( double ) s - > op_count / tb_div_count , s - > op_count_max ) ;
g_string_append_printf ( buf , " deleted ops/TB %0.2f \n " ,
( double ) s - > del_op_count / tb_div_count ) ;
g_string_append_printf ( buf , " avg temps/TB %0.2f max=%d \n " ,
( double ) s - > temp_count / tb_div_count ,
s - > temp_count_max ) ;
g_string_append_printf ( buf , " avg host code/TB %0.1f \n " ,
( double ) s - > code_out_len / tb_div_count ) ;
g_string_append_printf ( buf , " avg search data/TB %0.1f \n " ,
( double ) s - > search_out_len / tb_div_count ) ;
g_string_append_printf ( buf , " cycles/op %0.1f \n " ,
s - > op_count ? ( double ) tot / s - > op_count : 0 ) ;
g_string_append_printf ( buf , " cycles/in byte %0.1f \n " ,
s - > code_in_len ? ( double ) tot / s - > code_in_len : 0 ) ;
g_string_append_printf ( buf , " cycles/out byte %0.1f \n " ,
s - > code_out_len ? ( double ) tot / s - > code_out_len : 0 ) ;
g_string_append_printf ( buf , " cycles/search byte %0.1f \n " ,
s - > search_out_len ?
( double ) tot / s - > search_out_len : 0 ) ;
if ( tot = = 0 ) {
tot = 1 ;
}
g_string_append_printf ( buf , " gen_interm time %0.1f%% \n " ,
( double ) s - > interm_time / tot * 100.0 ) ;
g_string_append_printf ( buf , " gen_code time %0.1f%% \n " ,
( double ) s - > code_time / tot * 100.0 ) ;
g_string_append_printf ( buf , " optim./code time %0.1f%% \n " ,
( double ) s - > opt_time / ( s - > code_time ?
s - > code_time : 1 )
* 100.0 ) ;
g_string_append_printf ( buf , " liveness/code time %0.1f%% \n " ,
( double ) s - > la_time / ( s - > code_time ?
s - > code_time : 1 ) * 100.0 ) ;
g_string_append_printf ( buf , " cpu_restore count % " PRId64 " \n " ,
s - > restore_count ) ;
g_string_append_printf ( buf , " avg cycles %0.1f \n " ,
s - > restore_count ?
( double ) s - > restore_time / s - > restore_count : 0 ) ;
}
# else
void tcg_dump_info ( GString * buf )
{
g_string_append_printf ( buf , " [TCG profiler not compiled] \n " ) ;
}
# endif
# ifdef ELF_HOST_MACHINE
/* In order to use this feature, the backend needs to do three things: