lang.c (flag_use_divide_subroutine): New variable.
authorAndrew Haley <aph@cygnus.com>
Wed, 21 Jul 1999 14:28:33 +0000 (14:28 +0000)
committerAndrew Haley <aph@gcc.gnu.org>
Wed, 21 Jul 1999 14:28:33 +0000 (14:28 +0000)
1999-07-15  Andrew Haley  <aph@cygnus.com>

        * lang.c (flag_use_divide_subroutine): New variable.
        * typeck.c: (convert_ieee_real_to_integer): Bounds check
        fp-to-integer conversion.
        (convert): Call convert_ieee_real_to_integer when flag_fast_math
        is not set.

        * expr.c (build_java_soft_divmod): New function.
        (build_java_binop): Call build_java_soft_divmod if
        flag_use_divide_subroutine is set.
        * decl.c: soft_idiv_node, soft_irem_node, soft_ldiv_node, tree
        soft_lrem_node: new builtin functions.
        (init_decl_processing) Initialize the new builtins.
        * java-tree.h soft_idiv_node, soft_irem_node, soft_ldiv_node, tree
        soft_lrem_node: new builtin functions.
        (build_java_soft_divmod): New function.
        * parse.y: Call build_java_soft_divmod if
        flag_use_divide_subroutine is set.

From-SVN: r28208

gcc/java/ChangeLog
gcc/java/decl.c
gcc/java/expr.c
gcc/java/java-tree.h
gcc/java/lang.c
gcc/java/parse.y
gcc/java/typeck.c

index 2e7bb3a..372d294 100644 (file)
@@ -1,3 +1,23 @@
+1999-07-15  Andrew Haley  <aph@cygnus.com>
+
+       * lang.c (flag_use_divide_subroutine): New variable.
+       * typeck.c: (convert_ieee_real_to_integer): Bounds check
+       fp-to-integer conversion.
+       (convert): Call convert_ieee_real_to_integer when flag_fast_math
+       is not set.
+
+       * expr.c (build_java_soft_divmod): New function.
+       (build_java_binop): Call build_java_soft_divmod if
+       flag_use_divide_subroutine is set.
+       * decl.c: soft_idiv_node, soft_irem_node, soft_ldiv_node, tree
+       soft_lrem_node: new builtin functions.
+       (init_decl_processing) Initialize the new builtins.
+       * java-tree.h soft_idiv_node, soft_irem_node, soft_ldiv_node, tree
+       soft_lrem_node: new builtin functions.
+       (build_java_soft_divmod): New function.
+       * parse.y: Call build_java_soft_divmod if
+       flag_use_divide_subroutine is set.
+       
 Tue Jul 20 13:20:05 1999  Alexandre Petit-Bianco  <apbianco@cygnus.com>
 
        * parse.y (resolve_and_layout): Check methods only once.
index de03e5f..6779747 100644 (file)
@@ -365,6 +365,11 @@ tree soft_monitorexit_node;
 tree soft_lookupinterfacemethod_node;
 tree soft_fmod_node;
 tree soft_exceptioninfo_call_node;
+tree soft_idiv_node;
+tree soft_irem_node;
+tree soft_ldiv_node;
+tree soft_lrem_node;
+
 
 /* Build (and pushdecl) a "promoted type" for all standard
    types shorter than int.  */
@@ -812,6 +817,26 @@ init_decl_processing ()
                        BUILT_IN_FMOD, "fmodf");
 #endif
     
+  soft_idiv_node
+    = builtin_function ("_Jv_divI",
+                       build_function_type (int_type_node, t),
+                       NOT_BUILT_IN, NULL_PTR);
+
+  soft_irem_node
+    = builtin_function ("_Jv_remI",
+                       build_function_type (int_type_node, t),
+                       NOT_BUILT_IN, NULL_PTR);
+
+  soft_ldiv_node
+    = builtin_function ("_Jv_divJ",
+                       build_function_type (long_type_node, t),
+                       NOT_BUILT_IN, NULL_PTR);
+
+  soft_lrem_node
+    = builtin_function ("_Jv_remJ",
+                       build_function_type (long_type_node, t),
+                       NOT_BUILT_IN, NULL_PTR);
+
   init_class_processing ();
 }
 
