-static ir_node *transform_node_Proj(ir_node *proj)
-{
- ir_node *n = get_Proj_pred(proj);
- ir_node *b;
- tarval *tb;
- long proj_nr;
-
- switch (get_irn_opcode(n)) {
- case iro_Div:
- b = get_Div_right(n);
- tb = value_of(b);
-
- if (tb != tarval_bad && classify_tarval(tb) != TV_CLASSIFY_NULL) { /* div(x, c) && c != 0 */
- proj_nr = get_Proj_proj(proj);
-
- /* this node may float */
- set_irn_pinned(n, op_pin_state_floats);
-
- if (proj_nr == pn_Div_X_except) {
- /* we found an exception handler, remove it */
- return new_Bad();
- } else {
- /* the memory Proj can be removed */
- ir_node *res = get_Div_mem(n);
- set_Div_mem(n, get_irg_no_mem(current_ir_graph));
- if (proj_nr == pn_Div_M)
- return res;
- }
- }
- break;
- case iro_Mod:
- b = get_Mod_right(n);
- tb = value_of(b);
-
- if (tb != tarval_bad && classify_tarval(tb) != TV_CLASSIFY_NULL) { /* mod(x, c) && c != 0 */
- proj_nr = get_Proj_proj(proj);
-
- /* this node may float */
- set_irn_pinned(n, op_pin_state_floats);
-
- if (proj_nr == pn_Mod_X_except) {
- /* we found an exception handler, remove it */
- return new_Bad();
- } else {
- /* the memory Proj can be removed */
- ir_node *res = get_Mod_mem(n);
- set_Mod_mem(n, get_irg_no_mem(current_ir_graph));
- if (proj_nr == pn_Mod_M)
- return res;
- }
- }
- break;
- case iro_DivMod:
- b = get_DivMod_right(n);
- tb = value_of(b);
-
- if (tb != tarval_bad && classify_tarval(tb) != TV_CLASSIFY_NULL) { /* DivMod(x, c) && c != 0 */
- proj_nr = get_Proj_proj(proj);
-
- /* this node may float */
- set_irn_pinned(n, op_pin_state_floats);
-
- if (proj_nr == pn_DivMod_X_except) {
- /* we found an exception handler, remove it */
- return new_Bad();
- }
- else {
- /* the memory Proj can be removed */
- ir_node *res = get_DivMod_mem(n);
- set_DivMod_mem(n, get_irg_no_mem(current_ir_graph));
- if (proj_nr == pn_DivMod_M)
- return res;
- }
- }
- break;
-
- case iro_Cond:
- if (get_opt_unreachable_code()) {
- b = get_Cond_selector(n);
- tb = value_of(b);
-
- if (tb != tarval_bad && mode_is_int(get_tarval_mode(tb))) {
- /* we have a constant switch */
- long num = get_Proj_proj(proj);
-
- if (num != get_Cond_defaultProj(n)) { /* we cannot optimize default Proj's yet */
- if (get_tarval_long(tb) == num) {
- /* Do NOT create a jump here, or we will have 2 control flow ops
- * in a block. This case is optimized away in optimize_cf(). */
- return proj;
- }
- else
- return new_Bad();
- }
- }
- }
- return proj;
-
- case iro_Cmp:
- if (get_opt_reassociation()) {
- ir_node *left = get_Cmp_left(n);
- ir_node *right = get_Cmp_right(n);
- ir_node *c = NULL;
- tarval *tv = NULL;
- int changed = 0;
- ir_mode *mode = NULL;
-
- proj_nr = get_Proj_proj(proj);
-
- /*
- * First step: normalize the compare op
- * by placing the constant on the right site
- * or moving the lower address node to the left.
- * We ignore the case that both are constants, then
- * this compare should be optimized away.
- */
- if (get_irn_op(right) == op_Const)
- c = right;
- else if (get_irn_op(left) == op_Const) {
- c = left;
- left = right;
- right = c;
-
- proj_nr = get_swapped_pnc(proj_nr);
- changed |= 1;
- }
- else if (left > right) {
- ir_node *t = left;
-
- left = right;
- right = t;
-
- proj_nr = get_swapped_pnc(proj_nr);
- changed |= 1;
- }
-
- /*
- * Second step: Try to reduce the magnitude
- * of a constant. This may help to generate better code
- * later and may help to normalize more compares.
- * Of course this is only possible for integer values.
- */
- if (c) {
- mode = get_irn_mode(c);
- tv = get_Const_tarval(c);
-
- if (tv != tarval_bad) {
- /* the following optimization is possibe on non-int values either:
- * -a CMP c ==> a swap(CMP) -c */
- if (get_opt_constant_folding() && get_irn_op(left) == op_Minus) {
- left = get_Minus_op(left);
- tv = tarval_sub(get_tarval_one(mode), tv);
-
- proj_nr = get_swapped_pnc(proj_nr);
- changed |= 2;
- }
-
- /* for integer modes, we have more */
- if (mode_is_int(mode)) {
- /* Ne includes Unordered which is not possible on integers.
- * However, frontends often use this wrong, so fix it here */
- if (proj_nr == pn_Cmp_Ne)
- proj_nr = pn_Cmp_Lg;
-
- /* c > 0 : a < c ==> a <= (c-1) a >= c ==> a > (c-1) */
- if ((proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Ge) &&
- tarval_cmp(tv, get_tarval_null(mode)) == pn_Cmp_Gt) {
- tv = tarval_sub(tv, get_tarval_one(mode));
-
- proj_nr ^= pn_Cmp_Eq;
- changed |= 2;
- }
- /* c < 0 : a > c ==> a >= (c+1) a <= c ==> a < (c+1) */
- else if ((proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Le) &&
- tarval_cmp(tv, get_tarval_null(mode)) == pn_Cmp_Lt) {
- tv = tarval_add(tv, get_tarval_one(mode));
-
- proj_nr ^= pn_Cmp_Eq;
- changed |= 2;
- }
-
- /* the following reassociations work only for == and != */
-
- /* a-b == 0 ==> a == b, a-b != 0 ==> a != b */
- if (classify_tarval(tv) == TV_CLASSIFY_NULL && get_irn_op(left) == op_Sub) {
- if (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) {
- right = get_Sub_right(left);
- left = get_Sub_left(left);
-
- tv = value_of(right);
- changed = 1;
- }
- }
-
- if (tv != tarval_bad) {
- ir_op *op = get_irn_op(left);
-
- /* a-c1 == c2 ==> a == c2+c1, a-c1 != c2 ==> a != c2+c1 */
- if (op == op_Sub) {
- ir_node *c1 = get_Sub_right(left);
- tarval *tv2 = value_of(c1);
-
- if (tv2 != tarval_bad) {
- tv2 = tarval_add(tv, value_of(c1));
-
- if (tv2 != tarval_bad) {
- left = get_Sub_left(left);
- tv = tv2;
- changed = 2;
- }
- }
- }
- /* a+c1 == c2 ==> a == c2-c1, a+c1 != c2 ==> a != c2-c1 */
- else if (op == op_Add) {
- ir_node *a_l = get_Add_left(left);
- ir_node *a_r = get_Add_right(left);
- ir_node *a;
- tarval *tv2;
-
- if (get_irn_op(a_l) == op_Const) {
- a = a_r;
- tv2 = value_of(a_l);
- }
- else {
- a = a_l;
- tv2 = value_of(a_r);
- }
-
- if (tv2 != tarval_bad) {
- tv2 = tarval_sub(tv, tv2);
-
- if (tv2 != tarval_bad) {
- left = a;
- tv = tv2;
- changed = 2;
- }
- }
- }
- }
- }
- }
- }
-
- if (changed) {
- ir_node *block = get_nodes_block(n);
-
- if (changed & 2) /* need a new Const */
- right = new_Const(mode, tv);
-
- /* create a new compare */
- n = new_rd_Cmp(get_irn_dbg_info(n), current_ir_graph, block,
- left, right);
-
- set_Proj_pred(proj, n);
- set_Proj_proj(proj, proj_nr);
- }
- }
- return proj;
-
- case iro_Tuple:
- /* should not happen, but if it does will be optimized away */
- break;
-
- default:
- /* do nothing */
- return proj;
- }