+ ir_node *a = get_And_left(n);
+ ir_node *b = get_And_right(n);
+ ir_mode *mode;
+
+ mode = get_irn_mode(n);
+ HANDLE_BINOP_PHI(tarval_and, a, b, c, mode);
+
+ /* we can evaluate 2 Projs of the same Cmp */
+ if (mode == mode_b && is_Proj(a) && is_Proj(b)) {
+ ir_node *pred_a = get_Proj_pred(a);
+ ir_node *pred_b = get_Proj_pred(b);
+ if (pred_a == pred_b) {
+ dbg_info *dbgi = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(pred_a);
+ pn_Cmp pn_a = get_Proj_proj(a);
+ pn_Cmp pn_b = get_Proj_proj(b);
+ /* yes, we can simply calculate with pncs */
+ pn_Cmp new_pnc = pn_a & pn_b;
+
+ return new_rd_Proj(dbgi, current_ir_graph, block, pred_a, mode_b, new_pnc);
+ }
+ }
+ if (is_Or(a)) {
+ if (is_Not(b)) {
+ ir_node *op = get_Not_op(b);
+ if (is_And(op)) {
+ ir_node *ba = get_And_left(op);
+ ir_node *bb = get_And_right(op);
+
+ /* it's enough to test the following cases due to normalization! */
+ if (get_Or_left(a) == ba && get_Or_right(a) == bb) {
+ /* (a|b) & ~(a&b) = a^b */
+ ir_node *block = get_nodes_block(n);
+
+ n = new_rd_Eor(get_irn_dbg_info(n), current_ir_graph, block, ba, bb, mode);
+ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_TO_EOR);
+ return n;
+ }
+ }
+ }
+ }
+ if (is_Or(b)) {
+ if (is_Not(a)) {
+ ir_node *op = get_Not_op(a);
+ if (is_And(op)) {
+ ir_node *aa = get_And_left(op);
+ ir_node *ab = get_And_right(op);
+
+ /* it's enough to test the following cases due to normalization! */
+ if (get_Or_left(b) == aa && get_Or_right(b) == ab) {
+ /* (a|b) & ~(a&b) = a^b */
+ ir_node *block = get_nodes_block(n);
+
+ n = new_rd_Eor(get_irn_dbg_info(n), current_ir_graph, block, aa, ab, mode);
+ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_TO_EOR);
+ return n;
+ }
+ }
+ }
+ }
+ if (is_Eor(a)) {
+ ir_node *al = get_Eor_left(a);
+ ir_node *ar = get_Eor_right(a);
+
+ if (al == b) {
+ /* (b ^ a) & b -> ~a & b */
+ dbg_info *dbg = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(n);
+
+ ar = new_rd_Not(dbg, current_ir_graph, block, ar, mode);
+ n = new_rd_And(dbg, current_ir_graph, block, ar, b, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT);
+ return n;
+ }
+ if (ar == b) {
+ /* (a ^ b) & b -> ~a & b */
+ dbg_info *dbg = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(n);
+
+ al = new_rd_Not(dbg, current_ir_graph, block, al, mode);
+ n = new_rd_And(dbg, current_ir_graph, block, al, b, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT);
+ return n;
+ }
+ }
+ if (is_Eor(b)) {
+ ir_node *bl = get_Eor_left(b);
+ ir_node *br = get_Eor_right(b);
+
+ if (bl == a) {
+ /* a & (a ^ b) -> a & ~b */
+ dbg_info *dbg = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(n);
+
+ br = new_rd_Not(dbg, current_ir_graph, block, br, mode);
+ n = new_rd_And(dbg, current_ir_graph, block, br, a, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT);
+ return n;
+ }
+ if (br == a) {
+ /* a & (b ^ a) -> a & ~b */
+ dbg_info *dbg = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(n);
+
+ bl = new_rd_Not(dbg, current_ir_graph, block, bl, mode);
+ n = new_rd_And(dbg, current_ir_graph, block, bl, a, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT);
+ return n;
+ }
+ }
+ if (is_Not(a) && is_Not(b)) {
+ /* ~a & ~b = ~(a|b) */
+ ir_node *block = get_nodes_block(n);
+ ir_mode *mode = get_irn_mode(n);
+
+ a = get_Not_op(a);
+ b = get_Not_op(b);
+ n = new_rd_Or(get_irn_dbg_info(n), current_ir_graph, block, a, b, mode);
+ n = new_rd_Not(get_irn_dbg_info(n), current_ir_graph, block, n, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_DEMORGAN);
+ return n;
+ }
+
+ n = transform_bitwise_distributive(n, transform_node_And);
+
+ return n;
+} /* transform_node_And */
+
+/**
+ * Transform an Eor.
+ */
+static ir_node *transform_node_Eor(ir_node *n) {
+ ir_node *c, *oldn = n;
+ ir_node *a = get_Eor_left(n);
+ ir_node *b = get_Eor_right(n);
+ ir_mode *mode = get_irn_mode(n);
+
+ HANDLE_BINOP_PHI(tarval_eor, a, b, c, mode);
+
+ /* we can evaluate 2 Projs of the same Cmp */
+ if (mode == mode_b && is_Proj(a) && is_Proj(b)) {
+ ir_node *pred_a = get_Proj_pred(a);
+ ir_node *pred_b = get_Proj_pred(b);
+ if(pred_a == pred_b) {
+ dbg_info *dbgi = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(pred_a);
+ pn_Cmp pn_a = get_Proj_proj(a);
+ pn_Cmp pn_b = get_Proj_proj(b);
+ /* yes, we can simply calculate with pncs */
+ pn_Cmp new_pnc = pn_a ^ pn_b;
+
+ return new_rd_Proj(dbgi, current_ir_graph, block, pred_a, mode_b,
+ new_pnc);
+ }
+ }
+
+ if (a == b) {
+ /* a ^ a = 0 */
+ n = new_rd_Const(get_irn_dbg_info(n), current_ir_graph, get_irn_n(n, -1),
+ mode, get_mode_null(mode));
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_A_A);
+ } else if (mode == mode_b &&
+ is_Proj(a) &&
+ is_Const(b) && is_Const_one(b) &&
+ is_Cmp(get_Proj_pred(a))) {
+ /* The Eor negates a Cmp. The Cmp has the negated result anyways! */
+ n = new_r_Proj(current_ir_graph, get_irn_n(n, -1), get_Proj_pred(a),
+ mode_b, get_negated_pnc(get_Proj_proj(a), mode));
+
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT_BOOL);
+ } else if (is_Const(b)) {
+ if (is_Not(a)) { /* ~x ^ const -> x ^ ~const */
+ ir_node *cnst = new_Const(mode, tarval_not(get_Const_tarval(b)));
+ ir_node *not_op = get_Not_op(a);
+ dbg_info *dbg = get_irn_dbg_info(n);
+ ir_graph *irg = current_ir_graph;
+ ir_node *block = get_nodes_block(n);
+ ir_mode *mode = get_irn_mode(n);
+ n = new_rd_Eor(dbg, irg, block, not_op, cnst, mode);
+ return n;
+ } else if (is_Const_all_one(b)) { /* x ^ 1...1 -> ~1 */
+ n = new_r_Not(current_ir_graph, get_nodes_block(n), a, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT);
+ }
+ } else {
+ n = transform_bitwise_distributive(n, transform_node_Eor);
+ }
+
+ return n;
+} /* transform_node_Eor */
+
+/**
+ * Transform a Not.
+ */
+static ir_node *transform_node_Not(ir_node *n) {
+ ir_node *c, *oldn = n;
+ ir_node *a = get_Not_op(n);
+ ir_mode *mode = get_irn_mode(n);