index d47ed1a..dbf6db5 100644 (file)
@@ -1052,6 +1052,53 @@ expand_iinc (local_var_index, ival, pc)
     expand_assignment (local_var, res, 0, 0);
 }
 
+      
+tree
+build_java_soft_divmod (op, type, op1, op2)
+    enum tree_code op;
+    tree type, op1, op2;
+{
+  tree call = NULL;
+  tree arg1 = convert (type, op1);
+  tree arg2 = convert (type, op2);
+
+  if (type == int_type_node)
+    {    
+      switch (op)
+       {
+       case TRUNC_DIV_EXPR:
+         call = soft_idiv_node;
+         break;
+       case TRUNC_MOD_EXPR:
+         call = soft_irem_node;
+         break;
+       }
+    }
+  else if (type == long_type_node)
+    {    
+      switch (op)
+       {
+       case TRUNC_DIV_EXPR:
+         call = soft_ldiv_node;
+         break;
+       case TRUNC_MOD_EXPR:
+         call = soft_lrem_node;
+         break;
+       }
+    }
+
+  if (! call)
+    fatal ("Internal compiler error in build_java_soft_divmod");
+                 
+  call = build (CALL_EXPR, type,
+               build_address_of (call),
+               tree_cons (NULL_TREE, arg1,
+                          build_tree_list (NULL_TREE, arg2)),
+               NULL_TREE);
+         
+  return call;
+}
+
 tree
 build_java_binop (op, type, arg1, arg2)
      enum tree_code op;
@@ -1100,10 +1147,11 @@ build_java_binop (op, type, arg1, arg2)
                                            integer_zero_node));
        return fold (build (COND_EXPR, int_type_node,
                            ifexp1, integer_negative_one_node, second_compare));
-      }
-
+      }      
+    case TRUNC_DIV_EXPR:
     case TRUNC_MOD_EXPR:
-      if (TREE_CODE (type) == REAL_TYPE)
+      if (TREE_CODE (type) == REAL_TYPE
+         && op == TRUNC_MOD_EXPR)
        {
          tree call;
          if (type != double_type_node)
@@ -1120,6 +1168,12 @@ build_java_binop (op, type, arg1, arg2)
            call = convert (type, call);
          return call;
        }
+      
+      if (TREE_CODE (type) == INTEGER_TYPE
+         && flag_use_divide_subroutine
+         && ! flag_syntax_only)
+       return build_java_soft_divmod (op, type, arg1, arg2);
+      
       break;
     default:  ;
     }
index be1f143..307218c 100644 (file)
@@ -141,6 +141,9 @@ extern int flag_redundant;
 extern int flag_not_overriding;
 extern int flag_static_local_jdk1_1;
 
+/* When non zero, call a library routine to do integer divisions. */
+extern int flag_use_divide_subroutine;
+
 /* The Java .class file that provides main_class;  the main input file. */
 extern struct JCF *current_jcf;
 
@@ -283,6 +286,10 @@ extern tree soft_monitorexit_node;
 extern tree soft_lookupinterfacemethod_node;
 extern tree soft_fmod_node;
 extern tree soft_exceptioninfo_call_node;
+extern tree soft_idiv_node;
+extern tree soft_irem_node;
+extern tree soft_ldiv_node;
+extern tree soft_lrem_node;
 
 extern tree access_flags_type_node;
 
@@ -544,6 +551,7 @@ extern tree invoke_build_dtable PROTO ((int, tree));
 extern tree build_field_ref PROTO ((tree, tree, tree));
 extern void pushdecl_force_head PROTO ((tree));
 extern tree build_java_binop PROTO ((enum tree_code, tree, tree, tree));
+extern tree build_java_soft_divmod PROTO ((enum tree_code, tree, tree, tree));
 extern tree binary_numeric_promotion PROTO ((tree, tree, tree *, tree *));
 extern tree build_java_arrayaccess PROTO ((tree, tree, tree));
 extern tree build_newarray PROTO ((int, tree));
