Commit a7563a6c authored by Matthias Braun's avatar Matthias Braun
Browse files

x86_address_mode: add missing patterns, improve frame_addr matching

- This should fix some cases where we would not reassociate constants
  because of multiple users and missed address mode patterns for these
  cases.
parent 1cbd2f49
......@@ -4120,25 +4120,16 @@ static ir_node *create_immediate_or_transform(ir_node *const node)
return new_node;
}
/**
* Transforms a FrameAddr into an ia32 Add.
*/
static ir_node *gen_Member(ir_node *node)
{
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *ptr = get_Member_ptr(node);
/* the only non-lowered member nodes should select entities from the
* stackframe */
if (!is_Proj(ptr) || !be_is_Start(get_Proj_pred(ptr)))
panic("%+F not lowered", node);
ir_node *new_ptr = be_transform_node(ptr);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *new_node = new_bd_ia32_Lea(dbgi, block, new_ptr, noreg_GP);
ir_entity *entity = get_Member_entity(node);
set_ia32_frame_ent(new_node, entity);
set_ia32_use_frame(new_node);
x86_address_t addr;
memset(&addr, 0, sizeof(addr));
x86_create_address_mode(&addr, node, x86_create_am_force);
ir_node *new_node = create_lea_from_address(dbgi, block, &addr);
SET_IA32_ORIG_NODE(new_node, node);
return new_node;
}
......
......@@ -196,6 +196,13 @@ static ir_node *eat_immediates(x86_address_t *addr, ir_node *node,
eat_immediate(addr, right, true);
return eat_immediates(addr, left, x86_create_am_normal);
}
} else if (is_Member(node)) {
assert(addr->frame_entity == NULL);
addr->frame_entity = get_Member_entity(node);
addr->use_frame = true;
ir_node *ptr = get_Member_ptr(node);
assert(is_Start(get_Proj_pred(ptr)) || be_is_Start(get_Proj_pred(ptr)));
return ptr;
}
return node;
......@@ -256,23 +263,6 @@ static bool eat_shl(x86_address_t *addr, ir_node *node)
return true;
}
static bool is_frame_addr(const ir_node *const node)
{
if (!is_Member(node))
return false;
ir_node *base = get_Member_ptr(node);
return base == get_irg_frame(get_irn_irg(node));
}
static void set_frame_addr(x86_address_t *const addr, ir_node *const frame)
{
assert(!addr->base);
assert(!addr->frame_entity);
addr->base = get_Member_ptr(frame);
addr->frame_entity = get_Member_entity(frame);
addr->use_frame = true;
}
static bool is_downconv(const ir_node *node)
{
if (!is_Conv(node))
......@@ -335,9 +325,6 @@ void x86_create_address_mode(x86_address_t *addr, ir_node *node,
/* we can hit this case in x86_create_am_force mode */
eat_immediate(addr, node, false);
return;
} else if (is_frame_addr(node)) {
set_frame_addr(addr, node);
return;
} else if (is_Add(node)) {
ir_node *left = get_Add_left(node);
ir_node *right = get_Add_right(node);
......@@ -346,21 +333,14 @@ void x86_create_address_mode(x86_address_t *addr, ir_node *node,
left = skip_downconv(left);
right = skip_downconv(right);
}
left = eat_immediates(addr, left, flags);
right = eat_immediates(addr, right, flags);
if (eat_shl(addr, left)) {
left = NULL;
} else if (eat_shl(addr, right)) {
right = NULL;
}
if (left != NULL && is_frame_addr(left)
&& !x86_is_non_address_mode_node(left)) {
set_frame_addr(addr, left);
left = NULL;
} else if (right != NULL && is_frame_addr(right)
&& !x86_is_non_address_mode_node(right)) {
set_frame_addr(addr, right);
right = NULL;
}
/* (x & 0xFFFFFFFC) + (x >> 2) -> lea(x >> 2, x >> 2, 4) */
if (left != NULL && right != NULL) {
......@@ -400,22 +380,38 @@ tryit:
}
if (left != NULL) {
if (addr->base != NULL) {
ir_node *base = addr->base;
if (base == NULL) {
addr->base = left;
} else {
assert(addr->index == NULL && addr->scale == 0);
assert(right == NULL);
addr->index = left;
} else {
/* esp must be used as base */
if (is_Proj(left) && (is_Start(get_Proj_pred(left))
|| be_is_Start(get_Proj_pred(left)))) {
addr->index = base;
addr->base = left;
} else {
addr->index = left;
}
}
}
if (right != NULL) {
if (addr->base == NULL) {
ir_node *base = addr->base;
if (base == NULL) {
addr->base = right;
} else {
assert(addr->index == NULL && addr->scale == 0);
/* esp must be used as base */
if (is_Proj(right) && (is_Start(get_Proj_pred(right))
|| be_is_Start(get_Proj_pred(right)))) {
addr->index = base;
addr->base = right;
} else {
addr->index = right;
}
}
}
return;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment