From: Michael Beck Date: Mon, 13 Dec 2004 15:41:44 +0000 (+0000) Subject: Added new Mux(b, numP, numP) -> numP node X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=60c9f323685e93f335d0f26aad2da647b669886d;p=libfirm Added new Mux(b, numP, numP) -> numP node [r4652] --- diff --git a/ir/ir/ircons.c b/ir/ir/ircons.c index dd9388fb7..e06428bc0 100644 --- a/ir/ir/ircons.c +++ b/ir/ir/ircons.c @@ -860,13 +860,30 @@ new_rd_Filter (dbg_info *db, ir_graph *irg, ir_node *block, ir_node *arg, ir_mod res = optimize_node(res); IRN_VRFY_IRG(res, irg); return res; +} +INLINE ir_node * +new_rd_NoMem (ir_graph *irg) { + return irg->no_mem; } INLINE ir_node * -new_rd_NoMem (ir_graph *irg) +new_rd_Mux (dbg_info *db, ir_graph *irg, ir_node *block, + ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode) { - return irg->no_mem; + ir_node *in[3]; + ir_node *res; + + in[0] = sel; + in[1] = ir_false; + in[2] = ir_true; + + res = new_ir_node(db, irg, block, op_Mux, mode, 3, in); + assert(res); + + res = optimize_node(res); + IRN_VRFY_IRG(res, irg); + return res; } @@ -1061,6 +1078,10 @@ INLINE ir_node *new_r_Filter (ir_graph *irg, ir_node *block, ir_node *arg, INLINE ir_node *new_r_NoMem (ir_graph *irg) { return new_rd_NoMem(irg); } +INLINE ir_node *new_r_Mux (ir_graph *irg, ir_node *block, + ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode) { + return new_rd_Mux(NULL, irg, block, sel, ir_false, ir_true, mode); +} /** ********************/ @@ -2369,6 +2390,13 @@ ir_node * return __new_d_NoMem(); } +ir_node * +new_d_Mux (dbg_info *db, ir_node *sel, ir_node *ir_false, + ir_node *ir_true, ir_mode *mode) { + return new_rd_Mux (db, current_ir_graph, current_ir_graph->current_block, + sel, ir_false, ir_true, mode); +} + /* ********************************************************************* */ /* Comfortable interface with automatic Phi node construction. */ /* (Uses also constructors of ?? interface, except new_Block. */ @@ -2678,3 +2706,6 @@ ir_node *new_Filter (ir_node *arg, ir_mode *mode, long proj) { ir_node *new_NoMem (void) { return new_d_NoMem(); } +ir_node *new_Mux (ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode) { + return new_d_Mux(NULL, sel, ir_false, ir_true, mode); +} diff --git a/ir/ir/ircons.h b/ir/ir/ircons.h index 62a822187..ad8346d9f 100644 --- a/ir/ir/ircons.h +++ b/ir/ir/ircons.h @@ -289,6 +289,7 @@ * type *free_type); * ir_node *new_Proj (ir_node *arg, ir_mode *mode, long proj); * ir_node *new_NoMem (void); + * ir_node *new_Mux (ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode); * * void add_immBlock_pred (ir_node *block, ir_node *jmp); * void mature_immBlock (ir_node *block); @@ -798,6 +799,13 @@ * Output * The definition valid in this block. * + * ir_node *new_Mux (ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode) + * ----------------------------------------------------------------------------- + * + * Creates a Mux node. This node implements the following semantic: + * If the sel node (which must be of mode_b) evaluates to true, its value is + * ir_true, else ir_false; + * * * OPERATIONS TO MANAGE MEMORY EXPLICITLY * -------------------------------------- @@ -1734,6 +1742,7 @@ ir_node *new_rd_EndExcept(dbg_info *db, ir_graph *irg, ir_node *block); * * The constructor builds the Filter in intraprocedural view. * + * @param *db A pointer for debug information. * @param *irg The ir graph the node belong to. * @param *block The block the node belong to. * @param *arg The tuple value to project from. @@ -1752,6 +1761,21 @@ ir_node *new_rd_Filter (dbg_info *db, ir_graph *irg, ir_node *block, ir_node *ar */ ir_node *new_rd_NoMem (ir_graph *irg); +/** Constructor for a Mux node. + * + * Adds the node to the block in current_ir_block. + * + * @param *db A pointer for debug information. + * @param *irg The ir graph the node belong to. + * @param *block The block the node belong to. + * @param *sel The ir_node that calculates the boolean select. + * @param *ir_true The ir_node that calculates the true result. + * @param *ir_false The ir_node that calculates the false result. + * @param *mode The mode of the node (and it_true and ir_false). + */ +ir_node *new_rd_Mux (dbg_info *db, ir_graph *irg, ir_node *block, + ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode); + /*-------------------------------------------------------------------------*/ /* The raw interface without debug support */ /*-------------------------------------------------------------------------*/ @@ -2384,6 +2408,20 @@ ir_node *new_r_Filter (ir_graph *irg, ir_node *block, ir_node *arg, */ ir_node *new_r_NoMem (ir_graph *irg); +/** Constructor for a Mux node. + * + * Adds the node to the block in current_ir_block. + * + * @param *irg The ir graph the node belong to. + * @param *block The block the node belong to. + * @param *sel The ir_node that calculates the boolean select. + * @param *ir_true The ir_node that calculates the true result. + * @param *ir_false The ir_node that calculates the false result. + * @param *mode The mode of the node (and it_true and ir_false). + */ +ir_node *new_r_Mux (ir_graph *irg, ir_node *block, + ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode); + /*-----------------------------------------------------------------------*/ /* The block oriented interface */ /*-----------------------------------------------------------------------*/ @@ -3066,6 +3104,19 @@ ir_node *new_d_Filter (dbg_info *db, ir_node *arg, ir_mode *mode, long proj); */ ir_node *new_d_NoMem (void); +/** Constructor for a Mux node. + * + * Adds the node to the block in current_ir_block. + * + * @param *db A pointer for debug information. + * @param *sel The ir_node that calculates the boolean select. + * @param *ir_true The ir_node that calculates the true result. + * @param *ir_false The ir_node that calculates the false result. + * @param *mode The mode of the node (and it_true and ir_false). + */ +ir_node *new_d_Mux (dbg_info *db, ir_node *sel, + ir_node *ir_false, ir_node *ir_true, ir_mode *mode); + /*-----------------------------------------------------------------------*/ /* The block oriented interface without debug support */ /*-----------------------------------------------------------------------*/ @@ -3633,6 +3684,17 @@ ir_node *new_Unknown(ir_mode *m); */ ir_node *new_NoMem (void); +/** Constructor for a Mux node. + * + * Adds the node to the block in current_ir_block. + * + * @param *sel The ir_node that calculates the boolean select. + * @param *ir_true The ir_node that calculates the true result. + * @param *ir_false The ir_node that calculates the false result. + * @param *mode The mode of the node (and it_true and ir_false). + */ +ir_node *new_Mux (ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode); + /*---------------------------------------------------------------------*/ /* The comfortable interface. */ /* Supports automatic Phi node construction. */ diff --git a/ir/ir/irnode.c b/ir/ir/irnode.c index 108f654b5..2c448619c 100644 --- a/ir/ir/irnode.c +++ b/ir/ir/irnode.c @@ -1844,10 +1844,38 @@ ir_node *get_Filter_cg_pred(ir_node *node, int pos) { return node->attr.filter.in_cg[pos + 1]; } +/* Mux support */ +ir_node *get_Mux_sel (ir_node *node) { + assert(node->op == op_Mux); + return node->in[1]; +} +void set_Mux_sel (ir_node *node, ir_node *sel) { + assert(node->op == op_Mux); + node->in[1] = sel; +} + +ir_node *get_Mux_false (ir_node *node) { + assert(node->op == op_Mux); + return node->in[2]; +} +void set_Mux_false (ir_node *node, ir_node *ir_false) { + assert(node->op == op_Mux); + node->in[2] = ir_false; +} + +ir_node *get_Mux_true (ir_node *node) { + assert(node->op == op_Mux); + return node->in[3]; +} +void set_Mux_true (ir_node *node, ir_node *ir_true) { + assert(node->op == op_Mux); + node->in[3] = ir_true; +} + ir_graph * get_irn_irg(const ir_node *node) { - if (get_irn_op(node) != op_Block) + if (! is_Block(node)) node = get_nodes_block(node); if (is_Bad(node)) /* sometimes bad is predecessor of nodes instead of block: in case of optimization */ node = get_nodes_block(node); diff --git a/ir/ir/irnode.h b/ir/ir/irnode.h index 795e33017..cbaef7c9c 100644 --- a/ir/ir/irnode.h +++ b/ir/ir/irnode.h @@ -848,6 +848,14 @@ void set_Confirm_bound (ir_node *node, ir_node *bound); pn_Cmp get_Confirm_cmp (ir_node *node); void set_Confirm_cmp (ir_node *node, pn_Cmp cmp); +ir_node *get_Mux_sel (ir_node *node); +void set_Mux_sel (ir_node *node, ir_node *sel); +ir_node *get_Mux_false (ir_node *node); +void set_Mux_false (ir_node *node, ir_node *ir_false); +ir_node *get_Mux_true (ir_node *node); +void set_Mux_true (ir_node *node, ir_node *ir_true); + + /* * * NAME Auxiliary routines diff --git a/ir/ir/irop.c b/ir/ir/irop.c index 2d114655e..94b6b7060 100644 --- a/ir/ir/irop.c +++ b/ir/ir/irop.c @@ -88,6 +88,7 @@ ir_op *op_EndReg; ir_op *get_op_EndReg (void) { return op_EndReg; } ir_op *op_EndExcept; ir_op *get_op_EndExcept (void) { return op_EndExcept; } ir_op *op_NoMem; ir_op *get_op_NoMem (void) { return op_NoMem; } +ir_op *op_Mux; ir_op *get_op_Mux (void) { return op_Mux; } /* @@ -226,6 +227,7 @@ init_op(void) op_EndExcept = new_ir_op(iro_EndExcept, "EndExcept", op_pin_state_pinned, X|I, oparity_any, -1, sizeof(end_attr)); op_NoMem = new_ir_op(iro_NoMem, "NoMem", op_pin_state_pinned, 0, oparity_zero, -1, 0); + op_Mux = new_ir_op(iro_Mux, "Mux", op_pin_state_floats, 0, oparity_trinary, -1, 0); #undef Y #undef F @@ -297,6 +299,7 @@ void finish_op(void) { free_ir_op (op_EndExcept); op_EndExcept = NULL; free_ir_op (op_NoMem ); op_NoMem = NULL; + free_ir_op (op_Mux ); op_Mux = NULL; } /* Returns the string for the opcode. */ diff --git a/ir/ir/irop.h b/ir/ir/irop.h index 4effc9884..6527aa99f 100644 --- a/ir/ir/irop.h +++ b/ir/ir/irop.h @@ -40,7 +40,7 @@ typedef enum { iro_Load, iro_Store, iro_Alloc, iro_Free, iro_Sync, iro_Proj, iro_Tuple, iro_Id, iro_Bad, iro_Confirm, iro_Unknown, iro_Filter, iro_Break, iro_CallBegin, iro_EndReg, iro_EndExcept, - iro_NoMem, + iro_NoMem, iro_Mux, iro_MaxOpcode } opcode; @@ -105,6 +105,7 @@ extern ir_op *op_EndReg; ir_op *get_op_EndReg (void); extern ir_op *op_EndExcept; ir_op *get_op_EndExcept (void); extern ir_op *op_NoMem; ir_op *get_op_NoMem (void); +extern ir_op *op_Mux; ir_op *get_op_Mux (void); /** Returns the ident for the opcode name */ ident *get_op_ident(ir_op *op); diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 6b3e6b418..3672f0412 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -513,6 +513,26 @@ static tarval *computed_value_Proj(ir_node *n) return tarval_bad; } +/** + * calculate the value of a Mux: can be evaluated, if the + * sel and the right input are known + */ +static tarval *computed_value_Mux(ir_node *n) +{ + ir_node *sel = get_Mux_sel(n); + tarval *ts = value_of(sel); + + if (ts == get_tarval_b_true()) { + ir_node *v = get_Mux_true(n); + return value_of(v); + } + else if (ts == get_tarval_b_false()) { + ir_node *v = get_Mux_false(n); + return value_of(v); + } + return tarval_bad; +} + /** * If the parameter n can be computed, return its value, else tarval_bad. * Performs constant folding. @@ -557,6 +577,7 @@ static ir_op *firm_set_default_computed_value(ir_op *op) CASE(Rot); CASE(Conv); CASE(Proj); + CASE(Mux); default: op->computed_value = NULL; } @@ -1062,6 +1083,22 @@ static ir_node *equivalent_node_Id(ir_node *n) return n; } +/** + * optimize a Mux + */ +static ir_node *equivalent_node_Mux(ir_node *n) +{ + ir_node *sel = get_Mux_sel(n); + tarval *ts = value_of(sel); + + if (ts == get_tarval_b_true()) + return get_Mux_true(n); + else if (ts == get_tarval_b_false()) + return get_Mux_false(n); + + return n; +} + /** * equivalent_node() returns a node equivalent to input n. It skips all nodes that * perform no actual computation, as, e.g., the Id nodes. It does not create @@ -1110,6 +1147,7 @@ static ir_op *firm_set_default_equivalent_node(ir_op *op) CASE(Phi); CASE(Proj); CASE(Id); + CASE(Mux); default: op->equivalent_node = NULL; } diff --git a/ir/ir/irvrfy.c b/ir/ir/irvrfy.c index a7f3ef32f..62c86f2e5 100644 --- a/ir/ir/irvrfy.c +++ b/ir/ir/irvrfy.c @@ -1129,6 +1129,20 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) ); break; + case iro_Mux: + op1mode = get_irn_mode(in[1]); + op2mode = get_irn_mode(in[2]); + op3mode = get_irn_mode(in[3]); + ASSERT_AND_RET( + /* Mux: BB x b x numP x numP --> numP */ + op1mode == mode_b && + op2mode == mymode && + op3mode == mymode && + mode_is_numP(mymode), + "Mux node", 0 + ); + break; + default: break; }