(const_basic_block bb) { return EDGE_COUNT (bb->preds) == 1; } /* Returns the single successor edge of basic block BB. Aborts if BB does not have exactly one successor. */ static inline edge single_succ_edge (const_basic_block bb) { gcc_checking_assert (single_succ_p (bb)); return EDGE_SUCC (bb, 0); } /* Returns the single predecessor edge of basic block BB. Aborts if BB does not have exactly one predecessor. */ static inline edge single_pred_edge (const_basic_block bb) { gcc_checking_assert (single_pred_p (bb)); return EDGE_PRED (bb, 0); } /* Returns the single successor block of basic block BB. Aborts if BB does not have exactly one successor. */ static inline basic_block single_succ (const_basic_block bb) { return single_succ_edge (bb)->dest; } /* Returns the single predecessor block of basic block BB. Aborts if BB does not have exactly one predecessor.*/ static inline basic_block single_pred (const_basic_block bb) { return single_pred_edge (bb)->src; } /* Iterator object for edges. */ struct edge_iterator { unsigned index; vec **container; }; static inline vec * ei_container (edge_iterator i) { gcc_checking_assert (i.container); return *i.container; } #define ei_start(iter) ei_start_1 (&(iter)) #define ei_last(iter) ei_last_1 (&(iter)) /* Return an iterator pointing to the start of an edge vector. */ static inline edge_iterator ei_start_1 (vec **ev) { edge_iterator i; i.index = 0; i.container = ev; return i; } /* Return an iterator pointing to the last element of an edge vector. */ static inline edge_iterator ei_last_1 (vec **ev) { edge_iterator i; i.index = EDGE_COUNT (*ev) - 1; i.container = ev; return i; } /* Is the iterator `i' at the end of the sequence? */ static inline bool ei_end_p (edge_iterator i) { return (i.index == EDGE_COUNT (ei_container (i))); } /* Is the iterator `i' at one position before the end of the sequence? */ static inline bool ei_one_before_end_p (edge_iterator i) { return (i.index + 1 == EDGE_COUNT (ei_container (i))); } /* Advance the iterator to the next element. */ static inline void ei_next (edge_iterator *i) { gcc_checking_assert (i->index < EDGE_COUNT (ei_container (*i))); i->index++; } /* Move the iterator to the previous element. */ static inline void ei_prev (edge_iterator *i) { gcc_checking_assert (i->index > 0); i->index--; } /* Return the edge pointed to by the iterator `i'. */ static inline edge ei_edge (edge_iterator i) { return EDGE_I (ei_container (i), i.index); } /* Return an edge pointed to by the iterator. Do it safely so that NULL is returned when the iterator is pointing at the end of the sequence. */ static inline edge ei_safe_edge (edge_iterator i) { return !ei_end_p (i) ? ei_edge (i) : NULL; } /* Return 1 if we should continue to iterate. Return 0 otherwise. *Edge P is set to the next edge if we are to continue to iterate and NULL otherwise. */ static inline bool ei_cond (edge_iterator ei, edge *p) { if (!ei_end_p (ei)) { *p = ei_edge (ei); return 1; } else { *p = NULL; return 0; } } /* This macro serves as a convenient way to iterate each edge in a vector of predecessor or successor edges. It must not be used when an element might be removed during the traversal, otherwise elements will be missed. Instead, use a for-loop like that shown in the following pseudo-code: FOR (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ) { IF (e != taken_edge) remove_edge (e); ELSE ei_next (&ei); } */ #define FOR_EACH_EDGE(EDGE,ITER,EDGE_VEC) \ for ((ITER) = ei_start ((EDGE_VEC)); \ ei_cond ((ITER), &(EDGE)); \ ei_next (&(ITER))) #define CLEANUP_EXPENSIVE 1 /* Do relatively expensive optimizations except for edge forwarding */ #define CLEANUP_CROSSJUMP 2 /* Do crossjumping. */ #define CLEANUP_POST_REGSTACK 4 /* We run after reg-stack and need to care REG_DEAD notes. */ #define CLEANUP_THREADING 8 /* Do jump threading. */ #define CLEANUP_NO_INSN_DEL 16 /* Do not try to delete trivially dead insns. */ #define CLEANUP_CFGLAYOUT 32 /* Do cleanup in cfglayout mode. */ #define CLEANUP_CFG_CHANGED 64 /* The caller changed the CFG. */ /* Return true if BB is in a transaction. */ static inline bool bb_in_transaction (basic_block bb) { return bb->flags & BB_IN_TRANSACTION; } /* Return true when one of the predecessor edges of BB is marked with EDGE_EH. */ static inline bool bb_has_eh_pred (basic_block bb) { edge e; edge_iterator ei; FOR_EACH_EDGE (e, ei, bb->preds) { if (e->flags & EDGE_EH) return true; } return false; } /* Return true when one of the predecessor edges of BB is marked with EDGE_ABNORMAL. */ static inline bool bb_has_abnormal_pred (basic_block bb) { edge e; edge_iterator ei; FOR_EACH_EDGE (e, ei, bb->preds) { if (e->flags & EDGE_ABNORMAL) return true; } return false; } /* Return the fallthru edge in EDGES if it exists, NULL otherwise. */ static inline edge find_fallthru_edge (vec *edges) { edge e; edge_iterator ei; FOR_EACH_EDGE (e, ei, edges) if (e->flags & EDGE_FALLTHRU) break; return e; } /* Check tha probability is sane. */ static inline void check_probability (int prob) { gcc_checking_assert (prob >= 0 && prob <= REG_BR_PROB_BASE); } /* Given PROB1 and PROB2, return PROB1*PROB2/REG_BR_PROB_BASE. Used to combine BB probabilities. */ static inline int combine_probabilities (int prob1, int prob2) { check_probability (prob1); check_probability (prob2); return RDIV (prob1 * prob2, REG_BR_PROB_BASE); } /* Apply scale factor SCALE on frequency or count FREQ. Use this interface when potentially scaling up, so that SCALE is not constrained to be < REG_BR_PROB_BASE. */ static inline gcov_type apply_scale (gcov_type freq, gcov_type scale) { return RDIV (freq * scale, REG_BR_PROB_BASE); } /* Apply probability PROB on frequency or count FREQ. */ static inline gcov_type apply_probability (gcov_type freq, int prob) { check_probability (prob); return apply_scale (freq, prob); } /* Return inverse probability for PROB. */ static inline int inverse_probability (int prob1) { check_probability (prob1); return REG_BR_PROB_BASE - prob1; } /* Return true if BB has at least one abnormal outgoing edge. */ static inline bool has_abnormal_or_eh_outgoing_edge_p (basic_block bb) { edge e; edge_iterator ei; FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & (EDGE_ABNORMAL | EDGE_EH)) return true; return false; } /* Return true when one of the predecessor edges of BB is marked with EDGE_ABNORMAL_CALL or EDGE_EH. */ static inline bool has_abnormal_call_or_eh_pred_edge_p (basic_block bb) { edge e; edge_iterator ei; FOR_EACH_EDGE (e, ei, bb->preds) if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH)) return true; return false; } #endif /* GCC_BASIC_BLOCK_H */