2010-11-24 Maxim Kuvyrkov gcc/ * combine.c (subst, combine_simlify_rtx): Add new argument, use it to track processing of conditionals. Update all callers. (try_combine, simplify_if_then_else): Update. === modified file 'gcc/combine.c' --- old/gcc/combine.c 2010-11-04 12:39:28 +0000 +++ new/gcc/combine.c 2010-11-25 11:11:45 +0000 @@ -392,8 +392,8 @@ static void undo_all (void); static void undo_commit (void); static rtx *find_split_point (rtx *, rtx); -static rtx subst (rtx, rtx, rtx, int, int); -static rtx combine_simplify_rtx (rtx, enum machine_mode, int); +static rtx subst (rtx, rtx, rtx, int, int, int); +static rtx combine_simplify_rtx (rtx, enum machine_mode, int, int); static rtx simplify_if_then_else (rtx); static rtx simplify_set (rtx); static rtx simplify_logical (rtx); @@ -2944,12 +2944,12 @@ if (i1) { subst_low_luid = DF_INSN_LUID (i1); - i1src = subst (i1src, pc_rtx, pc_rtx, 0, 0); + i1src = subst (i1src, pc_rtx, pc_rtx, 0, 0, 0); } else { subst_low_luid = DF_INSN_LUID (i2); - i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0); + i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0, 0); } } @@ -2960,7 +2960,7 @@ to avoid self-referential rtl. */ subst_low_luid = DF_INSN_LUID (i2); - newpat = subst (PATTERN (i3), i2dest, i2src, 0, + newpat = subst (PATTERN (i3), i2dest, i2src, 0, 0, ! i1_feeds_i3 && i1dest_in_i1src); substed_i2 = 1; @@ -2991,7 +2991,7 @@ n_occurrences = 0; subst_low_luid = DF_INSN_LUID (i1); - newpat = subst (newpat, i1dest, i1src, 0, 0); + newpat = subst (newpat, i1dest, i1src, 0, 0, 0); substed_i1 = 1; } @@ -3053,7 +3053,7 @@ else /* See comment where i2pat is assigned. */ XVECEXP (newpat, 0, --total_sets) - = subst (i2pat, i1dest, i1src, 0, 0); + = subst (i2pat, i1dest, i1src, 0, 0, 0); } } @@ -4605,11 +4605,13 @@ IN_DEST is nonzero if we are processing the SET_DEST of a SET. + IN_COND is nonzero if we are on top level of the condition. + UNIQUE_COPY is nonzero if each substitution must be unique. We do this by copying if `n_occurrences' is nonzero. */ static rtx -subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy) +subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy) { enum rtx_code code = GET_CODE (x); enum machine_mode op0_mode = VOIDmode; @@ -4670,7 +4672,7 @@ && GET_CODE (XVECEXP (x, 0, 0)) == SET && GET_CODE (SET_SRC (XVECEXP (x, 0, 0))) == ASM_OPERANDS) { - new_rtx = subst (XVECEXP (x, 0, 0), from, to, 0, unique_copy); + new_rtx = subst (XVECEXP (x, 0, 0), from, to, 0, 0, unique_copy); /* If this substitution failed, this whole thing fails. */ if (GET_CODE (new_rtx) == CLOBBER @@ -4687,7 +4689,7 @@ && GET_CODE (dest) != CC0 && GET_CODE (dest) != PC) { - new_rtx = subst (dest, from, to, 0, unique_copy); + new_rtx = subst (dest, from, to, 0, 0, unique_copy); /* If this substitution failed, this whole thing fails. */ if (GET_CODE (new_rtx) == CLOBBER @@ -4733,8 +4735,8 @@ } else { - new_rtx = subst (XVECEXP (x, i, j), from, to, 0, - unique_copy); + new_rtx = subst (XVECEXP (x, i, j), from, to, 0, 0, + unique_copy); /* If this substitution failed, this whole thing fails. */ @@ -4811,7 +4813,9 @@ && (code == SUBREG || code == STRICT_LOW_PART || code == ZERO_EXTRACT)) || code == SET) - && i == 0), unique_copy); + && i == 0), + code == IF_THEN_ELSE && i == 0, + unique_copy); /* If we found that we will have to reject this combination, indicate that by returning the CLOBBER ourselves, rather than @@ -4868,7 +4872,7 @@ /* If X is sufficiently simple, don't bother trying to do anything with it. */ if (code != CONST_INT && code != REG && code != CLOBBER) - x = combine_simplify_rtx (x, op0_mode, in_dest); + x = combine_simplify_rtx (x, op0_mode, in_dest, in_cond); if (GET_CODE (x) == code) break; @@ -4888,10 +4892,12 @@ expression. OP0_MODE is the original mode of XEXP (x, 0). IN_DEST is nonzero - if we are inside a SET_DEST. */ + if we are inside a SET_DEST. IN_COND is nonzero if we are on the top level + of a condition. */ static rtx -combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) +combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest, + int in_cond) { enum rtx_code code = GET_CODE (x); enum machine_mode mode = GET_MODE (x); @@ -4946,8 +4952,8 @@ false arms to store-flag values. Be careful to use copy_rtx here since true_rtx or false_rtx might share RTL with x as a result of the if_then_else_cond call above. */ - true_rtx = subst (copy_rtx (true_rtx), pc_rtx, pc_rtx, 0, 0); - false_rtx = subst (copy_rtx (false_rtx), pc_rtx, pc_rtx, 0, 0); + true_rtx = subst (copy_rtx (true_rtx), pc_rtx, pc_rtx, 0, 0, 0); + false_rtx = subst (copy_rtx (false_rtx), pc_rtx, pc_rtx, 0, 0, 0); /* If true_rtx and false_rtx are not general_operands, an if_then_else is unlikely to be simpler. */ @@ -5291,7 +5297,7 @@ { /* Try to simplify the expression further. */ rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1)); - temp = combine_simplify_rtx (tor, mode, in_dest); + temp = combine_simplify_rtx (tor, mode, in_dest, 0); /* If we could, great. If not, do not go ahead with the IOR replacement, since PLUS appears in many special purpose @@ -5384,7 +5390,16 @@ ZERO_EXTRACT is indeed appropriate, it will be placed back by the call to make_compound_operation in the SET case. */ - if (STORE_FLAG_VALUE == 1 + if (in_cond) + /* Don't apply below optimizations if the caller would + prefer a comparison rather than a value. + E.g., for the condition in an IF_THEN_ELSE most targets need + an explicit comparison. */ + { + ; + } + + else if (STORE_FLAG_VALUE == 1 && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT && op1 == const0_rtx && mode == GET_MODE (op0) @@ -5628,11 +5643,11 @@ if (reg_mentioned_p (from, true_rtx)) true_rtx = subst (known_cond (copy_rtx (true_rtx), true_code, from, true_val), - pc_rtx, pc_rtx, 0, 0); + pc_rtx, pc_rtx, 0, 0, 0); if (reg_mentioned_p (from, false_rtx)) false_rtx = subst (known_cond (copy_rtx (false_rtx), false_code, from, false_val), - pc_rtx, pc_rtx, 0, 0); + pc_rtx, pc_rtx, 0, 0, 0); SUBST (XEXP (x, 1), swapped ? false_rtx : true_rtx); SUBST (XEXP (x, 2), swapped ? true_rtx : false_rtx); @@ -5849,11 +5864,11 @@ { temp = subst (simplify_gen_relational (true_code, m, VOIDmode, cond_op0, cond_op1), - pc_rtx, pc_rtx, 0, 0); + pc_rtx, pc_rtx, 0, 0, 0); temp = simplify_gen_binary (MULT, m, temp, simplify_gen_binary (MULT, m, c1, const_true_rtx)); - temp = subst (temp, pc_rtx, pc_rtx, 0, 0); + temp = subst (temp, pc_rtx, pc_rtx, 0, 0, 0); temp = simplify_gen_binary (op, m, gen_lowpart (m, z), temp); if (extend_op != UNKNOWN)