Commit dce1438a by Paolo Bonzini Committed by Paolo Bonzini

combine.c (gen_binary): Remove.

2004-05-25  Paolo Bonzini  <bonzini@gnu.org>

        * combine.c (gen_binary): Remove.
        (known_cond, simplify_shift_const
        find_split_point, combine_simplify_rtx,
        simplify_if_then_else, simplify_set,
        simplify_logical, expand_field_assignment,
        extract_left_shift, force_to_mode,
        if_then_else_cond, apply_distributive_law,
        simplify_and_const_int, simplify_shift_const,
        gen_lowpart_for_combine, simplify_comparison,
        reversed_comparison): Replace with
        simplify_gen_binary, simplify_gen_relational or
        distribute_and_simplify_rtx.
        (distribute_and_simplify_rtx): New function.
        * simplify-rtx.c (simplify_binary_operation):
        Use nonzero_bits to simplify ANDs where we are
        turning off bits already known to be off in OP0.

From-SVN: r82317
parent 42f806e5
2004-05-25 Paolo Bonzini <bonzini@gnu.org>
* combine.c (gen_binary): Remove.
(known_cond, simplify_shift_const
find_split_point, combine_simplify_rtx,
simplify_if_then_else, simplify_set,
simplify_logical, expand_field_assignment,
extract_left_shift, force_to_mode,
if_then_else_cond, apply_distributive_law,
simplify_and_const_int, simplify_shift_const,
gen_lowpart_for_combine, simplify_comparison,
reversed_comparison): Replace with
simplify_gen_binary, simplify_gen_relational or
distribute_and_simplify_rtx.
(distribute_and_simplify_rtx): New function.
* simplify-rtx.c (simplify_binary_operation):
Use nonzero_bits to simplify ANDs where we are
turning off bits already known to be off in OP0.
2004-05-27 Alan Modra <amodra@bigpond.net.au> 2004-05-27 Alan Modra <amodra@bigpond.net.au>
PR target/14478 PR target/14478
......
...@@ -372,6 +372,7 @@ static rtx known_cond (rtx, enum rtx_code, rtx, rtx); ...@@ -372,6 +372,7 @@ static rtx known_cond (rtx, enum rtx_code, rtx, rtx);
static int rtx_equal_for_field_assignment_p (rtx, rtx); static int rtx_equal_for_field_assignment_p (rtx, rtx);
static rtx make_field_assignment (rtx); static rtx make_field_assignment (rtx);
static rtx apply_distributive_law (rtx); static rtx apply_distributive_law (rtx);
static rtx distribute_and_simplify_rtx (rtx);
static rtx simplify_and_const_int (rtx, enum machine_mode, rtx, static rtx simplify_and_const_int (rtx, enum machine_mode, rtx,
unsigned HOST_WIDE_INT); unsigned HOST_WIDE_INT);
static int merge_outer_ops (enum rtx_code *, HOST_WIDE_INT *, enum rtx_code, static int merge_outer_ops (enum rtx_code *, HOST_WIDE_INT *, enum rtx_code,
...@@ -380,7 +381,6 @@ static rtx simplify_shift_const (rtx, enum rtx_code, enum machine_mode, rtx, ...@@ -380,7 +381,6 @@ static rtx simplify_shift_const (rtx, enum rtx_code, enum machine_mode, rtx,
int); int);
static int recog_for_combine (rtx *, rtx, rtx *); static int recog_for_combine (rtx *, rtx, rtx *);
static rtx gen_lowpart_for_combine (enum machine_mode, rtx); static rtx gen_lowpart_for_combine (enum machine_mode, rtx);
static rtx gen_binary (enum rtx_code, enum machine_mode, rtx, rtx);
static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *); static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *);
static void update_table_tick (rtx); static void update_table_tick (rtx);
static void record_value_for_reg (rtx, rtx, rtx); static void record_value_for_reg (rtx, rtx, rtx);
...@@ -3017,14 +3017,16 @@ find_split_point (rtx *loc, rtx insn) ...@@ -3017,14 +3017,16 @@ find_split_point (rtx *loc, rtx insn)
if (src == mask) if (src == mask)
SUBST (SET_SRC (x), SUBST (SET_SRC (x),
gen_binary (IOR, mode, dest, GEN_INT (src << pos))); simplify_gen_binary (IOR, mode, dest, GEN_INT (src << pos)));
else else
{
rtx negmask = gen_int_mode (~(mask << pos), mode);
SUBST (SET_SRC (x), SUBST (SET_SRC (x),
gen_binary (IOR, mode, simplify_gen_binary (IOR, mode,
gen_binary (AND, mode, dest, simplify_gen_binary (AND, mode,
gen_int_mode (~(mask << pos), dest, negmask),
mode)),
GEN_INT (src << pos))); GEN_INT (src << pos)));
}
SUBST (SET_DEST (x), dest); SUBST (SET_DEST (x), dest);
...@@ -3599,7 +3601,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -3599,7 +3601,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
new = simplify_shift_const (NULL_RTX, ASHIFTRT, mode, new, new = simplify_shift_const (NULL_RTX, ASHIFTRT, mode, new,
INTVAL (XEXP (XEXP (x, 0), 1))); INTVAL (XEXP (XEXP (x, 0), 1)));
SUBST (XEXP (x, 0), gen_binary (PLUS, mode, new, temp)); SUBST (XEXP (x, 0), simplify_gen_binary (PLUS, mode, new, temp));
} }
/* If this is a simple operation applied to an IF_THEN_ELSE, try /* If this is a simple operation applied to an IF_THEN_ELSE, try
...@@ -3656,12 +3658,14 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -3656,12 +3658,14 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
/* If the result values are STORE_FLAG_VALUE and zero, we can /* If the result values are STORE_FLAG_VALUE and zero, we can
just make the comparison operation. */ just make the comparison operation. */
if (true_rtx == const_true_rtx && false_rtx == const0_rtx) if (true_rtx == const_true_rtx && false_rtx == const0_rtx)
x = gen_binary (cond_code, mode, cond, cop1); x = simplify_gen_relational (cond_code, mode, VOIDmode,
cond, cop1);
else if (true_rtx == const0_rtx && false_rtx == const_true_rtx else if (true_rtx == const0_rtx && false_rtx == const_true_rtx
&& ((reversed = reversed_comparison_code_parts && ((reversed = reversed_comparison_code_parts
(cond_code, cond, cop1, NULL)) (cond_code, cond, cop1, NULL))
!= UNKNOWN)) != UNKNOWN))
x = gen_binary (reversed, mode, cond, cop1); x = simplify_gen_relational (reversed, mode, VOIDmode,
cond, cop1);
/* Likewise, we can make the negate of a comparison operation /* Likewise, we can make the negate of a comparison operation
if the result values are - STORE_FLAG_VALUE and zero. */ if the result values are - STORE_FLAG_VALUE and zero. */
...@@ -3669,8 +3673,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -3669,8 +3673,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
&& INTVAL (true_rtx) == - STORE_FLAG_VALUE && INTVAL (true_rtx) == - STORE_FLAG_VALUE
&& false_rtx == const0_rtx) && false_rtx == const0_rtx)
x = simplify_gen_unary (NEG, mode, x = simplify_gen_unary (NEG, mode,
gen_binary (cond_code, mode, cond, simplify_gen_relational (cond_code,
cop1), mode, VOIDmode,
cond, cop1),
mode); mode);
else if (GET_CODE (false_rtx) == CONST_INT else if (GET_CODE (false_rtx) == CONST_INT
&& INTVAL (false_rtx) == - STORE_FLAG_VALUE && INTVAL (false_rtx) == - STORE_FLAG_VALUE
...@@ -3679,13 +3684,17 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -3679,13 +3684,17 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
(cond_code, cond, cop1, NULL)) (cond_code, cond, cop1, NULL))
!= UNKNOWN)) != UNKNOWN))
x = simplify_gen_unary (NEG, mode, x = simplify_gen_unary (NEG, mode,
gen_binary (reversed, mode, simplify_gen_relational (reversed,
mode, VOIDmode,
cond, cop1), cond, cop1),
mode); mode);
else else
return gen_rtx_IF_THEN_ELSE (mode, return gen_rtx_IF_THEN_ELSE (mode,
gen_binary (cond_code, VOIDmode, simplify_gen_relational (cond_code,
cond, cop1), mode,
VOIDmode,
cond,
cop1),
true_rtx, false_rtx); true_rtx, false_rtx);
code = GET_CODE (x); code = GET_CODE (x);
...@@ -3788,7 +3797,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -3788,7 +3797,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
} }
if (inner) if (inner)
return gen_binary (code, mode, other, inner); return simplify_gen_binary (code, mode, other, inner);
} }
} }
...@@ -3890,7 +3899,8 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -3890,7 +3899,8 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
if (GET_CODE (XEXP (x, 0)) == XOR if (GET_CODE (XEXP (x, 0)) == XOR
&& XEXP (XEXP (x, 0), 1) == const1_rtx && XEXP (XEXP (x, 0), 1) == const1_rtx
&& nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1) && nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1)
return gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), constm1_rtx); return simplify_gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0),
constm1_rtx);
temp = expand_compound_operation (XEXP (x, 0)); temp = expand_compound_operation (XEXP (x, 0));
...@@ -4118,8 +4128,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -4118,8 +4128,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
in1 = XEXP (XEXP (XEXP (x, 0), 0), 0); in1 = XEXP (XEXP (XEXP (x, 0), 0), 0);
in2 = XEXP (XEXP (x, 0), 1); in2 = XEXP (XEXP (x, 0), 1);
return gen_binary (MINUS, mode, XEXP (x, 1), return simplify_gen_binary (MINUS, mode, XEXP (x, 1),
gen_binary (MULT, mode, in1, in2)); simplify_gen_binary (MULT, mode,
in1, in2));
} }
/* If we have (plus (plus (A const) B)), associate it so that CONST is /* If we have (plus (plus (A const) B)), associate it so that CONST is
...@@ -4128,8 +4139,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -4128,8 +4139,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
they are now checked elsewhere. */ they are now checked elsewhere. */
if (GET_CODE (XEXP (x, 0)) == PLUS if (GET_CODE (XEXP (x, 0)) == PLUS
&& CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1))) && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
return gen_binary (PLUS, mode, return simplify_gen_binary (PLUS, mode,
gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), simplify_gen_binary (PLUS, mode,
XEXP (XEXP (x, 0), 0),
XEXP (x, 1)), XEXP (x, 1)),
XEXP (XEXP (x, 0), 1)); XEXP (XEXP (x, 0), 1));
...@@ -4197,7 +4209,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -4197,7 +4209,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
& nonzero_bits (XEXP (x, 1), mode)) == 0) & nonzero_bits (XEXP (x, 1), mode)) == 0)
{ {
/* Try to simplify the expression further. */ /* Try to simplify the expression further. */
rtx tor = gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1)); 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);
/* If we could, great. If not, do not go ahead with the IOR /* If we could, great. If not, do not go ahead with the IOR
...@@ -4237,7 +4249,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -4237,7 +4249,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
in1 = XEXP (XEXP (XEXP (x, 1), 0), 0); in1 = XEXP (XEXP (XEXP (x, 1), 0), 0);
in2 = XEXP (XEXP (x, 1), 1); in2 = XEXP (XEXP (x, 1), 1);
return gen_binary (PLUS, mode, gen_binary (MULT, mode, in1, in2), return simplify_gen_binary (PLUS, mode,
simplify_gen_binary (MULT, mode,
in1, in2),
XEXP (x, 0)); XEXP (x, 0));
} }
...@@ -4250,15 +4264,18 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -4250,15 +4264,18 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
in1 = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 1), 0), mode); in1 = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 1), 0), mode);
in2 = XEXP (XEXP (x, 1), 1); in2 = XEXP (XEXP (x, 1), 1);
return gen_binary (MINUS, mode, gen_binary (MULT, mode, in1, in2), return simplify_gen_binary (MINUS, mode,
simplify_gen_binary (MULT, mode,
in1, in2),
XEXP (XEXP (x, 0), 0)); XEXP (XEXP (x, 0), 0));
} }
/* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for /* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for
integers. */ integers. */
if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode)) if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode))
return gen_binary (MINUS, mode, return simplify_gen_binary (MINUS, mode,
gen_binary (MINUS, mode, XEXP (x, 0), simplify_gen_binary (MINUS, mode,
XEXP (x, 0),
XEXP (XEXP (x, 1), 0)), XEXP (XEXP (x, 1), 0)),
XEXP (XEXP (x, 1), 1)); XEXP (XEXP (x, 1), 1));
break; break;
...@@ -4270,17 +4287,11 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -4270,17 +4287,11 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
if (GET_CODE (XEXP (x, 0)) == PLUS) if (GET_CODE (XEXP (x, 0)) == PLUS)
{ {
x = apply_distributive_law rtx result = distribute_and_simplify_rtx (x);
(gen_binary (PLUS, mode, if (result)
gen_binary (MULT, mode, return result;
XEXP (XEXP (x, 0), 0), XEXP (x, 1)),
gen_binary (MULT, mode,
XEXP (XEXP (x, 0), 1),
copy_rtx (XEXP (x, 1)))));
if (GET_CODE (x) != MULT)
return x;
} }
/* Try simplify a*(b/c) as (a*b)/c. */ /* Try simplify a*(b/c) as (a*b)/c. */
if (FLOAT_MODE_P (mode) && flag_unsafe_math_optimizations if (FLOAT_MODE_P (mode) && flag_unsafe_math_optimizations
&& GET_CODE (XEXP (x, 0)) == DIV) && GET_CODE (XEXP (x, 0)) == DIV)
...@@ -4289,7 +4300,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -4289,7 +4300,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 0), 0),
XEXP (x, 1)); XEXP (x, 1));
if (tem) if (tem)
return gen_binary (DIV, mode, tem, XEXP (XEXP (x, 0), 1)); return simplify_gen_binary (DIV, mode, tem, XEXP (XEXP (x, 0), 1));
} }
break; break;
...@@ -4369,7 +4380,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) ...@@ -4369,7 +4380,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
&& nonzero_bits (op0, mode) == 1) && nonzero_bits (op0, mode) == 1)
{ {
op0 = expand_compound_operation (op0); op0 = expand_compound_operation (op0);
return gen_binary (XOR, mode, return simplify_gen_binary (XOR, mode,
gen_lowpart (mode, op0), gen_lowpart (mode, op0),
const1_rtx); const1_rtx);
} }
...@@ -4614,7 +4625,8 @@ simplify_if_then_else (rtx x) ...@@ -4614,7 +4625,8 @@ simplify_if_then_else (rtx x)
/* Simplify storing of the truth value. */ /* Simplify storing of the truth value. */
if (comparison_p && true_rtx == const_true_rtx && false_rtx == const0_rtx) if (comparison_p && true_rtx == const_true_rtx && false_rtx == const0_rtx)
return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1)); return simplify_gen_relational (true_code, mode, VOIDmode,
XEXP (cond, 0), XEXP (cond, 1));
/* Also when the truth value has to be reversed. */ /* Also when the truth value has to be reversed. */
if (comparison_p if (comparison_p
...@@ -4764,16 +4776,16 @@ simplify_if_then_else (rtx x) ...@@ -4764,16 +4776,16 @@ simplify_if_then_else (rtx x)
{ {
case GE: case GE:
case GT: case GT:
return gen_binary (SMAX, mode, true_rtx, false_rtx); return simplify_gen_binary (SMAX, mode, true_rtx, false_rtx);
case LE: case LE:
case LT: case LT:
return gen_binary (SMIN, mode, true_rtx, false_rtx); return simplify_gen_binary (SMIN, mode, true_rtx, false_rtx);
case GEU: case GEU:
case GTU: case GTU:
return gen_binary (UMAX, mode, true_rtx, false_rtx); return simplify_gen_binary (UMAX, mode, true_rtx, false_rtx);
case LEU: case LEU:
case LTU: case LTU:
return gen_binary (UMIN, mode, true_rtx, false_rtx); return simplify_gen_binary (UMIN, mode, true_rtx, false_rtx);
default: default:
break; break;
} }
...@@ -4886,12 +4898,14 @@ simplify_if_then_else (rtx x) ...@@ -4886,12 +4898,14 @@ simplify_if_then_else (rtx x)
if (z) if (z)
{ {
temp = subst (gen_binary (true_code, m, cond_op0, cond_op1), 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);
temp = gen_binary (MULT, m, temp, temp = simplify_gen_binary (MULT, m, temp,
gen_binary (MULT, m, c1, const_true_rtx)); 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);
temp = gen_binary (op, m, gen_lowpart (m, z), temp); temp = simplify_gen_binary (op, m, gen_lowpart (m, z), temp);
if (extend_op != NIL) if (extend_op != NIL)
temp = simplify_gen_unary (extend_op, mode, temp, m); temp = simplify_gen_unary (extend_op, mode, temp, m);
...@@ -5076,7 +5090,8 @@ simplify_set (rtx x) ...@@ -5076,7 +5090,8 @@ simplify_set (rtx x)
PUT_CODE (*cc_use, old_code); PUT_CODE (*cc_use, old_code);
other_changed = 0; other_changed = 0;
op0 = gen_binary (XOR, GET_MODE (op0), op0, GEN_INT (mask)); op0 = simplify_gen_binary (XOR, GET_MODE (op0),
op0, GEN_INT (mask));
} }
} }
} }
...@@ -5240,17 +5255,18 @@ simplify_set (rtx x) ...@@ -5240,17 +5255,18 @@ simplify_set (rtx x)
&& rtx_equal_p (XEXP (false_rtx, 1), true_rtx)) && rtx_equal_p (XEXP (false_rtx, 1), true_rtx))
term1 = true_rtx, false_rtx = XEXP (false_rtx, 0), true_rtx = const0_rtx; term1 = true_rtx, false_rtx = XEXP (false_rtx, 0), true_rtx = const0_rtx;
term2 = gen_binary (AND, GET_MODE (src), term2 = simplify_gen_binary (AND, GET_MODE (src),
XEXP (XEXP (src, 0), 0), true_rtx); XEXP (XEXP (src, 0), 0), true_rtx);
term3 = gen_binary (AND, GET_MODE (src), term3 = simplify_gen_binary (AND, GET_MODE (src),
simplify_gen_unary (NOT, GET_MODE (src), simplify_gen_unary (NOT, GET_MODE (src),
XEXP (XEXP (src, 0), 0), XEXP (XEXP (src, 0), 0),
GET_MODE (src)), GET_MODE (src)),
false_rtx); false_rtx);
SUBST (SET_SRC (x), SUBST (SET_SRC (x),
gen_binary (IOR, GET_MODE (src), simplify_gen_binary (IOR, GET_MODE (src),
gen_binary (IOR, GET_MODE (src), term1, term2), simplify_gen_binary (IOR, GET_MODE (src),
term1, term2),
term3)); term3));
src = SET_SRC (x); src = SET_SRC (x);
...@@ -5286,15 +5302,17 @@ simplify_logical (rtx x) ...@@ -5286,15 +5302,17 @@ simplify_logical (rtx x)
if (GET_CODE (op0) == XOR if (GET_CODE (op0) == XOR
&& rtx_equal_p (XEXP (op0, 0), op1) && rtx_equal_p (XEXP (op0, 0), op1)
&& ! side_effects_p (op1)) && ! side_effects_p (op1))
x = gen_binary (AND, mode, x = simplify_gen_binary (AND, mode,
simplify_gen_unary (NOT, mode, XEXP (op0, 1), mode), simplify_gen_unary (NOT, mode,
XEXP (op0, 1), mode),
op1); op1);
if (GET_CODE (op0) == XOR if (GET_CODE (op0) == XOR
&& rtx_equal_p (XEXP (op0, 1), op1) && rtx_equal_p (XEXP (op0, 1), op1)
&& ! side_effects_p (op1)) && ! side_effects_p (op1))
x = gen_binary (AND, mode, x = simplify_gen_binary (AND, mode,
simplify_gen_unary (NOT, mode, XEXP (op0, 0), mode), simplify_gen_unary (NOT, mode,
XEXP (op0, 0), mode),
op1); op1);
/* Similarly for (~(A ^ B)) & A. */ /* Similarly for (~(A ^ B)) & A. */
...@@ -5302,13 +5320,13 @@ simplify_logical (rtx x) ...@@ -5302,13 +5320,13 @@ simplify_logical (rtx x)
&& GET_CODE (XEXP (op0, 0)) == XOR && GET_CODE (XEXP (op0, 0)) == XOR
&& rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1) && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1)
&& ! side_effects_p (op1)) && ! side_effects_p (op1))
x = gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1); x = simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1);
if (GET_CODE (op0) == NOT if (GET_CODE (op0) == NOT
&& GET_CODE (XEXP (op0, 0)) == XOR && GET_CODE (XEXP (op0, 0)) == XOR
&& rtx_equal_p (XEXP (XEXP (op0, 0), 1), op1) && rtx_equal_p (XEXP (XEXP (op0, 0), 1), op1)
&& ! side_effects_p (op1)) && ! side_effects_p (op1))
x = gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1); x = simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1);
/* We can call simplify_and_const_int only if we don't lose /* We can call simplify_and_const_int only if we don't lose
any (sign) bits when converting INTVAL (op1) to any (sign) bits when converting INTVAL (op1) to
...@@ -5328,8 +5346,9 @@ simplify_logical (rtx x) ...@@ -5328,8 +5346,9 @@ simplify_logical (rtx x)
&& GET_CODE (XEXP (op0, 1)) == CONST_INT && GET_CODE (XEXP (op0, 1)) == CONST_INT
&& GET_CODE (op1) == CONST_INT && GET_CODE (op1) == CONST_INT
&& (INTVAL (XEXP (op0, 1)) & INTVAL (op1)) != 0) && (INTVAL (XEXP (op0, 1)) & INTVAL (op1)) != 0)
return gen_binary (IOR, mode, return simplify_gen_binary (IOR, mode,
gen_binary (AND, mode, XEXP (op0, 0), simplify_gen_binary
(AND, mode, XEXP (op0, 0),
GEN_INT (INTVAL (XEXP (op0, 1)) GEN_INT (INTVAL (XEXP (op0, 1))
& ~INTVAL (op1))), op1); & ~INTVAL (op1))), op1);
...@@ -5348,54 +5367,16 @@ simplify_logical (rtx x) ...@@ -5348,54 +5367,16 @@ simplify_logical (rtx x)
&& ! side_effects_p (XEXP (op0, 1))) && ! side_effects_p (XEXP (op0, 1)))
return op1; return op1;
/* In the following group of tests (and those in case IOR below), /* If we have any of (and (ior A B) C) or (and (xor A B) C),
we start with some combination of logical operations and apply apply the distributive law and then the inverse distributive
the distributive law followed by the inverse distributive law. law to see if things simplify. */
Most of the time, this results in no change. However, if some of if (GET_CODE (op0) == IOR || GET_CODE (op0) == XOR
the operands are the same or inverses of each other, simplifications || GET_CODE (op1) == IOR || GET_CODE (op1) == XOR)
will result.
For example, (and (ior A B) (not B)) can occur as the result of
expanding a bit field assignment. When we apply the distributive
law to this, we get (ior (and (A (not B))) (and (B (not B)))),
which then simplifies to (and (A (not B))).
If we have (and (ior A B) C), apply the distributive law and then
the inverse distributive law to see if things simplify. */
if (GET_CODE (op0) == IOR || GET_CODE (op0) == XOR)
{ {
x = apply_distributive_law rtx result = distribute_and_simplify_rtx (x);
(gen_binary (GET_CODE (op0), mode, if (result)
gen_binary (AND, mode, XEXP (op0, 0), op1), return result;
gen_binary (AND, mode, XEXP (op0, 1),
copy_rtx (op1))));
if (GET_CODE (x) != AND)
return x;
} }
if (GET_CODE (op1) == IOR || GET_CODE (op1) == XOR)
return apply_distributive_law
(gen_binary (GET_CODE (op1), mode,
gen_binary (AND, mode, XEXP (op1, 0), op0),
gen_binary (AND, mode, XEXP (op1, 1),
copy_rtx (op0))));
/* Similarly, taking advantage of the fact that
(and (not A) (xor B C)) == (xor (ior A B) (ior A C)) */
if (GET_CODE (op0) == NOT && GET_CODE (op1) == XOR)
return apply_distributive_law
(gen_binary (XOR, mode,
gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)),
gen_binary (IOR, mode, copy_rtx (XEXP (op0, 0)),
XEXP (op1, 1))));
else if (GET_CODE (op1) == NOT && GET_CODE (op0) == XOR)
return apply_distributive_law
(gen_binary (XOR, mode,
gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 0)),
gen_binary (IOR, mode, copy_rtx (XEXP (op1, 0)), XEXP (op0, 1))));
break; break;
case IOR: case IOR:
...@@ -5416,28 +5397,11 @@ simplify_logical (rtx x) ...@@ -5416,28 +5397,11 @@ simplify_logical (rtx x)
/* If we have (ior (and A B) C), apply the distributive law and then /* If we have (ior (and A B) C), apply the distributive law and then
the inverse distributive law to see if things simplify. */ the inverse distributive law to see if things simplify. */
if (GET_CODE (op0) == AND) if (GET_CODE (op0) == AND || GET_CODE (op1) == AND)
{
x = apply_distributive_law
(gen_binary (AND, mode,
gen_binary (IOR, mode, XEXP (op0, 0), op1),
gen_binary (IOR, mode, XEXP (op0, 1),
copy_rtx (op1))));
if (GET_CODE (x) != IOR)
return x;
}
if (GET_CODE (op1) == AND)
{ {
x = apply_distributive_law rtx result = distribute_and_simplify_rtx (x);
(gen_binary (AND, mode, if (result)
gen_binary (IOR, mode, XEXP (op1, 0), op0), return result;
gen_binary (IOR, mode, XEXP (op1, 1),
copy_rtx (op0))));
if (GET_CODE (x) != IOR)
return x;
} }
/* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the /* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the
...@@ -5486,7 +5450,7 @@ simplify_logical (rtx x) ...@@ -5486,7 +5450,7 @@ simplify_logical (rtx x)
if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (op0, mode) && (nonzero_bits (op0, mode)
& nonzero_bits (op1, mode)) == 0) & nonzero_bits (op1, mode)) == 0)
return (gen_binary (IOR, mode, op0, op1)); return (simplify_gen_binary (IOR, mode, op0, op1));
/* Convert (XOR (NOT x) (NOT y)) to (XOR x y). /* Convert (XOR (NOT x) (NOT y)) to (XOR x y).
Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for
...@@ -5506,7 +5470,8 @@ simplify_logical (rtx x) ...@@ -5506,7 +5470,8 @@ simplify_logical (rtx x)
} }
else if (num_negated == 1) else if (num_negated == 1)
return return
simplify_gen_unary (NOT, mode, gen_binary (XOR, mode, op0, op1), simplify_gen_unary (NOT, mode,
simplify_gen_binary (XOR, mode, op0, op1),
mode); mode);
} }
...@@ -5517,15 +5482,17 @@ simplify_logical (rtx x) ...@@ -5517,15 +5482,17 @@ simplify_logical (rtx x)
if (GET_CODE (op0) == AND if (GET_CODE (op0) == AND
&& rtx_equal_p (XEXP (op0, 1), op1) && rtx_equal_p (XEXP (op0, 1), op1)
&& ! side_effects_p (op1)) && ! side_effects_p (op1))
return gen_binary (AND, mode, return simplify_gen_binary (AND, mode,
simplify_gen_unary (NOT, mode, XEXP (op0, 0), mode), simplify_gen_unary (NOT, mode,
XEXP (op0, 0), mode),
op1); op1);
else if (GET_CODE (op0) == AND else if (GET_CODE (op0) == AND
&& rtx_equal_p (XEXP (op0, 0), op1) && rtx_equal_p (XEXP (op0, 0), op1)
&& ! side_effects_p (op1)) && ! side_effects_p (op1))
return gen_binary (AND, mode, return simplify_gen_binary (AND, mode,
simplify_gen_unary (NOT, mode, XEXP (op0, 1), mode), simplify_gen_unary (NOT, mode,
XEXP (op0, 1), mode),
op1); op1);
/* (xor (comparison foo bar) (const_int 1)) can become the reversed /* (xor (comparison foo bar) (const_int 1)) can become the reversed
...@@ -5795,7 +5762,7 @@ expand_field_assignment (rtx x) ...@@ -5795,7 +5762,7 @@ expand_field_assignment (rtx x)
rtx inner; rtx inner;
rtx pos; /* Always counts from low bit. */ rtx pos; /* Always counts from low bit. */
int len; int len;
rtx mask; rtx mask, cleared, masked;
enum machine_mode compute_mode; enum machine_mode compute_mode;
/* Loop until we find something we can't simplify. */ /* Loop until we find something we can't simplify. */
...@@ -5833,8 +5800,9 @@ expand_field_assignment (rtx x) ...@@ -5833,8 +5800,9 @@ expand_field_assignment (rtx x)
/* If position is ADJUST - X, new position is X. */ /* If position is ADJUST - X, new position is X. */
pos = XEXP (pos, 0); pos = XEXP (pos, 0);
else else
pos = gen_binary (MINUS, GET_MODE (pos), pos = simplify_gen_binary (MINUS, GET_MODE (pos),
GEN_INT (GET_MODE_BITSIZE (GET_MODE (inner)) GEN_INT (GET_MODE_BITSIZE (
GET_MODE (inner))
- len), - len),
pos); pos);
} }
...@@ -5883,30 +5851,30 @@ expand_field_assignment (rtx x) ...@@ -5883,30 +5851,30 @@ expand_field_assignment (rtx x)
} }
/* Compute a mask of LEN bits, if we can do this on the host machine. */ /* Compute a mask of LEN bits, if we can do this on the host machine. */
if (len < HOST_BITS_PER_WIDE_INT) if (len >= HOST_BITS_PER_WIDE_INT)
mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1);
else
break; break;
/* Now compute the equivalent expression. Make a copy of INNER /* Now compute the equivalent expression. Make a copy of INNER
for the SET_DEST in case it is a MEM into which we will substitute; for the SET_DEST in case it is a MEM into which we will substitute;
we don't want shared RTL in that case. */ we don't want shared RTL in that case. */
x = gen_rtx_SET mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1);
(VOIDmode, copy_rtx (inner), cleared = simplify_gen_binary (AND, compute_mode,
gen_binary (IOR, compute_mode,
gen_binary (AND, compute_mode,
simplify_gen_unary (NOT, compute_mode, simplify_gen_unary (NOT, compute_mode,
gen_binary (ASHIFT, simplify_gen_binary (ASHIFT,
compute_mode, compute_mode,
mask, pos), mask, pos),
compute_mode), compute_mode),
inner), inner);
gen_binary (ASHIFT, compute_mode, masked = simplify_gen_binary (ASHIFT, compute_mode,
gen_binary (AND, compute_mode, simplify_gen_binary (
gen_lowpart AND, compute_mode,
(compute_mode, SET_SRC (x)), gen_lowpart (compute_mode, SET_SRC (x)),
mask), mask),
pos))); pos);
x = gen_rtx_SET (VOIDmode, copy_rtx (inner),
simplify_gen_binary (IOR, compute_mode,
cleared, masked));
} }
return x; return x;
...@@ -6362,7 +6330,7 @@ extract_left_shift (rtx x, int count) ...@@ -6362,7 +6330,7 @@ extract_left_shift (rtx x, int count)
if (GET_CODE (XEXP (x, 1)) == CONST_INT if (GET_CODE (XEXP (x, 1)) == CONST_INT
&& (INTVAL (XEXP (x, 1)) & ((((HOST_WIDE_INT) 1 << count)) - 1)) == 0 && (INTVAL (XEXP (x, 1)) & ((((HOST_WIDE_INT) 1 << count)) - 1)) == 0
&& (tem = extract_left_shift (XEXP (x, 0), count)) != 0) && (tem = extract_left_shift (XEXP (x, 0), count)) != 0)
return gen_binary (code, mode, tem, return simplify_gen_binary (code, mode, tem,
GEN_INT (INTVAL (XEXP (x, 1)) >> count)); GEN_INT (INTVAL (XEXP (x, 1)) >> count));
break; break;
...@@ -6854,7 +6822,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, ...@@ -6854,7 +6822,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
&& (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0) && (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0)
cval |= (HOST_WIDE_INT) -1 << width; cval |= (HOST_WIDE_INT) -1 << width;
y = gen_binary (AND, GET_MODE (x), XEXP (x, 0), GEN_INT (cval)); y = simplify_gen_binary (AND, GET_MODE (x),
XEXP (x, 0), GEN_INT (cval));
if (rtx_cost (y, SET) < rtx_cost (x, SET)) if (rtx_cost (y, SET) < rtx_cost (x, SET))
x = y; x = y;
} }
...@@ -6946,9 +6915,9 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, ...@@ -6946,9 +6915,9 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
{ {
temp = GEN_INT ((INTVAL (XEXP (x, 1)) & mask) temp = GEN_INT ((INTVAL (XEXP (x, 1)) & mask)
<< INTVAL (XEXP (XEXP (x, 0), 1))); << INTVAL (XEXP (XEXP (x, 0), 1)));
temp = gen_binary (GET_CODE (x), GET_MODE (x), temp = simplify_gen_binary (GET_CODE (x), GET_MODE (x),
XEXP (XEXP (x, 0), 0), temp); XEXP (XEXP (x, 0), 0), temp);
x = gen_binary (LSHIFTRT, GET_MODE (x), temp, x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), temp,
XEXP (XEXP (x, 0), 1)); XEXP (XEXP (x, 0), 1));
return force_to_mode (x, mode, mask, reg, next_select); return force_to_mode (x, mode, mask, reg, next_select);
} }
...@@ -6965,7 +6934,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, ...@@ -6965,7 +6934,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
reg, next_select)); reg, next_select));
if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0) || op1 != XEXP (x, 1)) if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
x = gen_binary (code, op_mode, op0, op1); x = simplify_gen_binary (code, op_mode, op0, op1);
break; break;
case ASHIFT: case ASHIFT:
...@@ -6999,7 +6968,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, ...@@ -6999,7 +6968,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
mask, reg, next_select)); mask, reg, next_select));
if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0)) if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0))
x = gen_binary (code, op_mode, op0, XEXP (x, 1)); x = simplify_gen_binary (code, op_mode, op0, XEXP (x, 1));
break; break;
case LSHIFTRT: case LSHIFTRT:
...@@ -7027,7 +6996,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, ...@@ -7027,7 +6996,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
inner = force_to_mode (inner, op_mode, inner_mask, reg, next_select); inner = force_to_mode (inner, op_mode, inner_mask, reg, next_select);
if (GET_MODE (x) != op_mode || inner != XEXP (x, 0)) if (GET_MODE (x) != op_mode || inner != XEXP (x, 0))
x = gen_binary (LSHIFTRT, op_mode, inner, XEXP (x, 1)); x = simplify_gen_binary (LSHIFTRT, op_mode, inner, XEXP (x, 1));
} }
/* If we have (and (lshiftrt FOO C1) C2) where the combination of the /* If we have (and (lshiftrt FOO C1) C2) where the combination of the
...@@ -7049,7 +7018,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, ...@@ -7049,7 +7018,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
/* Must be more sign bit copies than the mask needs. */ /* Must be more sign bit copies than the mask needs. */
&& ((int) num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0))) && ((int) num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
>= exact_log2 (mask + 1))) >= exact_log2 (mask + 1)))
x = gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0), x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0),
GEN_INT (GET_MODE_BITSIZE (GET_MODE (x)) GEN_INT (GET_MODE_BITSIZE (GET_MODE (x))
- exact_log2 (mask + 1))); - exact_log2 (mask + 1)));
...@@ -7116,7 +7085,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, ...@@ -7116,7 +7085,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
/* If MASK is 1, convert this to an LSHIFTRT. This can be done /* If MASK is 1, convert this to an LSHIFTRT. This can be done
even if the shift count isn't a constant. */ even if the shift count isn't a constant. */
if (mask == 1) if (mask == 1)
x = gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)); x = simplify_gen_binary (LSHIFTRT, GET_MODE (x),
XEXP (x, 0), XEXP (x, 1));
shiftrt: shiftrt:
...@@ -7181,8 +7151,10 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, ...@@ -7181,8 +7151,10 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
{ {
temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)), temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)),
GET_MODE (x)); GET_MODE (x));
temp = gen_binary (XOR, GET_MODE (x), XEXP (XEXP (x, 0), 0), temp); temp = simplify_gen_binary (XOR, GET_MODE (x),
x = gen_binary (LSHIFTRT, GET_MODE (x), temp, XEXP (XEXP (x, 0), 1)); XEXP (XEXP (x, 0), 0), temp);
x = simplify_gen_binary (LSHIFTRT, GET_MODE (x),
temp, XEXP (XEXP (x, 0), 1));
return force_to_mode (x, mode, mask, reg, next_select); return force_to_mode (x, mode, mask, reg, next_select);
} }
...@@ -7292,8 +7264,19 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse) ...@@ -7292,8 +7264,19 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse)
else if (cond1 == 0) else if (cond1 == 0)
true1 = copy_rtx (true1); true1 = copy_rtx (true1);
*ptrue = gen_binary (code, mode, true0, true1); if (COMPARISON_P (x))
*pfalse = gen_binary (code, mode, false0, false1); {
*ptrue = simplify_gen_relational (code, mode, VOIDmode,
true0, true1);
*pfalse = simplify_gen_relational (code, mode, VOIDmode,
false0, false1);
}
else
{
*ptrue = simplify_gen_binary (code, mode, true0, true1);
*pfalse = simplify_gen_binary (code, mode, false0, false1);
}
return cond0 ? cond0 : cond1; return cond0 ? cond0 : cond1;
} }
...@@ -7323,11 +7306,11 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse) ...@@ -7323,11 +7306,11 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse)
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0)))) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
&& ! side_effects_p (x)) && ! side_effects_p (x))
{ {
*ptrue = gen_binary (MULT, mode, op0, const_true_rtx); *ptrue = simplify_gen_binary (MULT, mode, op0, const_true_rtx);
*pfalse = gen_binary (MULT, mode, *pfalse = simplify_gen_binary (MULT, mode,
(code == MINUS (code == MINUS
? simplify_gen_unary (NEG, mode, op1, ? simplify_gen_unary (NEG, mode,
mode) op1, mode)
: op1), : op1),
const_true_rtx); const_true_rtx);
return cond0; return cond0;
...@@ -7833,7 +7816,7 @@ apply_distributive_law (rtx x) ...@@ -7833,7 +7816,7 @@ apply_distributive_law (rtx x)
|| GET_MODE_SIZE (GET_MODE (SUBREG_REG (lhs))) > UNITS_PER_WORD) || GET_MODE_SIZE (GET_MODE (SUBREG_REG (lhs))) > UNITS_PER_WORD)
return x; return x;
tem = gen_binary (code, GET_MODE (SUBREG_REG (lhs)), tem = simplify_gen_binary (code, GET_MODE (SUBREG_REG (lhs)),
SUBREG_REG (lhs), SUBREG_REG (rhs)); SUBREG_REG (lhs), SUBREG_REG (rhs));
return gen_lowpart (GET_MODE (x), tem); return gen_lowpart (GET_MODE (x), tem);
...@@ -7860,7 +7843,7 @@ apply_distributive_law (rtx x) ...@@ -7860,7 +7843,7 @@ apply_distributive_law (rtx x)
return x; return x;
/* Form the new inner operation, seeing if it simplifies first. */ /* Form the new inner operation, seeing if it simplifies first. */
tem = gen_binary (code, GET_MODE (x), lhs, rhs); tem = simplify_gen_binary (code, GET_MODE (x), lhs, rhs);
/* There is one exception to the general way of distributing: /* There is one exception to the general way of distributing:
(a | c) ^ (b | c) -> (a ^ b) & ~c */ (a | c) ^ (b | c) -> (a ^ b) & ~c */
...@@ -7873,10 +7856,97 @@ apply_distributive_law (rtx x) ...@@ -7873,10 +7856,97 @@ apply_distributive_law (rtx x)
/* We may be able to continuing distributing the result, so call /* We may be able to continuing distributing the result, so call
ourselves recursively on the inner operation before forming the ourselves recursively on the inner operation before forming the
outer operation, which we return. */ outer operation, which we return. */
return gen_binary (inner_code, GET_MODE (x), return simplify_gen_binary (inner_code, GET_MODE (x),
apply_distributive_law (tem), other); apply_distributive_law (tem), other);
} }
/* See if X is of the form (* (+ a b) c), and if so convert to
(+ (* a c) (* b c)) and try to simplify.
Most of the time, this results in no change. However, if some of
the operands are the same or inverses of each other, simplifications
will result.
For example, (and (ior A B) (not B)) can occur as the result of
expanding a bit field assignment. When we apply the distributive
law to this, we get (ior (and (A (not B))) (and (B (not B)))),
which then simplifies to (and (A (not B))).
Note that no checks happen on the validity of applying the inverse
distributive law. This is pointless since we can do it in the
few places where this routine is called. */
static rtx
distribute_and_simplify_rtx (rtx x)
{
enum machine_mode mode;
enum rtx_code outer, inner;
rtx op0, op1, inner_op0, inner_op1, new_op0, new_op1;
mode = GET_MODE (x);
outer = GET_CODE (x);
op0 = XEXP (x, 0);
op1 = XEXP (x, 1);
if (ARITHMETIC_P (op0))
{
inner = GET_CODE (op0);
inner_op0 = XEXP (op0, 0);
inner_op1 = XEXP (op0, 1);
/* (and (xor B C) (not A)) == (xor (ior A B) (ior A C)) */
if (outer == AND && inner == XOR && GET_CODE (op1) == NOT)
{
new_op0 = simplify_gen_binary (IOR, mode, inner_op0, op1);
new_op1 = simplify_gen_binary (IOR, mode, inner_op1, op1);
x = apply_distributive_law (simplify_gen_binary (XOR, mode,
new_op0, new_op1));
if (GET_CODE (x) != AND)
return x;
}
else
{
new_op0 = simplify_gen_binary (outer, mode, inner_op0, op1);
new_op1 = simplify_gen_binary (outer, mode, inner_op1, op1);
x = apply_distributive_law (simplify_gen_binary (inner, mode,
new_op0, new_op1));
if (GET_CODE (x) != outer)
return x;
}
}
if (ARITHMETIC_P (op1))
{
inner = GET_CODE (op1);
inner_op0 = XEXP (op1, 0);
inner_op1 = XEXP (op1, 1);
/* (and (not A) (xor B C)) == (xor (ior A B) (ior A C)) */
if (outer == AND && inner == XOR && GET_CODE (op0) == NOT)
{
new_op0 = simplify_gen_binary (IOR, mode, inner_op0, op0);
new_op1 = simplify_gen_binary (IOR, mode, inner_op1, op0);
x = apply_distributive_law (simplify_gen_binary (XOR, mode,
new_op0, new_op1));
if (GET_CODE (x) != AND)
return x;
}
else
{
new_op0 = simplify_gen_binary (outer, mode, op0, inner_op0);
new_op1 = simplify_gen_binary (outer, mode, op0, inner_op1);
x = apply_distributive_law (simplify_gen_binary (inner, mode,
new_op0, new_op1));
if (GET_CODE (x) != outer)
return x;
}
}
return NULL_RTX;
}
/* We have X, a logical `and' of VAROP with the constant CONSTOP, to be done /* We have X, a logical `and' of VAROP with the constant CONSTOP, to be done
in MODE. in MODE.
...@@ -7941,11 +8011,15 @@ simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop, ...@@ -7941,11 +8011,15 @@ simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop,
gen_lowpart gen_lowpart
(mode, (mode,
apply_distributive_law apply_distributive_law
(gen_binary (GET_CODE (varop), GET_MODE (varop), (simplify_gen_binary (GET_CODE (varop), GET_MODE (varop),
simplify_and_const_int (NULL_RTX, GET_MODE (varop), simplify_and_const_int (NULL_RTX,
XEXP (varop, 0), constop), GET_MODE (varop),
simplify_and_const_int (NULL_RTX, GET_MODE (varop), XEXP (varop, 0),
XEXP (varop, 1), constop)))); constop),
simplify_and_const_int (NULL_RTX,
GET_MODE (varop),
XEXP (varop, 1),
constop))));
/* If VAROP is PLUS, and the constant is a mask of low bite, distribute /* If VAROP is PLUS, and the constant is a mask of low bite, distribute
the AND and see if one of the operands simplifies to zero. If so, we the AND and see if one of the operands simplifies to zero. If so, we
...@@ -7986,7 +8060,7 @@ simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop, ...@@ -7986,7 +8060,7 @@ simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop,
constop = trunc_int_for_mode (constop, mode); constop = trunc_int_for_mode (constop, mode);
/* See how much, if any, of X we can use. */ /* See how much, if any, of X we can use. */
if (x == 0 || GET_CODE (x) != AND || GET_MODE (x) != mode) if (x == 0 || GET_CODE (x) != AND || GET_MODE (x) != mode)
x = gen_binary (AND, mode, varop, GEN_INT (constop)); x = simplify_gen_binary (AND, mode, varop, GEN_INT (constop));
else else
{ {
...@@ -8505,8 +8579,10 @@ simplify_shift_const (rtx x, enum rtx_code code, ...@@ -8505,8 +8579,10 @@ simplify_shift_const (rtx x, enum rtx_code code,
&& exact_log2 (INTVAL (XEXP (varop, 1))) >= 0) && exact_log2 (INTVAL (XEXP (varop, 1))) >= 0)
{ {
varop varop
= gen_binary (ASHIFT, GET_MODE (varop), XEXP (varop, 0), = simplify_gen_binary (ASHIFT, GET_MODE (varop),
GEN_INT (exact_log2 (INTVAL (XEXP (varop, 1))))); XEXP (varop, 0),
GEN_INT (exact_log2 (
INTVAL (XEXP (varop, 1)))));
continue; continue;
} }
break; break;
...@@ -8517,8 +8593,10 @@ simplify_shift_const (rtx x, enum rtx_code code, ...@@ -8517,8 +8593,10 @@ simplify_shift_const (rtx x, enum rtx_code code,
&& exact_log2 (INTVAL (XEXP (varop, 1))) >= 0) && exact_log2 (INTVAL (XEXP (varop, 1))) >= 0)
{ {
varop varop
= gen_binary (LSHIFTRT, GET_MODE (varop), XEXP (varop, 0), = simplify_gen_binary (LSHIFTRT, GET_MODE (varop),
GEN_INT (exact_log2 (INTVAL (XEXP (varop, 1))))); XEXP (varop, 0),
GEN_INT (exact_log2 (
INTVAL (XEXP (varop, 1)))));
continue; continue;
} }
break; break;
...@@ -8763,7 +8841,7 @@ simplify_shift_const (rtx x, enum rtx_code code, ...@@ -8763,7 +8841,7 @@ simplify_shift_const (rtx x, enum rtx_code code,
logical expression, make a new logical expression, and apply logical expression, make a new logical expression, and apply
the inverse distributive law. This also can't be done the inverse distributive law. This also can't be done
for some (ashiftrt (xor)). */ for some (ashiftrt (xor)). */
if (code != ASHIFTRT || GET_CODE (varop)!= XOR if (code != ASHIFTRT || GET_CODE (varop) != XOR
|| 0 <= trunc_int_for_mode (INTVAL (XEXP (varop, 1)), || 0 <= trunc_int_for_mode (INTVAL (XEXP (varop, 1)),
shift_mode)) shift_mode))
{ {
...@@ -8772,7 +8850,8 @@ simplify_shift_const (rtx x, enum rtx_code code, ...@@ -8772,7 +8850,8 @@ simplify_shift_const (rtx x, enum rtx_code code,
rtx rhs = simplify_shift_const (NULL_RTX, code, shift_mode, rtx rhs = simplify_shift_const (NULL_RTX, code, shift_mode,
XEXP (varop, 1), count); XEXP (varop, 1), count);
varop = gen_binary (GET_CODE (varop), shift_mode, lhs, rhs); varop = simplify_gen_binary (GET_CODE (varop), shift_mode,
lhs, rhs);
varop = apply_distributive_law (varop); varop = apply_distributive_law (varop);
count = 0; count = 0;
...@@ -9026,7 +9105,8 @@ simplify_shift_const (rtx x, enum rtx_code code, ...@@ -9026,7 +9105,8 @@ simplify_shift_const (rtx x, enum rtx_code code,
else if (GET_RTX_CLASS (outer_op) == RTX_UNARY) else if (GET_RTX_CLASS (outer_op) == RTX_UNARY)
x = simplify_gen_unary (outer_op, result_mode, x, result_mode); x = simplify_gen_unary (outer_op, result_mode, x, result_mode);
else else
x = gen_binary (outer_op, result_mode, x, GEN_INT (outer_const)); x = simplify_gen_binary (outer_op, result_mode, x,
GEN_INT (outer_const));
} }
return x; return x;
...@@ -9259,63 +9339,6 @@ gen_lowpart_for_combine (enum machine_mode mode, rtx x) ...@@ -9259,63 +9339,6 @@ gen_lowpart_for_combine (enum machine_mode mode, rtx x)
} }
} }
/* These routines make binary and unary operations by first seeing if they
fold; if not, a new expression is allocated. */
static rtx
gen_binary (enum rtx_code code, enum machine_mode mode, rtx op0, rtx op1)
{
rtx result;
rtx tem;
if (GET_CODE (op0) == CLOBBER)
return op0;
else if (GET_CODE (op1) == CLOBBER)
return op1;
if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
&& swap_commutative_operands_p (op0, op1))
tem = op0, op0 = op1, op1 = tem;
if (GET_RTX_CLASS (code) == RTX_COMPARE
|| GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
{
enum machine_mode op_mode = GET_MODE (op0);
/* Strip the COMPARE from (REL_OP (compare X Y) 0) to get
just (REL_OP X Y). */
if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
{
op1 = XEXP (op0, 1);
op0 = XEXP (op0, 0);
op_mode = GET_MODE (op0);
}
if (op_mode == VOIDmode)
op_mode = GET_MODE (op1);
result = simplify_relational_operation (code, mode, op_mode, op0, op1);
}
else
result = simplify_binary_operation (code, mode, op0, op1);
if (result)
return result;
/* Put complex operands first and constants second. */
if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
&& swap_commutative_operands_p (op0, op1))
return gen_rtx_fmt_ee (code, mode, op1, op0);
/* If we are turning off bits already known off in OP0, we need not do
an AND. */
else if (code == AND && GET_CODE (op1) == CONST_INT
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (op0, mode) & ~INTVAL (op1)) == 0)
return op0;
return gen_rtx_fmt_ee (code, mode, op0, op1);
}
/* Simplify a comparison between *POP0 and *POP1 where CODE is the /* Simplify a comparison between *POP0 and *POP1 where CODE is the
comparison code that will be tested. comparison code that will be tested.
...@@ -10150,7 +10173,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) ...@@ -10150,7 +10173,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& c1 != mask && c1 != mask
&& c1 != GET_MODE_MASK (tmode)) && c1 != GET_MODE_MASK (tmode))
{ {
op0 = gen_binary (AND, tmode, op0 = simplify_gen_binary (AND, tmode,
SUBREG_REG (XEXP (op0, 0)), SUBREG_REG (XEXP (op0, 0)),
gen_int_mode (c1, tmode)); gen_int_mode (c1, tmode));
op0 = gen_lowpart (mode, op0); op0 = gen_lowpart (mode, op0);
...@@ -10296,10 +10319,10 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) ...@@ -10296,10 +10319,10 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
{ {
rtx inner = XEXP (XEXP (XEXP (op0, 0), 0), 0); rtx inner = XEXP (XEXP (XEXP (op0, 0), 0), 0);
rtx add_const = XEXP (XEXP (op0, 0), 1); rtx add_const = XEXP (XEXP (op0, 0), 1);
rtx new_const = gen_binary (ASHIFTRT, GET_MODE (op0), add_const, rtx new_const = simplify_gen_binary (ASHIFTRT, GET_MODE (op0),
XEXP (op0, 1)); add_const, XEXP (op0, 1));
op0 = gen_binary (PLUS, tmode, op0 = simplify_gen_binary (PLUS, tmode,
gen_lowpart (tmode, inner), gen_lowpart (tmode, inner),
new_const); new_const);
continue; continue;
...@@ -10454,7 +10477,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) ...@@ -10454,7 +10477,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
make a new AND in the proper mode. */ make a new AND in the proper mode. */
if (GET_CODE (op0) == AND if (GET_CODE (op0) == AND
&& !have_insn_for (AND, mode)) && !have_insn_for (AND, mode))
op0 = gen_binary (AND, tmode, op0 = simplify_gen_binary (AND, tmode,
gen_lowpart (tmode, gen_lowpart (tmode,
XEXP (op0, 0)), XEXP (op0, 0)),
gen_lowpart (tmode, gen_lowpart (tmode,
...@@ -10473,10 +10496,11 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) ...@@ -10473,10 +10496,11 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
if (op1 == const0_rtx && (code == LT || code == GE) if (op1 == const0_rtx && (code == LT || code == GE)
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
{ {
op0 = gen_binary (AND, tmode, op0 = simplify_gen_binary (AND, tmode,
gen_lowpart (tmode, op0), gen_lowpart (tmode, op0),
GEN_INT ((HOST_WIDE_INT) 1 GEN_INT ((HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (mode) - 1))); << (GET_MODE_BITSIZE (mode)
- 1)));
code = (code == LT) ? NE : EQ; code = (code == LT) ? NE : EQ;
break; break;
} }
...@@ -10523,7 +10547,7 @@ reversed_comparison (rtx exp, enum machine_mode mode, rtx op0, rtx op1) ...@@ -10523,7 +10547,7 @@ reversed_comparison (rtx exp, enum machine_mode mode, rtx op0, rtx op1)
if (reversed_code == UNKNOWN) if (reversed_code == UNKNOWN)
return NULL_RTX; return NULL_RTX;
else else
return gen_binary (reversed_code, mode, op0, op1); return simplify_gen_relational (reversed_code, mode, VOIDmode, op0, op1);
} }
/* Utility function for following routine. Called when X is part of a value /* Utility function for following routine. Called when X is part of a value
......
...@@ -1844,9 +1844,11 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, ...@@ -1844,9 +1844,11 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
case AND: case AND:
if (trueop1 == const0_rtx && ! side_effects_p (op0)) if (trueop1 == const0_rtx && ! side_effects_p (op0))
return const0_rtx; return const0_rtx;
/* If we are turning off bits already known off in OP0, we need
not do an AND. */
if (GET_CODE (trueop1) == CONST_INT if (GET_CODE (trueop1) == CONST_INT
&& ((INTVAL (trueop1) & GET_MODE_MASK (mode)) && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
== GET_MODE_MASK (mode))) && (nonzero_bits (trueop0, mode) & ~INTVAL (trueop1)) == 0)
return op0; return op0;
if (trueop0 == trueop1 && ! side_effects_p (op0) if (trueop0 == trueop1 && ! side_effects_p (op0)
&& GET_MODE_CLASS (mode) != MODE_CC) && GET_MODE_CLASS (mode) != MODE_CC)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment