[gcjx] Patch: FYI: bytecode optimizer fix

Tom Tromey tromey@redhat.com
Wed Sep 14 03:58:00 GMT 2005


I'm checking this in on the gcjx branch.

While working on the previous fix I noticed that we were not
optimizing bytecode like this:

    ifnonnull X
    goto Y
  X:...

I forgot that we could also see this when the 'goto' is in its own
block.  While there I took the opportunity to turn a goto-to-return
into a plain return.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	* bytecode/byteutil.hh (return_p): New function.
	* bytecode/block.cc (optimize): Handle 'if' optimization when
	'goto' is in following block.  Optimize a 'goto' to a 'return'.
	Include byteutil.hh.

Index: bytecode/block.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/block.cc,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 block.cc
--- bytecode/block.cc 8 Mar 2005 00:17:53 -0000 1.1.2.3
+++ bytecode/block.cc 14 Sep 2005 03:56:13 -0000
@@ -25,6 +25,7 @@
 #include "bytecode/block.hh"
 #include "bytecode/attribute.hh"
 #include "bytecode/generate.hh"
+#include "bytecode/byteutil.hh"
 
 bool
 bytecode_block::optimize ()
@@ -87,10 +88,33 @@
 	      changed = true;
 	    }
 	}
+      else if (last->conditional_p ()
+	       && last->get_target () == next_block->next_block
+	       && ! next_block->relocations.empty ())
+	{
+	  // We might also encounter this case if the next block
+	  // starts with a goto.
+	  ref_relocation next_rel = next_block->relocations.front ();
+	  if (next_rel->get_kind () == reloc_goto)
+	    {
+	      // Remove the goto relocation and the byte representing
+	      // the instruction.
+	      next_block->relocations.pop_back ();
+	      next_block->bytecode.pop_back ();
+	      assert (! next_block->fall_through);
+	      next_block->fall_through = true;
+	      last->set_target (next_rel->get_target ());
+	      last->invert_condition ();
+	      // Rewrite the bytecode.  We know that the relocation
+	      // type can be directly converted to an instruction.
+	      bytecode[bytecode.size () - 1] = jbyte (last->get_kind ());
+	      changed = true;
+	    }
+	}
     }
 
-  // Second, we rewrite goto L; ... L: goto X by changing the first
-  // goto to jump directly to X.
+  // Rewrite goto L; ... L: goto X by changing the first goto to jump
+  // directly to X.
   for (std::list<ref_relocation>::iterator i = relocations.begin ();
        i != relocations.end ();
        ++i)
@@ -128,6 +152,22 @@
 	}
     }
 
+  // If we see goto L; ... L: return, we hoist the return into the
+  // original block.  Do this after hoisting gotos so that a chain of
+  // gotos leading to a return is optimized.
+  if (! relocations.empty () && relocations.back ()->get_kind () == reloc_goto)
+    {
+      int ret = (relocations.back ()->get_target ()->bytecode[0] & 0xff);
+      if (return_p (java_opcode (ret)))
+	{
+	  // Delete our last relocation.
+	  relocations.pop_back ();
+	  // Turn the last bytecode value into the appropriate return.
+	  bytecode[bytecode.size () - 1] = ret;
+	  changed = true;
+	}
+    }
+
   return changed;
 }
 
Index: bytecode/byteutil.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/byteutil.hh,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 byteutil.hh
--- bytecode/byteutil.hh 13 Jan 2005 03:18:34 -0000 1.1.2.1
+++ bytecode/byteutil.hh 14 Sep 2005 03:56:13 -0000
@@ -1,6 +1,6 @@
 // Bytecode utility functions.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -38,6 +38,14 @@
   return java_opcode ((base & 1) ? base + 1 : base - 1);
 }
 
+/// Return true if the value is a 'return' bytecode of any kind.
+inline bool
+return_p (int op)
+{
+  return (op == op_ireturn || op == op_lreturn || op == op_freturn
+	  || op == op_dreturn || op == op_areturn || op == op_return);
+}
+
 inline bool
 wide_p (const model_type *t)
 {



More information about the Java-patches mailing list