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
&& 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;
}
}
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, \
&& (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_at (tree_nonartificial_location (exp),
0, "%Kcall to %qs declared with attribute warning: %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))));
/* Check for a built-in function. */
/* 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,
/* 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, EXPAND_NORMAL);
+ 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, EXPAND_NORMAL);
+ 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, EXPAND_NORMAL);
+ expand_operands (subexp0, subexp1, subtarget, &op0, &op1, EXPAND_NORMAL);
return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
case TRUNC_DIV_EXPR:
case LTGT_EXPR:
temp = do_store_flag (exp,
modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
- tmode != VOIDmode ? tmode : mode);
+ (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 ();