Index: expr.c
===================================================================
--- expr.c	(revision 233190)
+++ expr.c	(working copy)
@@ -37,6 +37,7 @@
 #include "jcf.h"
 #include "parse.h"
 #include "tree-iterator.h"
+#include "tree-eh.h"
 
 static void flush_quick_stack (void);
 static void push_value (tree);
@@ -54,6 +55,7 @@
 static void expand_java_pushc (int, tree);
 static void expand_java_return (tree);
 static void expand_load_internal (int, tree, int);
+static void expand_store_internal (tree, int, int);
 static void expand_java_NEW (tree);
 static void expand_java_INSTANCEOF (tree);
 static void expand_java_CHECKCAST (tree);
@@ -273,10 +275,12 @@
   /* If the value has a side effect, then we need to evaluate it
      whether or not the result is used.  If the value ends up on the
      quick stack and is then popped, this won't happen -- so we flush
-     the quick stack.  It is safest to simply always flush, though,
-     since TREE_SIDE_EFFECTS doesn't capture COMPONENT_REF, and for
-     the latter we may need to strip conversions.  */
-  flush_quick_stack ();
+     the quick stack.  It is safest to always flush non-constant
+     operands.  */
+  if (! TREE_CONSTANT (value)
+      || TREE_SIDE_EFFECTS (value)
+      || tree_could_trap_p (value))
+    flush_quick_stack ();
 }
 
 /* Pop a type from the type stack.
@@ -778,19 +782,13 @@
 {
   tree node;
 
-  /* We need to build a COMPOUND_EXPR because _Jv_ThrowBadArrayIndex()
-     has void return type.  We cannot just set the type of the CALL_EXPR below
-     to int_type_node because we would lose it during gimplification.  */
+  /* _Jv_ThrowBadArrayIndex() has void return type.  */
   gcc_assert (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (soft_badarrayindex_node))));
   node = build_call_nary (void_type_node,
-			       build_address_of (soft_badarrayindex_node),
-			       1, index);
+			  build_address_of (soft_badarrayindex_node),
+			  1, index);
   TREE_SIDE_EFFECTS (node) = 1;
-
-  node = build2 (COMPOUND_EXPR, int_type_node, node, integer_zero_node);
-  TREE_SIDE_EFFECTS (node) = 1;	/* Allows expansion within ANDIF */
-
-  return (node);
+  return node;
 }
 
 /* Return the length of an array. Doesn't perform any checking on the nature
@@ -833,10 +831,12 @@
 {
   if (!flag_syntax_only && check)
     {
+      tree test;
       expr = save_expr (expr);
-      expr = build3 (COND_EXPR, TREE_TYPE (expr),
-		     build2 (EQ_EXPR, boolean_type_node,
-			     expr, null_pointer_node),
+      test = build2 (EQ_EXPR, boolean_type_node, expr, null_pointer_node);
+      test = build_call_expr (builtin_decl_implicit (BUILT_IN_EXPECT), 2,
+			      test, boolean_false_node);
+      expr = build3 (COND_EXPR, TREE_TYPE (expr), test,
 		     build_call_nary (void_type_node, 
 				      build_address_of (soft_nullpointer_node),
 				      0),
@@ -865,7 +865,7 @@
 tree
 build_java_arrayaccess (tree array, tree type, tree index)
 {
-  tree node, throw_expr = NULL_TREE;
+  tree node;
   tree data_field;
   tree ref;
   tree array_type = TREE_TYPE (TREE_TYPE (array));
@@ -882,9 +882,9 @@
     {
       /* Generate:
        * (unsigned jint) INDEX >= (unsigned jint) LEN
-       *    && throw ArrayIndexOutOfBoundsException.
+       *    ? throw ArrayIndexOutOfBoundsException : INDEX.
        * Note this is equivalent to and more efficient than:
-       * INDEX < 0 || INDEX >= LEN && throw ... */
+       * INDEX < 0 || INDEX >= LEN ? throw ... : INDEX. */
       tree test;
       tree len = convert (unsigned_int_type_node,
 			  build_java_array_length_access (array));
