return false;
}
+/* qsort compare function to sort FIELD_DECLs after their
+ DECL_FIELD_CONTEXT TYPE_UID. */
+
+static inline int
+ncr_compar (const void *field1_, const void *field2_)
+{
+ const_tree field1 = *(const_tree *) const_cast <void *>(field1_);
+ const_tree field2 = *(const_tree *) const_cast <void *>(field2_);
+ unsigned int uid1
+ = TYPE_UID (TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field1)));
+ unsigned int uid2
+ = TYPE_UID (TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field2)));
+ if (uid1 < uid2)
+ return -1;
+ else if (uid1 > uid2)
+ return 1;
+ return 0;
+}
+
/* Return true if we can determine that the fields referenced cannot
overlap for any pair of objects. */
nonoverlapping_component_refs_p (const_rtx rtlx, const_rtx rtly)
{
const_tree x = MEM_EXPR (rtlx), y = MEM_EXPR (rtly);
- const_tree fieldx, fieldy, typex, typey, orig_y;
if (!flag_strict_aliasing
|| !x || !y
|| TREE_CODE (y) != COMPONENT_REF)
return false;
- do
+ auto_vec<const_tree, 16> fieldsx;
+ while (TREE_CODE (x) == COMPONENT_REF)
{
- /* The comparison has to be done at a common type, since we don't
- know how the inheritance hierarchy works. */
- orig_y = y;
- do
- {
- fieldx = TREE_OPERAND (x, 1);
- typex = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldx));
-
- y = orig_y;
- do
- {
- fieldy = TREE_OPERAND (y, 1);
- typey = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldy));
-
- if (typex == typey)
- goto found;
+ tree field = TREE_OPERAND (x, 1);
+ tree type = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field));
+ if (TREE_CODE (type) == RECORD_TYPE)
+ fieldsx.safe_push (field);
+ x = TREE_OPERAND (x, 0);
+ }
+ if (fieldsx.length () == 0)
+ return false;
+ auto_vec<const_tree, 16> fieldsy;
+ while (TREE_CODE (y) == COMPONENT_REF)
+ {
+ tree field = TREE_OPERAND (y, 1);
+ tree type = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field));
+ if (TREE_CODE (type) == RECORD_TYPE)
+ fieldsy.safe_push (TREE_OPERAND (y, 1));
+ y = TREE_OPERAND (y, 0);
+ }
+ if (fieldsy.length () == 0)
+ return false;
- y = TREE_OPERAND (y, 0);
- }
- while (y && TREE_CODE (y) == COMPONENT_REF);
+ /* Most common case first. */
+ if (fieldsx.length () == 1
+ && fieldsy.length () == 1)
+ return ((TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldsx[0]))
+ == TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldsy[0])))
+ && fieldsx[0] != fieldsy[0]
+ && !(DECL_BIT_FIELD (fieldsx[0]) && DECL_BIT_FIELD (fieldsy[0])));
- x = TREE_OPERAND (x, 0);
+ if (fieldsx.length () == 2)
+ {
+ if (ncr_compar (&fieldsx[0], &fieldsx[1]) == 1)
+ {
+ const_tree tem = fieldsx[0];
+ fieldsx[0] = fieldsx[1];
+ fieldsx[1] = tem;
}
- while (x && TREE_CODE (x) == COMPONENT_REF);
- /* Never found a common type. */
- return false;
+ }
+ else
+ fieldsx.qsort (ncr_compar);
- found:
- /* If we're left with accessing different fields of a structure, then no
- possible overlap, unless they are both bitfields. */
- if (TREE_CODE (typex) == RECORD_TYPE && fieldx != fieldy)
- return !(DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy));
+ if (fieldsy.length () == 2)
+ {
+ if (ncr_compar (&fieldsy[0], &fieldsy[1]) == 1)
+ {
+ const_tree tem = fieldsy[0];
+ fieldsy[0] = fieldsy[1];
+ fieldsy[1] = tem;
+ }
+ }
+ else
+ fieldsy.qsort (ncr_compar);
- /* The comparison on the current field failed. If we're accessing
- a very nested structure, look at the next outer level. */
- x = TREE_OPERAND (x, 0);
- y = TREE_OPERAND (y, 0);
+ unsigned i = 0, j = 0;
+ do
+ {
+ const_tree fieldx = fieldsx[i];
+ const_tree fieldy = fieldsy[j];
+ tree typex = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldx));
+ tree typey = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldy));
+ if (typex == typey)
+ {
+ /* We're left with accessing different fields of a structure,
+ no possible overlap, unless they are both bitfields. */
+ if (fieldx != fieldy)
+ return !(DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy));
+ }
+ if (TYPE_UID (typex) < TYPE_UID (typey))
+ {
+ i++;
+ if (i == fieldsx.length ())
+ break;
+ }
+ else
+ {
+ j++;
+ if (j == fieldsy.length ())
+ break;
+ }
}
- while (x && y
- && TREE_CODE (x) == COMPONENT_REF
- && TREE_CODE (y) == COMPONENT_REF);
+ while (1);
return false;
}