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
This commit is contained in:
Roger Sayle 2004-04-12 17:28:11 +00:00 committed by Roger Sayle
parent e0fb1c5c37
commit 1e9b78b094
2 changed files with 109 additions and 43 deletions

View file

@ -1,3 +1,12 @@
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>
* config/rs6000/rs6000.md: Document why a pattern is not

View file

@ -1900,70 +1900,127 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
break;
case UDIV:
/* Convert divide by power of two into shift (divide by 1 handled
below). */
if (GET_CODE (trueop1) == CONST_INT
&& (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (arg1));
/* Fall through.... */
case DIV:
if (trueop1 == CONST1_RTX (mode))
/* 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)
{
/* On some platforms DIV uses narrower mode than its
operands. */
/* Handle narrowing UDIV. */
rtx x = gen_lowpart_common (mode, op0);
if (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);
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
modes with NaNs, since 0 / 0 will then be NaN rather than 0.
Nor is it safe for modes with signed zeros, since dividing
0 by a negative number gives -0, not 0. */
if (!HONOR_NANS (mode)
&& !HONOR_SIGNED_ZEROS (mode)
&& trueop0 == CONST0_RTX (mode)
&& ! side_effects_p (op1))
return op0;
/* Change division by a constant into multiplication. Only do
this with -funsafe-math-optimizations. */
else if (GET_CODE (trueop1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
&& trueop1 != CONST0_RTX (mode)
&& flag_unsafe_math_optimizations)
case DIV:
/* Handle floating point and integers separately. */
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
REAL_VALUE_TYPE d;
REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
/* 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)
&& ! side_effects_p (op1))
return op0;
/* x/1.0 is x. */
if (trueop1 == CONST1_RTX (mode)
&& !HONOR_SNANS (mode))
return op0;
if (! REAL_VALUES_EQUAL (d, dconst0))
if (GET_CODE (trueop1) == CONST_DOUBLE
&& trueop1 != CONST0_RTX (mode))
{
REAL_ARITHMETIC (d, rtx_to_tree_code (DIV), dconst1, d);
tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
return simplify_gen_binary (MULT, mode, op0, tem);
REAL_VALUE_TYPE d;
REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
/* 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, RDIV_EXPR, dconst1, d);
tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
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;
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
&& exact_log2 (INTVAL (trueop1)) > 0)
return simplify_gen_binary (AND, mode, op0,
GEN_INT (INTVAL (op1) - 1));
/* Fall through.... */
break;
case MOD:
if ((trueop0 == const0_rtx || trueop1 == const1_rtx)
&& ! side_effects_p (op0) && ! side_effects_p (op1))
return const0_rtx;
/* 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 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;
case ROTATERT: