+
+ DB((dbg, LEVEL_2, ">> Fixing users of %+F\n", node));
+
+ blocks[0] = block;
+ vals[0] = node;
+ blocks[1] = copy_block;
+ vals[1] = get_irn_link(node);
+ construct_ssa(blocks, vals, 2);
+ }
+}
+
+/**
+ * returns whether the cmp evaluates to true or false, or can't be evaluated!
+ * 1: true, 0: false, -1: can't evaluate
+ *
+ * @param pnc the compare mode of the Compare
+ * @param tv_left the left tarval
+ * @param tv_right the right tarval
+ */
+static int eval_cmp_tv(pn_Cmp pnc, tarval *tv_left, tarval *tv_right) {
+ pn_Cmp cmp_result = tarval_cmp(tv_left, tv_right);
+
+ /* does the compare evaluate to true? */
+ if (cmp_result == pn_Cmp_False)
+ return -1;
+ if ((cmp_result & pnc) != cmp_result)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * returns whether the cmp evaluates to true or false, or can't be evaluated!
+ * 1: true, 0: false, -1: can't evaluate
+ *
+ * @param env the environment
+ * @param cand the candidate node, either a Const or a Confirm
+ */
+static int eval_cmp(condeval_env_t *env, ir_node *cand) {
+ if (is_Const(cand)) {
+ tarval *tv_cand = get_Const_tarval(cand);
+ tarval *tv_cmp = get_Const_tarval(env->cnst);
+
+ return eval_cmp_tv(env->pnc, tv_cand, tv_cmp);
+ } else { /* a Confirm */
+ tarval *res = computed_value_Cmp_Confirm(env->cmp, cand, env->cnst, env->pnc);
+
+ if (res == tarval_bad)
+ return -1;
+ return res == tarval_b_true;
+ }
+}
+
+/**
+ * Check for Const or Confirm with Const.
+ */
+static int is_Const_or_Confirm(const ir_node *node) {
+ if (is_Confirm(node))
+ node = get_Confirm_bound(node);
+ return is_Const(node);
+}
+
+/**
+ * get the tarval of a Const or Confirm with
+ */
+static tarval *get_Const_or_Confirm_tarval(const ir_node *node) {
+ if (is_Confirm(node)) {
+ if (get_Confirm_bound(node))
+ node = get_Confirm_bound(node);
+ }
+ return get_Const_tarval(node);
+}
+
+static ir_node *find_const_or_confirm(condeval_env_t *env, ir_node *jump, ir_node *value)
+{
+ ir_node *block = get_nodes_block(jump);
+
+ if (irn_visited(value))
+ return NULL;
+ mark_irn_visited(value);
+
+ if (is_Const_or_Confirm(value)) {
+ if (eval_cmp(env, value) <= 0) {
+ return NULL;
+ }
+
+ DB((
+ dbg, LEVEL_1,
+ "> Found condition evaluation candidate %+F->%+F\n",
+ env->true_block, block
+ ));
+
+ /* adjust true_block to point directly towards our jump */
+ add_pred(env->true_block, jump);
+
+ split_critical_edge(env->true_block, 0);
+
+ /* we need a bigger visited nr when going back */
+ env->visited_nr++;
+
+ return block;
+ }
+
+ if(is_Phi(value)) {
+ int i, arity;
+
+ /* the Phi has to be in the same Block as the Jmp */
+ if(get_nodes_block(value) != block) {
+ return NULL;
+ }
+
+ arity = get_irn_arity(value);
+ for(i = 0; i < arity; ++i) {
+ ir_node *copy_block;
+ ir_node *phi_pred = get_Phi_pred(value, i);
+ ir_node *cfgpred = get_Block_cfgpred(block, i);
+
+ copy_block = find_const_or_confirm(env, cfgpred, phi_pred);
+ if(copy_block == NULL)
+ continue;
+
+ /* copy duplicated nodes in copy_block and fix SSA */
+ copy_and_fix(env, block, copy_block, i);
+
+ if(copy_block == get_nodes_block(cfgpred)) {
+ env->cnst_pred = block;
+ env->cnst_pos = i;
+ }
+
+ /* return now as we can't process more possibilities in 1 run */
+ return copy_block;
+ }
+ }
+
+ return NULL;
+}
+
+static ir_node *find_candidate(condeval_env_t *env, ir_node *jump,
+ ir_node *value)
+{
+ ir_node *block = get_nodes_block(jump);
+
+ if(irn_visited(value)) {
+ return NULL;
+ }
+ mark_irn_visited(value);
+
+ if (is_Const_or_Confirm(value)) {
+ tarval *tv = get_Const_or_Confirm_tarval(value);
+
+ if (tv != env->tv)
+ return NULL;
+
+ DB((
+ dbg, LEVEL_1,
+ "> Found condition evaluation candidate %+F->%+F\n",
+ env->true_block, block
+ ));
+
+ /* adjust true_block to point directly towards our jump */
+ add_pred(env->true_block, jump);
+
+ split_critical_edge(env->true_block, 0);
+
+ /* we need a bigger visited nr when going back */
+ env->visited_nr++;
+
+ return block;
+ }
+ if(is_Phi(value)) {
+ int i, arity;
+
+ /* the Phi has to be in the same Block as the Jmp */
+ if(get_nodes_block(value) != block)
+ return NULL;
+
+ arity = get_irn_arity(value);
+ for(i = 0; i < arity; ++i) {
+ ir_node *copy_block;
+ ir_node *phi_pred = get_Phi_pred(value, i);
+ ir_node *cfgpred = get_Block_cfgpred(block, i);
+
+ copy_block = find_candidate(env, cfgpred, phi_pred);
+ if(copy_block == NULL)
+ continue;
+
+ /* copy duplicated nodes in copy_block and fix SSA */
+ copy_and_fix(env, block, copy_block, i);
+
+ if(copy_block == get_nodes_block(cfgpred)) {
+ env->cnst_pred = block;
+ env->cnst_pos = i;
+ }
+
+ /* return now as we can't process more possibilities in 1 run */
+ return copy_block;