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