/*
- * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
return 1;
case iro_Add:
case iro_Sub:
- /* Add's and Sub's are typically supported as long as both operands are immediates */
+ /* Add's and Sub's are typically supported as long as both operands are
+ * immediates */
if(bitset_is_set(non_address_mode_nodes, get_irn_idx(node)))
return 0;
bitset_set(non_address_mode_nodes, get_irn_idx(node));
}
+static int value_last_used_here(ir_node *here, ir_node *value)
+{
+ ir_node *block = get_nodes_block(here);
+ const ir_edge_t *edge;
+
+ /* If the value is live end it is for sure it does not die here */
+ if (be_is_live_end(lv, block, value)) return 0;
+
+ /* if multiple nodes in this block use the value, then we cannot decide
+ * whether the value will die here (because there is no schedule yet).
+ * Assume it does not die in this case. */
+ foreach_out_edge(value, edge) {
+ ir_node *user = get_edge_src_irn(edge);
+ if (user != here && get_nodes_block(user) == block) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
/**
* Walker: mark those nodes that cannot be part of an address mode because
* there value must be access through an register
static void mark_non_address_nodes(ir_node *node, void *env)
{
int i, arity;
- ir_node *ptr;
- ir_node *mem;
ir_node *val;
- ir_node *block;
ir_node *left;
ir_node *right;
ir_mode *mode;
- const ir_edge_t *edge;
(void) env;
mode = get_irn_mode(node);
switch(get_irn_opcode(node)) {
case iro_Load:
- ptr = get_Load_ptr(node);
- mem = get_Load_mem(node);
-
- bitset_set(non_address_mode_nodes, get_irn_idx(mem));
+ /* Nothing to do. especially do not mark the pointer, because we want to
+ * turn it into AM. */
break;
case iro_Store:
+ /* Do not mark the pointer, because we want to turn it into AM. */
val = get_Store_value(node);
- ptr = get_Store_ptr(node);
- mem = get_Store_mem(node);
-
bitset_set(non_address_mode_nodes, get_irn_idx(val));
- bitset_set(non_address_mode_nodes, get_irn_idx(mem));
break;
case iro_Shl:
* pressure. Otherwise we fold them in aggressively in the hope, that
* the node itself doesn't exist anymore and we were able to save the
* register for the result */
- block = get_nodes_block(node);
left = get_binop_left(node);
right = get_binop_right(node);
- /* live end: we won't save a register by AM folding */
- if(be_is_live_end(lv, block, left) || be_is_live_end(lv, block, right))
+ /* Fold AM if any of the two operands does not die here. This duplicates
+ * an addition and has the same register pressure for the case that only
+ * one operand dies, but is faster (on Pentium 4).
+ * && instead of || only folds AM if both operands do not die here */
+ if (!value_last_used_here(node, left) ||
+ !value_last_used_here(node, right)) {
return;
-
- /* if multiple nodes in this block use left/right values, then we
- * can't really decide wether the values will die after node.
- * We use aggressive mode then, since it's usually just multiple address
- * calculations. */
- foreach_out_edge(left, edge) {
- ir_node *user = get_edge_src_irn(edge);
- if(user != node && get_nodes_block(user) == block)
- return;
- }
- foreach_out_edge(right, edge) {
- ir_node *user = get_edge_src_irn(edge);
- if(user != node && get_nodes_block(user) == block)
- return;
}
- /* noone-else in this block is using left/right so we'll reduce register
- * pressure if we don't fold the node */
+ /* At least one of left and right are not used by anyone else, so it is
+ * beneficial for the register pressure (if both are unused otherwise,
+ * else neutral) and ALU use to not fold AM. */
bitset_set(non_address_mode_nodes, get_irn_idx(node));
break;