+ assert(mode_needs_gp_reg(cmp_mode));
+
+ /* we prefer the Test instruction where possible except cases where
+ * we can use SourceAM */
+ cmp_unsigned = !mode_is_signed(cmp_mode);
+ if (is_Const_0(right)) {
+ if (is_And(left) &&
+ get_irn_n_edges(left) == 1 &&
+ can_fold_test_and(node)) {
+ /* Test(and_left, and_right) */
+ ir_node *and_left = get_And_left(left);
+ ir_node *and_right = get_And_right(left);
+ ir_mode *mode = get_irn_mode(and_left);
+
+ match_arguments(&am, block, and_left, and_right, match_commutative |
+ match_am | match_8bit_am | match_16bit_am |
+ match_am_and_immediates | match_immediate |
+ match_8bit | match_16bit);
+ if (get_mode_size_bits(mode) == 8) {
+ new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
+ addr->index, addr->mem, am.new_op1,
+ am.new_op2, am.ins_permuted,
+ cmp_unsigned);
+ } else {
+ new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
+ addr->index, addr->mem, am.new_op1,
+ am.new_op2, am.ins_permuted, cmp_unsigned);
+ }
+ } else {
+ match_arguments(&am, block, NULL, left, match_am | match_8bit_am |
+ match_16bit_am | match_8bit | match_16bit);
+ if (am.op_type == ia32_AddrModeS) {
+ /* Cmp(AM, 0) */
+ ir_node *imm_zero = try_create_Immediate(right, 0);
+ if (get_mode_size_bits(cmp_mode) == 8) {
+ new_node = new_rd_ia32_Cmp8Bit(dbgi, irg, new_block, addr->base,
+ addr->index, addr->mem, am.new_op2,
+ imm_zero, am.ins_permuted,
+ cmp_unsigned);
+ } else {
+ new_node = new_rd_ia32_Cmp(dbgi, irg, new_block, addr->base,
+ addr->index, addr->mem, am.new_op2,
+ imm_zero, am.ins_permuted, cmp_unsigned);
+ }
+ } else {
+ /* Test(left, left) */
+ if (get_mode_size_bits(cmp_mode) == 8) {
+ new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
+ addr->index, addr->mem, am.new_op2,
+ am.new_op2, am.ins_permuted,
+ cmp_unsigned);
+ } else {
+ new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
+ addr->index, addr->mem, am.new_op2,
+ am.new_op2, am.ins_permuted,
+ cmp_unsigned);
+ }
+ }
+ }
+ } else {
+ /* Cmp(left, right) */
+ match_arguments(&am, block, left, right, match_commutative | match_am |
+ match_8bit_am | match_16bit_am | match_am_and_immediates |
+ match_immediate | match_8bit | match_16bit);
+ if (get_mode_size_bits(cmp_mode) == 8) {
+ new_node = new_rd_ia32_Cmp8Bit(dbgi, irg, new_block, addr->base,
+ addr->index, addr->mem, am.new_op1,
+ am.new_op2, am.ins_permuted,
+ cmp_unsigned);
+ } else {
+ new_node = new_rd_ia32_Cmp(dbgi, irg, new_block, addr->base,
+ addr->index, addr->mem, am.new_op1,
+ am.new_op2, am.ins_permuted, cmp_unsigned);
+ }
+ }
+ set_am_attributes(new_node, &am);
+ assert(cmp_mode != NULL);
+ set_ia32_ls_mode(new_node, cmp_mode);
+
+ SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+
+ new_node = fix_mem_proj(new_node, &am);
+
+ return new_node;
+}
+
+static ir_node *create_CMov(ir_node *node, ir_node *new_flags, pn_Cmp pnc)
+{
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = get_nodes_block(node);
+ ir_node *new_block = be_transform_node(block);
+ ir_node *val_true = get_Psi_val(node, 0);
+ ir_node *val_false = get_Psi_default(node);
+ ir_node *new_node;
+ match_flags_t match_flags;
+ ia32_address_mode_t am;
+ ia32_address_t *addr;
+
+ assert(transform_config.use_cmov);
+ assert(mode_needs_gp_reg(get_irn_mode(val_true)));
+
+ addr = &am.addr;
+
+ match_flags = match_commutative | match_am | match_16bit_am |
+ match_mode_neutral;
+
+ match_arguments(&am, block, val_false, val_true, match_flags);
+
+ new_node = new_rd_ia32_CMov(dbgi, irg, new_block, addr->base, addr->index,
+ addr->mem, am.new_op1, am.new_op2, new_flags,
+ am.ins_permuted, pnc);
+ set_am_attributes(new_node, &am);
+
+ SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));