Commit 14d62813 by Jeff Law Committed by Jeff Law

tree-ssa-dom.c (edge_info::record_simple_equiv): Call derive_equivalences.

	* tree-ssa-dom.c (edge_info::record_simple_equiv): Call
	derive_equivalences.
	(derive_equivalences_from_bit_ior, record_temporary_equivalences):
	Code moved into....
	(edge_info::derive_equivalences): New private member function

	* gcc.dg/torture/pr57214.c: Fix type of loop counter.
	* gcc.dg/tree-ssa/ssa-sink-16.c: Disable DOM.
	* gcc.dg/tree-ssa/ssa-dom-thread-11.c: New test.
	* gcc.dg/tree-ssa/ssa-dom-thread-12.c: New test.
	* gcc.dg/tree-ssa/ssa-dom-thread-13.c: New test.
	* gcc.dg/tree-ssa/ssa-dom-thread-14.c: New test.
	* gcc.dg/tree-ssa/ssa-dom-thread-15.c: New test.
	* gcc.dg/tree-ssa/ssa-dom-thread-16.c: New test.
	* gcc.dg/tree-ssa/ssa-dom-thread-17.c: New test.

From-SVN: r251397
parent a09f784a
2017-08-28 Jeff Law <law@redhat.com> 2017-08-28 Jeff Law <law@redhat.com>
* tree-ssa-dom.c (edge_info::record_simple_equiv): Call
derive_equivalences.
(derive_equivalences_from_bit_ior, record_temporary_equivalences):
Code moved into....
(edge_info::derive_equivalences): New private member function
* tree-ssa-dom.c (class edge_info): Changed from a struct * tree-ssa-dom.c (class edge_info): Changed from a struct
to a class. Add ctor/dtor, methods and data members. to a class. Add ctor/dtor, methods and data members.
(edge_info::edge_info): Renamed from allocate_edge_info. (edge_info::edge_info): Renamed from allocate_edge_info.
......
2017-08-28 Jeff Law <law@redhat.com>
* gcc.dg/torture/pr57214.c: Fix type of loop counter.
* gcc.dg/tree-ssa/ssa-sink-16.c: Disable DOM.
* gcc.dg/tree-ssa/ssa-dom-thread-11.c: New test.
* gcc.dg/tree-ssa/ssa-dom-thread-12.c: New test.
* gcc.dg/tree-ssa/ssa-dom-thread-13.c: New test.
* gcc.dg/tree-ssa/ssa-dom-thread-14.c: New test.
* gcc.dg/tree-ssa/ssa-dom-thread-15.c: New test.
* gcc.dg/tree-ssa/ssa-dom-thread-16.c: New test.
* gcc.dg/tree-ssa/ssa-dom-thread-17.c: New test.
2017-08-28 Janus Weil <janus@gcc.gnu.org> 2017-08-28 Janus Weil <janus@gcc.gnu.org>
PR fortran/81770 PR fortran/81770
......
...@@ -15,7 +15,7 @@ bar (_Bool b) ...@@ -15,7 +15,7 @@ bar (_Bool b)
b = 1; b = 1;
baz (); baz ();
x = 0; x = 0;
int i; unsigned int i;
while (buf[i] && i) while (buf[i] && i)
i++; i++;
foo (); foo ();
......
/* { dg-do compile { target { ! logical_op_short_circuit } } } */
/* { dg-options "-O2 -fdump-tree-dom2-details" } */
static int *bb_ticks;
extern void frob (void);
void
mark_target_live_regs (int b, int block, int bb_tick)
{
if (b == block && b != -1 && bb_tick == bb_ticks[b])
return;
if (b != -1)
frob ();
}
/* When the first two conditionals in the first IF are true, but
the third conditional is false, then there's a jump threading
opportunity to bypass the second IF statement. */
/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
typedef long unsigned int size_t;
union tree_node;
typedef union tree_node *tree;
typedef union gimple_statement_d *gimple;
typedef const union gimple_statement_d *const_gimple;
union gimple_statement_d
{
unsigned num_ops;
tree exp;
};
unsigned int x;
static inline tree
gimple_op (const_gimple gs, unsigned i)
{
if (!(i < gs->num_ops))
abort ();
return gs->exp;
}
unsigned char
scan_function (gimple stmt)
{
unsigned i;
for (i = 0; i < stmt->num_ops - 3 ; i++)
gimple_call_arg (stmt, i);
gimple_op (stmt, 1);
}
/* The test which bypasses the loop is simplified prior to DOM to check
that stmt->num_ops - 3 != 0. When that test is false, we can derive
a value for stmt->num_ops. That in turn allows us to thread the jump
for the conditional at the start of the call to gimple_op. */
/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
union tree_node;
typedef union tree_node *tree;
extern unsigned char tree_contains_struct[0xdead][64];
struct tree_base
{
int code:16;
};
struct tree_typed
{
tree type;
};
struct tree_type_common
{
tree main_variant;
};
extern tree build_target_option_node (void);
union tree_node
{
struct tree_base base;
struct tree_typed typed;
struct tree_type_common type_common;
};
tree
convert (tree type, tree expr)
{
tree e = expr;
int code = (type)->base.code;
const char *invalid_conv_diag;
tree ret;
if (tree_contains_struct[expr->base.code][(42)] != 1)
abort ();
if (type->type_common.main_variant == expr->typed.type->type_common.main_variant
&& (expr->typed.type->base.code != 123
|| e->base.code == 456))
return arf ();
if (expr->typed.type->base.code == 42)
error ("void value not ignored as it ought to be");
}
/* When the *->base.code tests in the second IF statement are false, we
know that expr->typed.base->base.code has the value 123. That allows
us to thread the test for the final IF statement on that path. */
/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
/* { dg-do compile { target { ! logical_op_short_circuit } } } */
/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
enum optab_methods
{
OPTAB_DIRECT,
OPTAB_LIB,
OPTAB_WIDEN,
OPTAB_LIB_WIDEN,
OPTAB_MUST_WIDEN
};
struct optab_d { };
typedef struct optab_d *optab;
void
expand_shift_1 (int code, int unsignedp, int rotate,
optab lshift_optab, optab rshift_arith_optab)
{
int left = (code == 42 || code == 0xde);
int attempt;
enum optab_methods methods;
if (attempt == 0)
methods = OPTAB_DIRECT;
else if (attempt == 1)
methods = OPTAB_WIDEN;
if ((!unsignedp || (!left && methods == OPTAB_WIDEN)))
{
enum optab_methods methods1 = methods;
if (unsignedp)
methods1 = OPTAB_MUST_WIDEN;
expand_binop (left ? lshift_optab : rshift_arith_optab,
unsignedp, methods1);
}
}
/* When UNSIGNEDP is true, LEFT is false and METHOD == OPTAB_WIDEN
we will enter the TRUE arm of the conditional and we can thread
the test to compute the first first argument of the expand_binop
call if we look backwards through the boolean logicals. */
/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
struct rtx_def;
typedef struct rtx_def *rtx;
struct machine_frame_state
{
rtx cfa_reg;
long sp_offset;
};
struct machine_function {
struct machine_frame_state fs;
};
enum global_rtl_index
{
GR_PC,
GR_CC0,
GR_RETURN,
GR_SIMPLE_RETURN,
GR_STACK_POINTER,
GR_FRAME_POINTER,
GR_HARD_FRAME_POINTER,
GR_ARG_POINTER,
GR_VIRTUAL_INCOMING_ARGS,
GR_VIRTUAL_STACK_ARGS,
GR_VIRTUAL_STACK_DYNAMIC,
GR_VIRTUAL_OUTGOING_ARGS,
GR_VIRTUAL_CFA,
GR_VIRTUAL_PREFERRED_STACK_BOUNDARY,
GR_MAX
};
struct target_rtl {
rtx x_global_rtl[GR_MAX];
};
extern struct target_rtl default_target_rtl;
struct function {
struct machine_function * machine;
};
extern struct function *cfun;
struct ix86_frame
{
long stack_pointer_offset;
};
void
ix86_expand_prologue (void)
{
struct machine_function *m = (cfun + 0)->machine;
struct ix86_frame frame;
long allocate;
allocate = frame.stack_pointer_offset - m->fs.sp_offset;
if (allocate == 0)
;
else if (!ix86_target_stack_probe ())
{
pro_epilogue_adjust_stack ((((&default_target_rtl)->x_global_rtl)[GR_STACK_POINTER]), (((&default_target_rtl)->x_global_rtl)[GR_STACK_POINTER]),
gen_rtx_CONST_INT ((-allocate)), -1,
m->fs.cfa_reg == (((&default_target_rtl)->x_global_rtl)[GR_STACK_POINTER]));
}
((void)(!(m->fs.sp_offset == frame.stack_pointer_offset) ? fancy_abort ("../../gcc-4.7.3/gcc/config/i386/i386.c", 10435, __FUNCTION__), 0 : 0));
}
/* In the case where ALLOCATE is zero, we know that sp_offset and
stack_poitner_offset within their respective structures are the
same. That allows us to thread the jump from the true arm of the
first IF conditional around the test controlling the call to
fancy_abort. */
/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
/* { dg-do compile { target { ! logical_op_short_circuit } } } */
/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
unsigned char
validate_subreg (unsigned int offset, unsigned int isize, unsigned int osize, int zz, int qq)
{
if (osize >= (((zz & (1L << 2)) != 0) ? 8 : 4) && isize >= osize)
;
else if (qq == 99)
return 0;
if (osize > isize)
return offset == 0;
return 1;
}
/* When we test isize >= osize in the first IF conditional and it is
false and qq != 99, then we can thread the osize > isize test of
the second conditional. */
/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-dom2 -w" } */
struct rtx_def;
typedef struct rtx_def *rtx;
struct reload
{
rtx in;
rtx reg_rtx;
};
extern struct reload rld[(2 * 30 * (2 + 1))];
static rtx find_dummy_reload (rtx);
extern int frob ();
extern int arf ();
int
push_reload (rtx in, rtx out
)
{
int i;
if (out != 0 && in != out)
{
rld[i].reg_rtx = find_dummy_reload (out);
if (rld[i].reg_rtx == out)
rld[i].in = out;
}
}
rtx
find_dummy_reload (rtx real_out)
{
unsigned int nwords = frob ();
unsigned int regno = frob ();
unsigned int i;
for (i = 0; i < nwords; i++)
if (arf ())
break;
if (i == nwords)
return real_out;
return 0;
}
/* In the case where the call to find_dummy_reload returns 0,
the final test in push_reload will never be true and it will
be eliminated. */
/* { dg-final { scan-tree-dump-not "out_\[^\n\r]+ == 0" "dom2"} } */
/* { dg-do compile } */ /* { dg-do compile } */
/* Note PRE rotates the loop and blocks the sinking opportunity. */ /* Note PRE and DOM jump threading rotate the loop and blocks the sinking opportunity. */
/* { dg-options "-O2 -fno-tree-pre -fdump-tree-sink -fdump-tree-optimized" } */ /* { dg-options "-O2 -fno-tree-pre -fno-tree-dominator-opts -fdump-tree-sink -fdump-tree-optimized" } */
int f(int n) int f(int n)
{ {
......
...@@ -136,18 +136,239 @@ edge_info::edge_info (edge e) ...@@ -136,18 +136,239 @@ edge_info::edge_info (edge e)
} }
/* Destructor just needs to release the vectors. */ /* Destructor just needs to release the vectors. */
edge_info::~edge_info (void) edge_info::~edge_info (void)
{ {
this->cond_equivalences.release (); this->cond_equivalences.release ();
this->simple_equivalences.release (); this->simple_equivalences.release ();
} }
/* Record that LHS is known to be equal to RHS at runtime when the /* NAME is known to have the value VALUE, which must be a constant.
edge associated with THIS is traversed. */
Walk through its use-def chain to see if there are other equivalences
we might be able to derive.
RECURSION_LIMIT controls how far back we recurse through the use-def
chains. */
void
edge_info::derive_equivalences (tree name, tree value, int recursion_limit)
{
if (TREE_CODE (name) != SSA_NAME || TREE_CODE (value) != INTEGER_CST)
return;
/* This records the equivalence for the toplevel object. Do
this before checking the recursion limit. */
simple_equivalences.safe_push (equiv_pair (name, value));
/* Limit how far up the use-def chains we are willing to walk. */
if (recursion_limit == 0)
return;
/* We can walk up the use-def chains to potentially find more
equivalences. */
gimple *def_stmt = SSA_NAME_DEF_STMT (name);
if (is_gimple_assign (def_stmt))
{
/* We know the result of DEF_STMT was zero. See if that allows
us to deduce anything about the SSA_NAMEs used on the RHS. */
enum tree_code code = gimple_assign_rhs_code (def_stmt);
switch (code)
{
case BIT_IOR_EXPR:
if (integer_zerop (value))
{
tree rhs1 = gimple_assign_rhs1 (def_stmt);
tree rhs2 = gimple_assign_rhs2 (def_stmt);
value = build_zero_cst (TREE_TYPE (rhs1));
derive_equivalences (rhs1, value, recursion_limit - 1);
value = build_zero_cst (TREE_TYPE (rhs2));
derive_equivalences (rhs2, value, recursion_limit - 1);
}
break;
/* We know the result of DEF_STMT was one. See if that allows
us to deduce anything about the SSA_NAMEs used on the RHS. */
case BIT_AND_EXPR:
if (!integer_zerop (value))
{
tree rhs1 = gimple_assign_rhs1 (def_stmt);
tree rhs2 = gimple_assign_rhs2 (def_stmt);
/* If either operand has a boolean range, then we
know its value must be one, otherwise we just know it
is nonzero. The former is clearly useful, I haven't
seen cases where the latter is helpful yet. */
if (TREE_CODE (rhs1) == SSA_NAME)
{
if (ssa_name_has_boolean_range (rhs1))
{
value = build_one_cst (TREE_TYPE (rhs1));
derive_equivalences (rhs1, value, recursion_limit - 1);
}
}
if (TREE_CODE (rhs2) == SSA_NAME)
{
if (ssa_name_has_boolean_range (rhs2))
{
value = build_one_cst (TREE_TYPE (rhs2));
derive_equivalences (rhs2, value, recursion_limit - 1);
}
}
}
break;
/* If LHS is an SSA_NAME and RHS is a constant integer and LHS was
set via a widening type conversion, then we may be able to record
additional equivalences. */
case NOP_EXPR:
case CONVERT_EXPR:
{
tree rhs = gimple_assign_rhs1 (def_stmt);
tree rhs_type = TREE_TYPE (rhs);
if (INTEGRAL_TYPE_P (rhs_type)
&& (TYPE_PRECISION (TREE_TYPE (name))
>= TYPE_PRECISION (rhs_type))
&& int_fits_type_p (value, rhs_type))
derive_equivalences (rhs,
fold_convert (rhs_type, value),
recursion_limit - 1);
break;
}
/* We can invert the operation of these codes trivially if
one of the RHS operands is a constant to produce a known
value for the other RHS operand. */
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
{
tree rhs1 = gimple_assign_rhs1 (def_stmt);
tree rhs2 = gimple_assign_rhs2 (def_stmt);
/* If either argument is a constant, then we can compute
a constant value for the nonconstant argument. */
if (TREE_CODE (rhs1) == INTEGER_CST
&& TREE_CODE (rhs2) == SSA_NAME)
derive_equivalences (rhs2,
fold_binary (MINUS_EXPR, TREE_TYPE (rhs1),
value, rhs1),
recursion_limit - 1);
else if (TREE_CODE (rhs2) == INTEGER_CST
&& TREE_CODE (rhs1) == SSA_NAME)
derive_equivalences (rhs1,
fold_binary (MINUS_EXPR, TREE_TYPE (rhs1),
value, rhs2),
recursion_limit - 1);
break;
}
/* If one of the operands is a constant, then we can compute
the value of the other operand. If both operands are
SSA_NAMEs, then they must be equal if the result is zero. */
case MINUS_EXPR:
{
tree rhs1 = gimple_assign_rhs1 (def_stmt);
tree rhs2 = gimple_assign_rhs2 (def_stmt);
/* If either argument is a constant, then we can compute
a constant value for the nonconstant argument. */
if (TREE_CODE (rhs1) == INTEGER_CST
&& TREE_CODE (rhs2) == SSA_NAME)
derive_equivalences (rhs2,
fold_binary (MINUS_EXPR, TREE_TYPE (rhs1),
rhs1, value),
recursion_limit - 1);
else if (TREE_CODE (rhs2) == INTEGER_CST
&& TREE_CODE (rhs1) == SSA_NAME)
derive_equivalences (rhs1,
fold_binary (PLUS_EXPR, TREE_TYPE (rhs1),
value, rhs2),
recursion_limit - 1);
else if (integer_zerop (value))
{
tree cond = build2 (EQ_EXPR, boolean_type_node,
gimple_assign_rhs1 (def_stmt),
gimple_assign_rhs2 (def_stmt));
tree inverted = invert_truthvalue (cond);
record_conditions (&this->cond_equivalences, cond, inverted);
}
break;
}
case EQ_EXPR:
case NE_EXPR:
{
if ((code == EQ_EXPR && integer_onep (value))
|| (code == NE_EXPR && integer_zerop (value)))
{
tree rhs1 = gimple_assign_rhs1 (def_stmt);
tree rhs2 = gimple_assign_rhs2 (def_stmt);
/* If either argument is a constant, then record the
other argument as being the same as that constant.
If neither operand is a constant, then we have a
conditional name == name equivalence. */
if (TREE_CODE (rhs1) == INTEGER_CST)
derive_equivalences (rhs2, rhs1, recursion_limit - 1);
else if (TREE_CODE (rhs2) == INTEGER_CST)
derive_equivalences (rhs1, rhs2, recursion_limit - 1);
}
else
{
tree cond = build2 (code, boolean_type_node,
gimple_assign_rhs1 (def_stmt),
gimple_assign_rhs2 (def_stmt));
tree inverted = invert_truthvalue (cond);
if (integer_zerop (value))
std::swap (cond, inverted);
record_conditions (&this->cond_equivalences, cond, inverted);
}
break;
}
/* For BIT_NOT and NEGATE, we can just apply the operation to the
VALUE to get the new equivalence. It will always be a constant
so we can recurse. */
case BIT_NOT_EXPR:
case NEGATE_EXPR:
{
tree rhs = gimple_assign_rhs1 (def_stmt);
tree res = fold_build1 (code, TREE_TYPE (rhs), value);
derive_equivalences (rhs, res, recursion_limit - 1);
break;
}
default:
{
if (TREE_CODE_CLASS (code) == tcc_comparison)
{
tree cond = build2 (code, boolean_type_node,
gimple_assign_rhs1 (def_stmt),
gimple_assign_rhs2 (def_stmt));
tree inverted = invert_truthvalue (cond);
if (integer_zerop (value))
std::swap (cond, inverted);
record_conditions (&this->cond_equivalences, cond, inverted);
break;
}
break;
}
}
}
}
void void
edge_info::record_simple_equiv (tree lhs, tree rhs) edge_info::record_simple_equiv (tree lhs, tree rhs)
{ {
/* If the RHS is a constant, then we may be able to derive
further equivalences. Else just record the name = name
equivalence. */
if (TREE_CODE (rhs) == INTEGER_CST)
derive_equivalences (lhs, rhs, 4);
else
simple_equivalences.safe_push (equiv_pair (lhs, rhs)); simple_equivalences.safe_push (equiv_pair (lhs, rhs));
} }
...@@ -702,42 +923,6 @@ back_propagate_equivalences (tree lhs, edge e, ...@@ -702,42 +923,6 @@ back_propagate_equivalences (tree lhs, edge e,
BITMAP_FREE (domby); BITMAP_FREE (domby);
} }
/* Record NAME has the value zero and if NAME was set from a BIT_IOR_EXPR
recurse into both operands recording their values as zero too.
RECURSION_DEPTH controls how far back we recurse through the operands
of the BIT_IOR_EXPR. */
static void
derive_equivalences_from_bit_ior (tree name,
const_and_copies *const_and_copies,
int recursion_limit)
{
if (recursion_limit == 0)
return;
if (TREE_CODE (name) == SSA_NAME)
{
tree value = build_zero_cst (TREE_TYPE (name));
/* This records the equivalence for the toplevel object. */
record_equality (name, value, const_and_copies);
/* And we can recurse into each operand to potentially find more
equivalences. */
gimple *def_stmt = SSA_NAME_DEF_STMT (name);
if (is_gimple_assign (def_stmt)
&& gimple_assign_rhs_code (def_stmt) == BIT_IOR_EXPR)
{
derive_equivalences_from_bit_ior (gimple_assign_rhs1 (def_stmt),
const_and_copies,
recursion_limit - 1);
derive_equivalences_from_bit_ior (gimple_assign_rhs2 (def_stmt),
const_and_copies,
recursion_limit - 1);
}
}
}
/* Record into CONST_AND_COPIES and AVAIL_EXPRS_STACK any equivalences implied /* Record into CONST_AND_COPIES and AVAIL_EXPRS_STACK any equivalences implied
by traversing edge E (which are cached in E->aux). by traversing edge E (which are cached in E->aux).
...@@ -758,29 +943,8 @@ record_temporary_equivalences (edge e, ...@@ -758,29 +943,8 @@ record_temporary_equivalences (edge e,
/* If we have 0 = COND or 1 = COND equivalences, record them /* If we have 0 = COND or 1 = COND equivalences, record them
into our expression hash tables. */ into our expression hash tables. */
for (i = 0; edge_info->cond_equivalences.iterate (i, &eq); ++i) for (i = 0; edge_info->cond_equivalences.iterate (i, &eq); ++i)
{
avail_exprs_stack->record_cond (eq); avail_exprs_stack->record_cond (eq);
/* If the condition is testing that X == 0 is true or X != 0 is false
and X is set from a BIT_IOR_EXPR, then we can record equivalences
for the operands of the BIT_IOR_EXPR (and recurse on those). */
tree op0 = eq->cond.ops.binary.opnd0;
tree op1 = eq->cond.ops.binary.opnd1;
if (TREE_CODE (op0) == SSA_NAME && integer_zerop (op1))
{
enum tree_code code = eq->cond.ops.binary.op;
if ((code == EQ_EXPR && eq->value == boolean_true_node)
|| (code == NE_EXPR && eq->value == boolean_false_node))
derive_equivalences_from_bit_ior (op0, const_and_copies, 4);
/* TODO: We could handle BIT_AND_EXPR in a similar fashion
recording that the operands have a nonzero value. */
/* TODO: We can handle more cases here, particularly when OP0 is
known to have a boolean range. */
}
}
edge_info::equiv_pair *seq; edge_info::equiv_pair *seq;
for (i = 0; edge_info->simple_equivalences.iterate (i, &seq); ++i) for (i = 0; edge_info->simple_equivalences.iterate (i, &seq); ++i)
{ {
...@@ -813,35 +977,6 @@ record_temporary_equivalences (edge e, ...@@ -813,35 +977,6 @@ record_temporary_equivalences (edge e,
else else
record_equality (lhs, rhs, const_and_copies); record_equality (lhs, rhs, const_and_copies);
/* If LHS is an SSA_NAME and RHS is a constant integer and LHS was
set via a widening type conversion, then we may be able to record
additional equivalences. */
if (TREE_CODE (rhs) == INTEGER_CST)
{
gimple *defstmt = SSA_NAME_DEF_STMT (lhs);
if (defstmt
&& is_gimple_assign (defstmt)
&& CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (defstmt)))
{
tree old_rhs = gimple_assign_rhs1 (defstmt);
/* If the conversion widens the original value and
the constant is in the range of the type of OLD_RHS,
then convert the constant and record the equivalence.
Note that int_fits_type_p does not check the precision
if the upper and lower bounds are OK. */
if (INTEGRAL_TYPE_P (TREE_TYPE (old_rhs))
&& (TYPE_PRECISION (TREE_TYPE (lhs))
> TYPE_PRECISION (TREE_TYPE (old_rhs)))
&& int_fits_type_p (rhs, TREE_TYPE (old_rhs)))
{
tree newval = fold_convert (TREE_TYPE (old_rhs), rhs);
record_equality (old_rhs, newval, const_and_copies);
}
}
}
/* Any equivalence found for LHS may result in additional /* Any equivalence found for LHS may result in additional
equivalences for other uses of LHS that we have already equivalences for other uses of LHS that we have already
......
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