This handles calls and conds. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard. 2015-08-13 Richard Biener <rguent...@suse.de> * gimple.h (gcall::code_): New constant static member. (gcond::code_): Likewise. * gimple.c (gcall::code_): Define. (gcond::code_): Likewise. (is_a_helper <const gcond *>): Add. (gimple_call_lhs): Use GIMPLE_CHECK2 in the gimple overload and forward to a new gcall overload with less checking and a cheaper way to access the operand. (gimple_call_lhs_ptr): Likewise. (gimple_call_set_lhs): Likewise. (gimple_call_internal_p): Likewise. (gimple_call_with_bounds_p): Likewise. (gimple_call_set_with_bounds): Likewise. (gimple_call_internal_fn): Likewise. (gimple_call_set_ctrl_altering): Likewise. (gimple_call_ctrl_altering_p): Likewise. (gimple_call_fntype): Likewise. (gimple_call_fn): Likewise. (gimple_call_fn_ptr): Likewise. (gimple_call_set_fndecl): Likewise. (gimple_call_fndecl): Likewise. (gimple_call_chain): Likewise. (gimple_call_num_args): Likewise. (gimple_call_arg): Likewise. (gimple_call_arg_ptr): Likewise. (gimple_call_set_arg): Likewise. (gimple_call_noreturn_p): Likewise. (gimple_cond_code): Likewise. (gimple_cond_lhs): Likewise. (gimple_cond_rhs): Likewise. (gimple_has_lhs): Reduce checking. Index: gcc/gimple.c =================================================================== --- gcc/gimple.c (revision 226802) +++ gcc/gimple.c (working copy) @@ -91,6 +91,8 @@ static const char * const gimple_alloc_k /* Static gimple tuple members. */ const enum gimple_code gassign::code_; +const enum gimple_code gcall::code_; +const enum gimple_code gcond::code_; /* Gimple tuple constructors. Index: gcc/gimple.h =================================================================== --- gcc/gimple.h (revision 226802) +++ gcc/gimple.h (working copy) @@ -351,6 +351,8 @@ struct GTY((tag("GSS_CALL"))) of this structure. In particular, this means that this structure cannot be embedded inside another one. */ tree GTY((length ("%h.num_ops"))) op[1]; + + static const enum gimple_code code_ = GIMPLE_CALL; }; @@ -837,6 +839,7 @@ struct GTY((tag("GSS_WITH_OPS"))) gcond : public gimple_statement_with_ops { /* no additional fields; this uses the layout for GSS_WITH_OPS. */ + static const enum gimple_code code_ = GIMPLE_COND; }; /* A statement with the invariant that @@ -959,6 +962,14 @@ is_a_helper <gcond *>::test (gimple gs) template <> template <> inline bool +is_a_helper <const gcond *>::test (const_gimple gs) +{ + return gs->code == GIMPLE_COND; +} + +template <> +template <> +inline bool is_a_helper <gdebug *>::test (gimple gs) { return gs->code == GIMPLE_DEBUG; @@ -2746,113 +2757,174 @@ is_gimple_call (const_gimple gs) /* Return the LHS of call statement GS. */ static inline tree +gimple_call_lhs (const gcall *gs) +{ + return gs->op[0]; +} + +static inline tree gimple_call_lhs (const_gimple gs) { - GIMPLE_CHECK (gs, GIMPLE_CALL); - return gimple_op (gs, 0); + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_lhs (gc); } /* Return a pointer to the LHS of call statement GS. */ static inline tree * +gimple_call_lhs_ptr (const gcall *gs) +{ + return const_cast<tree *> (&gs->op[0]); +} + +static inline tree * gimple_call_lhs_ptr (const_gimple gs) { - GIMPLE_CHECK (gs, GIMPLE_CALL); - return gimple_op_ptr (gs, 0); + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_lhs_ptr (gc); } /* Set LHS to be the LHS operand of call statement GS. */ static inline void -gimple_call_set_lhs (gimple gs, tree lhs) +gimple_call_set_lhs (gcall *gs, tree lhs) { - GIMPLE_CHECK (gs, GIMPLE_CALL); - gimple_set_op (gs, 0, lhs); + gs->op[0] = lhs; if (lhs && TREE_CODE (lhs) == SSA_NAME) SSA_NAME_DEF_STMT (lhs) = gs; } +static inline void +gimple_call_set_lhs (gimple gs, tree lhs) +{ + gcall *gc = GIMPLE_CHECK2<gcall *> (gs); + gimple_call_set_lhs (gc, lhs); +} + /* Return true if call GS calls an internal-only function, as enumerated by internal_fn. */ static inline bool -gimple_call_internal_p (const_gimple gs) +gimple_call_internal_p (const gcall *gs) { - GIMPLE_CHECK (gs, GIMPLE_CALL); return (gs->subcode & GF_CALL_INTERNAL) != 0; } +static inline bool +gimple_call_internal_p (const_gimple gs) +{ + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_internal_p (gc); +} + /* Return true if call GS is marked as instrumented by Pointer Bounds Checker. */ static inline bool -gimple_call_with_bounds_p (const_gimple gs) +gimple_call_with_bounds_p (const gcall *gs) { - GIMPLE_CHECK (gs, GIMPLE_CALL); return (gs->subcode & GF_CALL_WITH_BOUNDS) != 0; } +static inline bool +gimple_call_with_bounds_p (const_gimple gs) +{ + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_with_bounds_p (gc); +} + /* If INSTRUMENTED_P is true, marm statement GS as instrumented by Pointer Bounds Checker. */ static inline void -gimple_call_set_with_bounds (gimple gs, bool with_bounds) +gimple_call_set_with_bounds (gcall *gs, bool with_bounds) { - GIMPLE_CHECK (gs, GIMPLE_CALL); if (with_bounds) gs->subcode |= GF_CALL_WITH_BOUNDS; else gs->subcode &= ~GF_CALL_WITH_BOUNDS; } +static inline void +gimple_call_set_with_bounds (gimple gs, bool with_bounds) +{ + gcall *gc = GIMPLE_CHECK2<gcall *> (gs); + gimple_call_set_with_bounds (gc, with_bounds); +} + /* Return the target of internal call GS. */ static inline enum internal_fn -gimple_call_internal_fn (const_gimple gs) +gimple_call_internal_fn (const gcall *gs) { gcc_gimple_checking_assert (gimple_call_internal_p (gs)); - return static_cast <const gcall *> (gs)->u.internal_fn; + return gs->u.internal_fn; +} + +static inline enum internal_fn +gimple_call_internal_fn (const_gimple gs) +{ + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_internal_fn (gc); } /* If CTRL_ALTERING_P is true, mark GIMPLE_CALL S to be a stmt that could alter control flow. */ static inline void -gimple_call_set_ctrl_altering (gimple s, bool ctrl_altering_p) +gimple_call_set_ctrl_altering (gcall *s, bool ctrl_altering_p) { - GIMPLE_CHECK (s, GIMPLE_CALL); if (ctrl_altering_p) s->subcode |= GF_CALL_CTRL_ALTERING; else s->subcode &= ~GF_CALL_CTRL_ALTERING; } +static inline void +gimple_call_set_ctrl_altering (gimple s, bool ctrl_altering_p) +{ + gcall *gc = GIMPLE_CHECK2<gcall *> (s); + gimple_call_set_ctrl_altering (gc, ctrl_altering_p); +} + /* Return true if call GS calls an func whose GF_CALL_CTRL_ALTERING flag is set. Such call could not be a stmt in the middle of a bb. */ static inline bool -gimple_call_ctrl_altering_p (const_gimple gs) +gimple_call_ctrl_altering_p (const gcall *gs) { - GIMPLE_CHECK (gs, GIMPLE_CALL); return (gs->subcode & GF_CALL_CTRL_ALTERING) != 0; } +static inline bool +gimple_call_ctrl_altering_p (const_gimple gs) +{ + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_ctrl_altering_p (gc); +} + /* Return the function type of the function called by GS. */ static inline tree -gimple_call_fntype (const_gimple gs) +gimple_call_fntype (const gcall *gs) { - const gcall *call_stmt = as_a <const gcall *> (gs); if (gimple_call_internal_p (gs)) return NULL_TREE; - return call_stmt->u.fntype; + return gs->u.fntype; +} + +static inline tree +gimple_call_fntype (const_gimple gs) +{ + const gcall *call_stmt = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_fntype (call_stmt); } /* Set the type of the function called by CALL_STMT to FNTYPE. */ @@ -2869,20 +2941,32 @@ gimple_call_set_fntype (gcall *call_stmt statement GS. */ static inline tree +gimple_call_fn (const gcall *gs) +{ + return gs->op[1]; +} + +static inline tree gimple_call_fn (const_gimple gs) { - GIMPLE_CHECK (gs, GIMPLE_CALL); - return gimple_op (gs, 1); + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_fn (gc); } /* Return a pointer to the tree node representing the function called by call statement GS. */ static inline tree * +gimple_call_fn_ptr (const gcall *gs) +{ + return const_cast<tree *> (&gs->op[1]); +} + +static inline tree * gimple_call_fn_ptr (const_gimple gs) { - GIMPLE_CHECK (gs, GIMPLE_CALL); - return gimple_op_ptr (gs, 1); + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_fn_ptr (gc); } @@ -2899,13 +2983,18 @@ gimple_call_set_fn (gcall *gs, tree fn) /* Set FNDECL to be the function called by call statement GS. */ static inline void -gimple_call_set_fndecl (gimple gs, tree decl) +gimple_call_set_fndecl (gcall *gs, tree decl) { - GIMPLE_CHECK (gs, GIMPLE_CALL); gcc_gimple_checking_assert (!gimple_call_internal_p (gs)); - gimple_set_op (gs, 1, build1_loc (gimple_location (gs), ADDR_EXPR, - build_pointer_type (TREE_TYPE (decl)), - decl)); + gs->op[1] = build1_loc (gimple_location (gs), ADDR_EXPR, + build_pointer_type (TREE_TYPE (decl)), decl); +} + +static inline void +gimple_call_set_fndecl (gimple gs, tree decl) +{ + gcall *gc = GIMPLE_CHECK2<gcall *> (gs); + gimple_call_set_fndecl (gc, decl); } @@ -2924,11 +3013,18 @@ gimple_call_set_internal_fn (gcall *call get_callee_fndecl in tree land. */ static inline tree -gimple_call_fndecl (const_gimple gs) +gimple_call_fndecl (const gcall *gs) { return gimple_call_addr_fndecl (gimple_call_fn (gs)); } +static inline tree +gimple_call_fndecl (const_gimple gs) +{ + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_fndecl (gc); +} + /* Return the type returned by call statement GS. */ @@ -2949,10 +3045,16 @@ gimple_call_return_type (const gcall *gs /* Return the static chain for call statement GS. */ static inline tree +gimple_call_chain (const gcall *gs) +{ + return gs->op[2]; +} + +static inline tree gimple_call_chain (const_gimple gs) { - GIMPLE_CHECK (gs, GIMPLE_CALL); - return gimple_op (gs, 2); + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_chain (gc); } @@ -2976,22 +3078,33 @@ gimple_call_set_chain (gcall *call_stmt, /* Return the number of arguments used by call statement GS. */ static inline unsigned +gimple_call_num_args (const gcall *gs) +{ + return gimple_num_ops (gs) - 3; +} + +static inline unsigned gimple_call_num_args (const_gimple gs) { - unsigned num_ops; - GIMPLE_CHECK (gs, GIMPLE_CALL); - num_ops = gimple_num_ops (gs); - return num_ops - 3; + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_num_args (gc); } /* Return the argument at position INDEX for call statement GS. */ static inline tree +gimple_call_arg (const gcall *gs, unsigned index) +{ + gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 3); + return gs->op[index + 3]; +} + +static inline tree gimple_call_arg (const_gimple gs, unsigned index) { - GIMPLE_CHECK (gs, GIMPLE_CALL); - return gimple_op (gs, index + 3); + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_arg (gc, index); } @@ -2999,20 +3112,34 @@ gimple_call_arg (const_gimple gs, unsign statement GS. */ static inline tree * +gimple_call_arg_ptr (const gcall *gs, unsigned index) +{ + gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 3); + return const_cast<tree *> (&gs->op[index + 3]); +} + +static inline tree * gimple_call_arg_ptr (const_gimple gs, unsigned index) { - GIMPLE_CHECK (gs, GIMPLE_CALL); - return gimple_op_ptr (gs, index + 3); + const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs); + return gimple_call_arg_ptr (gc, index); } /* Set ARG to be the argument at position INDEX for call statement GS. */ static inline void +gimple_call_set_arg (gcall *gs, unsigned index, tree arg) +{ + gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 3); + gs->op[index + 3] = arg; +} + +static inline void gimple_call_set_arg (gimple gs, unsigned index, tree arg) { - GIMPLE_CHECK (gs, GIMPLE_CALL); - gimple_set_op (gs, index + 3, arg); + gcall *gc = GIMPLE_CHECK2<gcall *> (gs); + gimple_call_set_arg (gc, index, arg); } @@ -3110,12 +3237,18 @@ gimple_call_va_arg_pack_p (gcall *s) /* Return true if S is a noreturn call. */ static inline bool -gimple_call_noreturn_p (gimple s) +gimple_call_noreturn_p (const gcall *s) { - GIMPLE_CHECK (s, GIMPLE_CALL); return (gimple_call_flags (s) & ECF_NORETURN) != 0; } +static inline bool +gimple_call_noreturn_p (const_gimple s) +{ + const gcall *gc = GIMPLE_CHECK2<const gcall *> (s); + return gimple_call_noreturn_p (gc); +} + /* If NOTHROW_P is true, GIMPLE_CALL S is a call that is known to not throw even if the called function can throw in other cases. */ @@ -3194,21 +3327,29 @@ gimple_call_clobber_set (gcall *call_stm static inline bool gimple_has_lhs (gimple stmt) { - return (is_gimple_assign (stmt) - || (is_gimple_call (stmt) - && gimple_call_lhs (stmt) != NULL_TREE)); + if (is_gimple_assign (stmt)) + return true; + if (gcall *call = dyn_cast <gcall *> (stmt)) + return gimple_call_lhs (call) != NULL_TREE; + return false; } /* Return the code of the predicate computed by conditional statement GS. */ static inline enum tree_code -gimple_cond_code (const_gimple gs) +gimple_cond_code (const gcond *gs) { - GIMPLE_CHECK (gs, GIMPLE_COND); return (enum tree_code) gs->subcode; } +static inline enum tree_code +gimple_cond_code (const_gimple gs) +{ + const gcond *gc = GIMPLE_CHECK2<const gcond *> (gs); + return gimple_cond_code (gc); +} + /* Set CODE to be the predicate code for the conditional statement GS. */ @@ -3222,10 +3363,16 @@ gimple_cond_set_code (gcond *gs, enum tr /* Return the LHS of the predicate computed by conditional statement GS. */ static inline tree +gimple_cond_lhs (const gcond *gs) +{ + return gs->op[0]; +} + +static inline tree gimple_cond_lhs (const_gimple gs) { - GIMPLE_CHECK (gs, GIMPLE_COND); - return gimple_op (gs, 0); + const gcond *gc = GIMPLE_CHECK2<const gcond *> (gs); + return gimple_cond_lhs (gc); } /* Return the pointer to the LHS of the predicate computed by conditional @@ -3250,10 +3397,16 @@ gimple_cond_set_lhs (gcond *gs, tree lhs /* Return the RHS operand of the predicate computed by conditional GS. */ static inline tree +gimple_cond_rhs (const gcond *gs) +{ + return gs->op[1]; +} + +static inline tree gimple_cond_rhs (const_gimple gs) { - GIMPLE_CHECK (gs, GIMPLE_COND); - return gimple_op (gs, 1); + const gcond *gc = GIMPLE_CHECK2<const gcond *> (gs); + return gimple_cond_rhs (gc); } /* Return the pointer to the RHS operand of the predicate computed by