/* Functions to analyze and validate GIMPLE trees.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
Rewritten by Jason Merrill <jason@redhat.com>
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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
case COMPLEX_CST:
case VECTOR_CST:
case OBJ_TYPE_REF:
+ case ASSERT_EXPR:
return true;
default:
bool
is_gimple_mem_rhs (tree t)
{
- /* If we're dealing with a renamable type, either source or dest
- must be a renamed variable. */
- if (is_gimple_reg_type (TREE_TYPE (t)))
+ /* If we're dealing with a renamable type, either source or dest must be
+ a renamed variable. Also force a temporary if the type doesn't need
+ to be stored in memory, since it's cheap and prevents erroneous
+ tailcalls (PR 17526). */
+ if (is_gimple_reg_type (TREE_TYPE (t))
+ || TYPE_MODE (TREE_TYPE (t)) != BLKmode)
return is_gimple_val (t);
else
return is_gimple_formal_tmp_rhs (t);
return is_gimple_mem_rhs;
}
-/* Returns true if T is a valid CONSTRUCTOR component in GIMPLE, either
- a val or another CONSTRUCTOR. */
-
-bool
-is_gimple_constructor_elt (tree t)
-{
- return (is_gimple_val (t)
- || TREE_CODE (t) == CONSTRUCTOR);
-}
-
/* Return true if T is a valid LHS for a GIMPLE assignment expression. */
bool
is_gimple_addressable (tree t)
{
return (is_gimple_id (t) || handled_component_p (t)
- || TREE_CODE (t) == REALPART_EXPR
- || TREE_CODE (t) == IMAGPART_EXPR
|| INDIRECT_REF_P (t));
-
}
/* Return true if T is function invariant. Or rather a restricted
case STRING_CST:
case COMPLEX_CST:
case VECTOR_CST:
- return !TREE_OVERFLOW (t);
+ return true;
default:
return false;
bool
is_gimple_reg_type (tree type)
{
- return (!AGGREGATE_TYPE_P (type)
- && TREE_CODE (type) != COMPLEX_TYPE);
+ return !AGGREGATE_TYPE_P (type);
}
-
-/* Return true if T is a scalar register variable. */
+/* Return true if T is a non-aggregate register variable. */
bool
is_gimple_reg (tree t)
{
+ var_ann_t ann;
+
if (TREE_CODE (t) == SSA_NAME)
t = SSA_NAME_VAR (t);
- return (is_gimple_variable (t)
- && is_gimple_reg_type (TREE_TYPE (t))
- /* A volatile decl is not acceptable because we can't reuse it as
- needed. We need to copy it into a temp first. */
- && ! TREE_THIS_VOLATILE (t)
- && ! needs_to_live_in_memory (t));
+ if (!is_gimple_variable (t))
+ return false;
+
+ if (!is_gimple_reg_type (TREE_TYPE (t)))
+ return false;
+
+ /* A volatile decl is not acceptable because we can't reuse it as
+ needed. We need to copy it into a temp first. */
+ if (TREE_THIS_VOLATILE (t))
+ return false;
+
+ /* We define "registers" as things that can be renamed as needed,
+ which with our infrastructure does not apply to memory. */
+ if (needs_to_live_in_memory (t))
+ return false;
+
+ /* Hard register variables are an interesting case. For those that
+ are call-clobbered, we don't know where all the calls are, since
+ we don't (want to) take into account which operations will turn
+ into libcalls at the rtl level. For those that are call-saved,
+ we don't currently model the fact that calls may in fact change
+ global hard registers, nor do we examine ASM_CLOBBERS at the tree
+ level, and so miss variable changes that might imply. All around,
+ it seems safest to not do too much optimization with these at the
+ tree level at all. We'll have to rely on the rtl optimizers to
+ clean this up, as there we've got all the appropriate bits exposed. */
+ if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
+ return false;
+
+ /* Complex values must have been put into ssa form. That is, no
+ assignments to the individual components. */
+ if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
+ return DECL_COMPLEX_GIMPLE_REG_P (t);
+
+ /* Some compiler temporaries are created to be used exclusively in
+ virtual operands (currently memory tags and sub-variables).
+ These variables should never be considered GIMPLE registers. */
+ if (DECL_ARTIFICIAL (t) && (ann = var_ann (t)) != NULL)
+ return ann->mem_tag_kind == NOT_A_TAG;
+
+ return true;
}
+
/* Returns true if T is a GIMPLE formal temporary variable. */
bool
return (is_gimple_variable (t) || is_gimple_min_invariant (t));
}
+/* Similarly, but accept hard registers as inputs to asm statements. */
+
+bool
+is_gimple_asm_val (tree t)
+{
+ if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
+ return true;
+
+ return is_gimple_val (t);
+}
/* Return true if T is a GIMPLE minimal lvalue. */
return NULL_TREE;
}
-/* Given a memory reference expression, return the base address. Note that,
- in contrast with get_base_var, this will not recurse inside INDIRECT_REF
- expressions. Therefore, given the reference PTR->FIELD, this function
- will return *PTR. Whereas get_base_var would've returned PTR. */
+/* Given a memory reference expression T, return its base address.
+ The base address of a memory reference expression is the main
+ object being referenced. For instance, the base address for
+ 'array[i].fld[j]' is 'array'. You can think of this as stripping
+ away the offset part from a memory address.
+
+ This function calls handled_component_p to strip away all the inner
+ parts of the memory reference until it reaches the base object. */
tree
get_base_address (tree t)
{
- while (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR
- || handled_component_p (t))
+ while (handled_component_p (t))
t = TREE_OPERAND (t, 0);
if (SSA_VAR_P (t)
recalculate_side_effects (tree t)
{
enum tree_code code = TREE_CODE (t);
- int fro = first_rtl_op (code);
+ int len = TREE_CODE_LENGTH (code);
int i;
switch (TREE_CODE_CLASS (code))
case tcc_binary: /* a binary arithmetic expression */
case tcc_reference: /* a reference */
TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
- for (i = 0; i < fro; ++i)
+ for (i = 0; i < len; ++i)
{
tree op = TREE_OPERAND (t, i);
if (op && TREE_SIDE_EFFECTS (op))