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, | ... | ... |