/**
* @file
* @brief This file contains functions for matching firm graphs for
- * nodes that can be used as addressmode for x86 commands
+ * nodes that can be used as address mode for x86 instructions
* @author Matthias Braun
* @version $Id$
*/
return mode_is_int(mode) || mode_is_reference(mode) || mode == mode_b;
}
-/**
- * Check, if a given node is a Down-Conv, ie. a integer Conv
- * from a mode with a mode with more bits to a mode with lesser bits.
- * Moreover, we return only true if the node has not more than 1 user.
- *
- * @param node the node
- * @return non-zero if node is a Down-Conv
- */
-static int is_downconv(const ir_node *node)
-{
- ir_mode *src_mode;
- ir_mode *dest_mode;
-
- if(!is_Conv(node))
- return 0;
-
- /* we only want to skip the conv when we're the only user
- * (not optimal but for now...)
- */
- if(get_irn_n_edges(node) > 1)
- return 0;
-
- src_mode = get_irn_mode(get_Conv_op(node));
- dest_mode = get_irn_mode(node);
- return mode_needs_gp_reg(src_mode)
- && mode_needs_gp_reg(dest_mode)
- && get_mode_size_bits(dest_mode) < get_mode_size_bits(src_mode);
-}
-
-/**
- * Skip all Down-Conv's on a given node and return the resulting node.
- */
-static ir_node *skip_downconv(ir_node *node)
-{
- while(is_downconv(node))
- node = get_Conv_op(node);
-
- return node;
-}
-
/* Create an address mode for a given node. */
void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force)
{
eat_imms = eat_immediates(addr, node, force);
if(eat_imms != node) {
if(force) {
- eat_imms = skip_downconv(eat_imms);
+ eat_imms = ia32_skip_downconv(eat_imms);
}
res = 1;
ir_node *right = get_Add_right(node);
if(force) {
- left = skip_downconv(left);
- right = skip_downconv(right);
+ left = ia32_skip_downconv(left);
+ right = ia32_skip_downconv(right);
}
assert(force || !is_immediate(addr, left, 0));
/* if we can do source address mode then we will never fold the add
* into address mode */
if(!mode_is_float(get_irn_mode(node)) && (is_immediate_simple(right) ||
- (!use_source_address_mode(get_nodes_block(node), left, right)
- && !use_source_address_mode(get_nodes_block(node), right, left))))
+ (!ia32_use_source_address_mode(get_nodes_block(node), left, right)
+ && !ia32_use_source_address_mode(get_nodes_block(node), right, left))))
{
break;
}
}
#endif /* NDEBUG */
-int use_source_address_mode(ir_node *block, ir_node *node, ir_node *other)
+int ia32_use_source_address_mode(ir_node *block, ir_node *node, ir_node *other)
{
ir_mode *mode = get_irn_mode(node);
ir_node *load;
set_ia32_commutative(node);
}
+/**
+ * Check, if a given node is a Down-Conv, ie. a integer Conv
+ * from a mode with a mode with more bits to a mode with lesser bits.
+ * Moreover, we return only true if the node has not more than 1 user.
+ *
+ * @param node the node
+ * @return non-zero if node is a Down-Conv
+ */
static int is_downconv(const ir_node *node)
{
ir_mode *src_mode;
&& get_mode_size_bits(dest_mode) < get_mode_size_bits(src_mode);
}
+/* Skip all Down-Conv's on a given node and return the resulting node. */
+ir_node *ia32_skip_downconv(ir_node *node) {
+ while (is_downconv(node))
+ node = get_Conv_op(node);
+
+ return node;
+}
+
+
typedef enum {
match_commutative = 1 << 0,
match_am_and_immediates = 1 << 1,
use_am = 0;
}
- while(is_downconv(op2)) {
- op2 = get_Conv_op(op2);
- }
- if(op1 != NULL) {
- while(is_downconv(op1)) {
- op1 = get_Conv_op(op1);
- }
- }
+ op2 = ia32_skip_downconv(op2);
+ if(op1 != NULL)
+ op1 = ia32_skip_downconv(op1);
new_op2 = (use_immediate ? try_create_Immediate(op2, 0) : NULL);
- if(new_op2 == NULL && use_am && use_source_address_mode(block, op2, op1)) {
+ if(new_op2 == NULL && use_am && ia32_use_source_address_mode(block, op2, op1)) {
build_address(am, op2);
new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
if(mode_is_float(mode)) {
}
am->op_type = ia32_AddrModeS;
} else if(commutative && (new_op2 == NULL || use_am_and_immediates) &&
- use_am && use_source_address_mode(block, op1, op2)) {
+ use_am && ia32_use_source_address_mode(block, op1, op2)) {
ir_node *noreg;
build_address(am, op1);
return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd, match_commutative);
}
- while(is_downconv(op2)) {
- op2 = get_Conv_op(op2);
- }
- while(is_downconv(op1)) {
- op1 = get_Conv_op(op1);
- }
+ op2 = ia32_skip_downconv(op2);
+ op1 = ia32_skip_downconv(op1);
/**
* Rules for an Add:
ir_node *left = get_Shl_left(node);
ir_node *right = get_Shl_right(node);
- while(is_downconv(left)) {
- left = get_Conv_op(left);
- }
-
+ left = ia32_skip_downconv(left);
return gen_shift_binop(node, left, right, new_rd_ia32_Shl);
}
res = new_rd_ia32_vfchs(dbgi, irg, block, new_op);
}
} else {
- while(is_downconv(op)) {
- op = get_Conv_op(op);
- }
+ op = ia32_skip_downconv(op);
res = gen_unop(node, op, new_rd_ia32_Neg);
}
assert(get_irn_mode(node) != mode_b); /* should be lowered already */
assert (! mode_is_float(get_irn_mode(node)));
- while(is_downconv(node)) {
- node = get_Conv_op(node);
- }
-
+ node = ia32_skip_downconv(node);
return gen_unop(node, op, new_rd_ia32_Not);
}
/* we prefer the Test instruction where possible except cases where
* we can use SourceAM */
- if(!use_source_address_mode(block, left, right) &&
- !use_source_address_mode(block, right, left)) {
+ if(!ia32_use_source_address_mode(block, left, right) &&
+ !ia32_use_source_address_mode(block, right, left)) {
res = try_create_Test(node);
if(res != NULL)
return res;