/* Type based alias analysis.
- Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This pass determines which types in the program contain only
instances that are completely encapsulated by the compilation unit.
case INTEGER_TYPE:
case QUAL_UNION_TYPE:
case REAL_TYPE:
+ case FIXED_POINT_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
case VECTOR_TYPE:
*/
-static bool
-is_array_access_through_pointer_and_index (tree op0, tree op1)
+bool
+is_array_access_through_pointer_and_index (enum tree_code code, tree op0,
+ tree op1, tree *base, tree *offset,
+ tree *offset_cast_stmt)
{
- tree base, offset, offset_cast_stmt;
tree before_cast, before_cast_def_stmt;
cast_t op0_cast, op1_cast;
+ *base = NULL;
+ *offset = NULL;
+ *offset_cast_stmt = NULL;
+
/* Check 1. */
+ if (code == POINTER_PLUS_EXPR)
+ {
+ tree op0type = TYPE_MAIN_VARIANT (TREE_TYPE (op0));
+ tree op1type = TYPE_MAIN_VARIANT (TREE_TYPE (op1));
- /* Init data for walk_use_def_chains function. */
- op0_cast.type = op1_cast.type = 0;
- op0_cast.stmt = op1_cast.stmt = NULL;
+ /* One of op0 and op1 is of pointer type and the other is numerical. */
+ if (POINTER_TYPE_P (op0type) && NUMERICAL_TYPE_CHECK (op1type))
+ {
+ *base = op0;
+ *offset = op1;
+ }
+ else if (POINTER_TYPE_P (op1type) && NUMERICAL_TYPE_CHECK (op0type))
+ {
+ *base = op1;
+ *offset = op0;
+ }
+ else
+ return false;
+ }
+ else
+ {
+ /* Init data for walk_use_def_chains function. */
+ op0_cast.type = op1_cast.type = 0;
+ op0_cast.stmt = op1_cast.stmt = NULL;
- visited_stmts = pointer_set_create ();
- walk_use_def_chains (op0, is_cast_from_non_pointer,(void *)(&op0_cast), false);
- pointer_set_destroy (visited_stmts);
+ visited_stmts = pointer_set_create ();
+ walk_use_def_chains (op0, is_cast_from_non_pointer,(void *)(&op0_cast),
+ false);
+ pointer_set_destroy (visited_stmts);
- visited_stmts = pointer_set_create ();
- walk_use_def_chains (op1, is_cast_from_non_pointer,(void *)(&op1_cast), false);
- pointer_set_destroy (visited_stmts);
+ visited_stmts = pointer_set_create ();
+ walk_use_def_chains (op1, is_cast_from_non_pointer,(void *)(&op1_cast),
+ false);
+ pointer_set_destroy (visited_stmts);
- if (op0_cast.type == 1 && op1_cast.type == 0)
- {
- base = op1;
- offset = op0;
- offset_cast_stmt = op0_cast.stmt;
- }
- else if (op0_cast.type == 0 && op1_cast.type == 1)
- {
- base = op0;
- offset = op1;
- offset_cast_stmt = op1_cast.stmt;
+ if (op0_cast.type == 1 && op1_cast.type == 0)
+ {
+ *base = op1;
+ *offset = op0;
+ *offset_cast_stmt = op0_cast.stmt;
+ }
+ else if (op0_cast.type == 0 && op1_cast.type == 1)
+ {
+ *base = op0;
+ *offset = op1;
+ *offset_cast_stmt = op1_cast.stmt;
+ }
+ else
+ return false;
}
- else
- return false;
-
+
/* Check 2.
offset_cast_stmt is of the form:
D.1606_7 = (struct str_t *) D.1605_6; */
- before_cast = SINGLE_SSA_TREE_OPERAND (offset_cast_stmt, SSA_OP_USE);
- if (!before_cast)
- return false;
+ if (*offset_cast_stmt)
+ {
+ before_cast = SINGLE_SSA_TREE_OPERAND (*offset_cast_stmt, SSA_OP_USE);
+ if (!before_cast)
+ return false;
- if (SSA_NAME_IS_DEFAULT_DEF(before_cast))
- return false;
+ if (SSA_NAME_IS_DEFAULT_DEF (before_cast))
+ return false;
- before_cast_def_stmt = SSA_NAME_DEF_STMT (before_cast);
- if (!before_cast_def_stmt)
- return false;
+ before_cast_def_stmt = SSA_NAME_DEF_STMT (before_cast);
+ if (!before_cast_def_stmt)
+ return false;
+ }
+ else
+ before_cast_def_stmt = SSA_NAME_DEF_STMT (*offset);
/* before_cast_def_stmt should be of the form:
D.1605_6 = i.1_5 * 16; */
okay_pointer_operation (enum tree_code code, tree op0, tree op1)
{
tree op0type = TYPE_MAIN_VARIANT (TREE_TYPE (op0));
- tree op1type = TYPE_MAIN_VARIANT (TREE_TYPE (op1));
switch (code)
{
break;
case MINUS_EXPR:
case PLUS_EXPR:
+ case POINTER_PLUS_EXPR:
{
- if (POINTER_TYPE_P (op1type)
+ tree base, offset, offset_cast_stmt;
+
+ if (POINTER_TYPE_P (op0type)
&& TREE_CODE (op0) == SSA_NAME
&& TREE_CODE (op1) == SSA_NAME
- && is_array_access_through_pointer_and_index (op0, op1))
+ && is_array_access_through_pointer_and_index (code, op0, op1,
+ &base,
+ &offset,
+ &offset_cast_stmt))
return true;
else
{
&& !(errorcount || sorrycount));
}
-struct tree_opt_pass pass_ipa_type_escape =
+struct simple_ipa_opt_pass pass_ipa_type_escape =
{
+ {
+ SIMPLE_IPA_PASS,
"type-escape-var", /* name */
gate_type_escape_vars, /* gate */
type_escape_execute, /* execute */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- 0, /* todo_flags_finish */
- 0 /* letter */
+ 0 /* todo_flags_finish */
+ }
};