From: Michael Beck Date: Tue, 20 May 2008 14:22:57 +0000 (+0000) Subject: - If-conversion can generate SSE min and max nodes again. X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=ecbc4dfb7c8af1b39985565e925d94ab0799928f;p=libfirm - If-conversion can generate SSE min and max nodes again. - preliminary support for If-conversion without Cmov [r19689] --- diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index ab6b3ebf0..2f7a48870 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -2066,37 +2066,88 @@ static ir_graph **ia32_get_irg_list(const void *self, ir_graph ***irg_list) */ static int ia32_is_psi_allowed(ir_node *sel, ir_node *phi_list, int i, int j) { - ir_node *phi; + ir_node *phi, *left; + ir_node *cmp = NULL; + ir_mode *cmp_mode; + + if (ia32_cg_config.use_cmov) { + /* we can't handle psis with 64bit compares yet */ + if (is_Proj(sel)) { + cmp = get_Proj_pred(sel); + if (is_Cmp(cmp)) { + left = get_Cmp_left(cmp); + cmp_mode = get_irn_mode(left); + if (!mode_is_float(cmp_mode) && get_mode_size_bits(cmp_mode) > 32) + return 0; + } else { + cmp = NULL; + } + } - (void)sel; - (void)i; - (void)j; + if (ia32_cg_config.use_sse2 && cmp != NULL) { + /* check the Phi nodes: no 64bit and no floating point cmov */ + for (phi = phi_list; phi; phi = get_irn_link(phi)) { + ir_mode *mode = get_irn_mode(phi); + + if (mode_is_float(mode)) { + /* check for Min, Max */ + ir_node *t = get_Phi_pred(phi, i); + ir_node *f = get_Phi_pred(phi, j); + pn_Cmp pn = get_Proj_proj(sel); + ir_node *cl = get_Cmp_left(cmp); + ir_node *cr = get_Cmp_right(cmp); + int res = 0; + + /* SSE2 supports Min & Max */ + if (pn == pn_Cmp_Lt || pn == pn_Cmp_Le || pn == pn_Cmp_Ge || pn == pn_Cmp_Gt) { + if (cl == t && cr == f) { + /* Psi(a <=/>= b, a, b) => MIN, MAX */ + res = 1; + } else if (cl == f && cr == t) { + /* Psi(a <=/>= b, b, a) => MAX, MIN */ + res = 1; + } + } + if (! res) + return 0; + + } else if (get_mode_size_bits(mode) > 32) + return 0; + } + } else { + /* check the Phi nodes: no 64bit and no floating point cmov */ + for (phi = phi_list; phi; phi = get_irn_link(phi)) { + ir_mode *mode = get_irn_mode(phi); - if(!ia32_cg_config.use_cmov) { - /* TODO: we could still handle abs(x)... */ - return 0; - } + if (mode_is_float(mode) || get_mode_size_bits(mode) > 32) + return 0; + } + } - /* we can't handle psis with 64bit compares yet */ - if(is_Proj(sel)) { - ir_node *pred = get_Proj_pred(sel); - if(is_Cmp(pred)) { - ir_node *left = get_Cmp_left(pred); - ir_mode *cmp_mode = get_irn_mode(left); - if(!mode_is_float(cmp_mode) && get_mode_size_bits(cmp_mode) > 32) + return 1; + } else { + /* No cmov, only some special cases */ + if (! is_Proj(sel)) + return 0; + cmp = get_Proj_pred(sel); + if (! is_Cmp(cmp)) + return 0; + + left = get_Cmp_left(cmp); + cmp_mode = get_irn_mode(left); + + /* no floating point and no 64bit yet */ + for (phi = phi_list; phi; phi = get_irn_link(phi)) { + ir_mode *mode = get_irn_mode(phi); + + if (mode_is_float(mode) || get_mode_size_bits(mode) > 32) return 0; } - } - - /* check the Phi nodes */ - for (phi = phi_list; phi; phi = get_irn_link(phi)) { - ir_mode *mode = get_irn_mode(phi); + /* Add checks for some supported cases here */ - if (mode_is_float(mode) || get_mode_size_bits(mode) > 32) - return 0; + return 0; } - - return 1; + return 0; } /** diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index e3b16f64c..e9d62b52f 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -2993,22 +2993,57 @@ static ir_node *gen_Psi(ir_node *node) ir_node *psi_true = get_Psi_val(node, 0); ir_node *psi_default = get_Psi_default(node); ir_node *cond = get_Psi_cond(node, 0); + ir_mode *mode = get_irn_mode(node); ir_node *flags = NULL; ir_node *new_node; pn_Cmp pnc; assert(get_Psi_n_conds(node) == 1); assert(get_irn_mode(cond) == mode_b); - assert(mode_needs_gp_reg(get_irn_mode(node))); - flags = get_flags_node(cond, &pnc); + if (mode_is_float(mode)) { + ir_node *cmp = get_Proj_pred(cond); + ir_node *cmp_left = get_Cmp_left(cmp); + ir_node *cmp_right = get_Cmp_right(cmp); + pn_Cmp pnc = get_Proj_proj(cond); + + if (ia32_cg_config.use_sse2) { + if (pnc == pn_Cmp_Lt || pnc == pn_Cmp_Le) { + if (cmp_left == psi_true && cmp_right == psi_default) { + /* psi(a <= b, a, b) => MIN */ + return gen_binop(node, cmp_left, cmp_right, new_rd_ia32_xMin, + match_commutative | match_am); + } else if (cmp_left == psi_default && cmp_right == psi_true) { + /* psi(a <= b, b, a) => MAX */ + return gen_binop(node, cmp_left, cmp_right, new_rd_ia32_xMax, + match_commutative | match_am); + } + } else if (pnc == pn_Cmp_Gt || pnc == pn_Cmp_Ge) { + if (cmp_left == psi_true && cmp_right == psi_default) { + /* psi(a >= b, a, b) => MAX */ + return gen_binop(node, cmp_left, cmp_right, new_rd_ia32_xMax, + match_commutative | match_am); + } else if (cmp_left == psi_default && cmp_right == psi_true) { + /* psi(a >= b, b, a) => MIN */ + return gen_binop(node, cmp_left, cmp_right, new_rd_ia32_xMin, + match_commutative | match_am); + } + } + } + panic("cannot transform floating point Psi"); - if(is_Const_1(psi_true) && is_Const_0(psi_default)) { - new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, 0); - } else if(is_Const_0(psi_true) && is_Const_1(psi_default)) { - new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, 1); } else { - new_node = create_CMov(node, cond, flags, pnc); + assert(mode_needs_gp_reg(mode)); + + flags = get_flags_node(cond, &pnc); + + if (is_Const_1(psi_true) && is_Const_0(psi_default)) { + new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, 0); + } else if(is_Const_0(psi_true) && is_Const_1(psi_default)) { + new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, 1); + } else { + new_node = create_CMov(node, cond, flags, pnc); + } } return new_node; }