stmt.c: Don't include insn-codes.h.
* stmt.c: Don't include insn-codes.h. (expand_end_case): Machine specific logic moved to expr.c. No need to worry about __builtin_classify_type. (check_for_full_enumeration_handling, emit_case_nodes): Kill #if 0 blocks. * builtins.o (expand_builtin_classify_type): Split up so code can be shared with fold_builtin_classify_type. (type_to_class, fold_builtin_classify_type): New functions. (fold_builtins): Handle __builtin_classify_type. * expr.c (do_tablejump): Now static. (case_values_threshold, try_casesi, try_tablejump): New; code mostly from stmt.c (expand_end_case). (expr.h): Update prototypes. * Makefile.in (stmt.o): Update dependencies. From-SVN: r45078
This commit is contained in:
parent
71038fd576
commit
ad82abb8e6
|
@ -1,9 +1,29 @@
|
||||||
|
2001-08-21 Zack Weinberg <zackw@panix.com>
|
||||||
|
|
||||||
|
* stmt.c: Don't include insn-codes.h.
|
||||||
|
(expand_end_case): Machine specific logic moved to expr.c.
|
||||||
|
No need to worry about __builtin_classify_type.
|
||||||
|
(check_for_full_enumeration_handling, emit_case_nodes):
|
||||||
|
Kill #if 0 blocks.
|
||||||
|
|
||||||
|
* builtins.o (expand_builtin_classify_type): Split up so code
|
||||||
|
can be shared with fold_builtin_classify_type.
|
||||||
|
(type_to_class, fold_builtin_classify_type): New functions.
|
||||||
|
(fold_builtins): Handle __builtin_classify_type.
|
||||||
|
|
||||||
|
* expr.c (do_tablejump): Now static.
|
||||||
|
(case_values_threshold, try_casesi, try_tablejump): New;
|
||||||
|
code mostly from stmt.c (expand_end_case).
|
||||||
|
(expr.h): Update prototypes.
|
||||||
|
|
||||||
|
* Makefile.in (stmt.o): Update dependencies.
|
||||||
|
|
||||||
2001-08-21 Will Cohen <wcohen@redhat.com>
|
2001-08-21 Will Cohen <wcohen@redhat.com>
|
||||||
|
|
||||||
* configure/alpha/alpha.h (CONDITIONAL_REGISTER_USAGE): Added local
|
* configure/alpha/alpha.h (CONDITIONAL_REGISTER_USAGE): Added local
|
||||||
declaration of variable i.
|
declaration of variable i.
|
||||||
* configure/rs6000/rs6000.h (CONDITIONAL_REGISTER_USAGE): Added local
|
* configure/rs6000/rs6000.h (CONDITIONAL_REGISTER_USAGE): Added local
|
||||||
declaration of variable i.
|
declaration of variable i.
|
||||||
|
|
||||||
2001-08-21 Richard Henderson <rth@redhat.com>
|
2001-08-21 Richard Henderson <rth@redhat.com>
|
||||||
|
|
||||||
|
|
|
@ -1383,7 +1383,7 @@ function.o : function.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
|
||||||
function.h insn-codes.h $(EXPR_H) libfuncs.h $(REGS_H) hard-reg-set.h \
|
function.h insn-codes.h $(EXPR_H) libfuncs.h $(REGS_H) hard-reg-set.h \
|
||||||
insn-config.h $(RECOG_H) output.h toplev.h except.h hash.h $(GGC_H) $(TM_P_H)
|
insn-config.h $(RECOG_H) output.h toplev.h except.h hash.h $(GGC_H) $(TM_P_H)
|
||||||
stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
|
stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
|
||||||
insn-config.h insn-codes.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \
|
insn-config.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \
|
||||||
$(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H)
|
$(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H)
|
||||||
except.o : except.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
|
except.o : except.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
|
||||||
except.h function.h $(EXPR_H) libfuncs.h integrate.h \
|
except.h function.h $(EXPR_H) libfuncs.h integrate.h \
|
||||||
|
|
|
@ -91,6 +91,7 @@ static rtx expand_builtin_apply_args PARAMS ((void));
|
||||||
static rtx expand_builtin_apply_args_1 PARAMS ((void));
|
static rtx expand_builtin_apply_args_1 PARAMS ((void));
|
||||||
static rtx expand_builtin_apply PARAMS ((rtx, rtx, rtx));
|
static rtx expand_builtin_apply PARAMS ((rtx, rtx, rtx));
|
||||||
static void expand_builtin_return PARAMS ((rtx));
|
static void expand_builtin_return PARAMS ((rtx));
|
||||||
|
static int type_to_class PARAMS ((tree));
|
||||||
static rtx expand_builtin_classify_type PARAMS ((tree));
|
static rtx expand_builtin_classify_type PARAMS ((tree));
|
||||||
static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx));
|
static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx));
|
||||||
static rtx expand_builtin_constant_p PARAMS ((tree));
|
static rtx expand_builtin_constant_p PARAMS ((tree));
|
||||||
|
@ -142,6 +143,7 @@ static rtx expand_builtin_fputs PARAMS ((tree, int));
|
||||||
static tree stabilize_va_list PARAMS ((tree, int));
|
static tree stabilize_va_list PARAMS ((tree, int));
|
||||||
static rtx expand_builtin_expect PARAMS ((tree, rtx));
|
static rtx expand_builtin_expect PARAMS ((tree, rtx));
|
||||||
static tree fold_builtin_constant_p PARAMS ((tree));
|
static tree fold_builtin_constant_p PARAMS ((tree));
|
||||||
|
static tree fold_builtin_classify_type PARAMS ((tree));
|
||||||
static tree build_function_call_expr PARAMS ((tree, tree));
|
static tree build_function_call_expr PARAMS ((tree, tree));
|
||||||
static int validate_arglist PARAMS ((tree, ...));
|
static int validate_arglist PARAMS ((tree, ...));
|
||||||
|
|
||||||
|
@ -1267,6 +1269,37 @@ expand_builtin_return (result)
|
||||||
expand_null_return ();
|
expand_null_return ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
|
||||||
|
static enum type_class
|
||||||
|
type_to_class (type)
|
||||||
|
tree type;
|
||||||
|
{
|
||||||
|
switch (TREE_CODE (type))
|
||||||
|
{
|
||||||
|
case VOID_TYPE: return void_type_class;
|
||||||
|
case INTEGER_TYPE: return integer_type_class;
|
||||||
|
case CHAR_TYPE: return char_type_class;
|
||||||
|
case ENUMERAL_TYPE: return enumeral_type_class;
|
||||||
|
case BOOLEAN_TYPE: return boolean_type_class;
|
||||||
|
case POINTER_TYPE: return pointer_type_class;
|
||||||
|
case REFERENCE_TYPE: return reference_type_class;
|
||||||
|
case OFFSET_TYPE: return offset_type_class;
|
||||||
|
case REAL_TYPE: return real_type_class;
|
||||||
|
case COMPLEX_TYPE: return complex_type_class;
|
||||||
|
case FUNCTION_TYPE: return function_type_class;
|
||||||
|
case METHOD_TYPE: return method_type_class;
|
||||||
|
case RECORD_TYPE: return record_type_class;
|
||||||
|
case UNION_TYPE:
|
||||||
|
case QUAL_UNION_TYPE: return union_type_class;
|
||||||
|
case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
|
||||||
|
? string_type_class : array_type_class);
|
||||||
|
case SET_TYPE: return set_type_class;
|
||||||
|
case FILE_TYPE: return file_type_class;
|
||||||
|
case LANG_TYPE: return lang_type_class;
|
||||||
|
default: return no_type_class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Expand a call to __builtin_classify_type with arguments found in
|
/* Expand a call to __builtin_classify_type with arguments found in
|
||||||
ARGLIST. */
|
ARGLIST. */
|
||||||
static rtx
|
static rtx
|
||||||
|
@ -1274,51 +1307,7 @@ expand_builtin_classify_type (arglist)
|
||||||
tree arglist;
|
tree arglist;
|
||||||
{
|
{
|
||||||
if (arglist != 0)
|
if (arglist != 0)
|
||||||
{
|
return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
|
||||||
tree type = TREE_TYPE (TREE_VALUE (arglist));
|
|
||||||
enum tree_code code = TREE_CODE (type);
|
|
||||||
if (code == VOID_TYPE)
|
|
||||||
return GEN_INT (void_type_class);
|
|
||||||
if (code == INTEGER_TYPE)
|
|
||||||
return GEN_INT (integer_type_class);
|
|
||||||
if (code == CHAR_TYPE)
|
|
||||||
return GEN_INT (char_type_class);
|
|
||||||
if (code == ENUMERAL_TYPE)
|
|
||||||
return GEN_INT (enumeral_type_class);
|
|
||||||
if (code == BOOLEAN_TYPE)
|
|
||||||
return GEN_INT (boolean_type_class);
|
|
||||||
if (code == POINTER_TYPE)
|
|
||||||
return GEN_INT (pointer_type_class);
|
|
||||||
if (code == REFERENCE_TYPE)
|
|
||||||
return GEN_INT (reference_type_class);
|
|
||||||
if (code == OFFSET_TYPE)
|
|
||||||
return GEN_INT (offset_type_class);
|
|
||||||
if (code == REAL_TYPE)
|
|
||||||
return GEN_INT (real_type_class);
|
|
||||||
if (code == COMPLEX_TYPE)
|
|
||||||
return GEN_INT (complex_type_class);
|
|
||||||
if (code == FUNCTION_TYPE)
|
|
||||||
return GEN_INT (function_type_class);
|
|
||||||
if (code == METHOD_TYPE)
|
|
||||||
return GEN_INT (method_type_class);
|
|
||||||
if (code == RECORD_TYPE)
|
|
||||||
return GEN_INT (record_type_class);
|
|
||||||
if (code == UNION_TYPE || code == QUAL_UNION_TYPE)
|
|
||||||
return GEN_INT (union_type_class);
|
|
||||||
if (code == ARRAY_TYPE)
|
|
||||||
{
|
|
||||||
if (TYPE_STRING_FLAG (type))
|
|
||||||
return GEN_INT (string_type_class);
|
|
||||||
else
|
|
||||||
return GEN_INT (array_type_class);
|
|
||||||
}
|
|
||||||
if (code == SET_TYPE)
|
|
||||||
return GEN_INT (set_type_class);
|
|
||||||
if (code == FILE_TYPE)
|
|
||||||
return GEN_INT (file_type_class);
|
|
||||||
if (code == LANG_TYPE)
|
|
||||||
return GEN_INT (lang_type_class);
|
|
||||||
}
|
|
||||||
return GEN_INT (no_type_class);
|
return GEN_INT (no_type_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3806,6 +3795,17 @@ fold_builtin_constant_p (arglist)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fold a call to __builtin_classify_type. */
|
||||||
|
static tree
|
||||||
|
fold_builtin_classify_type (arglist)
|
||||||
|
tree arglist;
|
||||||
|
{
|
||||||
|
if (arglist == 0)
|
||||||
|
return build_int_2 (no_type_class, 0);
|
||||||
|
|
||||||
|
return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Used by constant folding to eliminate some builtin calls early. EXP is
|
/* Used by constant folding to eliminate some builtin calls early. EXP is
|
||||||
the CALL_EXPR of a call to a builtin function. */
|
the CALL_EXPR of a call to a builtin function. */
|
||||||
|
|
||||||
|
@ -3825,6 +3825,9 @@ fold_builtin (exp)
|
||||||
case BUILT_IN_CONSTANT_P:
|
case BUILT_IN_CONSTANT_P:
|
||||||
return fold_builtin_constant_p (arglist);
|
return fold_builtin_constant_p (arglist);
|
||||||
|
|
||||||
|
case BUILT_IN_CLASSIFY_TYPE:
|
||||||
|
return fold_builtin_classify_type (arglist);
|
||||||
|
|
||||||
case BUILT_IN_STRLEN:
|
case BUILT_IN_STRLEN:
|
||||||
if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
|
if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
|
||||||
{
|
{
|
||||||
|
|
139
gcc/expr.c
139
gcc/expr.c
|
@ -177,6 +177,7 @@ static rtx do_store_flag PARAMS ((tree, rtx, enum machine_mode, int));
|
||||||
#ifdef PUSH_ROUNDING
|
#ifdef PUSH_ROUNDING
|
||||||
static void emit_single_push_insn PARAMS ((enum machine_mode, rtx, tree));
|
static void emit_single_push_insn PARAMS ((enum machine_mode, rtx, tree));
|
||||||
#endif
|
#endif
|
||||||
|
static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
|
||||||
|
|
||||||
/* Record for each mode whether we can move a register directly to or
|
/* Record for each mode whether we can move a register directly to or
|
||||||
from an object of that mode in memory. If we can't, we won't try
|
from an object of that mode in memory. If we can't, we won't try
|
||||||
|
@ -10717,11 +10718,112 @@ do_store_flag (exp, target, mode, only_cheap)
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate a tablejump instruction (used for switch statements). */
|
|
||||||
|
|
||||||
#ifdef HAVE_tablejump
|
/* Stubs in case we haven't got a casesi insn. */
|
||||||
|
#ifndef HAVE_casesi
|
||||||
|
# define HAVE_casesi 0
|
||||||
|
# define gen_casesi(a, b, c, d, e) (0)
|
||||||
|
# define CODE_FOR_casesi CODE_FOR_nothing
|
||||||
|
#endif
|
||||||
|
|
||||||
/* INDEX is the value being switched on, with the lowest value
|
/* If the machine does not have a case insn that compares the bounds,
|
||||||
|
this means extra overhead for dispatch tables, which raises the
|
||||||
|
threshold for using them. */
|
||||||
|
#ifndef CASE_VALUES_THRESHOLD
|
||||||
|
#define CASE_VALUES_THRESHOLD (HAVE_casesi ? 4 : 5)
|
||||||
|
#endif /* CASE_VALUES_THRESHOLD */
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
case_values_threshold ()
|
||||||
|
{
|
||||||
|
return CASE_VALUES_THRESHOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to generate a casesi instruction. Returns 1 if successful,
|
||||||
|
0 otherwise (i.e. if there is no casesi instruction). */
|
||||||
|
int
|
||||||
|
try_casesi (index_type, index_expr, minval, range,
|
||||||
|
table_label, default_label)
|
||||||
|
tree index_type, index_expr, minval, range;
|
||||||
|
rtx table_label ATTRIBUTE_UNUSED;
|
||||||
|
rtx default_label;
|
||||||
|
{
|
||||||
|
enum machine_mode index_mode = SImode;
|
||||||
|
int index_bits = GET_MODE_BITSIZE (index_mode);
|
||||||
|
rtx op1, op2, index;
|
||||||
|
enum machine_mode op_mode;
|
||||||
|
|
||||||
|
if (! HAVE_casesi)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Convert the index to SImode. */
|
||||||
|
if (GET_MODE_BITSIZE (TYPE_MODE (index_type)) > GET_MODE_BITSIZE (index_mode))
|
||||||
|
{
|
||||||
|
enum machine_mode omode = TYPE_MODE (index_type);
|
||||||
|
rtx rangertx = expand_expr (range, NULL_RTX, VOIDmode, 0);
|
||||||
|
|
||||||
|
/* We must handle the endpoints in the original mode. */
|
||||||
|
index_expr = build (MINUS_EXPR, index_type,
|
||||||
|
index_expr, minval);
|
||||||
|
minval = integer_zero_node;
|
||||||
|
index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
|
||||||
|
emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
|
||||||
|
omode, 1, 0, default_label);
|
||||||
|
/* Now we can safely truncate. */
|
||||||
|
index = convert_to_mode (index_mode, index, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (TYPE_MODE (index_type) != index_mode)
|
||||||
|
{
|
||||||
|
index_expr = convert (type_for_size (index_bits, 0),
|
||||||
|
index_expr);
|
||||||
|
index_type = TREE_TYPE (index_expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
|
||||||
|
}
|
||||||
|
emit_queue ();
|
||||||
|
index = protect_from_queue (index, 0);
|
||||||
|
do_pending_stack_adjust ();
|
||||||
|
|
||||||
|
op_mode = insn_data[(int) CODE_FOR_casesi].operand[0].mode;
|
||||||
|
if (! (*insn_data[(int) CODE_FOR_casesi].operand[0].predicate)
|
||||||
|
(index, op_mode))
|
||||||
|
index = copy_to_mode_reg (op_mode, index);
|
||||||
|
|
||||||
|
op1 = expand_expr (minval, NULL_RTX, VOIDmode, 0);
|
||||||
|
|
||||||
|
op_mode = insn_data[(int) CODE_FOR_casesi].operand[1].mode;
|
||||||
|
op1 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (minval)),
|
||||||
|
op1, TREE_UNSIGNED (TREE_TYPE (minval)));
|
||||||
|
if (! (*insn_data[(int) CODE_FOR_casesi].operand[1].predicate)
|
||||||
|
(op1, op_mode))
|
||||||
|
op1 = copy_to_mode_reg (op_mode, op1);
|
||||||
|
|
||||||
|
op2 = expand_expr (range, NULL_RTX, VOIDmode, 0);
|
||||||
|
|
||||||
|
op_mode = insn_data[(int) CODE_FOR_casesi].operand[2].mode;
|
||||||
|
op2 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (range)),
|
||||||
|
op2, TREE_UNSIGNED (TREE_TYPE (range)));
|
||||||
|
if (! (*insn_data[(int) CODE_FOR_casesi].operand[2].predicate)
|
||||||
|
(op2, op_mode))
|
||||||
|
op2 = copy_to_mode_reg (op_mode, op2);
|
||||||
|
|
||||||
|
emit_jump_insn (gen_casesi (index, op1, op2,
|
||||||
|
table_label, default_label));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to generate a tablejump instruction; same concept. */
|
||||||
|
#ifndef HAVE_tablejump
|
||||||
|
#define HAVE_tablejump 0
|
||||||
|
#define gen_tablejump(x, y) (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Subroutine of the next function.
|
||||||
|
|
||||||
|
INDEX is the value being switched on, with the lowest value
|
||||||
in the table already subtracted.
|
in the table already subtracted.
|
||||||
MODE is its expected mode (needed if INDEX is constant).
|
MODE is its expected mode (needed if INDEX is constant).
|
||||||
RANGE is the length of the jump table.
|
RANGE is the length of the jump table.
|
||||||
|
@ -10730,7 +10832,7 @@ do_store_flag (exp, target, mode, only_cheap)
|
||||||
DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
|
DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
|
||||||
index value is out of range. */
|
index value is out of range. */
|
||||||
|
|
||||||
void
|
static void
|
||||||
do_tablejump (index, mode, range, table_label, default_label)
|
do_tablejump (index, mode, range, table_label, default_label)
|
||||||
rtx index, range, table_label, default_label;
|
rtx index, range, table_label, default_label;
|
||||||
enum machine_mode mode;
|
enum machine_mode mode;
|
||||||
|
@ -10792,4 +10894,31 @@ do_tablejump (index, mode, range, table_label, default_label)
|
||||||
emit_barrier ();
|
emit_barrier ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_tablejump */
|
int
|
||||||
|
try_tablejump (index_type, index_expr, minval, range,
|
||||||
|
table_label, default_label)
|
||||||
|
tree index_type, index_expr, minval, range;
|
||||||
|
rtx table_label, default_label;
|
||||||
|
{
|
||||||
|
rtx index;
|
||||||
|
|
||||||
|
if (! HAVE_tablejump)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
index_expr = fold (build (MINUS_EXPR, index_type,
|
||||||
|
convert (index_type, index_expr),
|
||||||
|
convert (index_type, minval)));
|
||||||
|
index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
|
||||||
|
emit_queue ();
|
||||||
|
index = protect_from_queue (index, 0);
|
||||||
|
do_pending_stack_adjust ();
|
||||||
|
|
||||||
|
do_tablejump (index, TYPE_MODE (index_type),
|
||||||
|
convert_modes (TYPE_MODE (index_type),
|
||||||
|
TYPE_MODE (TREE_TYPE (range)),
|
||||||
|
expand_expr (range, NULL_RTX,
|
||||||
|
VOIDmode, 0),
|
||||||
|
TREE_UNSIGNED (TREE_TYPE (range))),
|
||||||
|
table_label, default_label);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
10
gcc/expr.h
10
gcc/expr.h
|
@ -540,8 +540,14 @@ extern void do_compare_rtx_and_jump PARAMS ((rtx, rtx, enum rtx_code, int,
|
||||||
enum machine_mode, rtx,
|
enum machine_mode, rtx,
|
||||||
unsigned int, rtx, rtx));
|
unsigned int, rtx, rtx));
|
||||||
|
|
||||||
/* Generate a tablejump instruction (used for switch statements). */
|
/* Two different ways of generating switch statements. */
|
||||||
extern void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
|
extern int try_casesi PARAMS ((tree, tree, tree, tree, rtx, rtx));
|
||||||
|
extern int try_tablejump PARAMS ((tree, tree, tree, tree, rtx, rtx));
|
||||||
|
|
||||||
|
/* Smallest number of adjacent cases before we use a jump table.
|
||||||
|
XXX Should be a target hook. */
|
||||||
|
extern unsigned int case_values_threshold PARAMS ((void));
|
||||||
|
|
||||||
|
|
||||||
#ifdef TREE_CODE
|
#ifdef TREE_CODE
|
||||||
/* rtl.h and tree.h were included. */
|
/* rtl.h and tree.h were included. */
|
||||||
|
|
158
gcc/stmt.c
158
gcc/stmt.c
|
@ -43,7 +43,6 @@ Boston, MA 02111-1307, USA. */
|
||||||
#include "except.h"
|
#include "except.h"
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
#include "insn-config.h"
|
#include "insn-config.h"
|
||||||
#include "insn-codes.h"
|
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "libfuncs.h"
|
#include "libfuncs.h"
|
||||||
#include "hard-reg-set.h"
|
#include "hard-reg-set.h"
|
||||||
|
@ -5021,10 +5020,6 @@ check_for_full_enumeration_handling (type)
|
||||||
{
|
{
|
||||||
register struct case_node *n;
|
register struct case_node *n;
|
||||||
register tree chain;
|
register tree chain;
|
||||||
#if 0 /* variable used by 'if 0'ed code below. */
|
|
||||||
register struct case_node **l;
|
|
||||||
int all_values = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* True iff the selector type is a numbered set mode. */
|
/* True iff the selector type is a numbered set mode. */
|
||||||
int sparseness = 0;
|
int sparseness = 0;
|
||||||
|
@ -5122,28 +5117,6 @@ check_for_full_enumeration_handling (type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* ??? This optimization is disabled because it causes valid programs to
|
|
||||||
fail. ANSI C does not guarantee that an expression with enum type
|
|
||||||
will have a value that is the same as one of the enumeration literals. */
|
|
||||||
|
|
||||||
/* If all values were found as case labels, make one of them the default
|
|
||||||
label. Thus, this switch will never fall through. We arbitrarily pick
|
|
||||||
the last one to make the default since this is likely the most
|
|
||||||
efficient choice. */
|
|
||||||
|
|
||||||
if (all_values)
|
|
||||||
{
|
|
||||||
for (l = &case_stack->data.case_stmt.case_list;
|
|
||||||
(*l)->right != 0;
|
|
||||||
l = &(*l)->right)
|
|
||||||
;
|
|
||||||
|
|
||||||
case_stack->data.case_stmt.default_label = (*l)->code_label;
|
|
||||||
*l = 0;
|
|
||||||
}
|
|
||||||
#endif /* 0 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free CN, and its children. */
|
/* Free CN, and its children. */
|
||||||
|
@ -5161,6 +5134,7 @@ free_case_nodes (cn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Terminate a case (Pascal) or switch (C) statement
|
/* Terminate a case (Pascal) or switch (C) statement
|
||||||
in which ORIG_INDEX is the expression to be tested.
|
in which ORIG_INDEX is the expression to be tested.
|
||||||
Generate the code to test it and jump to the right place. */
|
Generate the code to test it and jump to the right place. */
|
||||||
|
@ -5289,18 +5263,7 @@ expand_end_case (orig_index)
|
||||||
If the switch-index is a constant, do it this way
|
If the switch-index is a constant, do it this way
|
||||||
because we can optimize it. */
|
because we can optimize it. */
|
||||||
|
|
||||||
#ifndef CASE_VALUES_THRESHOLD
|
else if (count < case_values_threshold ()
|
||||||
#ifdef HAVE_casesi
|
|
||||||
#define CASE_VALUES_THRESHOLD (HAVE_casesi ? 4 : 5)
|
|
||||||
#else
|
|
||||||
/* If machine does not have a case insn that compares the
|
|
||||||
bounds, this means extra overhead for dispatch tables
|
|
||||||
which raises the threshold for using them. */
|
|
||||||
#define CASE_VALUES_THRESHOLD 5
|
|
||||||
#endif /* HAVE_casesi */
|
|
||||||
#endif /* CASE_VALUES_THRESHOLD */
|
|
||||||
|
|
||||||
else if (count < CASE_VALUES_THRESHOLD
|
|
||||||
|| compare_tree_int (range, 10 * count) > 0
|
|| compare_tree_int (range, 10 * count) > 0
|
||||||
/* RANGE may be signed, and really large ranges will show up
|
/* RANGE may be signed, and really large ranges will show up
|
||||||
as negative numbers. */
|
as negative numbers. */
|
||||||
|
@ -5309,12 +5272,6 @@ expand_end_case (orig_index)
|
||||||
|| flag_pic
|
|| flag_pic
|
||||||
#endif
|
#endif
|
||||||
|| TREE_CODE (index_expr) == INTEGER_CST
|
|| TREE_CODE (index_expr) == INTEGER_CST
|
||||||
/* These will reduce to a constant. */
|
|
||||||
|| (TREE_CODE (index_expr) == CALL_EXPR
|
|
||||||
&& TREE_CODE (TREE_OPERAND (index_expr, 0)) == ADDR_EXPR
|
|
||||||
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (index_expr, 0), 0)) == FUNCTION_DECL
|
|
||||||
&& DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (index_expr, 0), 0)) == BUILT_IN_NORMAL
|
|
||||||
&& DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (index_expr, 0), 0)) == BUILT_IN_CLASSIFY_TYPE)
|
|
||||||
|| (TREE_CODE (index_expr) == COMPOUND_EXPR
|
|| (TREE_CODE (index_expr) == COMPOUND_EXPR
|
||||||
&& TREE_CODE (TREE_OPERAND (index_expr, 1)) == INTEGER_CST))
|
&& TREE_CODE (TREE_OPERAND (index_expr, 1)) == INTEGER_CST))
|
||||||
{
|
{
|
||||||
|
@ -5399,100 +5356,15 @@ expand_end_case (orig_index)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int win = 0;
|
if (! try_casesi (index_type, index_expr, minval, range,
|
||||||
#ifdef HAVE_casesi
|
table_label, default_label))
|
||||||
if (HAVE_casesi)
|
|
||||||
{
|
|
||||||
enum machine_mode index_mode = SImode;
|
|
||||||
int index_bits = GET_MODE_BITSIZE (index_mode);
|
|
||||||
rtx op1, op2;
|
|
||||||
enum machine_mode op_mode;
|
|
||||||
|
|
||||||
/* Convert the index to SImode. */
|
|
||||||
if (GET_MODE_BITSIZE (TYPE_MODE (index_type))
|
|
||||||
> GET_MODE_BITSIZE (index_mode))
|
|
||||||
{
|
|
||||||
enum machine_mode omode = TYPE_MODE (index_type);
|
|
||||||
rtx rangertx = expand_expr (range, NULL_RTX, VOIDmode, 0);
|
|
||||||
|
|
||||||
/* We must handle the endpoints in the original mode. */
|
|
||||||
index_expr = build (MINUS_EXPR, index_type,
|
|
||||||
index_expr, minval);
|
|
||||||
minval = integer_zero_node;
|
|
||||||
index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
|
|
||||||
emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
|
|
||||||
omode, 1, 0, default_label);
|
|
||||||
/* Now we can safely truncate. */
|
|
||||||
index = convert_to_mode (index_mode, index, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (TYPE_MODE (index_type) != index_mode)
|
|
||||||
{
|
|
||||||
index_expr = convert (type_for_size (index_bits, 0),
|
|
||||||
index_expr);
|
|
||||||
index_type = TREE_TYPE (index_expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
|
|
||||||
}
|
|
||||||
emit_queue ();
|
|
||||||
index = protect_from_queue (index, 0);
|
|
||||||
do_pending_stack_adjust ();
|
|
||||||
|
|
||||||
op_mode = insn_data[(int) CODE_FOR_casesi].operand[0].mode;
|
|
||||||
if (! (*insn_data[(int) CODE_FOR_casesi].operand[0].predicate)
|
|
||||||
(index, op_mode))
|
|
||||||
index = copy_to_mode_reg (op_mode, index);
|
|
||||||
|
|
||||||
op1 = expand_expr (minval, NULL_RTX, VOIDmode, 0);
|
|
||||||
|
|
||||||
op_mode = insn_data[(int) CODE_FOR_casesi].operand[1].mode;
|
|
||||||
op1 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (minval)),
|
|
||||||
op1, TREE_UNSIGNED (TREE_TYPE (minval)));
|
|
||||||
if (! (*insn_data[(int) CODE_FOR_casesi].operand[1].predicate)
|
|
||||||
(op1, op_mode))
|
|
||||||
op1 = copy_to_mode_reg (op_mode, op1);
|
|
||||||
|
|
||||||
op2 = expand_expr (range, NULL_RTX, VOIDmode, 0);
|
|
||||||
|
|
||||||
op_mode = insn_data[(int) CODE_FOR_casesi].operand[2].mode;
|
|
||||||
op2 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (range)),
|
|
||||||
op2, TREE_UNSIGNED (TREE_TYPE (range)));
|
|
||||||
if (! (*insn_data[(int) CODE_FOR_casesi].operand[2].predicate)
|
|
||||||
(op2, op_mode))
|
|
||||||
op2 = copy_to_mode_reg (op_mode, op2);
|
|
||||||
|
|
||||||
emit_jump_insn (gen_casesi (index, op1, op2,
|
|
||||||
table_label, default_label));
|
|
||||||
win = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_tablejump
|
|
||||||
if (! win && HAVE_tablejump)
|
|
||||||
{
|
{
|
||||||
index_type = thiscase->data.case_stmt.nominal_type;
|
index_type = thiscase->data.case_stmt.nominal_type;
|
||||||
index_expr = fold (build (MINUS_EXPR, index_type,
|
if (! try_tablejump (index_type, index_expr, minval, range,
|
||||||
convert (index_type, index_expr),
|
table_label, default_label))
|
||||||
convert (index_type, minval)));
|
abort ();
|
||||||
index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
|
|
||||||
emit_queue ();
|
|
||||||
index = protect_from_queue (index, 0);
|
|
||||||
do_pending_stack_adjust ();
|
|
||||||
|
|
||||||
do_tablejump (index, TYPE_MODE (index_type),
|
|
||||||
convert_modes (TYPE_MODE (index_type),
|
|
||||||
TYPE_MODE (TREE_TYPE (range)),
|
|
||||||
expand_expr (range, NULL_RTX,
|
|
||||||
VOIDmode, 0),
|
|
||||||
TREE_UNSIGNED (TREE_TYPE (range))),
|
|
||||||
table_label, default_label);
|
|
||||||
win = 1;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (! win)
|
|
||||||
abort ();
|
|
||||||
|
|
||||||
/* Get table of labels to jump to, in order of case index. */
|
/* Get table of labels to jump to, in order of case index. */
|
||||||
|
|
||||||
ncases = TREE_INT_CST_LOW (range) + 1;
|
ncases = TREE_INT_CST_LOW (range) + 1;
|
||||||
|
@ -6133,20 +6005,6 @@ emit_case_nodes (index, node, default_label, index_type)
|
||||||
else if (node->right == 0 && node->left != 0)
|
else if (node->right == 0 && node->left != 0)
|
||||||
{
|
{
|
||||||
/* Just one subtree, on the left. */
|
/* Just one subtree, on the left. */
|
||||||
|
|
||||||
#if 0 /* The following code and comment were formerly part
|
|
||||||
of the condition here, but they didn't work
|
|
||||||
and I don't understand what the idea was. -- rms. */
|
|
||||||
/* If our "most probable entry" is less probable
|
|
||||||
than the default label, emit a jump to
|
|
||||||
the default label using condition codes
|
|
||||||
already lying around. With no right branch,
|
|
||||||
a branch-greater-than will get us to the default
|
|
||||||
label correctly. */
|
|
||||||
if (use_cost_table
|
|
||||||
&& COST_TABLE (TREE_INT_CST_LOW (node->high)) < 12)
|
|
||||||
;
|
|
||||||
#endif /* 0 */
|
|
||||||
if (node->left->left || node->left->right
|
if (node->left->left || node->left->right
|
||||||
|| !tree_int_cst_equal (node->left->low, node->left->high))
|
|| !tree_int_cst_equal (node->left->low, node->left->high))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue