@@ -301,11 +301,11 @@ static block_t *block_alloc(riscv_t *rv)
301
301
block_t * block = mpool_alloc (rv -> block_mp );
302
302
assert (block );
303
303
block -> n_insn = 0 ;
304
- block -> predict = NULL ;
305
304
#if RV32_HAS (JIT )
306
305
block -> translatable = true;
307
306
block -> hot = false;
308
307
block -> backward = false;
308
+ INIT_LIST_HEAD (& block -> list );
309
309
#endif
310
310
return block ;
311
311
}
@@ -979,6 +979,49 @@ static block_t *block_find_or_translate(riscv_t *rv)
979
979
/* insert the block into block cache */
980
980
block_t * delete_target = cache_put (rv -> block_cache , rv -> PC , & (* next ));
981
981
if (delete_target ) {
982
+ if (prev == delete_target )
983
+ prev = NULL ;
984
+ chain_entry_t * entry , * safe ;
985
+ /* correctly remove deleted block from its chained block */
986
+ rv_insn_t * taken = delete_target -> ir_tail -> branch_taken ,
987
+ * untaken = delete_target -> ir_tail -> branch_untaken ;
988
+ if (taken && taken -> pc != delete_target -> pc_start ) {
989
+ block_t * target = cache_get (rv -> block_cache , taken -> pc );
990
+ bool flag = false;
991
+ list_for_each_entry_safe (entry , safe , & target -> list , list ) {
992
+ if (entry -> block == delete_target ) {
993
+ list_del_init (& entry -> list );
994
+ mpool_free (rv -> chain_entry_mp , entry );
995
+ flag = true;
996
+ }
997
+ }
998
+ assert (flag );
999
+ }
1000
+ if (untaken && untaken -> pc != delete_target -> pc_start ) {
1001
+ block_t * target = cache_get (rv -> block_cache , untaken -> pc );
1002
+ assert (target );
1003
+ bool flag = false;
1004
+ list_for_each_entry_safe (entry , safe , & target -> list , list ) {
1005
+ if (entry -> block == delete_target ) {
1006
+ list_del_init (& entry -> list );
1007
+ mpool_free (rv -> chain_entry_mp , entry );
1008
+ flag = true;
1009
+ }
1010
+ }
1011
+ assert (flag );
1012
+ }
1013
+ /* correctly remove deleted block from the block chained to it */
1014
+ list_for_each_entry_safe (entry , safe , & delete_target -> list , list ) {
1015
+ if (entry -> block == delete_target )
1016
+ continue ;
1017
+ rv_insn_t * target = entry -> block -> ir_tail ;
1018
+ if (target -> branch_taken == delete_target -> ir_head )
1019
+ target -> branch_taken = NULL ;
1020
+ else if (target -> branch_untaken == delete_target -> ir_head )
1021
+ target -> branch_untaken = NULL ;
1022
+ mpool_free (rv -> chain_entry_mp , entry );
1023
+ }
1024
+ /* free deleted block */
982
1025
uint32_t idx ;
983
1026
rv_insn_t * ir , * next ;
984
1027
for (idx = 0 , ir = delete_target -> ir_head ;
@@ -990,13 +1033,6 @@ static block_t *block_find_or_translate(riscv_t *rv)
990
1033
mpool_free (rv -> block_mp , delete_target );
991
1034
}
992
1035
#endif
993
- /* update the block prediction.
994
- * When translating a new block, the block predictor may benefit,
995
- * but updating it after finding a particular block may penalize
996
- * significantly.
997
- */
998
- if (prev )
999
- prev -> predict = next ;
1000
1036
}
1001
1037
1002
1038
return next ;
@@ -1015,17 +1051,18 @@ void rv_step(riscv_t *rv, int32_t cycles)
1015
1051
1016
1052
/* loop until hitting the cycle target */
1017
1053
while (rv -> csr_cycle < cycles_target && !rv -> halt ) {
1018
- block_t * block ;
1019
- /* try to predict the next block */
1020
- if (prev && prev -> predict && prev -> predict -> pc_start == rv -> PC ) {
1021
- block = prev -> predict ;
1022
- } else {
1023
- /* lookup the next block in block map or translate a new block,
1024
- * and move onto the next block.
1025
- */
1026
- block = block_find_or_translate (rv );
1054
+ if (prev && prev -> pc_start != last_pc ) {
1055
+ /* update previous block */
1056
+ #if !RV32_HAS (JIT )
1057
+ prev = block_find (& rv -> block_map , last_pc );
1058
+ #else
1059
+ prev = cache_get (rv -> block_cache , last_pc );
1060
+ #endif
1027
1061
}
1028
-
1062
+ /* lookup the next block in block map or translate a new block,
1063
+ * and move onto the next block.
1064
+ */
1065
+ block_t * block = block_find_or_translate (rv );
1029
1066
/* by now, a block should be available */
1030
1067
assert (block );
1031
1068
@@ -1034,28 +1071,38 @@ void rv_step(riscv_t *rv, int32_t cycles)
1034
1071
* assigned to either the branch_taken or branch_untaken pointer of
1035
1072
* the previous block.
1036
1073
*/
1074
+
1037
1075
if (prev ) {
1038
- /* update previous block */
1039
- if (prev -> pc_start != last_pc )
1040
- #if !RV32_HAS (JIT )
1041
- prev = block_find (& rv -> block_map , last_pc );
1042
- #else
1043
- prev = cache_get (rv -> block_cache , last_pc );
1076
+ rv_insn_t * last_ir = prev -> ir_tail ;
1077
+ /* chain block */
1078
+ if (!insn_is_unconditional_branch (last_ir -> opcode )) {
1079
+ if (is_branch_taken && !last_ir -> branch_taken ) {
1080
+ last_ir -> branch_taken = block -> ir_head ;
1081
+ #if RV32_HAS (JIT )
1082
+ chain_entry_t * new_entry = mpool_alloc (rv -> chain_entry_mp );
1083
+ new_entry -> block = prev ;
1084
+ list_add (& new_entry -> list , & block -> list );
1044
1085
#endif
1045
- if (prev ) {
1046
- rv_insn_t * last_ir = prev -> ir_tail ;
1047
- /* chain block */
1048
- if (! insn_is_unconditional_branch ( last_ir -> opcode )) {
1049
- if ( is_branch_taken )
1050
- last_ir -> branch_taken = block -> ir_head ;
1051
- else if (! is_branch_taken )
1052
- last_ir -> branch_untaken = block -> ir_head ;
1053
- } else if (IF_insn (last_ir , jal )
1086
+ } else if (! is_branch_taken && ! last_ir -> branch_untaken ) {
1087
+ last_ir -> branch_untaken = block -> ir_head ;
1088
+ #if RV32_HAS ( JIT )
1089
+ chain_entry_t * new_entry = mpool_alloc ( rv -> chain_entry_mp );
1090
+ new_entry -> block = prev ;
1091
+ list_add ( & new_entry -> list , & block -> list ) ;
1092
+ #endif
1093
+ }
1094
+ } else if (IF_insn (last_ir , jal )
1054
1095
#if RV32_HAS (EXT_C )
1055
- || IF_insn (last_ir , cj ) || IF_insn (last_ir , cjal )
1096
+ || IF_insn (last_ir , cj ) || IF_insn (last_ir , cjal )
1056
1097
#endif
1057
- ) {
1098
+ ) {
1099
+ if (!last_ir -> branch_taken ) {
1058
1100
last_ir -> branch_taken = block -> ir_head ;
1101
+ #if RV32_HAS (JIT )
1102
+ chain_entry_t * new_entry = mpool_alloc (rv -> chain_entry_mp );
1103
+ new_entry -> block = prev ;
1104
+ list_add (& new_entry -> list , & block -> list );
1105
+ #endif
1059
1106
}
1060
1107
}
1061
1108
}
0 commit comments