static void mark_all_labels (rtx f) { rtx insn; if (current_ir_type () == IR_RTL_CFGLAYOUT) { basic_block bb; FOR_EACH_BB (bb) { /* In cfglayout mode, we don't bother with trivial next-insn propagation of LABEL_REFs into JUMP_LABEL. This will be handled by other optimizers using better algorithms. */ FOR_BB_INSNS (bb, insn) { gcc_assert (! INSN_DELETED_P (insn)); if (NONDEBUG_INSN_P (insn)) mark_jump_label (PATTERN (insn), insn, 0); } /* In cfglayout mode, there may be non-insns between the basic blocks. If those non-insns represent tablejump data, they contain label references that we must record. */ for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn)) if (INSN_P (insn)) { gcc_assert (JUMP_TABLE_DATA_P (insn)); mark_jump_label (PATTERN (insn), insn, 0); } for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn)) if (INSN_P (insn)) { gcc_assert (JUMP_TABLE_DATA_P (insn)); mark_jump_label (PATTERN (insn), insn, 0); } }
static void mark_all_labels (rtx f) { rtx insn; rtx prev_nonjump_insn = NULL; for (insn = f; insn; insn = NEXT_INSN (insn)) if (INSN_P (insn)) { mark_jump_label (PATTERN (insn), insn, 0); /* If the previous non-jump insn sets something to a label, something that this jump insn uses, make that label the primary target of this insn if we don't yet have any. That previous insn must be a single_set and not refer to more than one label. The jump insn must not refer to other labels as jump targets and must be a plain (set (pc) ...), maybe in a parallel, and may refer to the item being set only directly or as one of the arms in an IF_THEN_ELSE. */ if (! INSN_DELETED_P (insn) && JUMP_P (insn) && JUMP_LABEL (insn) == NULL) { rtx label_note = NULL; rtx pc = pc_set (insn); rtx pc_src = pc != NULL ? SET_SRC (pc) : NULL; if (prev_nonjump_insn != NULL) label_note = find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL); if (label_note != NULL && pc_src != NULL) { rtx label_set = single_set (prev_nonjump_insn); rtx label_dest = label_set != NULL ? SET_DEST (label_set) : NULL; if (label_set != NULL /* The source must be the direct LABEL_REF, not a PLUS, UNSPEC, IF_THEN_ELSE etc. */ && GET_CODE (SET_SRC (label_set)) == LABEL_REF && (rtx_equal_p (label_dest, pc_src) || (GET_CODE (pc_src) == IF_THEN_ELSE && (rtx_equal_p (label_dest, XEXP (pc_src, 1)) || rtx_equal_p (label_dest, XEXP (pc_src, 2)))))) { /* The CODE_LABEL referred to in the note must be the CODE_LABEL in the LABEL_REF of the "set". We can conveniently use it for the marker function, which requires a LABEL_REF wrapping. */ gcc_assert (XEXP (label_note, 0) == XEXP (SET_SRC (label_set), 0)); mark_jump_label_1 (label_set, insn, false, true); gcc_assert (JUMP_LABEL (insn) == XEXP (SET_SRC (label_set), 0)); } } } else if (! INSN_DELETED_P (insn)) prev_nonjump_insn = insn; } else if (LABEL_P (insn)) prev_nonjump_insn = NULL; /* If we are in cfglayout mode, there may be non-insns between the basic blocks. If those non-insns represent tablejump data, they contain label references that we must record. */ if (current_ir_type () == IR_RTL_CFGLAYOUT) { basic_block bb; rtx insn; FOR_EACH_BB (bb) { for (insn = bb->il.rtl->header; insn; insn = NEXT_INSN (insn)) if (INSN_P (insn)) { gcc_assert (JUMP_TABLE_DATA_P (insn)); mark_jump_label (PATTERN (insn), insn, 0); } for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn)) if (INSN_P (insn)) { gcc_assert (JUMP_TABLE_DATA_P (insn)); mark_jump_label (PATTERN (insn), insn, 0); } } }
static basic_block expand_gimple_basic_block (basic_block bb, FILE * dump_file) { block_stmt_iterator bsi = bsi_start (bb); tree stmt = NULL; rtx note, last; edge e; edge_iterator ei; if (dump_file) { fprintf (dump_file, "\n;; Generating RTL for tree basic block %d\n", bb->index); } if (!bsi_end_p (bsi)) stmt = bsi_stmt (bsi); if (stmt && TREE_CODE (stmt) == LABEL_EXPR) { last = get_last_insn (); expand_expr_stmt (stmt); /* Java emits line number notes in the top of labels. ??? Make this go away once line number notes are obsoleted. */ BB_HEAD (bb) = NEXT_INSN (last); if (NOTE_P (BB_HEAD (bb))) BB_HEAD (bb) = NEXT_INSN (BB_HEAD (bb)); bsi_next (&bsi); note = emit_note_after (NOTE_INSN_BASIC_BLOCK, BB_HEAD (bb)); maybe_dump_rtl_for_tree_stmt (stmt, last); } else note = BB_HEAD (bb) = emit_note (NOTE_INSN_BASIC_BLOCK); NOTE_BASIC_BLOCK (note) = bb; for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ) { /* Clear EDGE_EXECUTABLE. This flag is never used in the backend. */ e->flags &= ~EDGE_EXECUTABLE; /* At the moment not all abnormal edges match the RTL representation. It is safe to remove them here as find_sub_basic_blocks will rediscover them. In the future we should get this fixed properly. */ if (e->flags & EDGE_ABNORMAL) remove_edge (e); else ei_next (&ei); } for (; !bsi_end_p (bsi); bsi_next (&bsi)) { tree stmt = bsi_stmt (bsi); basic_block new_bb; if (!stmt) continue; /* Expand this statement, then evaluate the resulting RTL and fixup the CFG accordingly. */ if (TREE_CODE (stmt) == COND_EXPR) { new_bb = expand_gimple_cond_expr (bb, stmt); if (new_bb) return new_bb; } else { tree call = get_call_expr_in (stmt); if (call && CALL_EXPR_TAILCALL (call)) { bool can_fallthru; new_bb = expand_gimple_tailcall (bb, stmt, &can_fallthru); if (new_bb) { if (can_fallthru) bb = new_bb; else return new_bb; } } else { last = get_last_insn (); expand_expr_stmt (stmt); maybe_dump_rtl_for_tree_stmt (stmt, last); } } } do_pending_stack_adjust (); /* Find the block tail. The last insn in the block is the insn before a barrier and/or table jump insn. */ last = get_last_insn (); if (BARRIER_P (last)) last = PREV_INSN (last); if (JUMP_TABLE_DATA_P (last)) last = PREV_INSN (PREV_INSN (last)); BB_END (bb) = last; update_bb_for_insn (bb); return bb; }