#include "ircons_t.h"
#include "irgwalk.h"
#include "irtools.h"
+#include "iredges.h"
#include "tv.h"
#include "error.h"
#include "lowering.h"
+#include "pdeq.h"
static ir_mode *lowered_mode = NULL;
static int lower_direct_cmp = 0;
static ir_type *lowered_type = NULL;
+static pdeq *lowered_nodes = NULL;
+
+/**
+ * Removes a node if its out-edge count has reached 0.
+ * temporary hack until we have proper automatic dead code elimination.
+ */
+static void maybe_kill_node(ir_node *node)
+{
+ ir_graph *irg;
+ int i, arity;
+
+ if(get_irn_n_edges(node) != 0)
+ return;
+
+ irg = get_irn_irg(node);
+
+ assert(!is_Bad(node));
+
+ arity = get_irn_arity(node);
+ for (i = 0; i < arity; ++i) {
+ set_irn_n(node, i, new_Bad());
+ }
+ set_nodes_block(node, new_Bad());
+
+ edges_node_deleted(node, irg);
+}
static ir_node *create_not(dbg_info *dbgi, ir_node *node)
{
new_phi = new_rd_Phi(dbgi, irg, block, arity, in,
lowered_mode);
set_irn_link(node, new_phi);
+ pdeq_putr(lowered_nodes, node);
for(i = 0; i < arity; ++i) {
ir_node *in = get_irn_n(node, i);
set_irn_mode(copy, lowered_mode);
set_irn_link(node, copy);
+ pdeq_putr(lowered_nodes, node);
return copy;
}
if(op == op_Not) {
res = create_not(dbgi, low_op);
set_irn_link(node, res);
+ pdeq_putr(lowered_nodes, node);
return res;
}
if(op == op_Psi) {
lowered_mode);
set_irn_link(node, or);
+ pdeq_putr(lowered_nodes, node);
return or;
}
if(op == op_Conv) {
lowered_mode);
set_irn_link(node, psi);
+ pdeq_putr(lowered_nodes, node);
return psi;
}
if(op == op_Proj) {
if ((mode_is_int(mode) || mode_is_reference(mode)) && (
get_mode_size_bits(mode) < get_mode_size_bits(lowered_mode) ||
- (is_Const(right) && is_Const_null(right))
+ (mode_is_signed(mode) && is_Const(right) && is_Const_null(right))
)) {
int pnc = get_Proj_proj(node);
int need_not = 0;
a = left;
b = right;
} else if(pnc == pn_Cmp_Le) {
- /* a <= b -> ((a - b) >> 31) ^ 1 */
+ /* a <= b -> ~(a - b) >> 31 */
a = right;
b = left;
need_not = 1;
a = right;
b = left;
} else if(pnc == pn_Cmp_Ge) {
- /* a >= b -> ((a - b) >> 31) ^ 1 */
+ /* a >= b -> ~(a - b) >> 31 */
a = left;
b = right;
need_not = 1;
}
if(a != NULL) {
- tarval *tv = new_tarval_from_long(31, mode_Iu);
+ tarval *tv = new_tarval_from_long(get_mode_size_bits(lowered_mode) - 1, mode_Iu);
ir_node *shift_cnt = new_d_Const(dbgi, mode_Iu, tv);
if(mode != lowered_mode) {
}
res = new_rd_Sub(dbgi, irg, block, a, b, lowered_mode);
+ if(need_not) {
+ res = new_rd_Not(dbgi, irg, block, res, lowered_mode);
+ }
res = new_rd_Shr(dbgi, irg, block, res, shift_cnt,
lowered_mode);
- if(need_not) {
- res = create_not(dbgi, res);
- }
set_irn_link(node, res);
+ pdeq_putr(lowered_nodes, node);
return res;
}
}
lowered_mode);
set_irn_link(node, psi);
+ pdeq_putr(lowered_nodes, node);
return psi;
}
} else if(is_Proj(pred) && is_Call(get_Proj_pred(pred))) {
panic("invalid boolean const %+F", node);
}
set_irn_link(node, res);
+ pdeq_putr(lowered_nodes, node);
return res;
}
{
lowered_mode = mode;
lower_direct_cmp = do_lower_direct_cmp;
+ lowered_nodes = new_pdeq();
set_using_irn_link(irg);
+
irg_walk_graph(irg, clear_links, NULL, NULL);
irg_walk_graph(irg, lower_mode_b_walker, NULL, NULL);
+
+ while(!pdeq_empty(lowered_nodes)) {
+ ir_node *node = (ir_node*) pdeq_getr(lowered_nodes);
+ maybe_kill_node(node);
+ }
+ del_pdeq(lowered_nodes);
+
clear_using_irn_link(irg);
}