aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>1996-10-29 00:01:53 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>1996-10-29 00:01:53 +0000
commit0f13a422020fd379d217a7ef913b3bb1002730f3 (patch)
tree1ed7714bea75fe3fc71c5b94771ebeac2a84519f /gcc
parent8cc2ddb666cfba01a80f6d91cb5921958008125c (diff)
downloadgcc-0f13a422020fd379d217a7ef913b3bb1002730f3.zip
gcc-0f13a422020fd379d217a7ef913b3bb1002730f3.tar.gz
gcc-0f13a422020fd379d217a7ef913b3bb1002730f3.tar.bz2
Add some optimizations for TRUNCATE and ZERO_EXTEND
From-SVN: r13058
Diffstat (limited to 'gcc')
-rw-r--r--gcc/combine.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/gcc/combine.c b/gcc/combine.c
index 745427a..c9a14a7 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -3539,6 +3539,55 @@ simplify_rtx (x, op0_mode, last, in_dest)
SUBST (XEXP (x, 0),
force_to_mode (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
GET_MODE_MASK (mode), NULL_RTX, 0));
+
+ /* (truncate:SI ({sign,zero}_extend:DI foo:SI)) == foo:SI. */
+ if ((GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
+ || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND)
+ && GET_MODE (XEXP (XEXP (x, 0), 0)) == mode)
+ return XEXP (XEXP (x, 0), 0);
+
+ /* (truncate:SI (OP:DI ({sign,zero}_extend:DI foo:SI))) is
+ (OP:SI foo:SI) if OP is NEG or ABS. */
+ if ((GET_CODE (XEXP (x, 0)) == ABS
+ || GET_CODE (XEXP (x, 0)) == NEG)
+ && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SIGN_EXTEND
+ || GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND)
+ && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode)
+ return gen_unary (GET_CODE (XEXP (x, 0)), mode, mode,
+ XEXP (XEXP (XEXP (x, 0), 0), 0));
+
+ /* (truncate:SI (subreg:DI (truncate:SI X) 0)) is
+ (truncate:SI x). */
+ if (GET_CODE (XEXP (x, 0)) == SUBREG
+ && GET_CODE (SUBREG_REG (XEXP (x, 0))) == TRUNCATE
+ && subreg_lowpart_p (XEXP (x, 0)))
+ return SUBREG_REG (XEXP (x, 0));
+
+ /* If we know that the value is already truncated, we can
+ replace the TRUNCATE with a SUBREG. */
+ if (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) <= HOST_BITS_PER_WIDE_INT
+ && (nonzero_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
+ &~ GET_MODE_MASK (mode)) == 0)
+ return gen_lowpart_for_combine (mode, XEXP (x, 0));
+
+ /* A truncate of a comparison can be replaced with a subreg if
+ STORE_FLAG_VALUE permits. This is like the previous test,
+ but it works even if the comparison is done in a mode larger
+ than HOST_BITS_PER_WIDE_INT. */
+ if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+ && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
+ && ((HOST_WIDE_INT) STORE_FLAG_VALUE &~ GET_MODE_MASK (mode)) == 0)
+ return gen_lowpart_for_combine (mode, XEXP (x, 0));
+
+ /* Similarly, a truncate of a register whose value is a
+ comparison can be replaced with a subreg if STORE_FLAG_VALUE
+ permits. */
+ if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+ && ((HOST_WIDE_INT) STORE_FLAG_VALUE &~ GET_MODE_MASK (mode)) == 0
+ && (temp = get_last_value (XEXP (x, 0)))
+ && GET_RTX_CLASS (GET_CODE (temp)) == '<')
+ return gen_lowpart_for_combine (mode, XEXP (x, 0));
+
break;
case FLOAT_TRUNCATE:
@@ -4915,6 +4964,78 @@ expand_compound_operation (x)
return x;
}
+ /* We can optimize some special cases of ZERO_EXTEND. */
+ if (GET_CODE (x) == ZERO_EXTEND)
+ {
+ /* (zero_extend:DI (truncate:SI foo:DI)) is just foo:DI if we
+ know that the last value didn't have any inappropriate bits
+ set. */
+ if (GET_CODE (XEXP (x, 0)) == TRUNCATE
+ && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
+ && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
+ && (nonzero_bits (XEXP (XEXP (x, 0), 0), GET_MODE (x))
+ & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+ return XEXP (XEXP (x, 0), 0);
+
+ /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)). */
+ if (GET_CODE (XEXP (x, 0)) == SUBREG
+ && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x)
+ && subreg_lowpart_p (XEXP (x, 0))
+ && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
+ && (nonzero_bits (SUBREG_REG (XEXP (x, 0)), GET_MODE (x))
+ & ~ GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))) == 0)
+ return SUBREG_REG (XEXP (x, 0));
+
+ /* (zero_extend:DI (truncate:SI foo:DI)) is just foo:DI when foo
+ is a comparison and STORE_FLAG_VALUE permits. This is like
+ the first case, but it works even when GET_MODE (x) is larger
+ than HOST_WIDE_INT. */
+ if (GET_CODE (XEXP (x, 0)) == TRUNCATE
+ && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
+ && GET_RTX_CLASS (GET_CODE (XEXP (XEXP (x, 0), 0))) == '<'
+ && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
+ <= HOST_BITS_PER_WIDE_INT)
+ && ((HOST_WIDE_INT) STORE_FLAG_VALUE
+ & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+ return XEXP (XEXP (x, 0), 0);
+
+ /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)). */
+ if (GET_CODE (XEXP (x, 0)) == SUBREG
+ && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x)
+ && subreg_lowpart_p (XEXP (x, 0))
+ && GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (x, 0)))) == '<'
+ && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
+ <= HOST_BITS_PER_WIDE_INT)
+ && ((HOST_WIDE_INT) STORE_FLAG_VALUE
+ & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+ return SUBREG_REG (XEXP (x, 0));
+
+ /* If sign extension is cheaper than zero extension, then use it
+ if we know that no extraneous bits are set, and that the high
+ bit is not set. */
+ if (flag_expensive_optimizations
+ && ((GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
+ && ((nonzero_bits (XEXP (x, 0), GET_MODE (x))
+ & ~ (((unsigned HOST_WIDE_INT)
+ GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
+ >> 1))
+ == 0))
+ || (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
+ && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
+ <= HOST_BITS_PER_WIDE_INT)
+ && (((HOST_WIDE_INT) STORE_FLAG_VALUE
+ & ~ (((unsigned HOST_WIDE_INT)
+ GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
+ >> 1))
+ == 0))))
+ {
+ rtx temp = gen_rtx (SIGN_EXTEND, GET_MODE (x), XEXP (x, 0));
+
+ if (rtx_cost (temp, SET) < rtx_cost (x, SET))
+ return expand_compound_operation (temp);
+ }
+ }
+
/* If we reach here, we want to return a pair of shifts. The inner
shift is a left shift of BITSIZE - POS - LEN bits. The outer
shift is a right shift of BITSIZE - LEN bits. It is arithmetic or