]> git.proxmox.com Git - mirror_qemu.git/commitdiff
added 'pure' function attribute - fixed indirect function calls
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 17 May 2008 12:42:15 +0000 (12:42 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 17 May 2008 12:42:15 +0000 (12:42 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4469 c046a42c-6fe2-441c-8c8c-71466251a162

tcg/tcg.c
tcg/tcg.h

index aa46bcf3990301e347151bd8c9a33d7d8a184e47..b1d040283866478b6a3816d49d9daf634f87c3d8 100644 (file)
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -946,32 +946,51 @@ void tcg_liveness_analysis(TCGContext *s)
         def = &tcg_op_defs[op];
         switch(op) {
         case INDEX_op_call:
-            nb_args = args[-1];
-            args -= nb_args;
-            nb_iargs = args[0] & 0xffff;
-            nb_oargs = args[0] >> 16;
-            args++;
+            {
+                int call_flags;
 
-            /* output args are dead */
-            for(i = 0; i < nb_oargs; i++) {
-                arg = args[i];
-                dead_temps[arg] = 1;
-            }
-            
-            /* globals are live (they may be used by the call) */
-            memset(dead_temps, 0, s->nb_globals);
+                nb_args = args[-1];
+                args -= nb_args;
+                nb_iargs = args[0] & 0xffff;
+                nb_oargs = args[0] >> 16;
+                args++;
+                call_flags = args[nb_oargs + nb_iargs];
+
+                /* pure functions can be removed if their result is not
+                   used */
+                if (call_flags & TCG_CALL_PURE) {
+                    for(i = 0; i < nb_oargs; i++) {
+                        arg = args[i];
+                        if (!dead_temps[arg])
+                            goto do_not_remove_call;
+                    }
+                    tcg_set_nop(s, gen_opc_buf + op_index, 
+                                args - 1, nb_args);
+                } else {
+                do_not_remove_call:
 
-            /* input args are live */
-            dead_iargs = 0;
-            for(i = 0; i < nb_iargs; i++) {
-                arg = args[i + nb_oargs];
-                if (dead_temps[arg]) {
-                    dead_iargs |= (1 << i);
+                    /* output args are dead */
+                    for(i = 0; i < nb_oargs; i++) {
+                        arg = args[i];
+                        dead_temps[arg] = 1;
+                    }
+                    
+                    /* globals are live (they may be used by the call) */
+                    memset(dead_temps, 0, s->nb_globals);
+                    
+                    /* input args are live */
+                    dead_iargs = 0;
+                    for(i = 0; i < nb_iargs; i++) {
+                        arg = args[i + nb_oargs];
+                        if (dead_temps[arg]) {
+                            dead_iargs |= (1 << i);
+                        }
+                        dead_temps[arg] = 0;
+                    }
+                    s->op_dead_iargs[op_index] = dead_iargs;
                 }
-                dead_temps[arg] = 0;
+                args--;
             }
-            s->op_dead_iargs[op_index] = dead_iargs;
-            args--;
             break;
         case INDEX_op_set_label:
             args--;
@@ -1640,7 +1659,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
     }
     
     /* mark dead temporaries and free the associated registers */
-    for(i = 0; i < nb_params; i++) {
+    for(i = 0; i < nb_iargs; i++) {
         arg = args[nb_oargs + i];
         if (IS_DEAD_IARG(i)) {
             ts = &s->temps[arg];
index 66bbe73a4ab41b7d688052b0c7d2f53d7d3ab87d..1b8546729fbf42c3fcec6d6c543e39e7fd5bce0f 100644 (file)
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -148,6 +148,10 @@ typedef int TCGv;
 #define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */
 #define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */
 #define TCG_CALL_TYPE_REGPARM   0x0003 /* i386 style regparm call (3 regs) */
+/* A pure function only reads its arguments and globals variables and
+   cannot raise exceptions. Hence a call to a pure function can be
+   safely suppressed if the return value is not used. */
+#define TCG_CALL_PURE           0x0010 
 
 typedef enum {
     TCG_COND_EQ,