index cd6fb3b..976ed64 100644 (file)
@@ -105,6 +105,9 @@ int flag_not_overriding = 0;
 /* When non zero, warns that final local are treated as non final.  */
 int flag_static_local_jdk1_1 = 0;
 
+/* When non zero, call a library routine to do integer divisions. */
+int flag_use_divide_subroutine = 1;
+
 /* From gcc/flags.h, and indicates if exceptions are turned on or not.  */
 
 extern int flag_new_exceptions;
@@ -123,6 +126,7 @@ lang_f_options[] =
   {"assume-compiled", &flag_assume_compiled, 1},
   {"emit-class-file", &flag_emit_class_files, 1},
   {"emit-class-files", &flag_emit_class_files, 1},
+  {"use-divide-subroutine", &flag_use_divide_subroutine, 1},
 };
 
 JCF *current_jcf;
index be1c788..23b2c7a 100644 (file)
@@ -9411,6 +9411,12 @@ patch_binop (node, wfl_op1, wfl_op2)
       if (code == RDIV_EXPR && TREE_CODE (prom_type) == INTEGER_TYPE)
        TREE_SET_CODE (node, TRUNC_DIV_EXPR);
 
+      if (TREE_CODE (prom_type) == INTEGER_TYPE
+         && flag_use_divide_subroutine
+         && ! flag_emit_class_files
+         && (code == RDIV_EXPR || code == TRUNC_MOD_EXPR))
+       return build_java_soft_divmod (TREE_CODE (node), prom_type, op1, op2);
       /* This one is more complicated. FLOATs are processed by a
         function call to soft_fmod. Duplicate the value of the
         COMPOUND_ASSIGN_P flag. */
index 1416245..99536ff 100644 (file)
@@ -55,23 +55,43 @@ set_local_type (slot, type)
 
 /* Convert an IEEE real to an integer type.  The result of such a
    conversion when the source operand is a NaN isn't defined by
-   IEEE754, but by the Java language standard: it must be zero.  This
-   conversion produces something like:
-   
-   ({ double tmp = expr; (tmp != tmp) ? 0 : (int)tmp; })
-
-   */
+   IEEE754, but by the Java language standard: it must be zero.  Also,
+   overflows must be clipped to within range.  This conversion
+   produces something like:
+
+      ((expr >= (float)MAX_INT)
+       ? MAX_INT 
+       : ((expr <= (float)MIN_INT)
+         ? MIN_INT
+         : ((expr != expr)
+            ? 0 
+            : (int)expr))) */
 
 static tree
 convert_ieee_real_to_integer (type, expr)
      tree type, expr;
 {
+  tree result;
   expr = save_expr (expr);
 
-  return build (COND_EXPR, type, 
-               build (NE_EXPR, boolean_type_node, expr, expr),
-               convert (type, integer_zero_node),
-               convert_to_integer (type, expr));
+  result = build (COND_EXPR, type,
+                 build (NE_EXPR, boolean_type_node, expr, expr),
+                 convert (type, integer_zero_node),
+                 convert_to_integer (type, expr));
+                 
+  result = build (COND_EXPR, type, 
+                 build (LE_EXPR, boolean_type_node, expr, 
+                        convert (TREE_TYPE (expr), TYPE_MIN_VALUE (type))),
+                 TYPE_MIN_VALUE (type),
+                 result);
+
+  result = build (COND_EXPR, type,
+                 build (GE_EXPR, boolean_type_node, expr, 
+                        convert (TREE_TYPE (expr), TYPE_MAX_VALUE (type))),    
+                 TYPE_MAX_VALUE (type),
+                 result);
+
+  return result;
 }  
 
 /* Create an expression whose value is that of EXPR,
@@ -100,12 +120,9 @@ convert (type, expr)
     return fold (convert_to_boolean (type, expr));
   if (code == INTEGER_TYPE)
     {
-      if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
-#ifdef TARGET_SOFT_FLOAT
-         && !TARGET_SOFT_FLOAT
-#endif
-         && !flag_emit_class_files
-         && !flag_fast_math
+      if (! flag_fast_math
+         && ! flag_emit_class_files
+         && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
          && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
        return fold (convert_ieee_real_to_integer (type, expr));
       else