new file mode 100644
@@ -0,0 +1,35 @@
+/* { dg-do run { target bitint } } */
+
+#if __BITINT_MAXWIDTH__ >= 256
+unsigned a, b, c, d, e;
+unsigned _BitInt(256) f;
+
+__attribute__((noipa)) unsigned short
+bswap16 (int t)
+{
+ return __builtin_bswap16 (t);
+}
+
+void
+foo (unsigned z, unsigned _BitInt(512) y, unsigned *r)
+{
+ unsigned t = __builtin_sub_overflow_p (0, y << 509, f);
+ z *= bswap16 (t);
+ d = __builtin_sub_overflow_p (c, 3, (unsigned _BitInt(512)) 0);
+ unsigned q = z + c + b;
+ unsigned short n = q >> (8 + a);
+ *r = b + e + n;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 256
+ unsigned x;
+ foo (8, 2, &x);
+ if (x != 8)
+ __builtin_abort ();
+#endif
+ return 0;
+}
@@ -1666,8 +1666,9 @@ phi_translate_1 (bitmap_set_t dest,
if (!newoperands.exists ())
newoperands = operands.copy ();
newref = vn_reference_insert_pieces (newvuse, ref->set,
- ref->base_set, ref->type,
- newoperands,
+ ref->base_set,
+ ref->offset, ref->max_size,
+ ref->type, newoperands,
result, new_val_id);
newoperands = vNULL;
}
@@ -438,7 +438,7 @@ static void init_vn_nary_op_from_pieces (vn_nary_op_t, unsigned int,
enum tree_code, tree, tree *);
static tree vn_lookup_simplify_result (gimple_match_op *);
static vn_reference_t vn_reference_lookup_or_insert_for_pieces
- (tree, alias_set_type, alias_set_type, tree,
+ (tree, alias_set_type, alias_set_type, poly_int64, poly_int64, tree,
vec<vn_reference_op_s, va_heap>, tree);
/* Return whether there is value numbering information for a given SSA name. */
@@ -748,6 +748,8 @@ vn_reference_compute_hash (const vn_reference_t vr1)
vn_reference_op_compute_hash (vro, hstate);
}
}
+ /* Do not hash vr1->offset or vr1->max_size, we want to get collisions
+ to be able to identify compatible results. */
result = hstate.end ();
/* ??? We would ICE later if we hash instead of adding that in. */
if (vr1->vuse)
@@ -772,6 +774,16 @@ vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
if (vr1->vuse != vr2->vuse)
return false;
+ /* The offset/max_size used for the ao_ref during lookup has to be
+ the same. */
+ if (maybe_ne (vr1->offset, vr2->offset)
+ || maybe_ne (vr1->max_size, vr2->max_size))
+ {
+ /* But nothing known in the prevailing entry is OK to be used. */
+ if (maybe_ne (vr1->offset, 0) || known_size_p (vr1->max_size))
+ return false;
+ }
+
/* If the operands are the same we are done. */
if (vr1->operands == vr2->operands)
return true;
@@ -2076,6 +2088,7 @@ vn_walk_cb_data::finish (alias_set_type set, alias_set_type base_set, tree val)
vec<vn_reference_op_s> &operands
= saved_operands.exists () ? saved_operands : vr->operands;
return vn_reference_lookup_or_insert_for_pieces (last_vuse, set, base_set,
+ vr->offset, vr->max_size,
vr->type, operands, val);
}
@@ -2552,6 +2565,8 @@ static vn_reference_t
vn_reference_lookup_or_insert_for_pieces (tree vuse,
alias_set_type set,
alias_set_type base_set,
+ poly_int64 offset,
+ poly_int64 max_size,
tree type,
vec<vn_reference_op_s,
va_heap> operands,
@@ -2565,15 +2580,18 @@ vn_reference_lookup_or_insert_for_pieces (tree vuse,
vr1.type = type;
vr1.set = set;
vr1.base_set = base_set;
+ vr1.offset = offset;
+ vr1.max_size = max_size;
vr1.hashcode = vn_reference_compute_hash (&vr1);
if (vn_reference_lookup_1 (&vr1, &result))
return result;
+
if (TREE_CODE (value) == SSA_NAME)
value_id = VN_INFO (value)->value_id;
else
value_id = get_or_alloc_constant_value_id (value);
- return vn_reference_insert_pieces (vuse, set, base_set, type,
- operands.copy (), value, value_id);
+ return vn_reference_insert_pieces (vuse, set, base_set, offset, max_size,
+ type, operands.copy (), value, value_id);
}
/* Return a value-number for RCODE OPS... either by looking up an existing
@@ -3771,6 +3789,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
return (void *)-1;
}
*ref = r;
+ vr->offset = r.offset;
+ vr->max_size = r.max_size;
/* Do not update last seen VUSE after translating. */
data->last_vuse_ptr = NULL;
@@ -3959,6 +3979,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
if (maybe_ne (ref->size, r.size))
return (void *)-1;
*ref = r;
+ vr->offset = r.offset;
+ vr->max_size = r.max_size;
/* Do not update last seen VUSE after translating. */
data->last_vuse_ptr = NULL;
@@ -4023,6 +4045,10 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set,
vr1.type = type;
vr1.set = set;
vr1.base_set = base_set;
+ /* We can pretend there's no extra info fed in since the ao_refs offset
+ and max_size are computed only from the VN reference ops. */
+ vr1.offset = 0;
+ vr1.max_size = -1;
vr1.hashcode = vn_reference_compute_hash (&vr1);
if ((cst = fully_constant_vn_reference_p (&vr1)))
return cst;
@@ -4149,6 +4175,8 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
ao_ref_init (&op_ref, op);
vr1.set = ao_ref_alias_set (&op_ref);
vr1.base_set = ao_ref_base_alias_set (&op_ref);
+ vr1.offset = 0;
+ vr1.max_size = -1;
vr1.hashcode = vn_reference_compute_hash (&vr1);
if (mask == NULL_TREE)
if (tree cst = fully_constant_vn_reference_p (&vr1))
@@ -4171,7 +4199,13 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
if (!valueized_anything
|| !ao_ref_init_from_vn_reference (&r, vr1.set, vr1.base_set,
vr1.type, ops_for_ref))
- ao_ref_init (&r, op);
+ {
+ ao_ref_init (&r, op);
+ /* Record the extra info we're getting from the full ref. */
+ ao_ref_base (&r);
+ vr1.offset = r.offset;
+ vr1.max_size = r.max_size;
+ }
vn_walk_cb_data data (&vr1, r.ref ? NULL_TREE : op,
last_vuse_ptr, kind, tbaa_p, mask,
redundant_store_removal_p);
@@ -4227,6 +4261,8 @@ vn_reference_lookup_call (gcall *call, vn_reference_t *vnresult,
vr->punned = false;
vr->set = 0;
vr->base_set = 0;
+ vr->offset = 0;
+ vr->max_size = -1;
vr->hashcode = vn_reference_compute_hash (vr);
vn_reference_lookup_1 (vr, vnresult);
}
@@ -4290,6 +4326,10 @@ vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
ao_ref_init (&op_ref, op);
vr1->set = ao_ref_alias_set (&op_ref);
vr1->base_set = ao_ref_base_alias_set (&op_ref);
+ /* Specifically use an unknown extent here, we're not doing any lookup
+ and assume the caller didn't either (or it went VARYING). */
+ vr1->offset = 0;
+ vr1->max_size = -1;
vr1->hashcode = vn_reference_compute_hash (vr1);
vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
vr1->result_vdef = vdef;
@@ -4332,7 +4372,8 @@ vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
vn_reference_t
vn_reference_insert_pieces (tree vuse, alias_set_type set,
- alias_set_type base_set, tree type,
+ alias_set_type base_set,
+ poly_int64 offset, poly_int64 max_size, tree type,
vec<vn_reference_op_s> operands,
tree result, unsigned int value_id)
@@ -4349,6 +4390,8 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set,
vr1->punned = false;
vr1->set = set;
vr1->base_set = base_set;
+ vr1->offset = offset;
+ vr1->max_size = max_size;
vr1->hashcode = vn_reference_compute_hash (vr1);
if (result && TREE_CODE (result) == SSA_NAME)
result = SSA_VAL (result);
@@ -5867,6 +5910,8 @@ visit_reference_op_call (tree lhs, gcall *stmt)
vr2->type = vr1.type;
vr2->punned = vr1.punned;
vr2->set = vr1.set;
+ vr2->offset = vr1.offset;
+ vr2->max_size = vr1.max_size;
vr2->base_set = vr1.base_set;
vr2->hashcode = vr1.hashcode;
vr2->result = lhs;
@@ -145,6 +145,8 @@ typedef struct vn_reference_s
tree vuse;
alias_set_type set;
alias_set_type base_set;
+ poly_int64 offset;
+ poly_int64 max_size;
tree type;
unsigned punned : 1;
vec<vn_reference_op_s> operands;
@@ -268,6 +270,7 @@ tree vn_reference_lookup (tree, tree, vn_lookup_kind, vn_reference_t *, bool,
tree * = NULL, tree = NULL_TREE, bool = false);
void vn_reference_lookup_call (gcall *, vn_reference_t *, vn_reference_t);
vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, alias_set_type,
+ poly_int64, poly_int64,
tree, vec<vn_reference_op_s>,
tree, unsigned int);
void print_vn_reference_ops (FILE *, const vec<vn_reference_op_s>);