/* 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
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
#include "timevar.h"
#include "df.h"
#include "diagnostic.h"
+#include "ssaexpand.h"
/* Decide whether a function's arguments should be processed
from first to last or from last to first.
static void expand_operands (tree, tree, rtx, rtx*, rtx*,
enum expand_modifier);
static rtx reduce_to_bit_field_precision (rtx, rtx, tree);
-static rtx do_store_flag (tree, rtx, enum machine_mode, int);
+static rtx do_store_flag (tree, rtx, enum machine_mode);
#ifdef PUSH_ROUNDING
static void emit_single_push_insn (enum machine_mode, rtx, tree);
#endif
enum insn_code sync_new_xor_optab[NUM_MACHINE_MODES];
enum insn_code sync_new_nand_optab[NUM_MACHINE_MODES];
enum insn_code sync_compare_and_swap[NUM_MACHINE_MODES];
-enum insn_code sync_compare_and_swap_cc[NUM_MACHINE_MODES];
enum insn_code sync_lock_test_and_set[NUM_MACHINE_MODES];
enum insn_code sync_lock_release[NUM_MACHINE_MODES];
reg = gen_rtx_REG (VOIDmode, -1);
insn = rtx_alloc (INSN);
- pat = gen_rtx_SET (0, NULL_RTX, NULL_RTX);
+ pat = gen_rtx_SET (VOIDmode, NULL_RTX, NULL_RTX);
PATTERN (insn) = pat;
for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
if (unsignedp)
fill_value = const0_rtx;
else
- {
-#ifdef HAVE_slt
- if (HAVE_slt
- && insn_data[(int) CODE_FOR_slt].operand[0].mode == word_mode
- && STORE_FLAG_VALUE == -1)
- {
- emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX,
- lowpart_mode, 0);
- fill_value = gen_reg_rtx (word_mode);
- emit_insn (gen_slt (fill_value));
- }
- else
-#endif
- {
- fill_value
- = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom,
- size_int (GET_MODE_BITSIZE (lowpart_mode) - 1),
- NULL_RTX, 0);
- fill_value = convert_to_mode (word_mode, fill_value, 1);
- }
- }
+ fill_value = emit_store_flag (gen_reg_rtx (word_mode),
+ LT, lowfrom, const0_rtx,
+ VOIDmode, 0, -1);
/* Fill the remaining words. */
for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++)
use_reg (call_fusage, reg);
}
}
+
+/* Return the defining gimple statement for SSA_NAME NAME if it is an
+ assigment and the code of the expresion on the RHS is CODE. Return
+ NULL otherwise. */
+
+static gimple
+get_def_for_expr (tree name, enum tree_code code)
+{
+ gimple def_stmt;
+
+ if (TREE_CODE (name) != SSA_NAME)
+ return NULL;
+
+ def_stmt = get_gimple_for_ssa_name (name);
+ if (!def_stmt
+ || gimple_assign_rhs_code (def_stmt) != code)
+ return NULL;
+
+ return def_stmt;
+}
\f
/* Determine whether the LEN bytes generated by CONSTFUN can be
for the function we use for block clears. The first time FOR_CALL
is true, we call assemble_external. */
-static GTY(()) tree block_clear_fn;
+tree block_clear_fn;
void
init_block_clear_fn (const char *asmspec)
Don't do this if TO is a VAR_DECL or PARM_DECL whose DECL_RTL is REG
since it might be a promoted variable where the zero- or sign- extension
needs to be done. Handling this in the normal way is safe because no
- computation is done before the call. */
+ computation is done before the call. The same is true for SSA names. */
if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from, from)
&& COMPLETE_TYPE_P (TREE_TYPE (from))
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
- && ! ((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
- && REG_P (DECL_RTL (to))))
+ && ! (((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
+ && REG_P (DECL_RTL (to)))
+ || TREE_CODE (to) == SSA_NAME))
{
rtx value;
&& compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
{
rtx temp;
+ gimple nop_def;
/* If EXP is a NOP_EXPR of precision less than its mode, then that
implies a mask operation. If the precision is the same size as
the field we're storing into, that mask is redundant. This is
particularly common with bit field assignments generated by the
C front end. */
- if (TREE_CODE (exp) == NOP_EXPR)
+ nop_def = get_def_for_expr (exp, NOP_EXPR);
+ if (nop_def)
{
tree type = TREE_TYPE (exp);
if (INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < GET_MODE_BITSIZE (TYPE_MODE (type))
&& bitsize == TYPE_PRECISION (type))
{
- type = TREE_TYPE (TREE_OPERAND (exp, 0));
+ tree op = gimple_assign_rhs1 (nop_def);
+ type = TREE_TYPE (op);
if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) >= bitsize)
- exp = TREE_OPERAND (exp, 0);
+ exp = op;
}
}
else
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
}
-
-/* Return 1 if T is an expression that get_inner_reference handles. */
-
-int
-handled_component_p (const_tree t)
-{
- switch (TREE_CODE (t))
- {
- case BIT_FIELD_REF:
- case COMPONENT_REF:
- case ARRAY_REF:
- case ARRAY_RANGE_REF:
- case VIEW_CONVERT_EXPR:
- case REALPART_EXPR:
- case IMAGPART_EXPR:
- return 1;
-
- default:
- return 0;
- }
-}
\f
/* Given an rtx VALUE that may contain additions and multiplications, return
an equivalent value that just refers to a register, memory, or constant.
CONSTRUCTORs too, which should yield a memory reference for the
constructor's contents. Assume language specific tree nodes can
be expanded in some interesting way. */
+ gcc_assert (TREE_CODE (exp) < LAST_AND_UNUSED_TREE_CODE);
if (DECL_P (exp)
|| TREE_CODE (exp) == CONSTRUCTOR
- || TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE)
+ || TREE_CODE (exp) == COMPOUND_LITERAL_EXPR)
{
result = expand_expr (exp, target, tmode,
modifier == EXPAND_INITIALIZER
int ignore;
tree context, subexp0, subexp1;
bool reduce_bit_field;
+ gimple subexp0_def, subexp1_def;
+ tree top0, top1;
#define REDUCE_BIT_FIELD(expr) (reduce_bit_field \
? reduce_to_bit_field_precision ((expr), \
target, \
}
case SSA_NAME:
- return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier,
- NULL);
+ /* ??? ivopts calls expander, without any preparation from
+ out-of-ssa. So fake instructions as if this was an access to the
+ base variable. This unnecessarily allocates a pseudo, see how we can
+ reuse it, if partition base vars have it set already. */
+ if (!currently_expanding_to_rtl)
+ return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier, NULL);
+ {
+ 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);
+ }
+ decl_rtl = get_rtx_for_ssa_name (exp);
+ exp = SSA_NAME_VAR (exp);
+ goto expand_decl_rtl;
case PARM_DECL:
case VAR_DECL:
case FUNCTION_DECL:
case RESULT_DECL:
decl_rtl = DECL_RTL (exp);
+ expand_decl_rtl:
gcc_assert (decl_rtl);
decl_rtl = copy_rtx (decl_rtl);
&& (attr = lookup_attribute ("error",
DECL_ATTRIBUTES (fndecl))) != NULL)
error ("%Kcall to %qs declared with attribute error: %s",
- exp, lang_hooks.decl_printable_name (fndecl, 1),
+ exp, identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 1)),
TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
if (fndecl
&& (attr = lookup_attribute ("warning",
DECL_ATTRIBUTES (fndecl))) != NULL)
- warning (0, "%Kcall to %qs declared with attribute warning: %s",
- exp, lang_hooks.decl_printable_name (fndecl, 1),
- TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
+ warning_at (tree_nonartificial_location (exp),
+ 0, "%Kcall to %qs declared with attribute warning: %s",
+ exp, identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 1)),
+ TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
/* Check for a built-in function. */
if (fndecl && DECL_BUILT_IN (fndecl))
{
- if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_FRONTEND)
- return lang_hooks.expand_expr (exp, original_target,
- tmode, modifier, alt_rtl);
- else
- return expand_builtin (exp, target, subtarget, tmode, ignore);
+ gcc_assert (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_FRONTEND);
+ return expand_builtin (exp, target, subtarget, tmode, ignore);
}
}
return expand_call (exp, target, ignore);
/* 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
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. */
+ if (TYPE_PRECISION (sizetype) < TYPE_PRECISION (type))
+ exp = build2 (PLUS_EXPR, type,
+ TREE_OPERAND (exp, 0),
+ fold_convert (type,
+ fold_convert (ssizetype,
+ TREE_OPERAND (exp, 1))));
case PLUS_EXPR:
/* Check if this is a case for multiplication and addition. */
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == FIXED_POINT_TYPE)
- && TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR)
+ && (subexp0_def = get_def_for_expr (TREE_OPERAND (exp, 0),
+ MULT_EXPR)))
{
tree subsubexp0, subsubexp1;
- enum tree_code code0, code1, this_code;
+ gimple subsubexp0_def, subsubexp1_def;
+ enum tree_code this_code;
- subexp0 = TREE_OPERAND (exp, 0);
- subsubexp0 = TREE_OPERAND (subexp0, 0);
- subsubexp1 = TREE_OPERAND (subexp0, 1);
- code0 = TREE_CODE (subsubexp0);
- code1 = TREE_CODE (subsubexp1);
this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR
: FIXED_CONVERT_EXPR;
- if (code0 == this_code && code1 == this_code
- && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+ subsubexp0 = gimple_assign_rhs1 (subexp0_def);
+ subsubexp0_def = get_def_for_expr (subsubexp0, this_code);
+ subsubexp1 = gimple_assign_rhs2 (subexp0_def);
+ subsubexp1_def = get_def_for_expr (subsubexp1, this_code);
+ if (subsubexp0_def && subsubexp1_def
+ && (top0 = gimple_assign_rhs1 (subsubexp0_def))
+ && (top1 = gimple_assign_rhs1 (subsubexp1_def))
+ && (TYPE_PRECISION (TREE_TYPE (top0))
< TYPE_PRECISION (TREE_TYPE (subsubexp0)))
- && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))
- && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
- == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))))
+ && (TYPE_PRECISION (TREE_TYPE (top0))
+ == TYPE_PRECISION (TREE_TYPE (top1)))
+ && (TYPE_UNSIGNED (TREE_TYPE (top0))
+ == TYPE_UNSIGNED (TREE_TYPE (top1))))
{
- tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
+ tree op0type = TREE_TYPE (top0);
enum machine_mode innermode = TYPE_MODE (op0type);
bool zextend_p = TYPE_UNSIGNED (op0type);
bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0));
&& (optab_handler (this_optab, mode)->insn_code
!= CODE_FOR_nothing))
{
- expand_operands (TREE_OPERAND (subsubexp0, 0),
- TREE_OPERAND (subsubexp1, 0),
- NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+ expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+ EXPAND_NORMAL);
op2 = expand_expr (TREE_OPERAND (exp, 1), subtarget,
VOIDmode, EXPAND_NORMAL);
temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
|| mode != ptr_mode)
{
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
- subtarget, &op0, &op1, 0);
+ subtarget, &op0, &op1, EXPAND_NORMAL);
if (op0 == const0_rtx)
return op1;
if (op1 == const0_rtx)
/* Check if this is a case for multiplication and subtraction. */
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == FIXED_POINT_TYPE)
- && TREE_CODE (TREE_OPERAND (exp, 1)) == MULT_EXPR)
+ && (subexp1_def = get_def_for_expr (TREE_OPERAND (exp, 1),
+ MULT_EXPR)))
{
tree subsubexp0, subsubexp1;
- enum tree_code code0, code1, this_code;
+ gimple subsubexp0_def, subsubexp1_def;
+ enum tree_code this_code;
- subexp1 = TREE_OPERAND (exp, 1);
- subsubexp0 = TREE_OPERAND (subexp1, 0);
- subsubexp1 = TREE_OPERAND (subexp1, 1);
- code0 = TREE_CODE (subsubexp0);
- code1 = TREE_CODE (subsubexp1);
this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR
: FIXED_CONVERT_EXPR;
- if (code0 == this_code && code1 == this_code
- && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+ subsubexp0 = gimple_assign_rhs1 (subexp1_def);
+ subsubexp0_def = get_def_for_expr (subsubexp0, this_code);
+ subsubexp1 = gimple_assign_rhs2 (subexp1_def);
+ subsubexp1_def = get_def_for_expr (subsubexp1, this_code);
+ if (subsubexp0_def && subsubexp1_def
+ && (top0 = gimple_assign_rhs1 (subsubexp0_def))
+ && (top1 = gimple_assign_rhs1 (subsubexp1_def))
+ && (TYPE_PRECISION (TREE_TYPE (top0))
< TYPE_PRECISION (TREE_TYPE (subsubexp0)))
- && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))
- && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
- == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))))
+ && (TYPE_PRECISION (TREE_TYPE (top0))
+ == TYPE_PRECISION (TREE_TYPE (top1)))
+ && (TYPE_UNSIGNED (TREE_TYPE (top0))
+ == TYPE_UNSIGNED (TREE_TYPE (top1))))
{
- tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
+ tree op0type = TREE_TYPE (top0);
enum machine_mode innermode = TYPE_MODE (op0type);
bool zextend_p = TYPE_UNSIGNED (op0type);
bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0));
&& (optab_handler (this_optab, mode)->insn_code
!= CODE_FOR_nothing))
{
- expand_operands (TREE_OPERAND (subsubexp0, 0),
- TREE_OPERAND (subsubexp1, 0),
- NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+ expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+ EXPAND_NORMAL);
op2 = expand_expr (TREE_OPERAND (exp, 0), subtarget,
VOIDmode, EXPAND_NORMAL);
temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
subexp0 = TREE_OPERAND (exp, 0);
subexp1 = TREE_OPERAND (exp, 1);
+ 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 (TREE_CODE (subexp0) == NOP_EXPR
- && TREE_CODE (subexp1) == NOP_EXPR
+ 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 (TREE_OPERAND (subexp0, 0)))
- < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
- && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subexp0, 0)))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subexp1, 0))))
- && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subexp0, 0)))
- != TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subexp1, 0)))))
+ && (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))))
{
enum machine_mode innermode
- = TYPE_MODE (TREE_TYPE (TREE_OPERAND (subexp0, 0)));
+ = TYPE_MODE (TREE_TYPE (top0));
this_optab = usmul_widen_optab;
if (mode == GET_MODE_WIDER_MODE (innermode))
{
if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
{
- if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subexp0, 0))))
- expand_operands (TREE_OPERAND (subexp0, 0),
- TREE_OPERAND (subexp1, 0),
- NULL_RTX, &op0, &op1, 0);
+ if (TYPE_UNSIGNED (TREE_TYPE (top0)))
+ expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+ EXPAND_NORMAL);
else
- expand_operands (TREE_OPERAND (subexp0, 0),
- TREE_OPERAND (subexp1, 0),
- NULL_RTX, &op1, &op0, 0);
+ expand_operands (top0, top1, NULL_RTX, &op1, &op0,
+ EXPAND_NORMAL);
goto binop3;
}
}
}
- /* Check for a multiplication with matching signedness. */
- else if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
+ /* 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 (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
- < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
- && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
- && int_fits_type_p (TREE_OPERAND (exp, 1),
- TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
+ && (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 (TREE_OPERAND (exp, 1))))
+ && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (subexp1)))
> HOST_BITS_PER_WIDE_INT)
- || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0))
+ || exact_log2 (TREE_INT_CST_LOW (subexp1)) < 0))
||
- (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
- && (TYPE_PRECISION (TREE_TYPE
- (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
- == TYPE_PRECISION (TREE_TYPE
- (TREE_OPERAND
- (TREE_OPERAND (exp, 0), 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
- (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
- == TYPE_UNSIGNED (TREE_TYPE
- (TREE_OPERAND
- (TREE_OPERAND (exp, 0), 0)))))))
+ && (TYPE_UNSIGNED (TREE_TYPE (top1))
+ == TYPE_UNSIGNED (TREE_TYPE (top0)))))))
{
- tree op0type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0));
+ tree op0type = TREE_TYPE (top0);
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 (TREE_OPERAND (exp, 1)) == INTEGER_CST)
- expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
- TREE_OPERAND (exp, 1),
- NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+ if (TREE_CODE (subexp1) == INTEGER_CST)
+ expand_operands (top0, subexp1, 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, EXPAND_NORMAL);
+ expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+ EXPAND_NORMAL);
goto binop3;
}
else if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
&& innermode == word_mode)
{
rtx htem, hipart;
- op0 = expand_normal (TREE_OPERAND (TREE_OPERAND (exp, 0), 0));
- if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
+ op0 = expand_normal (top0);
+ if (TREE_CODE (subexp1) == INTEGER_CST)
op1 = convert_modes (innermode, mode,
- expand_normal (TREE_OPERAND (exp, 1)),
- unsignedp);
+ expand_normal (subexp1), unsignedp);
else
- op1 = expand_normal (TREE_OPERAND (TREE_OPERAND (exp, 1), 0));
+ op1 = expand_normal (top1);
temp = expand_binop (mode, other_optab, op0, op1, target,
unsignedp, OPTAB_LIB_WIDEN);
hipart = gen_highpart (innermode, temp);
}
}
}
- expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
- subtarget, &op0, &op1, 0);
+ expand_operands (subexp0, subexp1, subtarget, &op0, &op1, EXPAND_NORMAL);
return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
case TRUNC_DIV_EXPR:
then if the divisor is constant can optimize the case
where some terms of the dividend have coeffs divisible by it. */
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
- subtarget, &op0, &op1, 0);
+ subtarget, &op0, &op1, EXPAND_NORMAL);
return expand_divmod (0, code, mode, op0, op1, target, unsignedp);
case RDIV_EXPR:
if (modifier == EXPAND_STACK_PARM)
target = 0;
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
- subtarget, &op0, &op1, 0);
+ subtarget, &op0, &op1, EXPAND_NORMAL);
return expand_divmod (1, code, mode, op0, op1, target, unsignedp);
case FIXED_CONVERT_EXPR:
&& REGNO (target) < FIRST_PSEUDO_REGISTER))
target = gen_reg_rtx (mode);
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
- target, &op0, &op1, 0);
+ target, &op0, &op1, EXPAND_NORMAL);
/* First try to do it with a special MIN or MAX instruction.
If that does not win, use a conditional jump to select the proper
case LTGT_EXPR:
temp = do_store_flag (exp,
modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
- tmode != VOIDmode ? tmode : mode, 0);
+ (tmode != VOIDmode
+ /* do_store_flag does not handle target modes
+ of a different class than the comparison mode.
+ Avoid ICEing in convert_move. */
+ && GET_MODE_CLASS (tmode) == GET_MODE_CLASS (mode))
+ ? tmode : mode);
if (temp != 0)
return temp;
/* Lowered by gimplify.c. */
gcc_unreachable ();
- case CHANGE_DYNAMIC_TYPE_EXPR:
- /* This is ignored at the RTL level. The tree level set
- DECL_POINTER_ALIAS_SET of any variable to be 0, which is
- overkill for the RTL layer but is all that we can
- represent. */
- return const0_rtx;
-
case EXC_PTR_EXPR:
return get_exception_pointer ();
tree oprnd0 = TREE_OPERAND (exp, 0);
tree oprnd1 = TREE_OPERAND (exp, 1);
- expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, 0);
+ expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
target = expand_widen_pattern_expr (exp, op0, NULL_RTX, op1,
target, unsignedp);
return target;
case VEC_EXTRACT_ODD_EXPR:
{
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
- NULL_RTX, &op0, &op1, 0);
+ NULL_RTX, &op0, &op1, EXPAND_NORMAL);
this_optab = optab_for_tree_code (code, type, optab_default);
temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
OPTAB_WIDEN);
case VEC_INTERLEAVE_LOW_EXPR:
{
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
- NULL_RTX, &op0, &op1, 0);
+ NULL_RTX, &op0, &op1, EXPAND_NORMAL);
this_optab = optab_for_tree_code (code, type, optab_default);
temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
OPTAB_WIDEN);
tree oprnd0 = TREE_OPERAND (exp, 0);
tree oprnd1 = TREE_OPERAND (exp, 1);
- expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, 0);
+ expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
target = expand_widen_pattern_expr (exp, op0, op1, NULL_RTX,
target, unsignedp);
gcc_assert (target);
mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
goto binop;
+ case COMPOUND_LITERAL_EXPR:
+ {
+ /* Initialize the anonymous variable declared in the compound
+ literal, then return the variable. */
+ tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
+
+ /* Create RTL for this variable. */
+ if (!DECL_RTL_SET_P (decl))
+ {
+ if (DECL_HARD_REGISTER (decl))
+ /* The user specified an assembler name for this variable.
+ Set that up now. */
+ rest_of_decl_compilation (decl, 0, 0);
+ else
+ expand_decl (decl);
+ }
+
+ return expand_expr_real (decl, original_target, tmode,
+ modifier, alt_rtl);
+ }
+
default:
- return lang_hooks.expand_expr (exp, original_target, tmode,
- modifier, alt_rtl);
+ gcc_unreachable ();
}
/* Here to do an ordinary binary operator. */
binop:
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
- subtarget, &op0, &op1, 0);
+ subtarget, &op0, &op1, EXPAND_NORMAL);
binop2:
this_optab = optab_for_tree_code (code, type, optab_default);
binop3:
If TARGET is nonzero, store the result there if convenient.
- If ONLY_CHEAP is nonzero, only do this if it is likely to be very
- cheap.
-
Return zero if there is no suitable set-flag instruction
available on this machine.
set/jump/set sequence. */
static rtx
-do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap)
+do_store_flag (tree exp, rtx target, enum machine_mode mode)
{
enum rtx_code code;
tree arg0, arg1, type;
int invert = 0;
int unsignedp;
rtx op0, op1;
- enum insn_code icode;
rtx subtarget = target;
rtx result, label;
if (! can_compare_p (code, operand_mode, ccp_store_flag))
return 0;
- icode = setcc_gen_code[(int) code];
-
- if (icode == CODE_FOR_nothing)
- {
- enum machine_mode wmode;
-
- for (wmode = operand_mode;
- icode == CODE_FOR_nothing && wmode != VOIDmode;
- wmode = GET_MODE_WIDER_MODE (wmode))
- icode = optab_handler (cstore_optab, wmode)->insn_code;
- }
-
- if (icode == CODE_FOR_nothing
- || (only_cheap && insn_data[(int) icode].operand[0].mode != mode))
- {
- /* We can only do this if it is one of the special cases that
- can be handled without an scc insn. */
- if ((code == LT && integer_zerop (arg1))
- || (! only_cheap && code == GE && integer_zerop (arg1)))
- ;
- else if (! only_cheap && (code == NE || code == EQ)
- && TREE_CODE (type) != REAL_TYPE
- && ((optab_handler (abs_optab, operand_mode)->insn_code
- != CODE_FOR_nothing)
- || (optab_handler (ffs_optab, operand_mode)->insn_code
- != CODE_FOR_nothing)))
- ;
- else
- return 0;
- }
-
if (! get_subtarget (target)
|| GET_MODE (subtarget) != operand_mode)
subtarget = 0;
- expand_operands (arg0, arg1, subtarget, &op0, &op1, 0);
+ expand_operands (arg0, arg1, subtarget, &op0, &op1, EXPAND_NORMAL);
if (target == 0)
target = gen_reg_rtx (mode);
# define CODE_FOR_casesi CODE_FOR_nothing
#endif
-/* 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 (void)
-{
- 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