From dd773fe15c0af814dc5af6fcb0dad913d181a30d Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Wed, 25 Nov 2009 15:46:43 +0000 Subject: [PATCH] non 32-bit divisions need upconvs [r26741] --- ir/be/ia32/ia32_nodes_attr.h | 4 +++- ir/be/ia32/ia32_transform.c | 24 ++++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/ir/be/ia32/ia32_nodes_attr.h b/ir/be/ia32/ia32_nodes_attr.h index 8b4e92c81..9953d5047 100644 --- a/ir/be/ia32/ia32_nodes_attr.h +++ b/ir/be/ia32/ia32_nodes_attr.h @@ -61,7 +61,9 @@ typedef enum { by 32 bit operations */ match_try_am = 1 << 7, /**< only try to produce AM node, don't do anything if AM isn't possible */ - match_two_users = 1 << 8 /**< the instruction uses a load two times ... */ + match_two_users = 1 << 8, /**< the instruction uses a load two times ... */ + match_upconv_32 = 1 << 9 /**< 8/16 bit insn are processed by doing + an upconv to 32bit */ } match_flags_t; typedef struct ia32_op_attr_t ia32_op_attr_t; diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index e71396068..f02d7dec2 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -829,6 +829,7 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block, } am->op_type = ia32_AddrModeS; } else { + ir_mode *mode; am->op_type = ia32_Normal; if (flags & match_try_am) { @@ -837,11 +838,18 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block, return; } - new_op1 = (op1 == NULL ? NULL : be_transform_node(op1)); - if (new_op2 == NULL) - new_op2 = be_transform_node(op2); - am->ls_mode = - (flags & match_mode_neutral ? mode_Iu : get_irn_mode(op2)); + mode = get_irn_mode(op2); + if (flags & match_upconv_32 && get_mode_size_bits(mode) != 32) { + new_op1 = (op1 == NULL ? NULL : create_upconv(op1, NULL)); + if (new_op2 == NULL) + new_op2 = create_upconv(op2, NULL); + am->ls_mode = mode_Iu; + } else { + new_op1 = (op1 == NULL ? NULL : be_transform_node(op1)); + if (new_op2 == NULL) + new_op2 = be_transform_node(op2); + am->ls_mode = (flags & match_mode_neutral) ? mode_Iu : mode; + } } if (addr->base == NULL) addr->base = noreg_GP; @@ -1295,6 +1303,10 @@ static ir_node *gen_Mulh(ir_node *node) ir_node *new_node; ir_node *proj_res_high; + if (get_mode_size_bits(mode) != 32) { + panic("Mulh without 32bit size not supported in ia32 backend (%+F)", node); + } + if (mode_is_signed(mode)) { new_node = gen_binop(node, op1, op2, new_bd_ia32_IMul1OP, match_commutative | match_am); proj_res_high = new_rd_Proj(dbgi, new_block, new_node, mode_Iu, pn_ia32_IMul1OP_res_high); @@ -1519,7 +1531,7 @@ static ir_node *create_Div(ir_node *node) panic("invalid divmod node %+F", node); } - match_arguments(&am, block, op1, op2, NULL, match_am); + match_arguments(&am, block, op1, op2, NULL, match_am | match_upconv_32); /* Beware: We don't need a Sync, if the memory predecessor of the Div node is the memory of the consumed address. We can have only the second op as address -- 2.20.1