Commit aa4759c1 by Andrew Haley Committed by Andrew Haley

lang.c (flag_use_divide_subroutine): New variable.

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
parent 9c1ce433
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> Tue Jul 20 13:20:05 1999 Alexandre Petit-Bianco <apbianco@cygnus.com>
* parse.y (resolve_and_layout): Check methods only once. * parse.y (resolve_and_layout): Check methods only once.
......
...@@ -365,6 +365,11 @@ tree soft_monitorexit_node; ...@@ -365,6 +365,11 @@ tree soft_monitorexit_node;
tree soft_lookupinterfacemethod_node; tree soft_lookupinterfacemethod_node;
tree soft_fmod_node; tree soft_fmod_node;
tree soft_exceptioninfo_call_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 /* Build (and pushdecl) a "promoted type" for all standard
types shorter than int. */ types shorter than int. */
...@@ -812,6 +817,26 @@ init_decl_processing () ...@@ -812,6 +817,26 @@ init_decl_processing ()
BUILT_IN_FMOD, "fmodf"); BUILT_IN_FMOD, "fmodf");
#endif #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 (); init_class_processing ();
} }
......
...@@ -1052,6 +1052,53 @@ expand_iinc (local_var_index, ival, pc) ...@@ -1052,6 +1052,53 @@ expand_iinc (local_var_index, ival, pc)
expand_assignment (local_var, res, 0, 0); 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 tree
build_java_binop (op, type, arg1, arg2) build_java_binop (op, type, arg1, arg2)
enum tree_code op; enum tree_code op;
...@@ -1100,10 +1147,11 @@ build_java_binop (op, type, arg1, arg2) ...@@ -1100,10 +1147,11 @@ build_java_binop (op, type, arg1, arg2)
integer_zero_node)); integer_zero_node));
return fold (build (COND_EXPR, int_type_node, return fold (build (COND_EXPR, int_type_node,
ifexp1, integer_negative_one_node, second_compare)); ifexp1, integer_negative_one_node, second_compare));
} }
case TRUNC_DIV_EXPR:
case TRUNC_MOD_EXPR: case TRUNC_MOD_EXPR:
if (TREE_CODE (type) == REAL_TYPE) if (TREE_CODE (type) == REAL_TYPE
&& op == TRUNC_MOD_EXPR)
{ {
tree call; tree call;
if (type != double_type_node) if (type != double_type_node)
...@@ -1120,6 +1168,12 @@ build_java_binop (op, type, arg1, arg2) ...@@ -1120,6 +1168,12 @@ build_java_binop (op, type, arg1, arg2)
call = convert (type, call); call = convert (type, call);
return 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; break;
default: ; default: ;
} }
......
...@@ -141,6 +141,9 @@ extern int flag_redundant; ...@@ -141,6 +141,9 @@ extern int flag_redundant;
extern int flag_not_overriding; extern int flag_not_overriding;
extern int flag_static_local_jdk1_1; 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. */ /* The Java .class file that provides main_class; the main input file. */
extern struct JCF *current_jcf; extern struct JCF *current_jcf;
...@@ -283,6 +286,10 @@ extern tree soft_monitorexit_node; ...@@ -283,6 +286,10 @@ extern tree soft_monitorexit_node;
extern tree soft_lookupinterfacemethod_node; extern tree soft_lookupinterfacemethod_node;
extern tree soft_fmod_node; extern tree soft_fmod_node;
extern tree soft_exceptioninfo_call_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; extern tree access_flags_type_node;
...@@ -544,6 +551,7 @@ extern tree invoke_build_dtable PROTO ((int, tree)); ...@@ -544,6 +551,7 @@ extern tree invoke_build_dtable PROTO ((int, tree));
extern tree build_field_ref PROTO ((tree, tree, tree)); extern tree build_field_ref PROTO ((tree, tree, tree));
extern void pushdecl_force_head PROTO ((tree)); extern void pushdecl_force_head PROTO ((tree));
extern tree build_java_binop PROTO ((enum tree_code, tree, tree, 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 binary_numeric_promotion PROTO ((tree, tree, tree *, tree *));
extern tree build_java_arrayaccess PROTO ((tree, tree, tree)); extern tree build_java_arrayaccess PROTO ((tree, tree, tree));
extern tree build_newarray PROTO ((int, tree)); extern tree build_newarray PROTO ((int, tree));
......
...@@ -105,6 +105,9 @@ int flag_not_overriding = 0; ...@@ -105,6 +105,9 @@ int flag_not_overriding = 0;
/* When non zero, warns that final local are treated as non final. */ /* When non zero, warns that final local are treated as non final. */
int flag_static_local_jdk1_1 = 0; 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. */ /* From gcc/flags.h, and indicates if exceptions are turned on or not. */
extern int flag_new_exceptions; extern int flag_new_exceptions;
...@@ -123,6 +126,7 @@ lang_f_options[] = ...@@ -123,6 +126,7 @@ lang_f_options[] =
{"assume-compiled", &flag_assume_compiled, 1}, {"assume-compiled", &flag_assume_compiled, 1},
{"emit-class-file", &flag_emit_class_files, 1}, {"emit-class-file", &flag_emit_class_files, 1},
{"emit-class-files", &flag_emit_class_files, 1}, {"emit-class-files", &flag_emit_class_files, 1},
{"use-divide-subroutine", &flag_use_divide_subroutine, 1},
}; };
JCF *current_jcf; JCF *current_jcf;
......
...@@ -9411,6 +9411,12 @@ patch_binop (node, wfl_op1, wfl_op2) ...@@ -9411,6 +9411,12 @@ patch_binop (node, wfl_op1, wfl_op2)
if (code == RDIV_EXPR && TREE_CODE (prom_type) == INTEGER_TYPE) if (code == RDIV_EXPR && TREE_CODE (prom_type) == INTEGER_TYPE)
TREE_SET_CODE (node, TRUNC_DIV_EXPR); 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 /* This one is more complicated. FLOATs are processed by a
function call to soft_fmod. Duplicate the value of the function call to soft_fmod. Duplicate the value of the
COMPOUND_ASSIGN_P flag. */ COMPOUND_ASSIGN_P flag. */
......
...@@ -55,23 +55,43 @@ set_local_type (slot, type) ...@@ -55,23 +55,43 @@ set_local_type (slot, type)
/* Convert an IEEE real to an integer type. The result of such a /* 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 conversion when the source operand is a NaN isn't defined by
IEEE754, but by the Java language standard: it must be zero. This IEEE754, but by the Java language standard: it must be zero. Also,
conversion produces something like: overflows must be clipped to within range. This conversion
produces something like:
({ double tmp = expr; (tmp != tmp) ? 0 : (int)tmp; })
((expr >= (float)MAX_INT)
*/ ? MAX_INT
: ((expr <= (float)MIN_INT)
? MIN_INT
: ((expr != expr)
? 0
: (int)expr))) */
static tree static tree
convert_ieee_real_to_integer (type, expr) convert_ieee_real_to_integer (type, expr)
tree type, expr; tree type, expr;
{ {
tree result;
expr = save_expr (expr); expr = save_expr (expr);
return build (COND_EXPR, type, result = build (COND_EXPR, type,
build (NE_EXPR, boolean_type_node, expr, expr), build (NE_EXPR, boolean_type_node, expr, expr),
convert (type, integer_zero_node), convert (type, integer_zero_node),
convert_to_integer (type, expr)); 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, /* Create an expression whose value is that of EXPR,
...@@ -100,12 +120,9 @@ convert (type, expr) ...@@ -100,12 +120,9 @@ convert (type, expr)
return fold (convert_to_boolean (type, expr)); return fold (convert_to_boolean (type, expr));
if (code == INTEGER_TYPE) if (code == INTEGER_TYPE)
{ {
if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE if (! flag_fast_math
#ifdef TARGET_SOFT_FLOAT && ! flag_emit_class_files
&& !TARGET_SOFT_FLOAT && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
#endif
&& !flag_emit_class_files
&& !flag_fast_math
&& TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
return fold (convert_ieee_real_to_integer (type, expr)); return fold (convert_ieee_real_to_integer (type, expr));
else else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment