From 5474a1c188c9d59eea2c915515980cd9cbab58d8 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Wed, 11 Jan 2012 19:35:05 +0100 Subject: [PATCH 1/1] sparc: implement float->unsigned conversions --- ir/be/sparc/bearch_sparc.c | 75 +++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/ir/be/sparc/bearch_sparc.c b/ir/be/sparc/bearch_sparc.c index cfd45bb28..4dc330fe2 100644 --- a/ir/be/sparc/bearch_sparc.c +++ b/ir/be/sparc/bearch_sparc.c @@ -247,6 +247,71 @@ static void rewrite_unsigned_float_Conv(ir_node *node) } } +/** + * rewrite float->unsigned conversions. + * Sparc has no instruction for this so instead we do the following: + * + * if (x >= 2147483648.) { + * converted ^= (int)(x-2147483648.) ^ 0x80000000; + * } else { + * converted = (int)x; + * } + * return (unsigned)converted; + */ +static void rewrite_float_unsigned_Conv(ir_node *node) +{ + ir_graph *irg = get_irn_irg(node); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *lower_block = get_nodes_block(node); + + part_block(node); + + { + ir_node *block = get_nodes_block(node); + ir_node *float_x = get_Conv_op(node); + ir_mode *mode_u = get_irn_mode(node); + ir_mode *mode_s = find_signed_mode(mode_u); + ir_mode *mode_f = get_irn_mode(float_x); + ir_tarval *limit = new_tarval_from_double(2147483648., mode_f); + ir_node *limitc = new_r_Const(irg, limit); + ir_node *cmp = new_rd_Cmp(dbgi, block, float_x, limitc, + ir_relation_greater_equal); + ir_node *cond = new_rd_Cond(dbgi, block, cmp); + ir_node *proj_true = new_r_Proj(cond, mode_X, pn_Cond_true); + ir_node *proj_false = new_r_Proj(cond, mode_X, pn_Cond_false); + ir_node *in_true[1] = { proj_true }; + ir_node *in_false[1] = { proj_false }; + ir_node *true_block = new_r_Block(irg, ARRAY_SIZE(in_true), in_true); + ir_node *false_block = new_r_Block(irg, ARRAY_SIZE(in_false),in_false); + ir_node *true_jmp = new_r_Jmp(true_block); + ir_node *false_jmp = new_r_Jmp(false_block); + + ir_tarval *correction = new_tarval_from_long(0x80000000l, mode_s); + ir_node *c_const = new_r_Const(irg, correction); + ir_node *sub = new_rd_Sub(dbgi, true_block, float_x, limitc, + mode_f); + ir_node *sub_conv = new_rd_Conv(dbgi, true_block, sub, mode_s); + ir_node *xor = new_rd_Eor(dbgi, true_block, sub_conv, c_const, + mode_s); + + ir_node *converted = new_rd_Conv(dbgi, false_block, float_x,mode_s); + + ir_node *lower_in[2] = { true_jmp, false_jmp }; + ir_node *phi_in[2] = { xor, converted }; + ir_node *phi; + ir_node *res_conv; + + set_irn_in(lower_block, ARRAY_SIZE(lower_in), lower_in); + phi = new_r_Phi(lower_block, ARRAY_SIZE(phi_in), phi_in, mode_s); + assert(get_Block_phis(lower_block) == NULL); + set_Block_phis(lower_block, phi); + set_Phi_next(phi, NULL); + + res_conv = new_rd_Conv(dbgi, lower_block, phi, mode_u); + exchange(node, res_conv); + } +} + static int sparc_rewrite_Conv(ir_node *node, void *ctx) { ir_mode *to_mode = get_irn_mode(node); @@ -255,11 +320,17 @@ static int sparc_rewrite_Conv(ir_node *node, void *ctx) (void) ctx; if (mode_is_float(to_mode) && mode_is_int(from_mode) - && get_mode_size_bits(from_mode) == 32 - && !mode_is_signed(from_mode)) { + && get_mode_size_bits(from_mode) == 32 + && !mode_is_signed(from_mode)) { rewrite_unsigned_float_Conv(node); return 1; } + if (mode_is_float(from_mode) && mode_is_int(to_mode) + && get_mode_size_bits(to_mode) == 32 + && !mode_is_signed(to_mode)) { + rewrite_float_unsigned_Conv(node); + return 1; + } return 0; } -- 2.20.1