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);
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.
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;
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;
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(':');