X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-gimple.c;h=d1e47f65edab38c19c56f9799fc6d19524954bdd;hb=79d7a29d96471dd21e913afd1af615bed9533d15;hp=cabe5469eba14289a35082fe644a1d6bac4cd750;hpb=d471893dcbdfab38ec021b746517d648db7dbb42;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c index cabe5469eba..d1e47f65eda 100644 --- a/gcc/tree-gimple.c +++ b/gcc/tree-gimple.c @@ -1,5 +1,6 @@ /* Functions to analyze and validate GIMPLE trees. - Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. Contributed by Diego Novillo Rewritten by Jason Merrill @@ -7,7 +8,7 @@ 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) +the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, @@ -16,9 +17,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 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, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -33,162 +33,7 @@ Boston, MA 02111-1307, USA. */ #include "expr.h" #include "bitmap.h" -/* GCC GIMPLE structure - - Inspired by the SIMPLE C grammar at - - http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html - - function : FUNCTION_DECL - DECL_SAVED_TREE -> compound-stmt - - compound-stmt: STATEMENT_LIST - members -> stmt - - stmt : block - | if-stmt - | switch-stmt - | goto-stmt - | return-stmt - | resx-stmt - | label-stmt - | try-stmt - | modify-stmt - | call-stmt - - block : BIND_EXPR - BIND_EXPR_VARS -> chain of DECLs - BIND_EXPR_BLOCK -> BLOCK - BIND_EXPR_BODY -> compound-stmt - - if-stmt : COND_EXPR - op0 -> condition - op1 -> compound-stmt - op2 -> compound-stmt - - switch-stmt : SWITCH_EXPR - op0 -> val - op1 -> NULL - op2 -> TREE_VEC of CASE_LABEL_EXPRs - The CASE_LABEL_EXPRs are sorted by CASE_LOW, - and default is last. - - goto-stmt : GOTO_EXPR - op0 -> LABEL_DECL | val - - return-stmt : RETURN_EXPR - op0 -> return-value - - return-value : NULL - | RESULT_DECL - | MODIFY_EXPR - op0 -> RESULT_DECL - op1 -> lhs - - resx-stmt : RESX_EXPR - - label-stmt : LABEL_EXPR - op0 -> LABEL_DECL - - try-stmt : TRY_CATCH_EXPR - op0 -> compound-stmt - op1 -> handler - | TRY_FINALLY_EXPR - op0 -> compound-stmt - op1 -> compound-stmt - - handler : catch-seq - | EH_FILTER_EXPR - | compound-stmt - - catch-seq : STATEMENT_LIST - members -> CATCH_EXPR - - modify-stmt : MODIFY_EXPR - op0 -> lhs - op1 -> rhs - - call-stmt : CALL_EXPR - op0 -> val | OBJ_TYPE_REF - op1 -> call-arg-list - - call-arg-list: TREE_LIST - members -> lhs - - addr-expr-arg: ID - | compref - - addressable : addr-expr-arg - | indirectref - - with-size-arg: addressable - | call-stmt - - indirectref : INDIRECT_REF - op0 -> val - - lhs : addressable - | bitfieldref - | WITH_SIZE_EXPR - op0 -> with-size-arg - op1 -> val - - min-lval : ID - | indirectref - - bitfieldref : BIT_FIELD_REF - op0 -> inner-compref - op1 -> CONST - op2 -> var - - compref : inner-compref - | REALPART_EXPR - op0 -> inner-compref - | IMAGPART_EXPR - op0 -> inner-compref - - inner-compref: min-lval - | COMPONENT_REF - op0 -> inner-compref - op1 -> FIELD_DECL - op2 -> val - | ARRAY_REF - op0 -> inner-compref - op1 -> val - op2 -> val - op3 -> val - | ARRAY_RANGE_REF - op0 -> inner-compref - op1 -> val - op2 -> val - op3 -> val - | VIEW_CONVERT_EXPR - op0 -> inner-compref - - condition : val - | RELOP - op0 -> val - op1 -> val - - val : ID - | CONST - - rhs : lhs - | CONST - | call-stmt - | ADDR_EXPR - op0 -> addr-expr-arg - | UNOP - op0 -> val - | BINOP - op0 -> val - op1 -> val - | RELOP - op0 -> val - op1 -> val -*/ - -static inline bool is_gimple_id (tree); +/* For the definitive definition of GIMPLE, see doc/tree-ssa.texi. */ /* Validation of GIMPLE expressions. */ @@ -201,9 +46,9 @@ is_gimple_formal_tmp_rhs (tree t) switch (TREE_CODE_CLASS (code)) { - case '1': - case '2': - case '<': + case tcc_unary: + case tcc_binary: + case tcc_comparison: return true; default: @@ -216,16 +61,19 @@ is_gimple_formal_tmp_rhs (tree t) case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: case TRUTH_XOR_EXPR: + case COND_EXPR: case ADDR_EXPR: case CALL_EXPR: case CONSTRUCTOR: case COMPLEX_EXPR: case INTEGER_CST: case REAL_CST: + case FIXED_CST: case STRING_CST: case COMPLEX_CST: case VECTOR_CST: case OBJ_TYPE_REF: + case ASSERT_EXPR: return true; default: @@ -241,13 +89,13 @@ is_gimple_formal_tmp_rhs (tree t) bool is_gimple_reg_rhs (tree t) { - /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto + /* If the RHS of the GIMPLE_MODIFY_STMT may throw or make a nonlocal goto and the LHS is a user variable, then we need to introduce a formal temporary. This way the optimizers can determine that the user variable is only modified if evaluation of the RHS does not throw. Don't force a temp of a non-renamable type; the copy could be - arbitrarily expensive. Instead we will generate a V_MAY_DEF for + arbitrarily expensive. Instead we will generate a VDEF for the assignment. */ if (is_gimple_reg_type (TREE_TYPE (t)) @@ -264,9 +112,14 @@ is_gimple_reg_rhs (tree t) 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 + && (TREE_CODE (t) != CALL_EXPR + || ! aggregate_value_p (t, t)))) return is_gimple_val (t); else return is_gimple_formal_tmp_rhs (t); @@ -285,16 +138,6 @@ rhs_predicate_for (tree lhs) 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 @@ -312,8 +155,7 @@ is_gimple_lvalue (tree t) bool is_gimple_condexpr (tree t) { - return (is_gimple_val (t) - || TREE_CODE_CLASS (TREE_CODE (t)) == '<'); + return (is_gimple_val (t) || COMPARISON_CLASS_P (t)); } /* Return true if T is something whose address can be taken. */ @@ -322,16 +164,14 @@ 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 - || TREE_CODE (t) == INDIRECT_REF); + || INDIRECT_REF_P (t)); } -/* Return true if T is function invariant. Or rather a restricted +/* Return true if T is a GIMPLE minimal invariant. It's a restricted form of function invariant. */ bool -is_gimple_min_invariant (tree t) +is_gimple_min_invariant (const_tree t) { switch (TREE_CODE (t)) { @@ -340,10 +180,18 @@ is_gimple_min_invariant (tree t) case INTEGER_CST: case REAL_CST: + case FIXED_CST: case STRING_CST: case COMPLEX_CST: case VECTOR_CST: - return !TREE_OVERFLOW (t); + return true; + + /* Vector constant constructors are gimple invariant. */ + case CONSTRUCTOR: + if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE) + return TREE_CONSTANT (t); + else + return false; default: return false; @@ -355,13 +203,14 @@ is_gimple_min_invariant (tree t) bool is_gimple_stmt (tree t) { - enum tree_code code = TREE_CODE (t); - - if (IS_EMPTY_STMT (t)) - return 1; + const enum tree_code code = TREE_CODE (t); switch (code) { + case NOP_EXPR: + /* The only valid NOP_EXPR is the empty statement. */ + return IS_EMPTY_STMT (t); + case BIND_EXPR: case COND_EXPR: /* These are only valid if they're void. */ @@ -376,15 +225,29 @@ is_gimple_stmt (tree t) case TRY_FINALLY_EXPR: case EH_FILTER_EXPR: case CATCH_EXPR: + case CHANGE_DYNAMIC_TYPE_EXPR: case ASM_EXPR: case RESX_EXPR: case PHI_NODE: case STATEMENT_LIST: + case OMP_PARALLEL: + case OMP_FOR: + case OMP_SECTIONS: + case OMP_SECTIONS_SWITCH: + case OMP_SECTION: + case OMP_SINGLE: + case OMP_MASTER: + case OMP_ORDERED: + case OMP_CRITICAL: + case OMP_RETURN: + case OMP_CONTINUE: + case OMP_ATOMIC_LOAD: + case OMP_ATOMIC_STORE: /* These are always void. */ return true; case CALL_EXPR: - case MODIFY_EXPR: + case GIMPLE_MODIFY_STMT: /* These are valid regardless of their type. */ return true; @@ -406,7 +269,7 @@ is_gimple_variable (tree t) /* Return true if T is a GIMPLE identifier (something with an address). */ -static inline bool +bool is_gimple_id (tree t) { return (is_gimple_variable (t) @@ -422,12 +285,16 @@ is_gimple_id (tree t) bool is_gimple_reg_type (tree type) { - return (!AGGREGATE_TYPE_P (type) - && TREE_CODE (type) != COMPLEX_TYPE); -} + /* In addition to aggregate types, we also exclude complex types if not + optimizing because they can be subject to partial stores in GNU C by + means of the __real__ and __imag__ operators and we cannot promote + them to total stores (see gimplify_modify_expr_complex_part). */ + return !(AGGREGATE_TYPE_P (type) + || (TREE_CODE (type) == COMPLEX_TYPE && !optimize)); +} -/* 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) @@ -435,19 +302,56 @@ is_gimple_reg (tree t) 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 (MTAG_P (t)) + return false; + + 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 and vector values must have been put into SSA-like form. + That is, no assignments to the individual components. */ + if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE + || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE) + return DECL_GIMPLE_REG_P (t); + + return true; } + /* Returns true if T is a GIMPLE formal temporary variable. */ bool is_gimple_formal_tmp_var (tree t) { + if (TREE_CODE (t) == SSA_NAME) + return true; + return TREE_CODE (t) == VAR_DECL && DECL_GIMPLE_FORMAL_TEMP_P (t); } @@ -494,11 +398,21 @@ is_gimple_val (tree t) /* FIXME make these decls. That can happen only when we expose the entire landing-pad construct at the tree level. */ if (TREE_CODE (t) == EXC_PTR_EXPR || TREE_CODE (t) == FILTER_EXPR) - return 1; + return true; 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. */ @@ -516,13 +430,10 @@ is_gimple_cast (tree t) { return (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR - || TREE_CODE (t) == FIX_TRUNC_EXPR - || TREE_CODE (t) == FIX_CEIL_EXPR - || TREE_CODE (t) == FIX_FLOOR_EXPR - || TREE_CODE (t) == FIX_ROUND_EXPR); + || TREE_CODE (t) == FIX_TRUNC_EXPR); } -/* Return true if T is a valid op0 of a CALL_EXPR. */ +/* Return true if T is a valid function operand of a CALL_EXPR. */ bool is_gimple_call_addr (tree t) @@ -537,8 +448,10 @@ is_gimple_call_addr (tree t) tree get_call_expr_in (tree t) { - if (TREE_CODE (t) == MODIFY_EXPR) - t = TREE_OPERAND (t, 1); + /* FIXME tuples: delete the assertion below when conversion complete. */ + gcc_assert (TREE_CODE (t) != MODIFY_EXPR); + if (TREE_CODE (t) == GIMPLE_MODIFY_STMT) + t = GIMPLE_STMT_OPERAND (t, 1); if (TREE_CODE (t) == WITH_SIZE_EXPR) t = TREE_OPERAND (t, 0); if (TREE_CODE (t) == CALL_EXPR) @@ -546,22 +459,25 @@ get_call_expr_in (tree t) 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) || TREE_CODE (t) == STRING_CST || TREE_CODE (t) == CONSTRUCTOR - || TREE_CODE (t) == INDIRECT_REF) + || INDIRECT_REF_P (t)) return t; else return NULL_TREE; @@ -571,16 +487,16 @@ void recalculate_side_effects (tree t) { enum tree_code code = TREE_CODE (t); - int fro = first_rtl_op (code); + int len = TREE_OPERAND_LENGTH (t); int i; switch (TREE_CODE_CLASS (code)) { - case 'e': + case tcc_expression: switch (code) { case INIT_EXPR: - case MODIFY_EXPR: + case GIMPLE_MODIFY_STMT: case VA_ARG_EXPR: case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: @@ -595,17 +511,66 @@ recalculate_side_effects (tree t) } /* Fall through. */ - case '<': /* a comparison expression */ - case '1': /* a unary arithmetic expression */ - case '2': /* a binary arithmetic expression */ - case 'r': /* a reference */ + case tcc_comparison: /* a comparison expression */ + case tcc_unary: /* a unary arithmetic expression */ + case tcc_binary: /* a binary arithmetic expression */ + case tcc_reference: /* a reference */ + case tcc_vl_exp: /* a function call */ 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)) TREE_SIDE_EFFECTS (t) = 1; } break; + + default: + /* Can never be used with non-expressions. */ + gcc_unreachable (); } } + +/* Canonicalize a tree T for use in a COND_EXPR as conditional. Returns + a canonicalized tree that is valid for a COND_EXPR or NULL_TREE, if + we failed to create one. */ + +tree +canonicalize_cond_expr_cond (tree t) +{ + /* For (bool)x use x != 0. */ + if (TREE_CODE (t) == NOP_EXPR + && TREE_TYPE (t) == boolean_type_node) + { + tree top0 = TREE_OPERAND (t, 0); + t = build2 (NE_EXPR, TREE_TYPE (t), + top0, build_int_cst (TREE_TYPE (top0), 0)); + } + /* For !x use x == 0. */ + else if (TREE_CODE (t) == TRUTH_NOT_EXPR) + { + tree top0 = TREE_OPERAND (t, 0); + t = build2 (EQ_EXPR, TREE_TYPE (t), + top0, build_int_cst (TREE_TYPE (top0), 0)); + } + /* For cmp ? 1 : 0 use cmp. */ + else if (TREE_CODE (t) == COND_EXPR + && COMPARISON_CLASS_P (TREE_OPERAND (t, 0)) + && integer_onep (TREE_OPERAND (t, 1)) + && integer_zerop (TREE_OPERAND (t, 2))) + { + tree top0 = TREE_OPERAND (t, 0); + t = build2 (TREE_CODE (top0), TREE_TYPE (t), + TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1)); + } + + /* A valid conditional for a COND_EXPR is either a gimple value + or a comparison with two gimple value operands. */ + if (is_gimple_val (t) + || (COMPARISON_CLASS_P (t) + && is_gimple_val (TREE_OPERAND (t, 0)) + && is_gimple_val (TREE_OPERAND (t, 1)))) + return t; + + return NULL_TREE; +}