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,32 +946,51 @@ void tcg_liveness_analysis(TCGContext *s) | ||
946 | def = &tcg_op_defs[op]; | 946 | def = &tcg_op_defs[op]; |
947 | switch(op) { | 947 | switch(op) { |
948 | case INDEX_op_call: | 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 | break; | 994 | break; |
976 | case INDEX_op_set_label: | 995 | case INDEX_op_set_label: |
977 | args--; | 996 | args--; |
@@ -1640,7 +1659,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, | @@ -1640,7 +1659,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, | ||
1640 | } | 1659 | } |
1641 | 1660 | ||
1642 | /* mark dead temporaries and free the associated registers */ | 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 | arg = args[nb_oargs + i]; | 1663 | arg = args[nb_oargs + i]; |
1645 | if (IS_DEAD_IARG(i)) { | 1664 | if (IS_DEAD_IARG(i)) { |
1646 | ts = &s->temps[arg]; | 1665 | ts = &s->temps[arg]; |
tcg/tcg.h
@@ -148,6 +148,10 @@ typedef int TCGv; | @@ -148,6 +148,10 @@ typedef int TCGv; | ||
148 | #define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */ | 148 | #define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */ |
149 | #define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */ | 149 | #define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */ |
150 | #define TCG_CALL_TYPE_REGPARM 0x0003 /* i386 style regparm call (3 regs) */ | 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 | typedef enum { | 156 | typedef enum { |
153 | TCG_COND_EQ, | 157 | TCG_COND_EQ, |