/* Convert tree expression to rtl instructions, for GNU compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+ Inc.
This file is part of GCC.
rtx value, insns;
convert_optab tab;
- gcc_assert (GET_MODE_PRECISION (from_mode)
- != GET_MODE_PRECISION (to_mode));
+ gcc_assert ((GET_MODE_PRECISION (from_mode)
+ != GET_MODE_PRECISION (to_mode))
+ || (DECIMAL_FLOAT_MODE_P (from_mode)
+ != DECIMAL_FLOAT_MODE_P (to_mode)));
- if (GET_MODE_PRECISION (from_mode) < GET_MODE_PRECISION (to_mode))
+ if (GET_MODE_PRECISION (from_mode) == GET_MODE_PRECISION (to_mode))
+ /* Conversion between decimal float and binary float, same size. */
+ tab = DECIMAL_FLOAT_MODE_P (from_mode) ? trunc_optab : sext_optab;
+ else if (GET_MODE_PRECISION (from_mode) < GET_MODE_PRECISION (to_mode))
tab = sext_optab;
else
tab = trunc_optab;
call_expr, arg_list, NULL_TREE);
CALL_EXPR_TAILCALL (call_expr) = tailcall;
- retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+ retval = expand_normal (call_expr);
return retval;
}
call_expr, arg_list, NULL_TREE);
CALL_EXPR_TAILCALL (call_expr) = tailcall;
- retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+ retval = expand_normal (call_expr);
return retval;
}
{
rtx ret;
- if (reload_in_progress && MEM_P (x))
+ if (MEM_P (x))
{
- /* We can't use gen_lowpart here because it may call change_address
- which is not appropriate if we were called when a reload was in
- progress. We don't have to worry about changing the address since
- the size in bytes is supposed to be the same. Copy the MEM to
- change the mode and move any substitutions from the old MEM to
- the new one. */
-
- ret = adjust_address_nv (x, new_mode, 0);
- copy_replacements (x, ret);
+ /* We don't have to worry about changing the address since the
+ size in bytes is supposed to be the same. */
+ if (reload_in_progress)
+ {
+ /* Copy the MEM to change the mode and move any
+ substitutions from the old MEM to the new one. */
+ ret = adjust_address_nv (x, new_mode, 0);
+ copy_replacements (x, ret);
+ }
+ else
+ ret = adjust_address (x, new_mode, 0);
}
else
{
#endif
if (code == PRE_DEC || code == POST_DEC)
adjust = -adjust;
+ else if (code == PRE_MODIFY || code == POST_MODIFY)
+ {
+ rtx expr = XEXP (XEXP (x, 0), 1);
+ HOST_WIDE_INT val;
+
+ gcc_assert (GET_CODE (expr) == PLUS || GET_CODE (expr) == MINUS);
+ gcc_assert (GET_CODE (XEXP (expr, 1)) == CONST_INT);
+ val = INTVAL (XEXP (expr, 1));
+ if (GET_CODE (expr) == MINUS)
+ val = -val;
+ gcc_assert (adjust == val || adjust == -val);
+ adjust = val;
+ }
/* Do not use anti_adjust_stack, since we don't want to update
stack_pointer_delta. */
{
case PRE_INC:
case PRE_DEC:
+ case PRE_MODIFY:
temp = stack_pointer_rtx;
break;
case POST_INC:
- temp = plus_constant (stack_pointer_rtx, -GET_MODE_SIZE (mode));
- break;
case POST_DEC:
- temp = plus_constant (stack_pointer_rtx, GET_MODE_SIZE (mode));
+ case POST_MODIFY:
+ temp = plus_constant (stack_pointer_rtx, -adjust);
break;
default:
gcc_unreachable ();
if (COMPLEX_MODE_P (mode))
return emit_move_complex (mode, x, y);
+ if (GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT)
+ {
+ rtx result = emit_move_via_integer (mode, x, y, true);
+
+ /* If we can't find an integer mode, use multi words. */
+ if (result)
+ return result;
+ else
+ return emit_move_multi_word (mode, x, y);
+ }
+
if (GET_MODE_CLASS (mode) == MODE_CC)
return emit_move_ccmode (mode, x, y);
if (TREE_CODE (to) == ERROR_MARK)
{
- result = expand_expr (from, NULL_RTX, VOIDmode, 0);
+ result = expand_normal (from);
return;
}
/* If we are going to use store_bit_field and extract_bit_field,
make sure to_rtx will be safe for multiple use. */
- to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0);
+ to_rtx = expand_normal (tem);
if (offset != 0)
{
rtx value;
push_temp_slots ();
- value = expand_expr (from, NULL_RTX, VOIDmode, 0);
+ value = expand_normal (from);
if (to_rtx == 0)
to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
push_temp_slots ();
size = expr_size (from);
- from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
+ from_rtx = expand_normal (from);
emit_library_call (memmove_libfunc, LCT_NORMAL,
VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
case REAL_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
- case CHAR_TYPE:
case POINTER_TYPE:
case OFFSET_TYPE:
case REFERENCE_TYPE:
make_tree (TREE_TYPE (exp),
target));
- offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
+ offset_rtx = expand_normal (offset);
gcc_assert (MEM_P (to_rtx));
#ifdef POINTERS_EXTEND_UNSIGNED
rtx loop_end = gen_label_rtx ();
tree exit_cond;
- expand_expr (hi_index, NULL_RTX, VOIDmode, 0);
+ expand_normal (hi_index);
unsignedp = TYPE_UNSIGNED (domain);
index = build_decl (VAR_DECL, NULL_TREE, domain);
convert (ssizetype,
TYPE_SIZE_UNIT (elttype)));
- pos_rtx = expand_expr (position, 0, VOIDmode, 0);
+ pos_rtx = expand_normal (position);
xtarget = offset_address (target, pos_rtx,
highest_pow2_factor (position));
xtarget = adjust_address (xtarget, mode, 0);
convert (ssizetype,
TYPE_SIZE_UNIT (elttype)));
xtarget = offset_address (target,
- expand_expr (position, 0, VOIDmode, 0),
+ expand_normal (position),
highest_pow2_factor (position));
xtarget = adjust_address (xtarget, mode, 0);
store_expr (value, xtarget, 0);
vectors in the case of BLKmode vectors. */
gcc_assert (TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE);
RTVEC_ELT (vector, eltpos)
- = expand_expr (value, NULL_RTX, VOIDmode, 0);
+ = expand_normal (value);
}
else
{
}
}
- temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
+ temp = expand_normal (exp);
/* If BITSIZE is narrower than the size of the type of EXP
we will be narrowing TEMP. Normally, what's wanted are the
return subtarget;
}
- if (code == ZERO_EXTEND || code == SIGN_EXTEND)
- {
- if (!target)
- target = gen_reg_rtx (GET_MODE (value));
- convert_move (target, force_operand (XEXP (value, 0), NULL),
- code == ZERO_EXTEND);
- return target;
- }
-
if (ARITHMETIC_P (value))
{
op2 = XEXP (value, 1);
}
if (UNARY_P (value))
{
+ if (!target)
+ target = gen_reg_rtx (GET_MODE (value));
op1 = force_operand (XEXP (value, 0), NULL_RTX);
- return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
+ switch (code)
+ {
+ case ZERO_EXTEND:
+ case SIGN_EXTEND:
+ case TRUNCATE:
+ convert_move (target, op1, code == ZERO_EXTEND);
+ return target;
+
+ case FIX:
+ case UNSIGNED_FIX:
+ expand_fix (target, op1, code == UNSIGNED_FIX);
+ return target;
+
+ case FLOAT:
+ case UNSIGNED_FLOAT:
+ expand_float (target, op1, code == UNSIGNED_FLOAT);
+ return target;
+
+ default:
+ return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
+ }
}
#ifdef INSN_SCHEDULING
/* Get the signedness used for this variable. Ensure we get the
same mode we got when the variable was declared. */
pmode = promote_mode (type, DECL_MODE (exp), &unsignedp,
- (TREE_CODE (exp) == RESULT_DECL ? 1 : 0));
+ (TREE_CODE (exp) == RESULT_DECL
+ || TREE_CODE (exp) == PARM_DECL) ? 1 : 0);
gcc_assert (GET_MODE (DECL_RTL (exp)) == pmode);
temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
break;
}
}
- else if (TREE_CODE (init) == STRING_CST
- && 0 > compare_tree_int (index,
- TREE_STRING_LENGTH (init)))
+ else if(TREE_CODE (init) == STRING_CST)
{
- tree type = TREE_TYPE (TREE_TYPE (init));
- enum machine_mode mode = TYPE_MODE (type);
-
- if (GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_SIZE (mode) == 1)
- return gen_int_mode (TREE_STRING_POINTER (init)
- [TREE_INT_CST_LOW (index)], mode);
+ tree index1 = index;
+ tree low_bound = array_ref_low_bound (exp);
+ index1 = fold_convert (sizetype, TREE_OPERAND (exp, 1));
+
+ /* Optimize the special-case of a zero lower bound.
+
+ We convert the low_bound to sizetype to avoid some problems
+ with constant folding. (E.g. suppose the lower bound is 1,
+ and its mode is QI. Without the conversion,l (ARRAY
+ +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
+ +INDEX), which becomes (ARRAY+255+INDEX). Opps!) */
+
+ if (! integer_zerop (low_bound))
+ index1 = size_diffop (index1, fold_convert (sizetype,
+ low_bound));
+
+ if (0 > compare_tree_int (index1,
+ TREE_STRING_LENGTH (init)))
+ {
+ tree type = TREE_TYPE (TREE_TYPE (init));
+ enum machine_mode mode = TYPE_MODE (type);
+
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) == 1)
+ return gen_int_mode (TREE_STRING_POINTER (init)
+ [TREE_INT_CST_LOW (index1)],
+ mode);
+ }
}
}
}
if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
TREE_OPERAND (exp, 1),
- NULL_RTX, &op0, &op1, 0);
+ NULL_RTX, &op0, &op1, EXPAND_NORMAL);
else
expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
- NULL_RTX, &op0, &op1, 0);
+ NULL_RTX, &op0, &op1, EXPAND_NORMAL);
goto binop3;
}
else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
&& innermode == word_mode)
{
rtx htem, hipart;
- op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
- NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (TREE_OPERAND (TREE_OPERAND (exp, 0), 0));
if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
op1 = convert_modes (innermode, mode,
- expand_expr (TREE_OPERAND (exp, 1),
- NULL_RTX, VOIDmode, 0),
+ expand_normal (TREE_OPERAND (exp, 1)),
unsignedp);
else
- op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
- NULL_RTX, VOIDmode, 0);
+ op1 = expand_normal (TREE_OPERAND (TREE_OPERAND (exp, 1), 0));
temp = expand_binop (mode, other_optab, op0, op1, target,
unsignedp, OPTAB_LIB_WIDEN);
hipart = gen_highpart (innermode, temp);
gcc_unreachable (); /* Not used for C. */
case FIX_TRUNC_EXPR:
- op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (TREE_OPERAND (exp, 0));
if (target == 0 || modifier == EXPAND_STACK_PARM)
target = gen_reg_rtx (mode);
expand_fix (target, op0, unsignedp);
return target;
case FLOAT_EXPR:
- op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (TREE_OPERAND (exp, 0));
if (target == 0 || modifier == EXPAND_STACK_PARM)
target = gen_reg_rtx (mode);
/* expand_float can't figure out what to do if FROM has VOIDmode.
else
comparison_code = unsignedp ? LEU : LE;
- /* Canonicalize to comparsions against 0. */
+ /* Canonicalize to comparisons against 0. */
if (op1 == const1_rtx)
{
/* Converting (a >= 1 ? a : 1) into (a > 0 ? a : 1)
emit_move_insn (target, op0);
temp = gen_label_rtx ();
-
- /* If this mode is an integer too wide to compare properly,
- compare word by word. Rely on cse to optimize constant cases. */
- if (GET_MODE_CLASS (mode) == MODE_INT
- && ! can_compare_p (GE, mode, ccp_jump))
- {
- if (code == MAX_EXPR)
- do_jump_by_parts_greater_rtx (mode, unsignedp, target, op1,
- NULL_RTX, temp);
- else
- do_jump_by_parts_greater_rtx (mode, unsignedp, op1, target,
- NULL_RTX, temp);
- }
- else
- {
- do_compare_rtx_and_jump (target, cmpop1, comparison_code,
- unsignedp, mode, NULL_RTX, NULL_RTX, temp);
- }
+ do_compare_rtx_and_jump (target, cmpop1, comparison_code,
+ unsignedp, mode, NULL_RTX, NULL_RTX, temp);
}
emit_move_insn (target, op1);
emit_label (temp);
case COMPLEX_EXPR:
/* Get the rtx code of the operands. */
- op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
- op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
+ op0 = expand_normal (TREE_OPERAND (exp, 0));
+ op1 = expand_normal (TREE_OPERAND (exp, 1));
if (!target)
target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
return target;
case REALPART_EXPR:
- op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
+ op0 = expand_normal (TREE_OPERAND (exp, 0));
return read_complex_part (op0, false);
case IMAGPART_EXPR:
- op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
+ op0 = expand_normal (TREE_OPERAND (exp, 0));
return read_complex_part (op0, true);
case RESX_EXPR:
rtx op2;
this_optab = optab_for_tree_code (code, type);
- expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, 0);
- op2 = expand_expr (oprnd2, NULL_RTX, VOIDmode, 0);
+ expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+ op2 = expand_normal (oprnd2);
temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
target, unsignedp);
gcc_assert (temp);
return temp;
}
+ case DOT_PROD_EXPR:
+ {
+ tree oprnd0 = TREE_OPERAND (exp, 0);
+ tree oprnd1 = TREE_OPERAND (exp, 1);
+ tree oprnd2 = TREE_OPERAND (exp, 2);
+ rtx op2;
+
+ expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+ op2 = expand_normal (oprnd2);
+ target = expand_widen_pattern_expr (exp, op0, op1, op2,
+ target, unsignedp);
+ return target;
+ }
+
+ case WIDEN_SUM_EXPR:
+ {
+ tree oprnd0 = TREE_OPERAND (exp, 0);
+ tree oprnd1 = TREE_OPERAND (exp, 1);
+
+ expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, 0);
+ target = expand_widen_pattern_expr (exp, op0, NULL_RTX, op1,
+ target, unsignedp);
+ return target;
+ }
+
case REDUC_MAX_EXPR:
case REDUC_MIN_EXPR:
case REDUC_PLUS_EXPR:
{
- op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (TREE_OPERAND (exp, 0));
this_optab = optab_for_tree_code (code, type);
temp = expand_unop (mode, this_optab, op0, target, unsignedp);
gcc_assert (temp);
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);
+ rtx rangertx = expand_normal (range);
/* We must handle the endpoints in the original mode. */
index_expr = build2 (MINUS_EXPR, index_type,
index_expr, minval);
minval = integer_zero_node;
- index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
+ index = expand_normal (index_expr);
emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
omode, 1, default_label);
/* Now we can safely truncate. */
index_type = TREE_TYPE (index_expr);
}
- index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
+ index = expand_normal (index_expr);
}
do_pending_stack_adjust ();
(index, op_mode))
index = copy_to_mode_reg (op_mode, index);
- op1 = expand_expr (minval, NULL_RTX, VOIDmode, 0);
+ op1 = expand_normal (minval);
op_mode = insn_data[(int) CODE_FOR_casesi].operand[1].mode;
op1 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (minval)),
(op1, op_mode))
op1 = copy_to_mode_reg (op_mode, op1);
- op2 = expand_expr (range, NULL_RTX, VOIDmode, 0);
+ op2 = expand_normal (range);
op_mode = insn_data[(int) CODE_FOR_casesi].operand[2].mode;
op2 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (range)),
index_expr = fold_build2 (MINUS_EXPR, index_type,
convert (index_type, index_expr),
convert (index_type, minval));
- index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
+ index = expand_normal (index_expr);
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),
+ expand_normal (range),
TYPE_UNSIGNED (TREE_TYPE (range))),
table_label, default_label);
return 1;