| /* Tree SCC value numbering |
| Copyright (C) 2007-2017 Free Software Foundation, Inc. |
| Contributed by Daniel Berlin <dberlin@dberlin.org> |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify |
| under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| GCC is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 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 COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #ifndef TREE_SSA_SCCVN_H |
| #define TREE_SSA_SCCVN_H |
| |
| /* In tree-ssa-sccvn.c */ |
| bool expressions_equal_p (tree, tree); |
| |
| |
| /* TOP of the VN lattice. */ |
| extern tree VN_TOP; |
| |
| /* N-ary operations in the hashtable consist of length operands, an |
| opcode, and a type. Result is the value number of the operation, |
| and hashcode is stored to avoid having to calculate it |
| repeatedly. */ |
| |
| typedef struct vn_nary_op_s |
| { |
| /* Unique identify that all expressions with the same value have. */ |
| unsigned int value_id; |
| ENUM_BITFIELD(tree_code) opcode : 16; |
| unsigned length : 16; |
| hashval_t hashcode; |
| tree result; |
| tree type; |
| tree op[1]; |
| } *vn_nary_op_t; |
| typedef const struct vn_nary_op_s *const_vn_nary_op_t; |
| |
| /* Return the size of a vn_nary_op_t with LENGTH operands. */ |
| |
| static inline size_t |
| sizeof_vn_nary_op (unsigned int length) |
| { |
| return sizeof (struct vn_nary_op_s) + sizeof (tree) * length - sizeof (tree); |
| } |
| |
| /* Phi nodes in the hashtable consist of their non-VN_TOP phi |
| arguments, and the basic block the phi is in. Result is the value |
| number of the operation, and hashcode is stored to avoid having to |
| calculate it repeatedly. Phi nodes not in the same block are never |
| considered equivalent. */ |
| |
| typedef struct vn_phi_s |
| { |
| /* Unique identifier that all expressions with the same value have. */ |
| unsigned int value_id; |
| hashval_t hashcode; |
| vec<tree> phiargs; |
| basic_block block; |
| /* Controlling condition lhs/rhs. */ |
| tree cclhs; |
| tree ccrhs; |
| tree type; |
| tree result; |
| } *vn_phi_t; |
| typedef const struct vn_phi_s *const_vn_phi_t; |
| |
| /* Reference operands only exist in reference operations structures. |
| They consist of an opcode, type, and some number of operands. For |
| a given opcode, some, all, or none of the operands may be used. |
| The operands are there to store the information that makes up the |
| portion of the addressing calculation that opcode performs. */ |
| |
| typedef struct vn_reference_op_struct |
| { |
| ENUM_BITFIELD(tree_code) opcode : 16; |
| /* Dependence info, used for [TARGET_]MEM_REF only. */ |
| unsigned short clique; |
| unsigned short base; |
| /* 1 for instrumented calls. */ |
| unsigned with_bounds : 1; |
| unsigned reverse : 1; |
| /* For storing TYPE_ALIGN for array ref element size computation. */ |
| unsigned align : 6; |
| /* Constant offset this op adds or -1 if it is variable. */ |
| HOST_WIDE_INT off; |
| tree type; |
| tree op0; |
| tree op1; |
| tree op2; |
| } vn_reference_op_s; |
| typedef vn_reference_op_s *vn_reference_op_t; |
| typedef const vn_reference_op_s *const_vn_reference_op_t; |
| |
| inline unsigned |
| vn_ref_op_align_unit (vn_reference_op_t op) |
| { |
| return op->align ? ((unsigned)1 << (op->align - 1)) / BITS_PER_UNIT : 0; |
| } |
| |
| /* A reference operation in the hashtable is representation as |
| the vuse, representing the memory state at the time of |
| the operation, and a collection of operands that make up the |
| addressing calculation. If two vn_reference_t's have the same set |
| of operands, they access the same memory location. We also store |
| the resulting value number, and the hashcode. */ |
| |
| typedef struct vn_reference_s |
| { |
| /* Unique identifier that all expressions with the same value have. */ |
| unsigned int value_id; |
| hashval_t hashcode; |
| tree vuse; |
| alias_set_type set; |
| tree type; |
| vec<vn_reference_op_s> operands; |
| tree result; |
| tree result_vdef; |
| } *vn_reference_t; |
| typedef const struct vn_reference_s *const_vn_reference_t; |
| |
| typedef struct vn_constant_s |
| { |
| unsigned int value_id; |
| hashval_t hashcode; |
| tree constant; |
| } *vn_constant_t; |
| |
| enum vn_kind { VN_NONE, VN_CONSTANT, VN_NARY, VN_REFERENCE, VN_PHI }; |
| enum vn_kind vn_get_stmt_kind (gimple *); |
| |
| /* Hash the type TYPE using bits that distinguishes it in the |
| types_compatible_p sense. */ |
| |
| static inline hashval_t |
| vn_hash_type (tree type) |
| { |
| return (INTEGRAL_TYPE_P (type) |
| + (INTEGRAL_TYPE_P (type) |
| ? TYPE_PRECISION (type) + TYPE_UNSIGNED (type) : 0)); |
| } |
| |
| /* Hash the constant CONSTANT with distinguishing type incompatible |
| constants in the types_compatible_p sense. */ |
| |
| static inline hashval_t |
| vn_hash_constant_with_type (tree constant) |
| { |
| inchash::hash hstate; |
| inchash::add_expr (constant, hstate); |
| hstate.merge_hash (vn_hash_type (TREE_TYPE (constant))); |
| return hstate.end (); |
| } |
| |
| /* Compare the constants C1 and C2 with distinguishing type incompatible |
| constants in the types_compatible_p sense. */ |
| |
| static inline bool |
| vn_constant_eq_with_type (tree c1, tree c2) |
| { |
| return (expressions_equal_p (c1, c2) |
| && types_compatible_p (TREE_TYPE (c1), TREE_TYPE (c2))); |
| } |
| |
| typedef struct vn_ssa_aux |
| { |
| /* Value number. This may be an SSA name or a constant. */ |
| tree valnum; |
| /* Statements to insert if needs_insertion is true. */ |
| gimple_seq expr; |
| |
| /* Saved SSA name info. */ |
| tree_ssa_name::ssa_name_info_type info; |
| |
| /* Unique identifier that all expressions with the same value have. */ |
| unsigned int value_id; |
| |
| /* SCC information. */ |
| unsigned int dfsnum; |
| unsigned int low; |
| unsigned visited : 1; |
| unsigned on_sccstack : 1; |
| |
| /* Whether the SSA_NAME has been value numbered already. This is |
| only saying whether visit_use has been called on it at least |
| once. It cannot be used to avoid visitation for SSA_NAME's |
| involved in non-singleton SCC's. */ |
| unsigned use_processed : 1; |
| |
| /* Whether the SSA_NAME has no defining statement and thus an |
| insertion of such with EXPR as definition is required before |
| a use can be created of it. */ |
| unsigned needs_insertion : 1; |
| |
| /* Whether range-info is anti-range. */ |
| unsigned range_info_anti_range_p : 1; |
| } *vn_ssa_aux_t; |
| |
| enum vn_lookup_kind { VN_NOWALK, VN_WALK, VN_WALKREWRITE }; |
| |
| /* Return the value numbering info for an SSA_NAME. */ |
| extern vn_ssa_aux_t VN_INFO (tree); |
| extern vn_ssa_aux_t VN_INFO_GET (tree); |
| tree vn_get_expr_for (tree); |
| bool run_scc_vn (vn_lookup_kind); |
| void free_scc_vn (void); |
| void scc_vn_restore_ssa_info (void); |
| tree vn_nary_op_lookup (tree, vn_nary_op_t *); |
| tree vn_nary_op_lookup_stmt (gimple *, vn_nary_op_t *); |
| tree vn_nary_op_lookup_pieces (unsigned int, enum tree_code, |
| tree, tree *, vn_nary_op_t *); |
| vn_nary_op_t vn_nary_op_insert (tree, tree); |
| vn_nary_op_t vn_nary_op_insert_pieces (unsigned int, enum tree_code, |
| tree, tree *, tree, unsigned int); |
| bool ao_ref_init_from_vn_reference (ao_ref *, alias_set_type, tree, |
| vec<vn_reference_op_s> ); |
| vec<vn_reference_op_s> vn_reference_operands_for_lookup (tree); |
| tree vn_reference_lookup_pieces (tree, alias_set_type, tree, |
| vec<vn_reference_op_s> , |
| vn_reference_t *, vn_lookup_kind); |
| tree vn_reference_lookup (tree, tree, vn_lookup_kind, vn_reference_t *, bool); |
| void vn_reference_lookup_call (gcall *, vn_reference_t *, vn_reference_t); |
| vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree, |
| vec<vn_reference_op_s> , |
| tree, unsigned int); |
| |
| bool vn_nary_op_eq (const_vn_nary_op_t const vno1, |
| const_vn_nary_op_t const vno2); |
| bool vn_nary_may_trap (vn_nary_op_t); |
| bool vn_reference_may_trap (vn_reference_t); |
| bool vn_reference_eq (const_vn_reference_t const, const_vn_reference_t const); |
| unsigned int get_max_value_id (void); |
| unsigned int get_next_value_id (void); |
| unsigned int get_constant_value_id (tree); |
| unsigned int get_or_alloc_constant_value_id (tree); |
| bool value_id_constant_p (unsigned int); |
| tree fully_constant_vn_reference_p (vn_reference_t); |
| tree vn_nary_simplify (vn_nary_op_t); |
| |
| /* Valueize NAME if it is an SSA name, otherwise just return it. */ |
| |
| static inline tree |
| vn_valueize (tree name) |
| { |
| if (TREE_CODE (name) == SSA_NAME) |
| { |
| tree tem = VN_INFO (name)->valnum; |
| return tem == VN_TOP ? name : tem; |
| } |
| return name; |
| } |
| |
| /* Get at the original range info for NAME. */ |
| |
| inline range_info_def * |
| VN_INFO_RANGE_INFO (tree name) |
| { |
| return (VN_INFO (name)->info.range_info |
| ? VN_INFO (name)->info.range_info |
| : SSA_NAME_RANGE_INFO (name)); |
| } |
| |
| /* Whether the original range info of NAME is an anti-range. */ |
| |
| inline bool |
| VN_INFO_ANTI_RANGE_P (tree name) |
| { |
| return (VN_INFO (name)->info.range_info |
| ? VN_INFO (name)->range_info_anti_range_p |
| : SSA_NAME_ANTI_RANGE_P (name)); |
| } |
| |
| /* Get at the original range info kind for NAME. */ |
| |
| inline value_range_type |
| VN_INFO_RANGE_TYPE (tree name) |
| { |
| return VN_INFO_ANTI_RANGE_P (name) ? VR_ANTI_RANGE : VR_RANGE; |
| } |
| |
| /* Get at the original pointer info for NAME. */ |
| |
| inline ptr_info_def * |
| VN_INFO_PTR_INFO (tree name) |
| { |
| return (VN_INFO (name)->info.ptr_info |
| ? VN_INFO (name)->info.ptr_info |
| : SSA_NAME_PTR_INFO (name)); |
| } |
| |
| #endif /* TREE_SSA_SCCVN_H */ |