+ /* transform all reference nodes into mode_Iu nodes */
+ if (mode_is_reference(get_irn_mode(irn))) {
+ set_irn_mode(irn, mode_Iu);
+ }
+}
+
+/**
+ * Walks over the graph, transforms all firm consts into ia32 consts
+ * and places them into the "best" block.
+ * @param cg The ia32 codegenerator object
+ */
+static void ia32_transform_all_firm_consts(ia32_code_gen_t *cg) {
+ irg_walk_graph(cg->irg, NULL, ia32_place_consts_walker, cg);
+}
+
+/* Place all consts and change pointer arithmetics into unsigned integer arithmetics. */
+void ia32_pre_transform_phase(ia32_code_gen_t *cg) {
+ /*
+ We need to transform the consts twice:
+ - the psi condition tree transformer needs existing constants to be ia32 constants
+ - the psi condition tree transformer inserts new firm constants which need to be transformed
+ */
+ ia32_transform_all_firm_consts(cg);
+ irg_walk_graph(cg->irg, ia32_set_modes, ia32_transform_psi_cond_tree, cg);
+ ia32_transform_all_firm_consts(cg);
+}
+
+/********************************************************************************************************
+ * _____ _ _ ____ _ _ _ _ _
+ * | __ \ | | | | / __ \ | | (_) (_) | | (_)
+ * | |__) |__ ___ _ __ | |__ ___ | | ___ | | | |_ __ | |_ _ _ __ ___ _ ______ _| |_ _ ___ _ __
+ * | ___/ _ \/ _ \ '_ \| '_ \ / _ \| |/ _ \ | | | | '_ \| __| | '_ ` _ \| |_ / _` | __| |/ _ \| '_ \
+ * | | | __/ __/ |_) | | | | (_) | | __/ | |__| | |_) | |_| | | | | | | |/ / (_| | |_| | (_) | | | |
+ * |_| \___|\___| .__/|_| |_|\___/|_|\___| \____/| .__/ \__|_|_| |_| |_|_/___\__,_|\__|_|\___/|_| |_|
+ * | | | |
+ * |_| |_|
+ ********************************************************************************************************/
+
+/**
+ * NOTE: THESE PEEPHOLE OPTIMIZATIONS MUST BE CALLED AFTER SCHEDULING AND REGISTER ALLOCATION.
+ */
+
+static int ia32_cnst_compare(ir_node *n1, ir_node *n2) {
+ return get_ia32_id_cnst(n1) == get_ia32_id_cnst(n2);
+}
+
+/**
+ * Checks for potential CJmp/CJmpAM optimization candidates.
+ */
+static ir_node *ia32_determine_cjmp_cand(ir_node *irn, is_op_func_t *is_op_func) {
+ ir_node *cand = NULL;
+ ir_node *prev = sched_prev(irn);
+
+ if (is_Block(prev)) {
+ if (get_Block_n_cfgpreds(prev) == 1)
+ prev = get_Block_cfgpred(prev, 0);
+ else
+ prev = NULL;
+ }
+
+ /* The predecessor must be a ProjX. */
+ if (prev && is_Proj(prev) && get_irn_mode(prev) == mode_X) {
+ prev = get_Proj_pred(prev);
+
+ if (is_op_func(prev))
+ cand = prev;
+ }
+
+ return cand;
+}
+
+static int is_TestJmp_cand(const ir_node *irn) {
+ return is_ia32_TestJmp(irn) || is_ia32_And(irn);
+}
+
+/**
+ * Checks if two consecutive arguments of cand matches
+ * the two arguments of irn (TestJmp).
+ */
+static int is_TestJmp_replacement(ir_node *cand, ir_node *irn) {
+ ir_node *in1 = get_irn_n(irn, 0);
+ ir_node *in2 = get_irn_n(irn, 1);
+ int i, n = get_irn_arity(cand);
+ int same_args = 0;
+
+ for (i = 0; i < n - 1; i++) {
+ if (get_irn_n(cand, i) == in1 &&
+ get_irn_n(cand, i + 1) == in2)
+ {
+ same_args = 1;
+ break;
+ }
+ }
+
+ if (same_args)
+ return ia32_cnst_compare(cand, irn);
+
+ return 0;
+}
+
+/**
+ * Tries to replace a TestJmp by a CJmp or CJmpAM (in case of And)
+ */
+static void ia32_optimize_TestJmp(ir_node *irn, ia32_code_gen_t *cg) {
+ ir_node *cand = ia32_determine_cjmp_cand(irn, is_TestJmp_cand);
+ int replace = 0;
+
+ /* we found a possible candidate */
+ replace = cand ? is_TestJmp_replacement(cand, irn) : 0;