+ } else {
+ assert(ia32_cg_config.use_3dnow_prefetch);
+ /* 3DNow! style prefetch */
+ new_node = new_bd_ia32_Prefetch(dbgi, block, base, idx, mem);
+ }
+
+ set_irn_pinned(new_node, get_irn_pinned(node));
+ set_ia32_op_type(new_node, ia32_AddrModeS);
+ set_ia32_ls_mode(new_node, mode_Bu);
+ set_address(new_node, &addr);
+
+ SET_IA32_ORIG_NODE(new_node, node);
+
+ return new_r_Proj(new_node, mode_M, pn_ia32_Prefetch_M);
+}
+
+/**
+ * Transform bsf like node
+ */
+static ir_node *gen_unop_AM(ir_node *node, construct_binop_dest_func *func)
+{
+ ir_node *param = get_Builtin_param(node, 0);
+ dbg_info *dbgi = get_irn_dbg_info(node);
+
+ ir_node *block = get_nodes_block(node);
+ ir_node *new_block = be_transform_node(block);
+
+ ia32_address_mode_t am;
+ ia32_address_t *addr = &am.addr;
+ ir_node *cnt;
+
+ match_arguments(&am, block, NULL, param, NULL, match_am);
+
+ cnt = func(dbgi, new_block, addr->base, addr->index, addr->mem, am.new_op2);
+ set_am_attributes(cnt, &am);
+ set_ia32_ls_mode(cnt, get_irn_mode(param));
+
+ SET_IA32_ORIG_NODE(cnt, node);
+ return fix_mem_proj(cnt, &am);
+}
+
+/**
+ * Transform builtin ffs.
+ */
+static ir_node *gen_ffs(ir_node *node)
+{
+ ir_node *bsf = gen_unop_AM(node, new_bd_ia32_Bsf);
+ ir_node *real = skip_Proj(bsf);
+ dbg_info *dbgi = get_irn_dbg_info(real);
+ ir_node *block = get_nodes_block(real);
+ ir_node *flag, *set, *conv, *neg, *orn, *add;
+
+ /* bsf x */
+ if (get_irn_mode(real) != mode_T) {
+ set_irn_mode(real, mode_T);
+ bsf = new_r_Proj(real, mode_Iu, pn_ia32_res);
+ }
+
+ flag = new_r_Proj(real, mode_b, pn_ia32_flags);
+
+ /* sete */
+ set = new_bd_ia32_Setcc(dbgi, block, flag, ia32_cc_equal);
+ SET_IA32_ORIG_NODE(set, node);
+
+ /* conv to 32bit */
+ conv = new_bd_ia32_Conv_I2I_8bit(dbgi, block, noreg_GP, noreg_GP, nomem, set, mode_Bu);
+ SET_IA32_ORIG_NODE(conv, node);
+
+ /* neg */
+ neg = new_bd_ia32_Neg(dbgi, block, conv);
+
+ /* or */
+ orn = new_bd_ia32_Or(dbgi, block, noreg_GP, noreg_GP, nomem, bsf, neg);
+ set_ia32_ls_mode(orn, mode_Iu);
+ set_ia32_commutative(orn);
+
+ /* add 1 */
+ add = new_bd_ia32_Lea(dbgi, block, orn, noreg_GP);
+ add_ia32_am_offs_int(add, 1);
+ return add;
+}
+
+/**
+ * Transform builtin clz.
+ */
+static ir_node *gen_clz(ir_node *node)
+{
+ ir_node *bsr = gen_unop_AM(node, new_bd_ia32_Bsr);
+ ir_node *real = skip_Proj(bsr);
+ dbg_info *dbgi = get_irn_dbg_info(real);
+ ir_node *block = get_nodes_block(real);
+ ir_graph *irg = get_Block_irg(block);
+ ir_node *imm = ia32_create_Immediate(irg, NULL, 0, 31);
+
+ return new_bd_ia32_Xor(dbgi, block, noreg_GP, noreg_GP, nomem, bsr, imm);
+}
+
+/**
+ * Transform builtin ctz.
+ */
+static ir_node *gen_ctz(ir_node *node)
+{
+ return gen_unop_AM(node, new_bd_ia32_Bsf);
+}
+
+/**
+ * Transform builtin parity.
+ */
+static ir_node *gen_parity(ir_node *node)
+{
+ 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 *param = get_Builtin_param(node, 0);
+ ir_node *new_param = be_transform_node(param);
+ ir_node *new_node;
+
+ /* the x86 parity bit is stupid: it only looks at the lowest byte,
+ * so we have to do complicated xoring first.
+ * (we should also better lower this before the backend so we still have a
+ * chance for CSE, constant folding and other goodies for some of these
+ * operations)
+ */
+ ir_graph *const irg = get_Block_irg(new_block);
+ ir_node *const count = ia32_create_Immediate(irg, NULL, 0, 16);
+ ir_node *const shr = new_bd_ia32_Shr(dbgi, new_block, new_param, count);
+ ir_node *const xorn = new_bd_ia32_Xor(dbgi, new_block, noreg_GP, noreg_GP, nomem, shr, new_param);
+ ir_node *const xor2 = new_bd_ia32_XorHighLow(dbgi, new_block, xorn);
+ ir_node *flags;
+
+ set_ia32_ls_mode(xorn, mode_Iu);
+ set_ia32_commutative(xorn);
+
+ set_irn_mode(xor2, mode_T);
+ flags = new_r_Proj(xor2, mode_Iu, pn_ia32_XorHighLow_flags);
+
+ /* setp */
+ new_node = new_bd_ia32_Setcc(dbgi, new_block, flags, ia32_cc_not_parity);
+ SET_IA32_ORIG_NODE(new_node, node);
+
+ /* conv to 32bit */
+ new_node = new_bd_ia32_Conv_I2I_8bit(dbgi, new_block, noreg_GP, noreg_GP, nomem, new_node, mode_Bu);
+ SET_IA32_ORIG_NODE(new_node, node);
+ return new_node;
+}
+
+/**
+ * Transform builtin popcount
+ */
+static ir_node *gen_popcount(ir_node *node)
+{
+ ir_node *param = get_Builtin_param(node, 0);
+ 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 *new_param;
+ ir_node *imm, *simm, *m1, *s1, *s2, *s3, *s4, *s5, *m2, *m3, *m4, *m5, *m6, *m7, *m8, *m9, *m10, *m11, *m12, *m13;
+
+ /* check for SSE4.2 or SSE4a and use the popcnt instruction */
+ if (ia32_cg_config.use_popcnt) {
+ ia32_address_mode_t am;
+ ia32_address_t *addr = &am.addr;
+ ir_node *cnt;
+
+ match_arguments(&am, block, NULL, param, NULL, match_am | match_16bit_am | match_upconv);
+
+ cnt = new_bd_ia32_Popcnt(dbgi, new_block, addr->base, addr->index, addr->mem, am.new_op2);
+ set_am_attributes(cnt, &am);
+ set_ia32_ls_mode(cnt, get_irn_mode(param));
+
+ SET_IA32_ORIG_NODE(cnt, node);
+ return fix_mem_proj(cnt, &am);
+ }
+
+ new_param = be_transform_node(param);
+
+ /* do the standard popcount algo */
+ /* TODO: This is stupid, we should transform this before the backend,
+ * to get CSE, localopts, etc. for the operations
+ * TODO: This is also not the optimal algorithm (it is just the starting
+ * example in hackers delight, they optimize it more on the following page)
+ * But I'm too lazy to fix this now, as the code should get lowered before
+ * the backend anyway.
+ */
+ ir_graph *const irg = get_Block_irg(new_block);
+
+ /* m1 = x & 0x55555555 */
+ imm = ia32_create_Immediate(irg, NULL, 0, 0x55555555);
+ m1 = new_bd_ia32_And(dbgi, new_block, noreg_GP, noreg_GP, nomem, new_param, imm);
+
+ /* s1 = x >> 1 */
+ simm = ia32_create_Immediate(irg, NULL, 0, 1);
+ s1 = new_bd_ia32_Shr(dbgi, new_block, new_param, simm);
+
+ /* m2 = s1 & 0x55555555 */
+ m2 = new_bd_ia32_And(dbgi, new_block, noreg_GP, noreg_GP, nomem, s1, imm);