Commit cc7b5acf by Richard Biener Committed by Richard Biener

match.pd: Implement patterns from associate_plusminus and factor in differences from the...

2014-11-11  Richard Biener  <rguenther@suse.de>

	* match.pd: Implement patterns from associate_plusminus
	and factor in differences from the fold-const.c implementation.
	* fold-const.c (fold_binary_loc): Remove patterns here.
	* tree-ssa-forwprop.c (associate_plusminus): Remove.
	(pass_forwprop::execute): Don't call it.
	* tree.c (tree_nop_conversion_p): New function, factored
	from tree_nop_conversion.
	* tree.h (tree_nop_conversion_p): Declare.

From-SVN: r217349
parent 9310366b
2014-11-11 Richard Biener <rguenther@suse.de>
* match.pd: Implement patterns from associate_plusminus
and factor in differences from the fold-const.c implementation.
* fold-const.c (fold_binary_loc): Remove patterns here.
* tree-ssa-forwprop.c (associate_plusminus): Remove.
(pass_forwprop::execute): Don't call it.
* tree.c (tree_nop_conversion_p): New function, factored
from tree_nop_conversion.
* tree.h (tree_nop_conversion_p): Declare.
2014-11-11 Uros Bizjak <ubizjak@gmail.com>
* system.h: Include algorithm and utility.
......@@ -9939,59 +9939,8 @@ fold_binary_loc (location_t loc,
return NULL_TREE;
case PLUS_EXPR:
/* A + (-B) -> A - B */
if (TREE_CODE (arg1) == NEGATE_EXPR
&& (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
return fold_build2_loc (loc, MINUS_EXPR, type,
fold_convert_loc (loc, type, arg0),
fold_convert_loc (loc, type,
TREE_OPERAND (arg1, 0)));
/* (-A) + B -> B - A */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& reorder_operands_p (TREE_OPERAND (arg0, 0), arg1)
&& (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
return fold_build2_loc (loc, MINUS_EXPR, type,
fold_convert_loc (loc, type, arg1),
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
{
/* Convert ~A + 1 to -A. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& integer_each_onep (arg1))
return fold_build1_loc (loc, NEGATE_EXPR, type,
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
/* ~X + X is -1. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& !TYPE_OVERFLOW_TRAPS (type))
{
tree tem = TREE_OPERAND (arg0, 0);
STRIP_NOPS (tem);
if (operand_equal_p (tem, arg1, 0))
{
t1 = build_all_ones_cst (type);
return omit_one_operand_loc (loc, type, t1, arg1);
}
}
/* X + ~X is -1. */
if (TREE_CODE (arg1) == BIT_NOT_EXPR
&& !TYPE_OVERFLOW_TRAPS (type))
{
tree tem = TREE_OPERAND (arg1, 0);
STRIP_NOPS (tem);
if (operand_equal_p (arg0, tem, 0))
{
t1 = build_all_ones_cst (type);
return omit_one_operand_loc (loc, type, t1, arg0);
}
}
/* X + (X / CST) * -CST is X % CST. */
if (TREE_CODE (arg1) == MULT_EXPR
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
......@@ -10469,11 +10418,6 @@ fold_binary_loc (location_t loc,
return fold_build2_loc (loc, MINUS_EXPR, type, tmp, arg11);
}
}
/* A - (-B) -> A + B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
return fold_build2_loc (loc, PLUS_EXPR, type, op0,
fold_convert_loc (loc, type,
TREE_OPERAND (arg1, 0)));
/* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& negate_expr_p (arg1)
......
......@@ -25,8 +25,9 @@ along with GCC; see the file COPYING3. If not see
/* Generic tree predicates we inherit. */
(define_predicates
integer_onep integer_zerop integer_all_onesp
real_zerop real_onep
integer_onep integer_zerop integer_all_onesp integer_minus_onep
integer_each_onep
real_zerop real_onep real_minus_onep
CONSTANT_CLASS_P
tree_expr_nonnegative_p)
......@@ -239,10 +240,6 @@ along with GCC; see the file COPYING3. If not see
(bit_not (bit_not @0))
@0)
(simplify
(negate (negate @0))
@0)
/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */
(simplify
......@@ -278,6 +275,116 @@ along with GCC; see the file COPYING3. If not see
(bit_and @0 { algn; })))
/* We can't reassociate at all for saturating types. */
(if (!TYPE_SATURATING (type))
/* Contract negates. */
/* A + (-B) -> A - B */
(simplify
(plus:c (convert1? @0) (convert2? (negate @1)))
/* Apply STRIP_NOPS on @0 and the negate. */
(if (tree_nop_conversion_p (type, TREE_TYPE (@0))
&& tree_nop_conversion_p (type, TREE_TYPE (@1))
&& (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
(minus (convert @0) (convert @1))))
/* A - (-B) -> A + B */
(simplify
(minus (convert1? @0) (convert2? (negate @1)))
(if (tree_nop_conversion_p (type, TREE_TYPE (@0))
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(plus (convert @0) (convert @1))))
/* -(-A) -> A */
(simplify
(negate (convert? (negate @1)))
(if (tree_nop_conversion_p (type, TREE_TYPE (@1))
&& (TYPE_OVERFLOW_WRAPS (type)
|| (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0))
@1))
/* We can't reassociate floating-point or fixed-point plus or minus
because of saturation to +-Inf. */
(if (!FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))
/* Match patterns that allow contracting a plus-minus pair
irrespective of overflow issues. */
/* (A +- B) - A -> +- B */
/* (A +- B) -+ B -> A */
/* A - (A +- B) -> -+ B */
/* A +- (B -+ A) -> +- B */
(simplify
(minus (plus:c @0 @1) @0)
@1)
(simplify
(minus (minus @0 @1) @0)
(negate @1))
(simplify
(plus:c (minus @0 @1) @1)
@0)
(simplify
(minus @0 (plus:c @0 @1))
(negate @1))
(simplify
(minus @0 (minus @0 @1))
@1)
/* (A +- CST) +- CST -> A + CST */
(for outer_op (plus minus)
(for inner_op (plus minus)
(simplify
(outer_op (inner_op @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
/* If the constant operation overflows we cannot do the transform
as we would introduce undefined overflow, for example
with (a - 1) + INT_MIN. */
(with { tree cst = fold_binary (outer_op == inner_op
? PLUS_EXPR : MINUS_EXPR, type, @1, @2); }
(if (cst && !TREE_OVERFLOW (cst))
(inner_op @0 { cst; } ))))))
/* (CST - A) +- CST -> CST - A */
(for outer_op (plus minus)
(simplify
(outer_op (minus CONSTANT_CLASS_P@1 @0) CONSTANT_CLASS_P@2)
(with { tree cst = fold_binary (outer_op, type, @1, @2); }
(if (cst && !TREE_OVERFLOW (cst))
(minus { cst; } @0)))))
/* ~A + A -> -1 */
(simplify
(plus:c (bit_not @0) @0)
(if (!TYPE_OVERFLOW_TRAPS (type))
{ build_all_ones_cst (type); }))
/* ~A + 1 -> -A */
(simplify
(plus (bit_not @0) integer_each_onep)
(negate @0))
/* (T)(P + A) - (T)P -> (T) A */
(for add (plus pointer_plus)
(simplify
(minus (convert (add @0 @1))
(convert @0))
(if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
/* For integer types, if A has a smaller type
than T the result depends on the possible
overflow in P + A.
E.g. T=size_t, A=(unsigned)429497295, P>0.
However, if an overflow in P + A would cause
undefined behavior, we can assume that there
is no overflow. */
|| (INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
/* For pointer types, if the conversion of A to the
final type requires a sign- or zero-extension,
then we have to punt - it is not defined which
one is correct. */
|| (POINTER_TYPE_P (TREE_TYPE (@0))
&& TREE_CODE (@1) == INTEGER_CST
&& tree_int_cst_sign_bit (@1) == 0))
(convert @1))))))
/* Simplifications of conversions. */
/* Basic strip-useless-type-conversions / strip_nops. */
......
......@@ -1920,359 +1920,6 @@ simplify_rotate (gimple_stmt_iterator *gsi)
return true;
}
/* Perform re-associations of the plus or minus statement STMT that are
always permitted. Returns true if the CFG was changed. */
static bool
associate_plusminus (gimple_stmt_iterator *gsi)
{
gimple stmt = gsi_stmt (*gsi);
tree rhs1 = gimple_assign_rhs1 (stmt);
tree rhs2 = gimple_assign_rhs2 (stmt);
enum tree_code code = gimple_assign_rhs_code (stmt);
bool changed;
/* We can't reassociate at all for saturating types. */
if (TYPE_SATURATING (TREE_TYPE (rhs1)))
return false;
/* First contract negates. */
do
{
changed = false;
/* A +- (-B) -> A -+ B. */
if (TREE_CODE (rhs2) == SSA_NAME)
{
gimple def_stmt = SSA_NAME_DEF_STMT (rhs2);
if (is_gimple_assign (def_stmt)
&& gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR
&& can_propagate_from (def_stmt))
{
code = (code == MINUS_EXPR) ? PLUS_EXPR : MINUS_EXPR;
gimple_assign_set_rhs_code (stmt, code);
rhs2 = gimple_assign_rhs1 (def_stmt);
gimple_assign_set_rhs2 (stmt, rhs2);
gimple_set_modified (stmt, true);
changed = true;
}
}
/* (-A) + B -> B - A. */
if (TREE_CODE (rhs1) == SSA_NAME
&& code == PLUS_EXPR)
{
gimple def_stmt = SSA_NAME_DEF_STMT (rhs1);
if (is_gimple_assign (def_stmt)
&& gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR
&& can_propagate_from (def_stmt))
{
code = MINUS_EXPR;
gimple_assign_set_rhs_code (stmt, code);
rhs1 = rhs2;
gimple_assign_set_rhs1 (stmt, rhs1);
rhs2 = gimple_assign_rhs1 (def_stmt);
gimple_assign_set_rhs2 (stmt, rhs2);
gimple_set_modified (stmt, true);
changed = true;
}
}
}
while (changed);
/* We can't reassociate floating-point or fixed-point plus or minus
because of saturation to +-Inf. */
if (FLOAT_TYPE_P (TREE_TYPE (rhs1))
|| FIXED_POINT_TYPE_P (TREE_TYPE (rhs1)))
goto out;
/* Second match patterns that allow contracting a plus-minus pair
irrespective of overflow issues.
(A +- B) - A -> +- B
(A +- B) -+ B -> A
(CST +- A) +- CST -> CST +- A
(A +- CST) +- CST -> A +- CST
~A + A -> -1
~A + 1 -> -A
A - (A +- B) -> -+ B
A +- (B +- A) -> +- B
CST +- (CST +- A) -> CST +- A
CST +- (A +- CST) -> CST +- A
A + ~A -> -1
(T)(P + A) - (T)P -> (T)A
via commutating the addition and contracting operations to zero
by reassociation. */
if (TREE_CODE (rhs1) == SSA_NAME)
{
gimple def_stmt = SSA_NAME_DEF_STMT (rhs1);
if (is_gimple_assign (def_stmt) && can_propagate_from (def_stmt))
{
enum tree_code def_code = gimple_assign_rhs_code (def_stmt);
if (def_code == PLUS_EXPR
|| def_code == MINUS_EXPR)
{
tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
tree def_rhs2 = gimple_assign_rhs2 (def_stmt);
if (operand_equal_p (def_rhs1, rhs2, 0)
&& code == MINUS_EXPR)
{
/* (A +- B) - A -> +- B. */
code = ((def_code == PLUS_EXPR)
? TREE_CODE (def_rhs2) : NEGATE_EXPR);
rhs1 = def_rhs2;
rhs2 = NULL_TREE;
gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
gcc_assert (gsi_stmt (*gsi) == stmt);
gimple_set_modified (stmt, true);
}
else if (operand_equal_p (def_rhs2, rhs2, 0)
&& code != def_code)
{
/* (A +- B) -+ B -> A. */
code = TREE_CODE (def_rhs1);
rhs1 = def_rhs1;
rhs2 = NULL_TREE;
gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
gcc_assert (gsi_stmt (*gsi) == stmt);
gimple_set_modified (stmt, true);
}
else if (CONSTANT_CLASS_P (rhs2)
&& CONSTANT_CLASS_P (def_rhs1))
{
/* (CST +- A) +- CST -> CST +- A. */
tree cst = fold_binary (code, TREE_TYPE (rhs1),
def_rhs1, rhs2);
if (cst && !TREE_OVERFLOW (cst))
{
code = def_code;
gimple_assign_set_rhs_code (stmt, code);
rhs1 = cst;
gimple_assign_set_rhs1 (stmt, rhs1);
rhs2 = def_rhs2;
gimple_assign_set_rhs2 (stmt, rhs2);
gimple_set_modified (stmt, true);
}
}
else if (CONSTANT_CLASS_P (rhs2)
&& CONSTANT_CLASS_P (def_rhs2))
{
/* (A +- CST) +- CST -> A +- CST. */
enum tree_code mix = (code == def_code)
? PLUS_EXPR : MINUS_EXPR;
tree cst = fold_binary (mix, TREE_TYPE (rhs1),
def_rhs2, rhs2);
if (cst && !TREE_OVERFLOW (cst))
{
code = def_code;
gimple_assign_set_rhs_code (stmt, code);
rhs1 = def_rhs1;
gimple_assign_set_rhs1 (stmt, rhs1);
rhs2 = cst;
gimple_assign_set_rhs2 (stmt, rhs2);
gimple_set_modified (stmt, true);
}
}
}
else if (def_code == BIT_NOT_EXPR && code == PLUS_EXPR)
{
tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
if (operand_equal_p (def_rhs1, rhs2, 0))
{
/* ~A + A -> -1. */
rhs1 = build_all_ones_cst (TREE_TYPE (rhs2));
rhs2 = NULL_TREE;
code = TREE_CODE (rhs1);
gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
gcc_assert (gsi_stmt (*gsi) == stmt);
gimple_set_modified (stmt, true);
}
else if ((TREE_CODE (TREE_TYPE (rhs2)) != COMPLEX_TYPE
&& integer_onep (rhs2))
|| (TREE_CODE (rhs2) == COMPLEX_CST
&& integer_onep (TREE_REALPART (rhs2))
&& integer_onep (TREE_IMAGPART (rhs2))))
{
/* ~A + 1 -> -A. */
code = NEGATE_EXPR;
rhs1 = def_rhs1;
rhs2 = NULL_TREE;
gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
gcc_assert (gsi_stmt (*gsi) == stmt);
gimple_set_modified (stmt, true);
}
}
else if (code == MINUS_EXPR
&& CONVERT_EXPR_CODE_P (def_code)
&& TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
&& TREE_CODE (rhs2) == SSA_NAME)
{
/* (T)(P + A) - (T)P -> (T)A. */
gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs2);
if (is_gimple_assign (def_stmt2)
&& can_propagate_from (def_stmt2)
&& CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
&& TREE_CODE (gimple_assign_rhs1 (def_stmt2)) == SSA_NAME)
{
/* Now we have (T)X - (T)P. */
tree p = gimple_assign_rhs1 (def_stmt2);
def_stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
if (is_gimple_assign (def_stmt2)
&& can_propagate_from (def_stmt2)
&& (gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
|| gimple_assign_rhs_code (def_stmt2) == PLUS_EXPR)
&& gimple_assign_rhs1 (def_stmt2) == p)
{
/* And finally (T)(P + A) - (T)P. */
tree a = gimple_assign_rhs2 (def_stmt2);
if (TYPE_PRECISION (TREE_TYPE (rhs1))
<= TYPE_PRECISION (TREE_TYPE (a))
/* For integer types, if A has a smaller type
than T the result depends on the possible
overflow in P + A.
E.g. T=size_t, A=(unsigned)429497295, P>0.
However, if an overflow in P + A would cause
undefined behavior, we can assume that there
is no overflow. */
|| (INTEGRAL_TYPE_P (TREE_TYPE (p))
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (p)))
/* For pointer types, if the conversion of A to the
final type requires a sign- or zero-extension,
then we have to punt - it is not defined which
one is correct. */
|| (POINTER_TYPE_P (TREE_TYPE (p))
&& TREE_CODE (a) == INTEGER_CST
&& tree_int_cst_sign_bit (a) == 0))
{
if (issue_strict_overflow_warning
(WARN_STRICT_OVERFLOW_MISC)
&& TYPE_PRECISION (TREE_TYPE (rhs1))
> TYPE_PRECISION (TREE_TYPE (a))
&& INTEGRAL_TYPE_P (TREE_TYPE (p)))
warning_at (gimple_location (stmt),
OPT_Wstrict_overflow,
"assuming signed overflow does not "
"occur when assuming that "
"(T)(P + A) - (T)P is always (T)A");
if (useless_type_conversion_p (TREE_TYPE (rhs1),
TREE_TYPE (a)))
code = TREE_CODE (a);
else
code = NOP_EXPR;
rhs1 = a;
rhs2 = NULL_TREE;
gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
rhs2);
gcc_assert (gsi_stmt (*gsi) == stmt);
gimple_set_modified (stmt, true);
}
}
}
}
}
}
if (rhs2 && TREE_CODE (rhs2) == SSA_NAME)
{
gimple def_stmt = SSA_NAME_DEF_STMT (rhs2);
if (is_gimple_assign (def_stmt) && can_propagate_from (def_stmt))
{
enum tree_code def_code = gimple_assign_rhs_code (def_stmt);
if (def_code == PLUS_EXPR
|| def_code == MINUS_EXPR)
{
tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
tree def_rhs2 = gimple_assign_rhs2 (def_stmt);
if (operand_equal_p (def_rhs1, rhs1, 0)
&& code == MINUS_EXPR)
{
/* A - (A +- B) -> -+ B. */
code = ((def_code == PLUS_EXPR)
? NEGATE_EXPR : TREE_CODE (def_rhs2));
rhs1 = def_rhs2;
rhs2 = NULL_TREE;
gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
gcc_assert (gsi_stmt (*gsi) == stmt);
gimple_set_modified (stmt, true);
}
else if (operand_equal_p (def_rhs2, rhs1, 0)
&& code != def_code)
{
/* A +- (B +- A) -> +- B. */
code = ((code == PLUS_EXPR)
? TREE_CODE (def_rhs1) : NEGATE_EXPR);
rhs1 = def_rhs1;
rhs2 = NULL_TREE;
gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
gcc_assert (gsi_stmt (*gsi) == stmt);
gimple_set_modified (stmt, true);
}
else if (CONSTANT_CLASS_P (rhs1)
&& CONSTANT_CLASS_P (def_rhs1))
{
/* CST +- (CST +- A) -> CST +- A. */
tree cst = fold_binary (code, TREE_TYPE (rhs2),
rhs1, def_rhs1);
if (cst && !TREE_OVERFLOW (cst))
{
code = (code == def_code ? PLUS_EXPR : MINUS_EXPR);
gimple_assign_set_rhs_code (stmt, code);
rhs1 = cst;
gimple_assign_set_rhs1 (stmt, rhs1);
rhs2 = def_rhs2;
gimple_assign_set_rhs2 (stmt, rhs2);
gimple_set_modified (stmt, true);
}
}
else if (CONSTANT_CLASS_P (rhs1)
&& CONSTANT_CLASS_P (def_rhs2))
{
/* CST +- (A +- CST) -> CST +- A. */
tree cst = fold_binary (def_code == code
? PLUS_EXPR : MINUS_EXPR,
TREE_TYPE (rhs2),
rhs1, def_rhs2);
if (cst && !TREE_OVERFLOW (cst))
{
rhs1 = cst;
gimple_assign_set_rhs1 (stmt, rhs1);
rhs2 = def_rhs1;
gimple_assign_set_rhs2 (stmt, rhs2);
gimple_set_modified (stmt, true);
}
}
}
else if (def_code == BIT_NOT_EXPR)
{
tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
if (code == PLUS_EXPR
&& operand_equal_p (def_rhs1, rhs1, 0))
{
/* A + ~A -> -1. */
rhs1 = build_all_ones_cst (TREE_TYPE (rhs1));
rhs2 = NULL_TREE;
code = TREE_CODE (rhs1);
gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
gcc_assert (gsi_stmt (*gsi) == stmt);
gimple_set_modified (stmt, true);
}
}
}
}
out:
if (gimple_modified_p (stmt))
{
fold_stmt_inplace (gsi);
update_stmt (stmt);
return true;
}
return false;
}
/* Combine an element access with a shuffle. Returns true if there were
any changes made, else it returns false. */
......@@ -2805,14 +2452,6 @@ pass_forwprop::execute (function *fun)
|| code == BIT_XOR_EXPR)
&& simplify_rotate (&gsi))
changed = true;
else if (code == PLUS_EXPR
|| code == MINUS_EXPR)
{
changed = associate_plusminus (&gsi);
if (changed
&& maybe_clean_or_replace_eh_stmt (stmt, stmt))
bitmap_set_bit (to_purge, bb->index);
}
else if (code == VEC_PERM_EXPR)
{
int did_something = simplify_permutation (&gsi);
......
......@@ -11659,6 +11659,27 @@ block_ultimate_origin (const_tree block)
}
}
/* Return true iff conversion from INNER_TYPE to OUTER_TYPE generates
no instruction. */
bool
tree_nop_conversion_p (const_tree outer_type, const_tree inner_type)
{
/* Use precision rather then machine mode when we can, which gives
the correct answer even for submode (bit-field) types. */
if ((INTEGRAL_TYPE_P (outer_type)
|| POINTER_TYPE_P (outer_type)
|| TREE_CODE (outer_type) == OFFSET_TYPE)
&& (INTEGRAL_TYPE_P (inner_type)
|| POINTER_TYPE_P (inner_type)
|| TREE_CODE (inner_type) == OFFSET_TYPE))
return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
/* Otherwise fall back on comparing machine modes (e.g. for
aggregate types, floats). */
return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
}
/* Return true iff conversion in EXP generates no instruction. Mark
it inline so that we fully inline into the stripping functions even
though we have two uses of this function. */
......@@ -11680,19 +11701,7 @@ tree_nop_conversion (const_tree exp)
if (!inner_type)
return false;
/* Use precision rather then machine mode when we can, which gives
the correct answer even for submode (bit-field) types. */
if ((INTEGRAL_TYPE_P (outer_type)
|| POINTER_TYPE_P (outer_type)
|| TREE_CODE (outer_type) == OFFSET_TYPE)
&& (INTEGRAL_TYPE_P (inner_type)
|| POINTER_TYPE_P (inner_type)
|| TREE_CODE (inner_type) == OFFSET_TYPE))
return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
/* Otherwise fall back on comparing machine modes (e.g. for
aggregate types, floats). */
return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
return tree_nop_conversion_p (outer_type, inner_type);
}
/* Return true iff conversion in EXP generates no instruction. Don't
......
......@@ -4226,6 +4226,7 @@ extern bool is_typedef_decl (tree x);
extern bool typedef_variant_p (tree);
extern bool auto_var_in_fn_p (const_tree, const_tree);
extern tree build_low_bits_mask (tree, unsigned);
extern bool tree_nop_conversion_p (const_tree, const_tree);
extern tree tree_strip_nop_conversions (tree);
extern tree tree_strip_sign_nop_conversions (tree);
extern const_tree strip_invariant_refs (const_tree);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment