Commit 1e9b78b0 by Roger Sayle Committed by Roger Sayle

simplify-rtx.c (simplify_binary_operation): Remove fall throughs.


	* simplify-rtx.c (simplify_binary_operation) <UDIV, DIV, UMOD, MOD>:
	Remove fall throughs.  Convert 0/x and 0%x into x&0 when x has
	side-effects.  Don't convert x/1.0 into x if we honor signaling NaNs.
	Convert x/-1.0 into -x if we don't honor signaling NaNs.  Convert
	x/-1 into -x.  Optimize x%1 into x&0 if x has side-effects.  Optimize
	x%-1 into 0 (or x&0 if x has side-effects).

From-SVN: r80625
parent e0fb1c5c
2004-04-12 Roger Sayle <roger@eyesopen.com>
* simplify-rtx.c (simplify_binary_operation) <UDIV, DIV, UMOD, MOD>:
Remove fall throughs. Convert 0/x and 0%x into x&0 when x has
side-effects. Don't convert x/1.0 into x if we honor signaling NaNs.
Convert x/-1.0 into -x if we don't honor signaling NaNs. Convert
x/-1 into -x. Optimize x%1 into x&0 if x has side-effects. Optimize
x%-1 into 0 (or x&0 if x has side-effects).
2004-04-11 Aldy Hernandez <aldyh@redhat.com> 2004-04-11 Aldy Hernandez <aldyh@redhat.com>
* config/rs6000/rs6000.md: Document why a pattern is not * config/rs6000/rs6000.md: Document why a pattern is not
......
...@@ -1900,70 +1900,127 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, ...@@ -1900,70 +1900,127 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
break; break;
case UDIV: case UDIV:
/* Convert divide by power of two into shift (divide by 1 handled /* 0/x is 0 (or x&0 if x has side-effects). */
below). */ if (trueop0 == const0_rtx)
if (GET_CODE (trueop1) == CONST_INT return side_effects_p (op1)
&& (arg1 = exact_log2 (INTVAL (trueop1))) > 0) ? simplify_gen_binary (AND, mode, op1, const0_rtx)
return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (arg1)); : const0_rtx;
/* x/1 is x. */
/* Fall through.... */ if (trueop1 == const1_rtx)
{
case DIV: /* Handle narrowing UDIV. */
if (trueop1 == CONST1_RTX (mode))
{
/* On some platforms DIV uses narrower mode than its
operands. */
rtx x = gen_lowpart_common (mode, op0); rtx x = gen_lowpart_common (mode, op0);
if (x) if (x)
return x; return x;
else if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode) if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
return gen_lowpart_SUBREG (mode, op0); return gen_lowpart_SUBREG (mode, op0);
else
return op0; return op0;
} }
/* Convert divide by power of two into shift. */
if (GET_CODE (trueop1) == CONST_INT
&& (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (arg1));
break;
/* Maybe change 0 / x to 0. This transformation isn't safe for case DIV:
modes with NaNs, since 0 / 0 will then be NaN rather than 0. /* Handle floating point and integers separately. */
Nor is it safe for modes with signed zeros, since dividing if (GET_MODE_CLASS (mode) == MODE_FLOAT)
0 by a negative number gives -0, not 0. */ {
if (!HONOR_NANS (mode) /* Maybe change 0.0 / x to 0.0. This transformation isn't
safe for modes with NaNs, since 0.0 / 0.0 will then be
NaN rather than 0.0. Nor is it safe for modes with signed
zeros, since dividing 0 by a negative number gives -0.0 */
if (trueop0 == CONST0_RTX (mode)
&& !HONOR_NANS (mode)
&& !HONOR_SIGNED_ZEROS (mode) && !HONOR_SIGNED_ZEROS (mode)
&& trueop0 == CONST0_RTX (mode)
&& ! side_effects_p (op1)) && ! side_effects_p (op1))
return op0; return op0;
/* x/1.0 is x. */
if (trueop1 == CONST1_RTX (mode)
&& !HONOR_SNANS (mode))
return op0;
/* Change division by a constant into multiplication. Only do if (GET_CODE (trueop1) == CONST_DOUBLE
this with -funsafe-math-optimizations. */ && trueop1 != CONST0_RTX (mode))
else if (GET_CODE (trueop1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
&& trueop1 != CONST0_RTX (mode)
&& flag_unsafe_math_optimizations)
{ {
REAL_VALUE_TYPE d; REAL_VALUE_TYPE d;
REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1); REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
if (! REAL_VALUES_EQUAL (d, dconst0)) /* x/-1.0 is -x. */
if (REAL_VALUES_EQUAL (d, dconstm1)
&& !HONOR_SNANS (mode))
return simplify_gen_unary (NEG, mode, op0, mode);
/* Change FP division by a constant into multiplication.
Only do this with -funsafe-math-optimizations. */
if (flag_unsafe_math_optimizations
&& !REAL_VALUES_EQUAL (d, dconst0))
{ {
REAL_ARITHMETIC (d, rtx_to_tree_code (DIV), dconst1, d); REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d);
tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode); tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
return simplify_gen_binary (MULT, mode, op0, tem); return simplify_gen_binary (MULT, mode, op0, tem);
} }
} }
}
else
{
/* 0/x is 0 (or x&0 if x has side-effects). */
if (trueop0 == const0_rtx)
return side_effects_p (op1)
? simplify_gen_binary (AND, mode, op1, const0_rtx)
: const0_rtx;
/* x/1 is x. */
if (trueop1 == const1_rtx)
{
/* Handle narrowing DIV. */
rtx x = gen_lowpart_common (mode, op0);
if (x)
return x;
if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
return gen_lowpart_SUBREG (mode, op0);
return op0;
}
/* x/-1 is -x. */
if (trueop1 == constm1_rtx)
{
rtx x = gen_lowpart_common (mode, op0);
if (!x)
x = (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
? gen_lowpart_SUBREG (mode, op0) : op0;
return simplify_gen_unary (NEG, mode, x, mode);
}
}
break; break;
case UMOD: case UMOD:
/* Handle modulus by power of two (mod with 1 handled below). */ /* 0%x is 0 (or x&0 if x has side-effects). */
if (trueop0 == const0_rtx)
return side_effects_p (op1)
? simplify_gen_binary (AND, mode, op1, const0_rtx)
: const0_rtx;
/* x%1 is 0 (of x&0 if x has side-effects). */
if (trueop1 == const1_rtx)
return side_effects_p (op0)
? simplify_gen_binary (AND, mode, op0, const0_rtx)
: const0_rtx;
/* Implement modulus by power of two as AND. */
if (GET_CODE (trueop1) == CONST_INT if (GET_CODE (trueop1) == CONST_INT
&& exact_log2 (INTVAL (trueop1)) > 0) && exact_log2 (INTVAL (trueop1)) > 0)
return simplify_gen_binary (AND, mode, op0, return simplify_gen_binary (AND, mode, op0,
GEN_INT (INTVAL (op1) - 1)); GEN_INT (INTVAL (op1) - 1));
break;
/* Fall through.... */
case MOD: case MOD:
if ((trueop0 == const0_rtx || trueop1 == const1_rtx) /* 0%x is 0 (or x&0 if x has side-effects). */
&& ! side_effects_p (op0) && ! side_effects_p (op1)) if (trueop0 == const0_rtx)
return const0_rtx; return side_effects_p (op1)
? simplify_gen_binary (AND, mode, op1, const0_rtx)
: const0_rtx;
/* x%1 and x%-1 is 0 (or x&0 if x has side-effects). */
if (trueop1 == const1_rtx || trueop1 == constm1_rtx)
return side_effects_p (op0)
? simplify_gen_binary (AND, mode, op0, const0_rtx)
: const0_rtx;
break; break;
case ROTATERT: case ROTATERT:
......
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