vec<vn_reference_op_s> operands
= vn_reference_operands_for_lookup (rhs1);
vn_reference_t ref;
+
+ /* We handle &MEM[ptr + 5].b[1].c as
+ POINTER_PLUS_EXPR. */
+ if (operands[0].opcode == ADDR_EXPR
+ && operands.last ().opcode == SSA_NAME)
+ {
+ tree ops[2];
+ if (vn_pp_nary_for_addr (operands, ops))
+ {
+ vn_nary_op_t nary;
+ vn_nary_op_lookup_pieces (2, POINTER_PLUS_EXPR,
+ TREE_TYPE (rhs1), ops,
+ &nary);
+ operands.release ();
+ if (nary && !nary->predicated_values)
+ {
+ unsigned value_id = nary->value_id;
+ if (value_id_constant_p (value_id))
+ continue;
+ result = get_or_alloc_expr_for_nary
+ (nary, value_id, gimple_location (stmt));
+ break;
+ }
+ continue;
+ }
+ }
+
vn_reference_lookup_pieces (gimple_vuse (stmt), set,
base_set, TREE_TYPE (rhs1),
operands, &ref, VN_WALK);
return NULL_TREE;
}
+/* When OPERANDS is an ADDR_EXPR that can be possibly expressed as a
+ POINTER_PLUS_EXPR return true and fill in its operands in OPS. */
+
+bool
+vn_pp_nary_for_addr (const vec<vn_reference_op_s>& operands, tree ops[2])
+{
+ gcc_assert (operands[0].opcode == ADDR_EXPR
+ && operands.last ().opcode == SSA_NAME);
+ poly_int64 off = 0;
+ vn_reference_op_t vro;
+ unsigned i;
+ for (i = 1; operands.iterate (i, &vro); ++i)
+ {
+ if (vro->opcode == SSA_NAME)
+ break;
+ else if (known_eq (vro->off, -1))
+ break;
+ off += vro->off;
+ }
+ if (i == operands.length () - 1
+ && maybe_ne (off, 0)
+ /* Make sure we the offset we accumulated in a 64bit int
+ fits the address computation carried out in target
+ offset precision. */
+ && (off.coeffs[0]
+ == sext_hwi (off.coeffs[0], TYPE_PRECISION (sizetype))))
+ {
+ gcc_assert (operands[i-1].opcode == MEM_REF);
+ ops[0] = operands[i].op0;
+ ops[1] = wide_int_to_tree (sizetype, off);
+ return true;
+ }
+ return false;
+}
+
/* Lookup OP in the current hash table, and return the resulting value
number if it exists in the hash table. Return NULL_TREE if it does
not exist in the hash table or if the result field of the structure
&& operands[0].opcode == ADDR_EXPR
&& operands.last ().opcode == SSA_NAME)
{
- poly_int64 off = 0;
- vn_reference_op_t vro;
- unsigned i;
- for (i = 1; operands.iterate (i, &vro); ++i)
+ tree ops[2];
+ if (vn_pp_nary_for_addr (operands, ops))
{
- if (vro->opcode == SSA_NAME)
- break;
- else if (known_eq (vro->off, -1))
- break;
- off += vro->off;
- }
- if (i == operands.length () - 1
- /* Make sure we the offset we accumulated in a 64bit int
- fits the address computation carried out in target
- offset precision. */
- && (off.coeffs[0]
- == sext_hwi (off.coeffs[0], TYPE_PRECISION (sizetype))))
- {
- gcc_assert (operands[i-1].opcode == MEM_REF);
- tree ops[2];
- ops[0] = operands[i].op0;
- ops[1] = wide_int_to_tree (sizetype, off);
tree res = vn_nary_op_lookup_pieces (2, POINTER_PLUS_EXPR,
TREE_TYPE (op), ops, NULL);
if (res)
&& operands[0].opcode == ADDR_EXPR
&& operands.last ().opcode == SSA_NAME)
{
- poly_int64 off = 0;
- vn_reference_op_t vro;
- unsigned i;
- for (i = 1; operands.iterate (i, &vro); ++i)
+ tree ops[2];
+ if (vn_pp_nary_for_addr (operands, ops))
{
- if (vro->opcode == SSA_NAME)
- break;
- else if (known_eq (vro->off, -1))
- break;
- off += vro->off;
- }
- if (i == operands.length () - 1
- /* Make sure we the offset we accumulated in a 64bit int
- fits the address computation carried out in target
- offset precision. */
- && (off.coeffs[0]
- == sext_hwi (off.coeffs[0], TYPE_PRECISION (sizetype))))
- {
- gcc_assert (operands[i-1].opcode == MEM_REF);
- tree ops[2];
- ops[0] = operands[i].op0;
- ops[1] = wide_int_to_tree (sizetype, off);
vn_nary_op_insert_pieces (2, POINTER_PLUS_EXPR,
TREE_TYPE (op), ops, result,
VN_INFO (result)->value_id);
const T *end () const { return address () + length (); }
const T &operator[] (unsigned) const;
T &operator[] (unsigned);
+ const T &last (void) const;
T &last (void);
bool space (unsigned) const;
bool iterate (unsigned, T *) const;
/* Get the final element of the vector, which must not be empty. */
+template<typename T, typename A>
+inline const T &
+vec<T, A, vl_embed>::last (void) const
+{
+ gcc_checking_assert (m_vecpfx.m_num > 0);
+ return (*this)[m_vecpfx.m_num - 1];
+}
+
template<typename T, typename A>
inline T &
vec<T, A, vl_embed>::last (void)
const T *end () const { return begin () + length (); }
const T &operator[] (unsigned ix) const
{ return (*m_vec)[ix]; }
+ const T &last (void) const
+ { return m_vec->last (); }
bool operator!=(const vec &other) const
{ return !(*this == other); }