X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_emitter.c;h=21bd11ad5868f8dcd7dfe93b7532ee47b34ca415;hb=7c4e33eb7648d9e1cc7efcffc8682a2f27a570a3;hp=1b8292666b8c83ccd504709fb501849952a2672c;hpb=efdfc8f707c7e48c856cf9a945209ba421f26b70;p=libfirm diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 1b8292666..21bd11ad5 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -424,16 +424,6 @@ void ia32_emit_x87_binop(const ir_node *node) { } } -void ia32_emit_am_or_dest_register(const ir_node *node, - int pos) { - if(get_ia32_op_type(node) == ia32_Normal) { - ia32_emit_dest_register(node, pos); - } else { - assert(get_ia32_op_type(node) == ia32_AddrModeD); - ia32_emit_am(node); - } -} - /** * Emits registers and/or address mode of a unary operation. */ @@ -1819,7 +1809,7 @@ static void emit_be_Return(const ir_node *node) be_emit_cstring("\tret"); pop = be_Return_get_pop(node); - if(pop > 0) { + if (pop > 0 || be_Return_get_emit_pop(node)) { be_emit_irprintf(" $%d", pop); } be_emit_finish_line_gas(node); @@ -1943,12 +1933,12 @@ static void ia32_emit_alignment(unsigned align, unsigned skip) static void ia32_emit_align_label(void) { unsigned align = ia32_cg_config.label_alignment; - unsigned maximum_skip = (1 << align) - 1; + unsigned maximum_skip = ia32_cg_config.label_alignment_max_skip; ia32_emit_alignment(align, maximum_skip); } /** - * Test wether a block should be aligned. + * Test whether a block should be aligned. * For cpus in the P4/Athlon class it is useful to align jump labels to * 16 bytes. However we should only do that if the alignment nops before the * label aren't executed more often than we have jumps to the label. @@ -1991,7 +1981,10 @@ static int should_align_block(ir_node *block, ir_node *prev) return jmp_freq > ia32_cg_config.label_alignment_factor; } -static int can_omit_block_label(ir_node *cfgpred) +/** + * Return non-zero, if a instruction in a fall-through. + */ +static int is_fallthrough(ir_node *cfgpred) { ir_node *pred; @@ -2004,7 +1997,13 @@ static int can_omit_block_label(ir_node *cfgpred) return 1; } -static void ia32_emit_block_header(ir_node *block, ir_node *prev) +/** + * Emit the block header for a block. + * + * @param block the block + * @param prev_block the previous block + */ +static void ia32_emit_block_header(ir_node *block, ir_node *prev_block) { ir_graph *irg = current_ir_graph; int n_cfgpreds; @@ -2021,16 +2020,38 @@ static void ia32_emit_block_header(ir_node *block, ir_node *prev) need_label = 0; } else if(n_cfgpreds == 1) { ir_node *cfgpred = get_Block_cfgpred(block, 0); - if(get_nodes_block(cfgpred) == prev && can_omit_block_label(cfgpred)) { + if(get_nodes_block(cfgpred) == prev_block && is_fallthrough(cfgpred)) { need_label = 0; } } - if (should_align_block(block, prev)) { - ia32_emit_align_label(); + if (ia32_cg_config.label_alignment > 0) { + /* align the current block if: + * a) if should be aligned due to its execution frequency + * b) there is no fall-through here + */ + if (should_align_block(block, prev_block)) { + ia32_emit_align_label(); + } else { + /* if the predecessor block has no fall-through, + we can always align the label. */ + int i; + ir_node *check_node = NULL; + + for (i = n_cfgpreds - 1; i >= 0; --i) { + ir_node *cfg_pred = get_Block_cfgpred(block, i); + + if (get_nodes_block(skip_Proj(cfg_pred)) == prev_block) { + check_node = cfg_pred; + break; + } + } + if (check_node == NULL || !is_fallthrough(check_node)) + ia32_emit_align_label(); + } } - if(need_label) { + if (need_label) { ia32_emit_block_name(block); be_emit_char(':');