Commit c6e113f5680538a551f79df3ab19b69aed628521
1 parent
0b6ce4cf
added 'pure' function attribute - fixed indirect function calls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4469 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
46 additions
and
23 deletions
tcg/tcg.c
... | ... | @@ -946,32 +946,51 @@ void tcg_liveness_analysis(TCGContext *s) |
946 | 946 | def = &tcg_op_defs[op]; |
947 | 947 | switch(op) { |
948 | 948 | case INDEX_op_call: |
949 | - nb_args = args[-1]; | |
950 | - args -= nb_args; | |
951 | - nb_iargs = args[0] & 0xffff; | |
952 | - nb_oargs = args[0] >> 16; | |
953 | - args++; | |
949 | + { | |
950 | + int call_flags; | |
954 | 951 | |
955 | - /* output args are dead */ | |
956 | - for(i = 0; i < nb_oargs; i++) { | |
957 | - arg = args[i]; | |
958 | - dead_temps[arg] = 1; | |
959 | - } | |
960 | - | |
961 | - /* globals are live (they may be used by the call) */ | |
962 | - memset(dead_temps, 0, s->nb_globals); | |
952 | + nb_args = args[-1]; | |
953 | + args -= nb_args; | |
954 | + nb_iargs = args[0] & 0xffff; | |
955 | + nb_oargs = args[0] >> 16; | |
956 | + args++; | |
957 | + call_flags = args[nb_oargs + nb_iargs]; | |
958 | + | |
959 | + /* pure functions can be removed if their result is not | |
960 | + used */ | |
961 | + if (call_flags & TCG_CALL_PURE) { | |
962 | + for(i = 0; i < nb_oargs; i++) { | |
963 | + arg = args[i]; | |
964 | + if (!dead_temps[arg]) | |
965 | + goto do_not_remove_call; | |
966 | + } | |
967 | + tcg_set_nop(s, gen_opc_buf + op_index, | |
968 | + args - 1, nb_args); | |
969 | + } else { | |
970 | + do_not_remove_call: | |
963 | 971 | |
964 | - /* input args are live */ | |
965 | - dead_iargs = 0; | |
966 | - for(i = 0; i < nb_iargs; i++) { | |
967 | - arg = args[i + nb_oargs]; | |
968 | - if (dead_temps[arg]) { | |
969 | - dead_iargs |= (1 << i); | |
972 | + /* output args are dead */ | |
973 | + for(i = 0; i < nb_oargs; i++) { | |
974 | + arg = args[i]; | |
975 | + dead_temps[arg] = 1; | |
976 | + } | |
977 | + | |
978 | + /* globals are live (they may be used by the call) */ | |
979 | + memset(dead_temps, 0, s->nb_globals); | |
980 | + | |
981 | + /* input args are live */ | |
982 | + dead_iargs = 0; | |
983 | + for(i = 0; i < nb_iargs; i++) { | |
984 | + arg = args[i + nb_oargs]; | |
985 | + if (dead_temps[arg]) { | |
986 | + dead_iargs |= (1 << i); | |
987 | + } | |
988 | + dead_temps[arg] = 0; | |
989 | + } | |
990 | + s->op_dead_iargs[op_index] = dead_iargs; | |
970 | 991 | } |
971 | - dead_temps[arg] = 0; | |
992 | + args--; | |
972 | 993 | } |
973 | - s->op_dead_iargs[op_index] = dead_iargs; | |
974 | - args--; | |
975 | 994 | break; |
976 | 995 | case INDEX_op_set_label: |
977 | 996 | args--; |
... | ... | @@ -1640,7 +1659,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, |
1640 | 1659 | } |
1641 | 1660 | |
1642 | 1661 | /* mark dead temporaries and free the associated registers */ |
1643 | - for(i = 0; i < nb_params; i++) { | |
1662 | + for(i = 0; i < nb_iargs; i++) { | |
1644 | 1663 | arg = args[nb_oargs + i]; |
1645 | 1664 | if (IS_DEAD_IARG(i)) { |
1646 | 1665 | ts = &s->temps[arg]; | ... | ... |
tcg/tcg.h
... | ... | @@ -148,6 +148,10 @@ typedef int TCGv; |
148 | 148 | #define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */ |
149 | 149 | #define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */ |
150 | 150 | #define TCG_CALL_TYPE_REGPARM 0x0003 /* i386 style regparm call (3 regs) */ |
151 | +/* A pure function only reads its arguments and globals variables and | |
152 | + cannot raise exceptions. Hence a call to a pure function can be | |
153 | + safely suppressed if the return value is not used. */ | |
154 | +#define TCG_CALL_PURE 0x0010 | |
151 | 155 | |
152 | 156 | typedef enum { |
153 | 157 | TCG_COND_EQ, | ... | ... |