@@ -893,19 +893,14 @@
 			  len);
       if (! integer_zerop (test))
 	{
-	  throw_expr
-	    = build2 (TRUTH_ANDIF_EXPR, int_type_node, test,
-		      build_java_throw_out_of_bounds_exception (index));
-	  /* allows expansion within COMPOUND */
-	  TREE_SIDE_EFFECTS( throw_expr ) = 1;
+	  test = build_call_expr (builtin_decl_implicit (BUILT_IN_EXPECT), 2,
+				  test, boolean_false_node);
+          index = build3(COND_EXPR, int_type_node, test,
+			 build_java_throw_out_of_bounds_exception (index),
+                         index);
 	}
     }
 
-  /* If checking bounds, wrap the index expr with a COMPOUND_EXPR in order
-     to have the bounds check evaluated first. */
-  if (throw_expr != NULL_TREE)
-    index = build2 (COMPOUND_EXPR, int_type_node, throw_expr, index);
-
   data_field = lookup_field (&array_type, get_identifier ("data"));
 
   ref = build3 (COMPONENT_REF, TREE_TYPE (data_field),    
@@ -919,9 +914,11 @@
 
   /* Multiply the index by the size of an element to obtain a byte
      offset.  Convert the result to a pointer to the element type.  */
-  index = build2 (MULT_EXPR, sizetype, 
-		  fold_convert (sizetype, index), 
-		  size_exp);
+  index = fold_convert (sizetype, index);
+  if (! integer_onep (size_exp))
+    {
+      index = build2 (MULT_EXPR, sizetype, index, size_exp);
+    }
 
   /* Sum the byte offset and the address of the data field.  */
   node = fold_build_pointer_plus (node, index);
@@ -1026,6 +1023,34 @@
   return indexed_type;
 }
 
+/* When optimizing, wrap calls to array allocation functions taking
+   constant length arguments, in a COMPOUND_EXPR, containing an
+   explict assignment of the .length field, for GCC's optimizers.  */
+
+static tree
+build_array_length_annotation (tree call, tree length)
+{
+  if (optimize
+      && TREE_CONSTANT (length)
+      && is_array_type_p (TREE_TYPE (call)))
+    {
+      tree type, note;
+      type = TREE_TYPE (call);
+      call = save_expr(call);
+      note = build3 (COMPONENT_REF, int_type_node,
+		     build1 (INDIRECT_REF, TREE_TYPE (type), call),
+		     lookup_field (&TREE_TYPE (type),
+				   get_identifier ("length")),
+		     NULL_TREE);
+      note = build2 (MODIFY_EXPR, int_type_node, note, length);
+      TREE_SIDE_EFFECTS (note) = 1;
+      call = build2 (COMPOUND_EXPR, TREE_TYPE (call), note, call);
+      TREE_SIDE_EFFECTS (call) = 1;
+    }
+  return call;
+}
+
+
 /* newarray triggers a call to _Jv_NewPrimArray. This function should be 
    called with an integer code (the type of array to create), and the length
    of the array to create.  */
@@ -1033,7 +1058,7 @@
 tree
 build_newarray (int atype_value, tree length)
 {
-  tree type_arg;
+  tree type_arg, call;
 
   tree prim_type = decode_newarray_type (atype_value);
   tree type
@@ -1045,9 +1070,10 @@
      some work.  */
   type_arg = build_class_ref (prim_type);
 
-  return build_call_nary (promote_type (type),
+  call = build_call_nary (promote_type (type),
 			  build_address_of (soft_newarray_node),
 			  2, type_arg, length);
+  return build_array_length_annotation (call, length);
 }
 
 /* Generates anewarray from a given CLASS_TYPE. Gets from the stack the size
@@ -1061,12 +1087,14 @@
 			     tree_fits_shwi_p (length)
 			     ? tree_to_shwi (length) : -1);
 
-  return build_call_nary (promote_type (type),
-			  build_address_of (soft_anewarray_node),
-			  3,
-			  length,
-			  build_class_ref (class_type),
-			  null_pointer_node);
+  tree call = build_call_nary (promote_type (type),
+			       build_address_of (soft_anewarray_node),
+			       3,
+			       length,
+			       build_class_ref (class_type),
+			       null_pointer_node);
+
+  return build_array_length_annotation (call, length);
 }
 
 /* Return a node the evaluates 'new TYPE[LENGTH]'. */
