- moved the imul mem,imm32 splitting into peephole optimizations
[libfirm] / ir / be / ia32 / ia32_emitter.c
index 1b82926..21bd11a 100644 (file)
@@ -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(':');