/* 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, 2006, 2007, 2008, 2009
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#include "output.h"
#include "typeclass.h"
#include "toplev.h"
-#include "ggc.h"
#include "langhooks.h"
#include "intl.h"
#include "tm_p.h"
&& GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT
&& CONST_INT_P (x) && INTVAL (x) < 0)
{
- HOST_WIDE_INT val = INTVAL (x);
+ double_int val = uhwi_to_double_int (INTVAL (x));
- if (oldmode != VOIDmode
- && HOST_BITS_PER_WIDE_INT > GET_MODE_BITSIZE (oldmode))
- {
- int width = GET_MODE_BITSIZE (oldmode);
+ /* We need to zero extend VAL. */
+ if (oldmode != VOIDmode)
+ val = double_int_zext (val, GET_MODE_BITSIZE (oldmode));
- /* We need to zero extend VAL. */
- val &= ((HOST_WIDE_INT) 1 << width) - 1;
- }
-
- return immed_double_const (val, (HOST_WIDE_INT) 0, mode);
+ return immed_double_int_const (val, mode);
}
/* We can do this with a gen_lowpart if both desired and current modes
}
align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
+ gcc_assert (align >= BITS_PER_UNIT);
gcc_assert (MEM_P (x));
gcc_assert (MEM_P (y));
an outgoing argument. */
#if defined (REG_PARM_STACK_SPACE)
fn = emit_block_move_libcall_fn (false);
+ /* Avoid set but not used warning if *REG_PARM_STACK_SPACE doesn't
+ depend on its argument. */
+ (void) fn;
if (OUTGOING_REG_PARM_STACK_SPACE ((!fn ? NULL_TREE : TREE_TYPE (fn)))
&& REG_PARM_STACK_SPACE (fn) != 0)
return false;
if (len == 0)
return 1;
- if (! (memsetp
+ if (! (memsetp
? SET_BY_PIECES_P (len, align)
: STORE_BY_PIECES_P (len, align)))
return 0;
/* In case we are returning the contents of an object which overlaps
the place the value is being stored, use a safe function when copying
a value through a pointer into a structure value return block. */
- if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF
+ if (TREE_CODE (to) == RESULT_DECL
+ && TREE_CODE (from) == INDIRECT_REF
&& ADDR_SPACE_GENERIC_P
- (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (from, 0)))))
+ (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (from, 0)))))
+ && refs_may_alias_p (to, from)
&& cfun->returns_struct
&& !cfun->returns_pcc_struct)
{
If CALL_PARAM_P is nonzero, this is a store into a call param on the
stack, and block moves may need to be treated specially.
-
+
If NONTEMPORAL is true, try using a nontemporal store instruction. */
rtx
do_pending_stack_adjust ();
NO_DEFER_POP;
- jumpifnot (TREE_OPERAND (exp, 0), lab1);
+ jumpifnot (TREE_OPERAND (exp, 0), lab1, -1);
store_expr (TREE_OPERAND (exp, 1), target, call_param_p,
nontemporal);
emit_jump_insn (gen_jump (lab2));
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, purpose, value)
{
- HOST_WIDE_INT mult;
+ HOST_WIDE_INT mult = 1;
- mult = 1;
if (TREE_CODE (purpose) == RANGE_EXPR)
{
tree lo_index = TREE_OPERAND (purpose, 0);
break;
default:
- nz_elts += mult;
- elt_count += mult;
+ {
+ HOST_WIDE_INT tc = count_type_elements (TREE_TYPE (value), true);
+ if (tc < 1)
+ tc = 1;
+ nz_elts += mult * tc;
+ elt_count += mult * tc;
- if (const_from_elts_p && const_p)
- const_p = initializer_constant_valid_p (value, TREE_TYPE (value))
- != NULL_TREE;
+ if (const_from_elts_p && const_p)
+ const_p = initializer_constant_valid_p (value, TREE_TYPE (value))
+ != NULL_TREE;
+ }
break;
}
}
/* Generate a conditional jump to exit the loop. */
exit_cond = build2 (LT_EXPR, integer_type_node,
index, hi_index);
- jumpif (exit_cond, loop_end);
+ jumpif (exit_cond, loop_end, -1);
/* Update the loop counter, and jump to the head of
the loop. */
ALIAS_SET is the alias set for the destination. This value will
(in general) be different from that for TARGET, since TARGET is a
reference to the containing structure.
-
+
If NONTEMPORAL is true, try generating a nontemporal store. */
static rtx
/* First get the mode, signedness, and size. We do this from just the
outermost expression. */
+ *pbitsize = -1;
if (TREE_CODE (exp) == COMPONENT_REF)
{
tree field = TREE_OPERAND (exp, 1);
case COMPONENT_REF:
{
tree field = TREE_OPERAND (exp, 1);
- packed_p = DECL_PACKED (field)
+ packed_p = DECL_PACKED (field)
|| TYPE_PACKED (TREE_TYPE (field))
|| TYPE_PACKED (TREE_TYPE (exp));
if (packed_p)
{
unsigned HOST_WIDE_INT talign = target_align (target) / BITS_PER_UNIT;
unsigned HOST_WIDE_INT factor = highest_pow2_factor (exp);
-
+
return MAX (factor, talign);
}
\f
return expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
case CONST_DECL:
- /* Recurse and make the output_constant_def clause above handle this. */
- return expand_expr_addr_expr_1 (DECL_INITIAL (exp), target,
- tmode, modifier, as);
+ /* Expand the initializer like constants above. */
+ return XEXP (expand_expr_constant (DECL_INITIAL (exp), 0, modifier), 0);
case REALPART_EXPR:
/* The real part of the complex number is always first, therefore
if (modifier != EXPAND_NORMAL)
result = force_operand (result, NULL);
- tmp = expand_expr (offset, NULL_RTX, tmode,
+ tmp = expand_expr (offset, NULL_RTX, tmode,
modifier == EXPAND_INITIALIZER
? EXPAND_INITIALIZER : EXPAND_NORMAL);
if (cfun && EXPR_HAS_LOCATION (exp))
{
location_t saved_location = input_location;
+ location_t saved_curr_loc = get_curr_insn_source_location ();
+ tree saved_block = get_curr_insn_block ();
input_location = EXPR_LOCATION (exp);
set_curr_insn_source_location (input_location);
ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
input_location = saved_location;
+ set_curr_insn_block (saved_block);
+ set_curr_insn_source_location (saved_curr_loc);
}
else
{
optab this_optab;
rtx subtarget, original_target;
int ignore;
- tree subexp0, subexp1;
bool reduce_bit_field;
gimple subexp0_def, subexp1_def;
tree top0, top1;
return CONST0_RTX (mode);
}
- case POINTER_PLUS_EXPR:
+ case POINTER_PLUS_EXPR:
/* Even though the sizetype mode and the pointer's mode can be different
- expand is able to handle this correctly and get the correct result out
+ expand is able to handle this correctly and get the correct result out
of the PLUS_EXPR code. */
/* Make sure to sign-extend the sizetype offset in a POINTER_PLUS_EXPR
if sizetype precision is smaller than pointer precision. */
goto binop2;
- case MULT_EXPR:
- /* If this is a fixed-point operation, then we cannot use the code
- below because "expand_mult" doesn't support sat/no-sat fixed-point
- multiplications. */
- if (ALL_FIXED_POINT_MODE_P (mode))
- goto binop;
-
+ case WIDEN_MULT_EXPR:
/* If first operand is constant, swap them.
Thus the following special case checks need only
check the second operand. */
treeop1 = t1;
}
- /* Attempt to return something suitable for generating an
- indexed address, for machines that support that. */
-
- if (modifier == EXPAND_SUM && mode == ptr_mode
- && host_integerp (treeop1, 0))
- {
- tree exp1 = treeop1;
-
- op0 = expand_expr (treeop0, subtarget, VOIDmode,
- EXPAND_SUM);
-
- if (!REG_P (op0))
- op0 = force_operand (op0, NULL_RTX);
- if (!REG_P (op0))
- op0 = copy_to_mode_reg (mode, op0);
-
- return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
- gen_int_mode (tree_low_cst (exp1, 0),
- TYPE_MODE (TREE_TYPE (exp1)))));
- }
-
- if (modifier == EXPAND_STACK_PARM)
- target = 0;
-
- /* Check for multiplying things that have been extended
- from a narrower type. If this machine supports multiplying
- in that narrower type with a result in the desired type,
- do it that way, and avoid the explicit type-conversion. */
-
- subexp0 = treeop0;
- subexp1 = treeop1;
- subexp0_def = get_def_for_expr (subexp0, NOP_EXPR);
- subexp1_def = get_def_for_expr (subexp1, NOP_EXPR);
- top0 = top1 = NULL_TREE;
-
/* First, check if we have a multiplication of one signed and one
unsigned operand. */
- if (subexp0_def
- && (top0 = gimple_assign_rhs1 (subexp0_def))
- && subexp1_def
- && (top1 = gimple_assign_rhs1 (subexp1_def))
- && TREE_CODE (type) == INTEGER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (top0))
- < TYPE_PRECISION (TREE_TYPE (subexp0)))
- && (TYPE_PRECISION (TREE_TYPE (top0))
- == TYPE_PRECISION (TREE_TYPE (top1)))
- && (TYPE_UNSIGNED (TREE_TYPE (top0))
- != TYPE_UNSIGNED (TREE_TYPE (top1))))
+ if (TREE_CODE (treeop1) != INTEGER_CST
+ && (TYPE_UNSIGNED (TREE_TYPE (treeop0))
+ != TYPE_UNSIGNED (TREE_TYPE (treeop1))))
{
- enum machine_mode innermode
- = TYPE_MODE (TREE_TYPE (top0));
+ enum machine_mode innermode = TYPE_MODE (TREE_TYPE (treeop0));
this_optab = usmul_widen_optab;
- if (mode == GET_MODE_WIDER_MODE (innermode))
+ if (mode == GET_MODE_2XWIDER_MODE (innermode))
{
if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
{
- if (TYPE_UNSIGNED (TREE_TYPE (top0)))
- expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+ if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))
+ expand_operands (treeop0, treeop1, subtarget, &op0, &op1,
EXPAND_NORMAL);
else
- expand_operands (top0, top1, NULL_RTX, &op1, &op0,
+ expand_operands (treeop0, treeop1, subtarget, &op1, &op0,
EXPAND_NORMAL);
-
goto binop3;
}
}
}
- /* Check for a multiplication with matching signedness. If
- valid, TOP0 and TOP1 were set in the previous if
- condition. */
- else if (top0
- && TREE_CODE (type) == INTEGER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (top0))
- < TYPE_PRECISION (TREE_TYPE (subexp0)))
- && ((TREE_CODE (subexp1) == INTEGER_CST
- && int_fits_type_p (subexp1, TREE_TYPE (top0))
- /* Don't use a widening multiply if a shift will do. */
- && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (subexp1)))
- > HOST_BITS_PER_WIDE_INT)
- || exact_log2 (TREE_INT_CST_LOW (subexp1)) < 0))
- ||
- (top1
- && (TYPE_PRECISION (TREE_TYPE (top1))
- == TYPE_PRECISION (TREE_TYPE (top0))
- /* If both operands are extended, they must either both
- be zero-extended or both be sign-extended. */
- && (TYPE_UNSIGNED (TREE_TYPE (top1))
- == TYPE_UNSIGNED (TREE_TYPE (top0)))))))
+ /* Check for a multiplication with matching signedness. */
+ else if ((TREE_CODE (treeop1) == INTEGER_CST
+ && int_fits_type_p (treeop1, TREE_TYPE (treeop0)))
+ || (TYPE_UNSIGNED (TREE_TYPE (treeop1))
+ == TYPE_UNSIGNED (TREE_TYPE (treeop0))))
{
- tree op0type = TREE_TYPE (top0);
+ tree op0type = TREE_TYPE (treeop0);
enum machine_mode innermode = TYPE_MODE (op0type);
bool zextend_p = TYPE_UNSIGNED (op0type);
optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
{
if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
{
- if (TREE_CODE (subexp1) == INTEGER_CST)
- expand_operands (top0, subexp1, NULL_RTX, &op0, &op1,
- EXPAND_NORMAL);
- else
- expand_operands (top0, top1, NULL_RTX, &op0, &op1,
- EXPAND_NORMAL);
- goto binop3;
+ expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
+ EXPAND_NORMAL);
+ temp = expand_widening_mult (mode, op0, op1, target,
+ unsignedp, this_optab);
+ return REDUCE_BIT_FIELD (temp);
}
- else if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
- && innermode == word_mode)
+ if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
+ && innermode == word_mode)
{
rtx htem, hipart;
- op0 = expand_normal (top0);
- if (TREE_CODE (subexp1) == INTEGER_CST)
+ op0 = expand_normal (treeop0);
+ if (TREE_CODE (treeop1) == INTEGER_CST)
op1 = convert_modes (innermode, mode,
- expand_normal (subexp1), unsignedp);
+ expand_normal (treeop1), unsignedp);
else
- op1 = expand_normal (top1);
+ op1 = expand_normal (treeop1);
temp = expand_binop (mode, other_optab, op0, op1, target,
unsignedp, OPTAB_LIB_WIDEN);
hipart = gen_highpart (innermode, temp);
}
}
}
- expand_operands (subexp0, subexp1, subtarget, &op0, &op1, EXPAND_NORMAL);
+ treeop0 = fold_build1 (CONVERT_EXPR, type, treeop0);
+ treeop1 = fold_build1 (CONVERT_EXPR, type, treeop1);
+ expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL);
+ return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
+
+ case MULT_EXPR:
+ /* If this is a fixed-point operation, then we cannot use the code
+ below because "expand_mult" doesn't support sat/no-sat fixed-point
+ multiplications. */
+ if (ALL_FIXED_POINT_MODE_P (mode))
+ goto binop;
+
+ /* If first operand is constant, swap them.
+ Thus the following special case checks need only
+ check the second operand. */
+ if (TREE_CODE (treeop0) == INTEGER_CST)
+ {
+ tree t1 = treeop0;
+ treeop0 = treeop1;
+ treeop1 = t1;
+ }
+
+ /* Attempt to return something suitable for generating an
+ indexed address, for machines that support that. */
+
+ if (modifier == EXPAND_SUM && mode == ptr_mode
+ && host_integerp (treeop1, 0))
+ {
+ tree exp1 = treeop1;
+
+ op0 = expand_expr (treeop0, subtarget, VOIDmode,
+ EXPAND_SUM);
+
+ if (!REG_P (op0))
+ op0 = force_operand (op0, NULL_RTX);
+ if (!REG_P (op0))
+ op0 = copy_to_mode_reg (mode, op0);
+
+ return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
+ gen_int_mode (tree_low_cst (exp1, 0),
+ TYPE_MODE (TREE_TYPE (exp1)))));
+ }
+
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
+
+ expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL);
return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
case TRUNC_DIV_EXPR:
temp = gen_label_rtx ();
do_compare_rtx_and_jump (target, cmpop1, comparison_code,
- unsignedp, mode, NULL_RTX, NULL_RTX, temp);
+ unsignedp, mode, NULL_RTX, NULL_RTX, temp,
+ -1);
}
emit_move_insn (target, op1);
emit_label (temp);
emit_move_insn (target, const0_rtx);
op1 = gen_label_rtx ();
- jumpifnot_1 (code, treeop0, treeop1, op1);
+ jumpifnot_1 (code, treeop0, treeop1, op1, -1);
emit_move_insn (target, const1_rtx);
{
gimple g = get_gimple_for_ssa_name (exp);
if (g)
- return expand_expr_real_1 (gimple_assign_rhs_to_tree (g), target,
- tmode, modifier, NULL);
+ return expand_expr_real (gimple_assign_rhs_to_tree (g), target,
+ tmode, modifier, NULL);
}
decl_rtl = get_rtx_for_ssa_name (exp);
exp = SSA_NAME_VAR (exp);
{
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
struct mem_address addr;
+ tree base;
get_address_description (exp, &addr);
op0 = addr_for_mem_ref (&addr, as, true);
temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, TMR_ORIGINAL (exp), 0);
set_mem_addr_space (temp, as);
+ base = get_base_address (TMR_ORIGINAL (exp));
+ if (INDIRECT_REF_P (base)
+ && TMR_BASE (exp)
+ && TREE_CODE (TMR_BASE (exp)) == SSA_NAME
+ && POINTER_TYPE_P (TREE_TYPE (TMR_BASE (exp))))
+ {
+ set_mem_expr (temp, build1 (INDIRECT_REF,
+ TREE_TYPE (exp), TMR_BASE (exp)));
+ set_mem_offset (temp, NULL_RTX);
+ }
}
return temp;
op0 = force_reg (GET_MODE (op0), op0);
op0 = gen_lowpart (mode, op0);
}
- /* If both modes are integral, then we can convert from one to the
- other. */
- else if (SCALAR_INT_MODE_P (GET_MODE (op0)) && SCALAR_INT_MODE_P (mode))
- op0 = convert_modes (mode, GET_MODE (op0), op0,
+ /* If both types are integral, convert from one mode to the other. */
+ else if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (treeop0)))
+ op0 = convert_modes (mode, GET_MODE (op0), op0,
TYPE_UNSIGNED (TREE_TYPE (treeop0)));
/* As a last resort, spill op0 to memory, and reload it in a
different mode. */
emit_move_insn (target, const0_rtx);
op1 = gen_label_rtx ();
- jumpifnot_1 (code, treeop0, treeop1, op1);
+ jumpifnot_1 (code, treeop0, treeop1, op1, -1);
if (target)
emit_move_insn (target, const1_rtx);
NO_DEFER_POP;
op0 = gen_label_rtx ();
op1 = gen_label_rtx ();
- jumpifnot (treeop0, op0);
+ jumpifnot (treeop0, op0, -1);
store_expr (treeop1, temp,
modifier == EXPAND_STACK_PARM,
false);
int value = TREE_CODE (rhs) == BIT_IOR_EXPR;
do_jump (TREE_OPERAND (rhs, 1),
value ? label : 0,
- value ? 0 : label);
+ value ? 0 : label, -1);
expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value),
MOVE_NONTEMPORAL (exp));
do_pending_stack_adjust ();
}
else if (TYPE_UNSIGNED (type))
{
- rtx mask;
- if (prec < HOST_BITS_PER_WIDE_INT)
- mask = immed_double_const (((unsigned HOST_WIDE_INT) 1 << prec) - 1, 0,
- GET_MODE (exp));
- else
- mask = immed_double_const ((unsigned HOST_WIDE_INT) -1,
- ((unsigned HOST_WIDE_INT) 1
- << (prec - HOST_BITS_PER_WIDE_INT)) - 1,
- GET_MODE (exp));
+ rtx mask = immed_double_int_const (double_int_mask (prec),
+ GET_MODE (exp));
return expand_and (GET_MODE (exp), exp, mask, target);
}
else
RTVEC_ELT (v, i) = CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (elt),
inner);
else
- RTVEC_ELT (v, i) = immed_double_const (TREE_INT_CST_LOW (elt),
- TREE_INT_CST_HIGH (elt),
- inner);
+ RTVEC_ELT (v, i) = immed_double_int_const (tree_to_double_int (elt),
+ inner);
}
/* Initialize remaining elements to 0. */