Commit c6e113f5680538a551f79df3ab19b69aed628521

Authored by bellard
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,